diff options
| author | Thomas Wienecke <wienecke.t@gmail.com> | 2014-03-03 15:28:28 +0100 | 
|---|---|---|
| committer | Thiago de Arruda <tpadilha84@gmail.com> | 2014-03-04 06:54:08 -0300 | 
| commit | 92a0374d7b6b27cb91e51e5cfe735fbde100632c (patch) | |
| tree | 7599eacc421b28d301f4ba2690dba1cc8ad6ed87 | |
| parent | 7e8c8cf5a1552602f5fb7308f77291c3e6a71779 (diff) | |
| download | rneovim-92a0374d7b6b27cb91e51e5cfe735fbde100632c.tar.gz rneovim-92a0374d7b6b27cb91e51e5cfe735fbde100632c.tar.bz2 rneovim-92a0374d7b6b27cb91e51e5cfe735fbde100632c.zip | |
Rename and refactor mch_FullName.
* Rename mch_FullName to mch_full_name to match the style guide.
* Add mch_full_dir_name, which saves the absolute path of a given
directory relative to cwd into a given buffer.
* Add function append_path, which glues together two given paths with a
slash.
* Adapt moonscript coding style to the tests.
| -rw-r--r-- | src/buffer.c | 2 | ||||
| -rw-r--r-- | src/eval.c | 2 | ||||
| -rw-r--r-- | src/ex_getln.c | 2 | ||||
| -rw-r--r-- | src/fileio.c | 2 | ||||
| -rw-r--r-- | src/memline.c | 2 | ||||
| -rw-r--r-- | src/misc1.c | 6 | ||||
| -rw-r--r-- | src/os/fs.c | 163 | ||||
| -rw-r--r-- | src/os/os.h | 4 | ||||
| -rw-r--r-- | src/os_unix.c | 2 | ||||
| -rw-r--r-- | src/syntax.c | 2 | ||||
| -rw-r--r-- | src/window.c | 4 | ||||
| -rw-r--r-- | test/unit/os/fs.moon | 198 | 
12 files changed, 265 insertions, 124 deletions
| diff --git a/src/buffer.c b/src/buffer.c index 1c1c0dc6d9..4a13e4bcc9 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -2418,7 +2418,7 @@ void buflist_altfpos(win_T *win)  /*   * Return TRUE if 'ffname' is not the same file as current file. - * Fname must have a full path (expanded by mch_FullName()). + * Fname must have a full path (expanded by mch_full_name()).   */  int otherfile(char_u *ffname)  { diff --git a/src/eval.c b/src/eval.c index 08496e05bd..4eee644536 100644 --- a/src/eval.c +++ b/src/eval.c @@ -12467,7 +12467,7 @@ static void f_resolve(typval_T *argvars, typval_T *rettv)            q[-1] = NUL;            q = gettail(p);          } -        if (q > p && !mch_isFullName(buf)) { +        if (q > p && !mch_is_full_name(buf)) {            /* symlink is relative to directory of argument */            cpy = alloc((unsigned)(STRLEN(p) + STRLEN(buf) + 1));            if (cpy != NULL) { diff --git a/src/ex_getln.c b/src/ex_getln.c index dabe2e49e2..53f30471f5 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -3944,7 +3944,7 @@ expand_shellcmd (    flags |= EW_FILE | EW_EXEC;    /* For an absolute name we don't use $PATH. */ -  if (mch_isFullName(pat)) +  if (mch_is_full_name(pat))      path = (char_u *)" ";    else if ((pat[0] == '.' && (vim_ispathsep(pat[1])                                || (pat[1] == '.' && vim_ispathsep(pat[2]))))) diff --git a/src/fileio.c b/src/fileio.c index 54631ad34a..4613c7cf1a 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -4769,7 +4769,7 @@ void shorten_fnames(int force)          && !path_with_url(buf->b_fname)          && (force              || buf->b_sfname == NULL -            || mch_isFullName(buf->b_sfname))) { +            || mch_is_full_name(buf->b_sfname))) {        vim_free(buf->b_sfname);        buf->b_sfname = NULL;        p = shorten_fname(buf->b_ffname, dirname); diff --git a/src/memline.c b/src/memline.c index 7ccd39b9fc..6fb29c2ddb 100644 --- a/src/memline.c +++ b/src/memline.c @@ -3381,7 +3381,7 @@ int resolve_symlink(char_u *fname, char_u *buf)       * portion of the filename (if any) and the path the symlink       * points to.       */ -    if (mch_isFullName(buf)) +    if (mch_is_full_name(buf))        STRCPY(tmp, buf);      else {        char_u *tail; diff --git a/src/misc1.c b/src/misc1.c index 0fca08188b..770e870069 100644 --- a/src/misc1.c +++ b/src/misc1.c @@ -7945,7 +7945,7 @@ static void expand_path_option(char_u *curdir, garray_T *gap)      else if (path_with_url(buf))        /* URL can't be used here */        continue; -    else if (!mch_isFullName(buf)) { +    else if (!mch_is_full_name(buf)) {        /* Expand relative path to their full path equivalent */        len = (int)STRLEN(curdir);        if (len + (int)STRLEN(buf) + 3 > MAXPATHL) @@ -8086,7 +8086,7 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)          break;        } -    if (mch_isFullName(path)) { +    if (mch_is_full_name(path)) {        /*         * Last resort: shorten relative to curdir if possible.         * 'possible' means: @@ -8375,7 +8375,7 @@ gen_expand_wildcards (         */        if (mch_has_exp_wildcard(p)) {          if ((flags & EW_PATH) -            && !mch_isFullName(p) +            && !mch_is_full_name(p)              && !(p[0] == '.'                   && (vim_ispathsep(p[1])                       || (p[1] == '.' && vim_ispathsep(p[2])))) diff --git a/src/os/fs.c b/src/os/fs.c index bc9a495984..0b83ca319e 100644 --- a/src/os/fs.c +++ b/src/os/fs.c @@ -1,4 +1,4 @@ -/* vi:set ts=8 sts=4 sw=4: +/* vi:set ts=2 sts=2 sw=2:   *   * VIM - Vi IMproved	by Bram Moolenaar   * @@ -33,96 +33,129 @@ int mch_chdir(char *path) {  int mch_dirname(char_u *buf, int len)  {    int errno; -  if ((errno = uv_cwd((char *)buf, len)) != 0) { +  if ((errno = uv_cwd((char *) buf, len)) != 0) {        STRCPY(buf, uv_strerror(errno));        return FAIL;    }    return OK;  } -/* - * Get absolute file name into "buf[len]". +/*  + * Get the absolute name of the given relative directory.   * + * parameter directory: Directory name, relative to current directory.   * return FAIL for failure, OK for success   */ -int mch_FullName( -        char_u      *fname, -        char_u      *buf, -        int len, -        int force                       /* also expand when already absolute path */ -        ) +int mch_full_dir_name(char *directory, char *buffer, int len)  { -  int l; -  char_u olddir[MAXPATHL]; -  char_u      *p;    int retval = OK; +  if(0 == STRLEN(directory)) { +    return mch_dirname((char_u *) buffer, len); +  } +  char old_dir[MAXPATHL]; -  /* expand it if forced or not an absolute path */ -  if (force || !mch_isFullName(fname)) { -    /* -     * If the file name has a path, change to that directory for a moment, -     * and then do the getwd() (and get back to where we were). -     * This will get the correct path name with "../" things. -     */ -    if ((p = vim_strrchr(fname, '/')) != NULL) { +  /* Get current directory name. */ +  if (FAIL == mch_dirname((char_u *) old_dir, MAXPATHL)) { +    return FAIL; +  } -      /* Only change directory when we are sure we can return to where -       * we are now.  After doing "su" chdir(".") might not work. */ -      if ((mch_dirname(olddir, MAXPATHL) == FAIL -         || mch_chdir((char *)olddir) != 0)) { -        p = NULL;               /* can't get current dir: don't chdir */ -        retval = FAIL; -      } else   { -        /* The directory is copied into buf[], to be able to remove -         * the file name without changing it (could be a string in -         * read-only memory) */ -        if (p - fname >= len) -          retval = FAIL; -        else { -          vim_strncpy(buf, fname, p - fname); -          if (mch_chdir((char *)buf)) -            retval = FAIL; -          else -            fname = p + 1; -          *buf = NUL; -        } -      } -    } -    if (mch_dirname(buf, len) == FAIL) { -      retval = FAIL; -      *buf = NUL; -    } -    if (p != NULL) { -      l = mch_chdir((char *)olddir); -      if (l != 0) -        EMSG(_(e_prev_dir)); -    } +  /* We have to get back to the current dir at the end, check if that works. */ +  if (0 != mch_chdir(old_dir)) { +    return FAIL; +  } -    l = STRLEN(buf); -    if (l >= len - 1) -      retval = FAIL;       /* no space for trailing "/" */ -    else if (l > 0 && buf[l - 1] != '/' && *fname != NUL -             && STRCMP(fname, ".") != 0) -      STRCAT(buf, "/"); +  if (0 != mch_chdir(directory)) { +    retval = FAIL;    } -  /* Catch file names which are too long. */ -  if (retval == FAIL || (int)(STRLEN(buf) + STRLEN(fname)) >= len) -    return FAIL; +  if ((FAIL == retval) || (FAIL == mch_dirname((char_u *) buffer, len))) { +    retval = FAIL; +  } +    +  if (0 != mch_chdir(old_dir)) { +    /* That shouldn't happen, since we've tested if it works. */ +    retval = FAIL; +    EMSG(_(e_prev_dir)); +  } +  return retval; +} + +/*  + * Append to_append to path with a slash in between. + */ +int append_path(char *path, char *to_append, int max_len) +{ +  int current_length = STRLEN(path); +  int to_append_length = STRLEN(to_append); + +  /* Do not append empty strings. */ +  if (0 == to_append_length) +    return OK; + +  /* Do not append a dot. */ +  if (STRCMP(to_append, ".") == 0) +    return OK; -  /* Do not append ".", "/dir/." is equal to "/dir". */ -  if (STRCMP(fname, ".") != 0) -    STRCAT(buf, fname); +  /* Glue both paths with a slash. */ +  if (current_length > 0 && path[current_length-1] != '/') { +    current_length += 1; /* Count the trailing slash. */ +    if (current_length > max_len) +      return FAIL; + +    STRCAT(path, "/"); +  } + +  /* +1 for the NUL at the end. */ +  if (current_length + to_append_length +1 > max_len) { +    return FAIL; +  } + +  STRCAT(path, to_append);    return OK;  }  /* + * Get absolute file name into "buf[len]". + * + * parameter force: Also expand when the given path in fname is already + * absolute. + * + * return FAIL for failure, OK for success + */ +int mch_full_name(char_u *fname, char_u *buf, int len, int force) +{ +  char_u *p; +  *buf = NUL; + +  char relative_directory[len]; +  char *end_of_path = (char *) fname; + +  /* expand it if forced or not an absolute path */ +  if (force || !mch_is_full_name(fname)) { +    if ((p = vim_strrchr(fname, '/')) != NULL) { + +      STRNCPY(relative_directory, fname, p-fname); +      relative_directory[p-fname] = NUL; +      end_of_path = (char *) (p + 1); +    } else { +      relative_directory[0] = NUL; +      end_of_path = (char *) fname; +    } + +    if (FAIL == mch_full_dir_name(relative_directory, (char *) buf, len)) { +      return FAIL; +    } +  } +  return append_path((char *) buf, (char *) end_of_path, len); +} + +/*   * Return TRUE if "fname" does not depend on the current directory.   */ -int mch_isFullName(char_u *fname) +int mch_is_full_name(char_u *fname)  {    return *fname == '/' || *fname == '~';  } diff --git a/src/os/os.h b/src/os/os.h index 9cf2116091..1ef311b32c 100644 --- a/src/os/os.h +++ b/src/os/os.h @@ -6,7 +6,7 @@  long_u mch_total_mem(int special);  int mch_chdir(char *path);  int mch_dirname(char_u *buf, int len); -int mch_FullName (char_u *fname, char_u *buf, int len, int force); -int mch_isFullName (char_u *fname); +int mch_full_name (char_u *fname, char_u *buf, int len, int force); +int mch_is_full_name (char_u *fname);  #endif diff --git a/src/os_unix.c b/src/os_unix.c index 80832024c9..003e45c2a0 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -1364,7 +1364,7 @@ int mch_can_exe(char_u *name)    int retval;    /* If it's an absolute or relative path don't need to use $PATH. */ -  if (mch_isFullName(name) || (name[0] == '.' && (name[1] == '/' +  if (mch_is_full_name(name) || (name[0] == '.' && (name[1] == '/'                                                    || (name[1] == '.' &&                                                        name[2] == '/'))))      return executable_file(name); diff --git a/src/syntax.c b/src/syntax.c index fb3285729f..ba33f16e23 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -4187,7 +4187,7 @@ static void syn_cmd_include(exarg_T *eap, int syncing)     */    eap->argt |= (XFILE | NOSPC);    separate_nextcmd(eap); -  if (*eap->arg == '<' || *eap->arg == '$' || mch_isFullName(eap->arg)) { +  if (*eap->arg == '<' || *eap->arg == '$' || mch_is_full_name(eap->arg)) {      /* For an absolute path, "$VIM/..." or "<sfile>.." we ":source" the       * file.  Need to expand the file name first.  In other cases       * ":runtime!" is used. */ diff --git a/src/window.c b/src/window.c index cd96365902..16acf013ab 100644 --- a/src/window.c +++ b/src/window.c @@ -5065,7 +5065,7 @@ int path_with_url(char_u *fname)   */  int vim_isAbsName(char_u *name)  { -  return path_with_url(name) != 0 || mch_isFullName(name); +  return path_with_url(name) != 0 || mch_is_full_name(name);  }  /* @@ -5090,7 +5090,7 @@ vim_FullName (    url = path_with_url(fname);    if (!url) -    retval = mch_FullName(fname, buf, len, force); +    retval = mch_full_name(fname, buf, len, force);    if (url || retval == FAIL) {      /* something failed; use the file name (truncate when too long) */      vim_strncpy(buf, fname, len - 1); diff --git a/test/unit/os/fs.moon b/test/unit/os/fs.moon index cb4abdba7e..8c1b9618db 100644 --- a/test/unit/os/fs.moon +++ b/test/unit/os/fs.moon @@ -5,87 +5,195 @@ fs = cimport './src/fs.h'  cstr = ffi.typeof 'char[?]'  describe 'fs function', -> + +  export OK = 1 +  export FAIL = 0 +    describe 'mch_dirname', ->      ffi.cdef 'int mch_dirname(char *buf, int len);'      mch_dirname = (buf, len) ->        fs.mch_dirname buf, len -    OK = 1 -    FAIL = 0 -      before_each -> -      export len = string.len(lfs.currentdir()) + 1 +      export len = (string.len lfs.currentdir!) + 1 +      export buf = cstr len, '' -    it 'returns OK and writes current directory into the buffer if it is buffer -    is large enough', -> -      buf = ffi.new 'char[?]', len +    it 'returns OK and writes current directory into the buffer if it is large +    enough', ->        eq OK, (mch_dirname buf, len) -      eq lfs.currentdir(), ffi.string(buf) +      eq lfs.currentdir!, (ffi.string buf)      -- What kind of other failing cases are possible?      it 'returns FAIL if the buffer is too small', -> -      buf = ffi.new 'char[?]', 0 -      eq FAIL, (mch_dirname buf, 0) +      buf = cstr (len-1), '' +      eq FAIL, (mch_dirname buf, (len-1)) + +  describe 'mch_full_dir_name', -> +    ffi.cdef 'int mch_full_dir_name(char *directory, char *buffer, int len);' -  describe 'mch_FullName', -> -    ffi.cdef 'int mch_FullName(char *fname, char *buf, int len, int force);' +    mch_full_dir_name = (directory, buffer, len) -> +      directory = cstr (string.len directory), directory +      fs.mch_full_dir_name(directory, buffer, len) + +    before_each -> +      -- Create empty string buffer which will contain the resulting path. +      export len = (string.len lfs.currentdir!) + 22 +      export buffer = cstr len, '' + +    it 'returns the absolute directory name of a given relative one', -> +      result = mch_full_dir_name '..', buffer, len +      eq OK, result +      old_dir = lfs.currentdir! +      lfs.chdir '..' +      expected = lfs.currentdir! +      lfs.chdir old_dir +      eq expected, (ffi.string buffer) + +    it 'returns the current directory name if the given string is empty', -> +      eq OK, (mch_full_dir_name '', buffer, len) +      eq lfs.currentdir!, (ffi.string buffer) + +    it 'fails if the given directory does not exist', -> +      eq FAIL, mch_full_dir_name('does_not_exist', buffer, len) + +    it 'works with a normal relative dir', -> +      lfs.mkdir('empty-test-directory') +      result = mch_full_dir_name('empty-test-directory', buffer, len) +      lfs.rmdir('empty-test-directory') +      eq lfs.currentdir! .. '/empty-test-directory', ffi.string(buffer) +      eq OK, result -    mch_FullName = (filename, buffer, length, force) -> -      filename = cstr(string.len(filename) + 1, filename) -      fs.mch_FullName(filename, buffer, length, force) +  describe 'mch_full_name', -> +    ffi.cdef 'int mch_full_name(char *fname, char *buf, int len, int force);' -    OK = 1 -    FAIL = 0 +    mch_full_name = (filename, buffer, length, force) -> +      filename = cstr (string.len filename) + 1, filename +      fs.mch_full_name filename, buffer, length, force      before_each -> -      -- Create empty string buffer which will contain the resulting path -      export len = string.len(lfs.currentdir()) + 11 -      export buffer = cstr(len, '') +      -- Create empty string buffer which will contain the resulting path. +      export len = (string.len lfs.currentdir!) + 33 +      export buffer = cstr len, '' + +      -- Create a directory and an empty file inside in order to know some +      -- existing relative path. +      lfs.mkdir('empty-test-directory') +      lfs.touch('empty-test-directory/empty.file') -    it 'failes if given filename contains non-existing directory', -> -      result = mch_FullName('nonexistingdir/test.file', buffer, len, 1) +    after_each -> +      lfs.rmdir('empty-test-directory') + +    it 'fails if given filename contains non-existing directory', -> +      force_expansion = 1 +      result = mch_full_name 'non_existing_dir/test.file', buffer, len, force_expansion        eq FAIL, result      it 'concatenates given filename if it does not contain a slash', -> -      result = mch_FullName('test.file', buffer, len, 1) +      force_expansion = 1 +      result = mch_full_name 'test.file', buffer, len, force_expansion +      expected = lfs.currentdir! .. '/test.file' +      eq expected, (ffi.string buffer)        eq OK, result -      expected = lfs.currentdir() .. '/test.file' -      eq expected, ffi.string(buffer)      it 'concatenates given filename if it is a directory but does not contain a      slash', -> -      result = mch_FullName('..', buffer, len, 1) +      force_expansion = 1 +      result = mch_full_name '..', buffer, len, force_expansion +      expected = lfs.currentdir! .. '/..' +      eq expected, (ffi.string buffer)        eq OK, result -      expected = lfs.currentdir() .. '/..' -      eq expected, ffi.string(buffer)      -- Is it possible for every developer to enter '..' directory while running      -- the unit tests? Which other directory would be better? -    it 'enters given directory if possible and if path contains a slash', -> -      result = mch_FullName('../test.file', buffer, 200, 1) +    it 'enters given directory (instead of just concatenating the strings) if +    possible and if path contains a slash', -> +      force_expansion = 1 +      result = mch_full_name '../test.file', buffer, len, force_expansion +      old_dir = lfs.currentdir! +      lfs.chdir '..' +      expected = lfs.currentdir! .. '/test.file' +      lfs.chdir old_dir +      eq expected, (ffi.string buffer) +      eq OK, result + +    it 'just copies the path if it is already absolute and force=0', -> +      force_expansion = 0 +      absolute_path = '/absolute/path' +      result = mch_full_name absolute_path, buffer, len, force_expansion +      eq absolute_path, (ffi.string buffer)        eq OK, result -      old_dir = lfs.currentdir() -      lfs.chdir('..') -      expected = lfs.currentdir() .. '/test.file' -      lfs.chdir(old_dir) -      eq expected, ffi.string(buffer) -  describe 'mch_isFullName', -> -    ffi.cdef 'int mch_isFullName(char *fname);' +    it 'fails when the path is relative to HOME', -> +      force_expansion = 1 +      absolute_path = '~/home.file' +      result = mch_full_name absolute_path, buffer, len, force_expansion +      eq FAIL, result -    mch_isFullName = (filename) -> -      filename = cstr(string.len(filename) + 1, filename) -      fs.mch_isFullName(filename) +    it 'works with some "normal" relative path with directories', -> +      force_expansion = 1 +      result = mch_full_name 'empty-test-directory/empty.file', buffer, len, force_expansion +      eq OK, result +      eq lfs.currentdir! .. '/empty-test-directory/empty.file', (ffi.string buffer) + +    it 'does not modify the given filename', -> +      force_expansion = 1 +      filename = cstr 100, 'empty-test-directory/empty.file' +      result = fs.mch_full_name filename, buffer, len, force_expansion +      eq lfs.currentdir! .. '/empty-test-directory/empty.file', (ffi.string buffer) +      eq 'empty-test-directory/empty.file', (ffi.string filename) +      eq OK, result -    TRUE = 1 -    FALSE = 0 +  describe 'append_path', -> +    ffi.cdef 'int append_path(char *path, char *to_append, int max_len);' + +    it 'joins given paths with a slash', -> +     path = cstr 100, 'path1' +     to_append = cstr 6, 'path2' +     eq OK, (fs.append_path path, to_append, 100) +     eq "path1/path2", (ffi.string path) + +    it 'joins given paths without adding an unnecessary slash', -> +     path = cstr 100, 'path1/' +     to_append = cstr 6, 'path2' +     eq OK, fs.append_path path, to_append, 100 +     eq "path1/path2", (ffi.string path) + +    it 'fails if there is not enough space left for to_append', -> +      path = cstr 11, 'path1/' +      to_append = cstr 6, 'path2' +      eq FAIL, (fs.append_path path, to_append, 11) + +    it 'does not append a slash if to_append is empty', -> +      path = cstr 6, 'path1' +      to_append = cstr 1, '' +      eq OK, (fs.append_path path, to_append, 6) +      eq 'path1', (ffi.string path) + +    it 'does not append unnecessary dots', -> +      path = cstr 6, 'path1' +      to_append = cstr 2, '.' +      eq OK, (fs.append_path path, to_append, 6) +      eq 'path1', (ffi.string path) + +    it 'copies to_append to path, if path is empty', -> +      path = cstr 7, '' +      to_append = cstr 7, '/path2' +      eq OK, (fs.append_path path, to_append, 7) +      eq '/path2', (ffi.string path) + +  describe 'mch_is_full_name', -> +    ffi.cdef 'int mch_is_full_name(char *fname);' + +    mch_is_full_name = (filename) -> +      filename = cstr (string.len filename) + 1, filename +      fs.mch_is_full_name filename      it 'returns true if filename starts with a slash', -> -      eq TRUE, mch_isFullName('/some/directory/') +      eq OK, mch_is_full_name '/some/directory/'      it 'returns true if filename starts with a tilde', -> -      eq TRUE, mch_isFullName('~/in/my/home~/directory') +      eq OK, mch_is_full_name '~/in/my/home~/directory'      it 'returns false if filename starts not with slash nor tilde', -> -      eq FALSE, mch_isFullName('not/in/my/home~/directory') +      eq FAIL, mch_is_full_name 'not/in/my/home~/directory' | 
