summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Johannes Schindelin <johannes.schindelin@gmx.de>2016-01-12 08:57:36 +0100
committerLibravatar Junio C Hamano <gitster@pobox.com>2016-01-12 10:40:54 -0800
commit824682ab51e3510817f7a7303decc9f9df38ee9a (patch)
tree73954cad2a8b561b21c193feb741e77e60c4afd4
parentcompat/basename: make basename() conform to POSIX (diff)
downloadtgif-824682ab51e3510817f7a7303decc9f9df38ee9a.tar.xz
compat/basename.c: provide a dirname() compatibility function
When there is no `libgen.h` to our disposal, we miss the `dirname()` function. Earlier we added basename() compatibility function for the same reason at e1c06886 (compat: add a basename() compatibility function, 2009-05-31). So far, we only had one user of that function: credential-cache--daemon (which was only compiled when Unix sockets are available, anyway). But now we also have `builtin/am.c` as user, so we need it. Since `dirname()` is a sibling of `basename()`, we simply put our very own `gitdirname()` implementation next to `gitbasename()` and use it if `NO_LIBGEN_H` has been set. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--compat/basename.c44
-rw-r--r--git-compat-util.h2
2 files changed, 46 insertions, 0 deletions
diff --git a/compat/basename.c b/compat/basename.c
index 0f1b0b0930..96bd9533b4 100644
--- a/compat/basename.c
+++ b/compat/basename.c
@@ -1,4 +1,5 @@
#include "../git-compat-util.h"
+#include "../strbuf.h"
/* Adapted from libiberty's basename.c. */
char *gitbasename (char *path)
@@ -25,3 +26,46 @@ char *gitbasename (char *path)
}
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;
+}
diff --git a/git-compat-util.h b/git-compat-util.h
index 38397d7afb..1cc6de194d 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -253,6 +253,8 @@ struct itimerval {
#else
#define basename gitbasename
extern char *gitbasename(char *);
+#define dirname gitdirname
+extern char *gitdirname(char *);
#endif
#ifndef NO_ICONV