diff options
author | Junio C Hamano <gitster@pobox.com> | 2016-02-05 14:54:17 -0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2016-02-05 14:54:17 -0800 |
commit | 07be1da216debe1f76cd4d03ac5effcb9e40e6c6 (patch) | |
tree | 7642a42d6b7348710a13374c6b6dda1b6a51d225 /compat/basename.c | |
parent | 081363dde231346c2f051cd7d41622f6fa02e3cb (diff) | |
parent | e7d5ce816579723150c341116737fb51d8e33eb3 (diff) | |
download | git-07be1da216debe1f76cd4d03ac5effcb9e40e6c6.tar.gz git-07be1da216debe1f76cd4d03ac5effcb9e40e6c6.tar.xz |
Merge branch 'js/dirname-basename' into maint
dirname() emulation has been added, as Msys2 lacks it.
* js/dirname-basename:
mingw: avoid linking to the C library's isalpha()
t0060: loosen overly strict expectations
t0060: verify that basename() and dirname() work as expected
compat/basename.c: provide a dirname() compatibility function
compat/basename: make basename() conform to POSIX
Refactor skipping DOS drive prefixes
Diffstat (limited to 'compat/basename.c')
-rw-r--r-- | compat/basename.c | 66 |
1 files changed, 61 insertions, 5 deletions
diff --git a/compat/basename.c b/compat/basename.c index d8f8a3c6d..96bd9533b 100644 --- a/compat/basename.c +++ b/compat/basename.c @@ -1,15 +1,71 @@ #include "../git-compat-util.h" +#include "../strbuf.h" /* Adapted from libiberty's basename.c. */ char *gitbasename (char *path) { const char *base; - /* Skip over the disk name in MSDOS pathnames. */ - if (has_dos_drive_prefix(path)) - path += 2; + + if (path) + skip_dos_drive_prefix(&path); + + if (!path || !*path) + return "."; + for (base = path; *path; path++) { - if (is_dir_sep(*path)) - base = path + 1; + if (!is_dir_sep(*path)) + continue; + do { + path++; + } while (is_dir_sep(*path)); + if (*path) + base = path; + else + while (--path != base && is_dir_sep(*path)) + *path = '\0'; } return (char *)base; } + +char *gitdirname(char *path) +{ + static struct strbuf buf = STRBUF_INIT; + char *p = path, *slash = NULL, c; + int dos_drive_prefix; + + if (!p) + return "."; + + if ((dos_drive_prefix = skip_dos_drive_prefix(&p)) && !*p) + goto dot; + + /* + * POSIX.1-2001 says dirname("/") should return "/", and dirname("//") + * should return "//", but dirname("///") should return "/" again. + */ + if (is_dir_sep(*p)) { + if (!p[1] || (is_dir_sep(p[1]) && !p[2])) + return path; + slash = ++p; + } + while ((c = *(p++))) + if (is_dir_sep(c)) { + char *tentative = p - 1; + + /* POSIX.1-2001 says to ignore trailing slashes */ + while (is_dir_sep(*p)) + p++; + if (*p) + slash = tentative; + } + + if (slash) { + *slash = '\0'; + return path; + } + +dot: + strbuf_reset(&buf); + strbuf_addf(&buf, "%.*s.", dos_drive_prefix, path); + return buf.buf; +} |