diff options
author | Johannes Schindelin <johannes.schindelin@gmx.de> | 2016-01-12 08:57:36 +0100 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2016-01-12 10:40:54 -0800 |
commit | 824682ab51e3510817f7a7303decc9f9df38ee9a (patch) | |
tree | 73954cad2a8b561b21c193feb741e77e60c4afd4 | |
parent | compat/basename: make basename() conform to POSIX (diff) | |
download | tgif-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.c | 44 | ||||
-rw-r--r-- | git-compat-util.h | 2 |
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 |