Merge branch 'rs/archive-with-attr-pathspec-fix'
[git/gitster.git] / compat / basename.c
blobc33579ef612d9540bf188f09168fbd29adda8b8c
1 #include "../git-compat-util.h"
2 #include "../strbuf.h"
4 /* Adapted from libiberty's basename.c. */
5 char *gitbasename (char *path)
7 const char *base;
9 if (path)
10 skip_dos_drive_prefix(&path);
12 if (!path || !*path)
14 * basename(3P) is mis-specified because it returns a
15 * non-constant pointer even though it is specified to return a
16 * pointer to internal memory at times. The cast is a result of
17 * that.
19 return (char *) ".";
21 for (base = path; *path; path++) {
22 if (!is_dir_sep(*path))
23 continue;
24 do {
25 path++;
26 } while (is_dir_sep(*path));
27 if (*path)
28 base = path;
29 else
30 while (--path != base && is_dir_sep(*path))
31 *path = '\0';
33 return (char *)base;
36 char *gitdirname(char *path)
38 static struct strbuf buf = STRBUF_INIT;
39 char *p = path, *slash = NULL, c;
40 int dos_drive_prefix;
42 if (!p)
44 * dirname(3P) is mis-specified because it returns a
45 * non-constant pointer even though it is specified to return a
46 * pointer to internal memory at times. The cast is a result of
47 * that.
49 return (char *) ".";
51 if ((dos_drive_prefix = skip_dos_drive_prefix(&p)) && !*p)
52 goto dot;
55 * POSIX.1-2001 says dirname("/") should return "/", and dirname("//")
56 * should return "//", but dirname("///") should return "/" again.
58 if (is_dir_sep(*p)) {
59 if (!p[1] || (is_dir_sep(p[1]) && !p[2]))
60 return path;
61 slash = ++p;
63 while ((c = *(p++)))
64 if (is_dir_sep(c)) {
65 char *tentative = p - 1;
67 /* POSIX.1-2001 says to ignore trailing slashes */
68 while (is_dir_sep(*p))
69 p++;
70 if (*p)
71 slash = tentative;
74 if (slash) {
75 *slash = '\0';
76 return path;
79 dot:
80 strbuf_reset(&buf);
81 strbuf_addf(&buf, "%.*s.", dos_drive_prefix, path);
82 return buf.buf;