summaryrefslogtreecommitdiff
path: root/compat/basename.c
diff options
context:
space:
mode:
Diffstat (limited to 'compat/basename.c')
-rw-r--r--compat/basename.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/compat/basename.c b/compat/basename.c
new file mode 100644
index 0000000000..96bd9533b4
--- /dev/null
+++ b/compat/basename.c
@@ -0,0 +1,71 @@
+#include "../git-compat-util.h"
+#include "../strbuf.h"
+
+/* Adapted from libiberty's basename.c. */
+char *gitbasename (char *path)
+{
+ const char *base;
+
+ if (path)
+ skip_dos_drive_prefix(&path);
+
+ if (!path || !*path)
+ return ".";
+
+ for (base = path; *path; path++) {
+ 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;
+}