aboutsummaryrefslogtreecommitdiff
path: root/compat/basename.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2016-02-05 14:54:17 -0800
committerJunio C Hamano <gitster@pobox.com>2016-02-05 14:54:17 -0800
commit07be1da216debe1f76cd4d03ac5effcb9e40e6c6 (patch)
tree7642a42d6b7348710a13374c6b6dda1b6a51d225 /compat/basename.c
parent081363dde231346c2f051cd7d41622f6fa02e3cb (diff)
parente7d5ce816579723150c341116737fb51d8e33eb3 (diff)
downloadgit-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.c66
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;
+}