undo: Do some refactoring

Specifically refactor u_get_undo_file_name which will be modified to
automatically create undo directory and replace `char_u` with `char` in some of
the related functions.
This commit is contained in:
ZyX
2015-10-29 01:14:01 +03:00
parent 1af15494c2
commit d99941777d
4 changed files with 95 additions and 75 deletions

View File

@@ -16678,10 +16678,11 @@ static void f_undofile(typval_T *argvars, typval_T *rettv)
/* If there is no file name there will be no undo file. */ /* If there is no file name there will be no undo file. */
rettv->vval.v_string = NULL; rettv->vval.v_string = NULL;
} else { } else {
char_u *ffname = (char_u *)FullName_save((char *)fname, FALSE); char *ffname = FullName_save((char *)fname, false);
if (ffname != NULL) if (ffname != NULL) {
rettv->vval.v_string = u_get_undo_file_name(ffname, FALSE); rettv->vval.v_string = (char_u *)u_get_undo_file_name(ffname, false);
}
xfree(ffname); xfree(ffname);
} }
} }

View File

@@ -7193,7 +7193,7 @@ static void ex_wundo(exarg_T *eap)
char_u hash[UNDO_HASH_SIZE]; char_u hash[UNDO_HASH_SIZE];
u_compute_hash(hash); u_compute_hash(hash);
u_write_undo(eap->arg, eap->forceit, curbuf, hash); u_write_undo((char *) eap->arg, eap->forceit, curbuf, hash);
} }
static void ex_rundo(exarg_T *eap) static void ex_rundo(exarg_T *eap)
@@ -7201,7 +7201,7 @@ static void ex_rundo(exarg_T *eap)
char_u hash[UNDO_HASH_SIZE]; char_u hash[UNDO_HASH_SIZE];
u_compute_hash(hash); u_compute_hash(hash);
u_read_undo(eap->arg, hash, NULL); u_read_undo((char *) eap->arg, hash, NULL);
} }
/* /*

View File

@@ -2990,7 +2990,7 @@ static void ml_lineadd(buf_T *buf, int count)
* If it worked returns OK and the resolved link in "buf[MAXPATHL]". * If it worked returns OK and the resolved link in "buf[MAXPATHL]".
* Otherwise returns FAIL. * Otherwise returns FAIL.
*/ */
int resolve_symlink(char_u *fname, char_u *buf) int resolve_symlink(const char_u *fname, char_u *buf)
{ {
char_u tmp[MAXPATHL]; char_u tmp[MAXPATHL];
int ret; int ret;

View File

@@ -638,64 +638,74 @@ void u_compute_hash(char_u *hash)
sha256_finish(&ctx, hash); sha256_finish(&ctx, hash);
} }
/* /// Return an allocated string of the full path of the target undofile.
* Return an allocated string of the full path of the target undofile. ///
* When "reading" is TRUE find the file to read, go over all directories in /// @param[in] buf_ffname Full file name for which undo file location should
* 'undodir'. /// be found.
* When "reading" is FALSE use the first name where the directory exists. /// @param[in] reading If true, find the file to read by traversing all of the
* Returns NULL when there is no place to write or no file to read. /// directories in &undodir. If false use the first
*/ /// existing directory.
char_u *u_get_undo_file_name(char_u *buf_ffname, int reading) ///
/// @return [allocated] File name to read from/write to or NULL.
char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{ {
char_u *dirp; char *dirp;
char_u dir_name[IOSIZE + 1]; char dir_name[MAXPATHL + 1];
char_u *munged_name = NULL; char *munged_name = NULL;
char_u *undo_file_name = NULL; char *undo_file_name = NULL;
char_u *p; const char *ffname = buf_ffname;
char_u *ffname = buf_ffname;
#ifdef HAVE_READLINK #ifdef HAVE_READLINK
char_u fname_buf[MAXPATHL]; char fname_buf[MAXPATHL];
#endif #endif
if (ffname == NULL) if (ffname == NULL) {
return NULL; return NULL;
}
#ifdef HAVE_READLINK #ifdef HAVE_READLINK
/* Expand symlink in the file name, so that we put the undo file with the // Expand symlink in the file name, so that we put the undo file with the
* actual file instead of with the symlink. */ // actual file instead of with the symlink.
if (resolve_symlink(ffname, fname_buf) == OK) if (resolve_symlink((const char_u *)ffname, (char_u *)fname_buf) == OK) {
ffname = fname_buf; ffname = fname_buf;
}
#endif #endif
/* Loop over 'undodir'. When reading find the first file that exists. // Loop over 'undodir'. When reading find the first file that exists.
* When not reading use the first directory that exists or ".". */ // When not reading use the first directory that exists or ".".
dirp = p_udir; dirp = (char *) p_udir;
while (*dirp != NUL) { while (*dirp != NUL) {
size_t dir_len = copy_option_part(&dirp, dir_name, IOSIZE, ","); size_t dir_len = copy_option_part((char_u **)&dirp, (char_u *)dir_name,
MAXPATHL, ",");
if (dir_len == 1 && dir_name[0] == '.') { if (dir_len == 1 && dir_name[0] == '.') {
/* Use same directory as the ffname, // Use same directory as the ffname,
* "dir/name" -> "dir/.name.un~" */ // "dir/name" -> "dir/.name.un~"
undo_file_name = vim_strnsave(ffname, STRLEN(ffname) + 5); const size_t ffname_len = strlen(ffname);
p = path_tail(undo_file_name); undo_file_name = xmalloc(ffname_len + 6);
memmove(p + 1, p, STRLEN(p) + 1); memmove(undo_file_name, ffname, ffname_len + 1);
*p = '.'; char *const tail = (char *) path_tail((char_u *) undo_file_name);
STRCAT(p, ".un~"); const size_t tail_len = strlen(tail);
memmove(tail + 1, tail, tail_len + 1);
*tail = '.';
memmove(tail + tail_len + 1, ".un~", sizeof(".un~"));
} else { } else {
dir_name[dir_len] = NUL; dir_name[dir_len] = NUL;
if (os_isdir(dir_name)) { if (os_isdir((char_u *)dir_name)) {
if (munged_name == NULL) { if (munged_name == NULL) {
munged_name = vim_strsave(ffname); munged_name = xstrdup(ffname);
for (p = munged_name; *p != NUL; mb_ptr_adv(p)) for (char *p = munged_name; *p != NUL; mb_ptr_adv(p)) {
if (vim_ispathsep(*p)) if (vim_ispathsep(*p)) {
*p = '%'; *p = '%';
} }
undo_file_name = (char_u *)concat_fnames((char *)dir_name, (char *)munged_name, TRUE); }
}
undo_file_name = concat_fnames(dir_name, munged_name, true);
} }
} }
// When reading check if the file exists. // When reading check if the file exists.
if (undo_file_name != NULL && if (undo_file_name != NULL
(!reading || os_file_exists(undo_file_name))) { && (!reading || os_file_exists((char_u *)undo_file_name))) {
break; break;
} }
xfree(undo_file_name); xfree(undo_file_name);
@@ -706,7 +716,13 @@ char_u *u_get_undo_file_name(char_u *buf_ffname, int reading)
return undo_file_name; return undo_file_name;
} }
static void corruption_error(char *mesg, char_u *file_name) /// Display an error for corrupted undo file
///
/// @param[in] mesg Identifier of the corruption kind.
/// @param[in] file_name File in which error occurred.
static void corruption_error(const char *const mesg,
const char *const file_name)
FUNC_ATTR_NONNULL_ALL
{ {
EMSG3(_("E825: Corrupted undo file (%s): %s"), mesg, file_name); EMSG3(_("E825: Corrupted undo file (%s): %s"), mesg, file_name);
} }
@@ -821,7 +837,8 @@ static bool serialize_uhp(bufinfo_T *bi, u_header_T *uhp)
return true; return true;
} }
static u_header_T *unserialize_uhp(bufinfo_T *bi, char_u *file_name) static u_header_T *unserialize_uhp(bufinfo_T *bi,
const char *file_name)
{ {
u_header_T *uhp = xmalloc(sizeof(u_header_T)); u_header_T *uhp = xmalloc(sizeof(u_header_T));
memset(uhp, 0, sizeof(u_header_T)); memset(uhp, 0, sizeof(u_header_T));
@@ -918,7 +935,8 @@ static bool serialize_uep(bufinfo_T *bi, u_entry_T *uep)
return true; return true;
} }
static u_entry_T *unserialize_uep(bufinfo_T * bi, bool *error, char_u *file_name) static u_entry_T *unserialize_uep(bufinfo_T * bi, bool *error,
const char *file_name)
{ {
u_entry_T *uep = xmalloc(sizeof(u_entry_T)); u_entry_T *uep = xmalloc(sizeof(u_entry_T));
memset(uep, 0, sizeof(u_entry_T)); memset(uep, 0, sizeof(u_entry_T));
@@ -1000,19 +1018,20 @@ static void unserialize_visualinfo(bufinfo_T *bi, visualinfo_T *info)
info->vi_curswant = undo_read_4c(bi); info->vi_curswant = undo_read_4c(bi);
} }
/* /// Write the undo tree in an undo file.
* Write the undo tree in an undo file. ///
* When "name" is not NULL, use it as the name of the undo file. /// @param[in] name Name of the undo file or NULL if this function needs to
* Otherwise use buf->b_ffname to generate the undo file name. /// generate the undo file name based on buf->b_ffname.
* "buf" must never be null, buf->b_ffname is used to obtain the original file /// @param[in] forceit True for `:wundo!`, false otherwise.
* permissions. /// @param[in] buf Buffer for which undo file is written.
* "forceit" is TRUE for ":wundo!", FALSE otherwise. /// @param[in] hash Hash value of the buffer text. Must have #UNDO_HASH_SIZE
* "hash[UNDO_HASH_SIZE]" must be the hash value of the buffer text. /// size.
*/ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
void u_write_undo(char_u *name, int forceit, buf_T *buf, char_u *hash) char_u *const hash)
FUNC_ATTR_NONNULL_ARG(3, 4)
{ {
u_header_T *uhp; u_header_T *uhp;
char_u *file_name; char *file_name;
int mark; int mark;
#ifdef U_DEBUG #ifdef U_DEBUG
int headers_written = 0; int headers_written = 0;
@@ -1024,7 +1043,7 @@ void u_write_undo(char_u *name, int forceit, buf_T *buf, char_u *hash)
bufinfo_T bi; bufinfo_T bi;
if (name == NULL) { if (name == NULL) {
file_name = u_get_undo_file_name(buf->b_ffname, FALSE); file_name = u_get_undo_file_name((char *) buf->b_ffname, false);
if (file_name == NULL) { if (file_name == NULL) {
if (p_verbose > 0) { if (p_verbose > 0) {
verbose_enter(); verbose_enter();
@@ -1033,8 +1052,9 @@ void u_write_undo(char_u *name, int forceit, buf_T *buf, char_u *hash)
} }
return; return;
} }
} else } else {
file_name = name; file_name = (char *) name;
}
/* /*
* Decide about the permission to use for the undo file. If the buffer * Decide about the permission to use for the undo file. If the buffer
@@ -1054,10 +1074,10 @@ void u_write_undo(char_u *name, int forceit, buf_T *buf, char_u *hash)
/* If the undo file already exists, verify that it actually is an undo /* If the undo file already exists, verify that it actually is an undo
* file, and delete it. */ * file, and delete it. */
if (os_file_exists(file_name)) { if (os_file_exists((char_u *)file_name)) {
if (name == NULL || !forceit) { if (name == NULL || !forceit) {
/* Check we can read it and it's an undo file. */ /* Check we can read it and it's an undo file. */
fd = os_open((char *)file_name, O_RDONLY, 0); fd = os_open(file_name, O_RDONLY, 0);
if (fd < 0) { if (fd < 0) {
if (name != NULL || p_verbose > 0) { if (name != NULL || p_verbose > 0) {
if (name == NULL) if (name == NULL)
@@ -1086,7 +1106,7 @@ void u_write_undo(char_u *name, int forceit, buf_T *buf, char_u *hash)
} }
} }
} }
os_remove((char *)file_name); os_remove(file_name);
} }
/* If there is no undo information at all, quit here after deleting any /* If there is no undo information at all, quit here after deleting any
@@ -1097,13 +1117,12 @@ void u_write_undo(char_u *name, int forceit, buf_T *buf, char_u *hash)
goto theend; goto theend;
} }
fd = os_open((char *)file_name, fd = os_open(file_name, O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, perm);
O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, perm);
if (fd < 0) { if (fd < 0) {
EMSG2(_(e_not_open), file_name); EMSG2(_(e_not_open), file_name);
goto theend; goto theend;
} }
(void)os_setperm(file_name, perm); (void)os_setperm((char_u *)file_name, perm);
if (p_verbose > 0) { if (p_verbose > 0) {
verbose_enter(); verbose_enter();
smsg(_("Writing undo file: %s"), file_name); smsg(_("Writing undo file: %s"), file_name);
@@ -1125,10 +1144,10 @@ void u_write_undo(char_u *name, int forceit, buf_T *buf, char_u *hash)
FileInfo file_info_new; FileInfo file_info_new;
if (buf->b_ffname != NULL if (buf->b_ffname != NULL
&& os_fileinfo((char *)buf->b_ffname, &file_info_old) && os_fileinfo((char *)buf->b_ffname, &file_info_old)
&& os_fileinfo((char *)file_name, &file_info_new) && os_fileinfo(file_name, &file_info_new)
&& file_info_old.stat.st_gid != file_info_new.stat.st_gid && file_info_old.stat.st_gid != file_info_new.stat.st_gid
&& os_fchown(fd, (uv_uid_t)-1, (uv_gid_t)file_info_old.stat.st_gid)) { && os_fchown(fd, (uv_uid_t)-1, (uv_gid_t)file_info_old.stat.st_gid)) {
os_setperm(file_name, (perm & 0707) | ((perm & 07) << 3)); os_setperm((char_u *)file_name, (perm & 0707) | ((perm & 07) << 3));
} }
# ifdef HAVE_SELINUX # ifdef HAVE_SELINUX
if (buf->b_ffname != NULL) if (buf->b_ffname != NULL)
@@ -1140,7 +1159,7 @@ void u_write_undo(char_u *name, int forceit, buf_T *buf, char_u *hash)
if (fp == NULL) { if (fp == NULL) {
EMSG2(_(e_not_open), file_name); EMSG2(_(e_not_open), file_name);
close(fd); close(fd);
os_remove((char *)file_name); os_remove(file_name);
goto theend; goto theend;
} }
@@ -1209,7 +1228,7 @@ write_error:
/* For systems that support ACL: get the ACL from the original file. */ /* For systems that support ACL: get the ACL from the original file. */
acl = mch_get_acl(buf->b_ffname); acl = mch_get_acl(buf->b_ffname);
mch_set_acl(file_name, acl); mch_set_acl((char_u *)file_name, acl);
mch_free_acl(acl); mch_free_acl(acl);
} }
#endif #endif
@@ -1224,15 +1243,15 @@ theend:
/// a bit more verbose. /// a bit more verbose.
/// Otherwise use curbuf->b_ffname to generate the undo file name. /// Otherwise use curbuf->b_ffname to generate the undo file name.
/// "hash[UNDO_HASH_SIZE]" must be the hash value of the buffer text. /// "hash[UNDO_HASH_SIZE]" must be the hash value of the buffer text.
void u_read_undo(char_u *name, char_u *hash, char_u *orig_name) void u_read_undo(char *name, char_u *hash, char_u *orig_name)
FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_NONNULL_ARG(2)
{ {
u_header_T **uhp_table = NULL; u_header_T **uhp_table = NULL;
char_u *line_ptr = NULL; char_u *line_ptr = NULL;
char_u *file_name; char *file_name;
if (name == NULL) { if (name == NULL) {
file_name = u_get_undo_file_name(curbuf->b_ffname, TRUE); file_name = u_get_undo_file_name((char *) curbuf->b_ffname, true);
if (file_name == NULL) { if (file_name == NULL) {
return; return;
} }
@@ -1256,7 +1275,7 @@ void u_read_undo(char_u *name, char_u *hash, char_u *orig_name)
} }
#endif #endif
} else { } else {
file_name = name; file_name = (char *) name;
} }
if (p_verbose > 0) { if (p_verbose > 0) {
@@ -1265,7 +1284,7 @@ void u_read_undo(char_u *name, char_u *hash, char_u *orig_name)
verbose_leave(); verbose_leave();
} }
FILE *fp = mch_fopen((char *)file_name, "r"); FILE *fp = mch_fopen(file_name, "r");
if (fp == NULL) { if (fp == NULL) {
if (name != NULL || p_verbose > 0) { if (name != NULL || p_verbose > 0) {
EMSG2(_("E822: Cannot open undo file for reading: %s"), file_name); EMSG2(_("E822: Cannot open undo file for reading: %s"), file_name);