{"thread":{"id":"19603","subject":"[PATCH v5 1/3] compat: add a mkstemps() compatibility function","startedAt":"2009-05-30T02:18:08Z","lastAt":"2009-05-30T22:14:14Z","messageCount":5,"participants":["David Aguilar","Jeff King"],"isPatch":true,"patchVersion":5,"patchTotal":3},"messages":[{"id":"115067","messageId":"1243649890-4522-1-git-send-email-davvid@gmail.com","threadId":"19603","inReplyTo":null,"subject":"[PATCH v5 1/3] compat: add a mkstemps() compatibility function","fromName":"David Aguilar","fromEmail":"davvid@gmail.com","sentAt":"2009-05-30T02:18:08Z","receivedAt":"2009-05-30T02:18:08Z","isPatch":true,"sender":{"key":"davvid@gmail.com","avatar":"https://avatars.githubusercontent.com/u/13196?v=4"},"body":"mkstemps() is a BSD extension so provide an implementation\nfor cross-platform use.\n\nSigned-off-by: David Aguilar <davvid@gmail.com>\nTested-by: Johannes Sixt <j6t@kdbg.org> (Windows)\n---\n\nThis is unchanged since v3, but I'm including it for\ncompleteness.\n\n Makefile          |   19 +++++++++++++++\n compat/mkstemps.c |   67 +++++++++++++++++++++++++++++++++++++++++++++++++++++\n config.mak.in     |    1 +\n configure.ac      |    6 ++++\n git-compat-util.h |    5 ++++\n 5 files changed, 98 insertions(+), 0 deletions(-)\n create mode 100644 compat/mkstemps.c\n\ndiff --git a/Makefile b/Makefile\nindex eaae45d..a70b5f0 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -52,6 +52,8 @@ all::\n #\n # Define NO_MKDTEMP if you don't have mkdtemp in the C library.\n #\n+# Define NO_MKSTEMPS if you don't have mkstemps in the C library.\n+#\n # Define NO_SYS_SELECT_H if you don't have sys/select.h.\n #\n # Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link.\n@@ -636,10 +638,12 @@ EXTLIBS =\n \n ifeq ($(uname_S),Linux)\n \tNO_STRLCPY = YesPlease\n+\tNO_MKSTEMPS = YesPlease\n \tTHREADED_DELTA_SEARCH = YesPlease\n endif\n ifeq ($(uname_S),GNU/kFreeBSD)\n \tNO_STRLCPY = YesPlease\n+\tNO_MKSTEMPS = YesPlease\n \tTHREADED_DELTA_SEARCH = YesPlease\n endif\n ifeq ($(uname_S),UnixWare)\n@@ -651,6 +655,7 @@ ifeq ($(uname_S),UnixWare)\n \tSHELL_PATH = /usr/local/bin/bash\n \tNO_IPV6 = YesPlease\n \tNO_HSTRERROR = YesPlease\n+\tNO_MKSTEMPS = YesPlease\n \tBASIC_CFLAGS += -Kthread\n \tBASIC_CFLAGS += -I/usr/local/include\n \tBASIC_LDFLAGS += -L/usr/local/lib\n@@ -674,6 +679,7 @@ ifeq ($(uname_S),SCO_SV)\n \tSHELL_PATH = /usr/bin/bash\n \tNO_IPV6 = YesPlease\n \tNO_HSTRERROR = YesPlease\n+\tNO_MKSTEMPS = YesPlease\n \tBASIC_CFLAGS += -I/usr/local/include\n \tBASIC_LDFLAGS += -L/usr/local/lib\n \tNO_STRCASESTR = YesPlease\n@@ -702,6 +708,7 @@ ifeq ($(uname_S),SunOS)\n \tNO_MEMMEM = YesPlease\n \tNO_HSTRERROR = YesPlease\n \tNO_MKDTEMP = YesPlease\n+\tNO_MKSTEMPS = YesPlease\n \tOLD_ICONV = UnfortunatelyYes\n \tifeq ($(uname_R),5.8)\n \t\tNO_UNSETENV = YesPlease\n@@ -724,6 +731,7 @@ ifeq ($(uname_O),Cygwin)\n \tNO_D_INO_IN_DIRENT = YesPlease\n \tNO_STRCASESTR = YesPlease\n \tNO_MEMMEM = YesPlease\n+\tNO_MKSTEMPS = YesPlease\n \tNO_SYMLINK_HEAD = YesPlease\n \tNEEDS_LIBICONV = YesPlease\n \tNO_FAST_WORKING_DIRECTORY = UnfortunatelyYes\n@@ -767,11 +775,13 @@ ifeq ($(uname_S),NetBSD)\n \tBASIC_LDFLAGS += -L/usr/pkg/lib $(CC_LD_DYNPATH)/usr/pkg/lib\n \tTHREADED_DELTA_SEARCH = YesPlease\n \tUSE_ST_TIMESPEC = YesPlease\n+\tNO_MKSTEMPS = YesPlease\n endif\n ifeq ($(uname_S),AIX)\n \tNO_STRCASESTR=YesPlease\n \tNO_MEMMEM = YesPlease\n \tNO_MKDTEMP = YesPlease\n+\tNO_MKSTEMPS = YesPlease\n \tNO_STRLCPY = YesPlease\n \tNO_NSEC = YesPlease\n \tFREAD_READS_DIRECTORIES = UnfortunatelyYes\n@@ -787,12 +797,14 @@ endif\n ifeq ($(uname_S),GNU)\n \t# GNU/Hurd\n \tNO_STRLCPY=YesPlease\n+\tNO_MKSTEMPS = YesPlease\n endif\n ifeq ($(uname_S),IRIX64)\n \tNO_IPV6=YesPlease\n \tNO_SETENV=YesPlease\n \tNO_STRCASESTR=YesPlease\n \tNO_MEMMEM = YesPlease\n+\tNO_MKSTEMPS = YesPlease\n \tNO_STRLCPY = YesPlease\n \tNO_SOCKADDR_STORAGE=YesPlease\n \tSHELL_PATH=/usr/gnu/bin/bash\n@@ -805,6 +817,7 @@ ifeq ($(uname_S),HP-UX)\n \tNO_SETENV=YesPlease\n \tNO_STRCASESTR=YesPlease\n \tNO_MEMMEM = YesPlease\n+\tNO_MKSTEMPS = YesPlease\n \tNO_STRLCPY = YesPlease\n \tNO_MKDTEMP = YesPlease\n \tNO_UNSETENV = YesPlease\n@@ -834,6 +847,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))\n \tNO_C99_FORMAT = YesPlease\n \tNO_STRTOUMAX = YesPlease\n \tNO_MKDTEMP = YesPlease\n+\tNO_MKSTEMPS = YesPlease\n \tSNPRINTF_RETURNS_BOGUS = YesPlease\n \tNO_SVN_TESTS = YesPlease\n \tNO_PERL_MAKEMAKER = YesPlease\n@@ -853,6 +867,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))\n endif\n ifneq (,$(findstring arm,$(uname_M)))\n \tARM_SHA1 = YesPlease\n+\tNO_MKSTEMPS = YesPlease\n endif\n \n -include config.mak.autogen\n@@ -1011,6 +1026,10 @@ ifdef NO_MKDTEMP\n \tCOMPAT_CFLAGS += -DNO_MKDTEMP\n \tCOMPAT_OBJS += compat/mkdtemp.o\n endif\n+ifdef NO_MKSTEMPS\n+\tCOMPAT_CFLAGS += -DNO_MKSTEMPS\n+\tCOMPAT_OBJS += compat/mkstemps.o\n+endif\n ifdef NO_UNSETENV\n \tCOMPAT_CFLAGS += -DNO_UNSETENV\n \tCOMPAT_OBJS += compat/unsetenv.o\ndiff --git a/compat/mkstemps.c b/compat/mkstemps.c\nnew file mode 100644\nindex 0000000..87ebc2a\n--- /dev/null\n+++ b/compat/mkstemps.c\n@@ -0,0 +1,67 @@\n+#include \"../git-compat-util.h\"\n+\n+#ifndef TMP_MAX\n+#define TMP_MAX 16384\n+#endif\n+\n+/* Adapted from libiberty's mkstemp.c. */\n+int gitmkstemps(char *pattern, int suffix_len)\n+{\n+\tstatic const char letters[] =\n+\t\t\"abcdefghijklmnopqrstuvwxyz\"\n+\t\t\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n+\t\t\"0123456789\";\n+\tstatic const int num_letters = 62;\n+\tuint64_t value;\n+\tstruct timeval tv;\n+\tchar *template;\n+\tsize_t len;\n+\tint fd, count;\n+\n+\tlen = strlen(pattern);\n+\n+\tif (len < 6 + suffix_len) {\n+\t\terrno = EINVAL;\n+\t\treturn -1;\n+\t}\n+\n+\tif (strncmp(&pattern[len - 6 - suffix_len], \"XXXXXX\", 6)) {\n+\t\terrno = EINVAL;\n+\t\treturn -1;\n+\t}\n+\n+\t/* Replace pattern's XXXXXX characters with randomness.\n+\t * Try TMP_MAX different filenames.\n+\t */\n+\tgettimeofday(&tv, NULL);\n+\tvalue = ((size_t)(tv.tv_usec << 16)) ^ tv.tv_sec ^ getpid();\n+\ttemplate = &pattern[len - 6 - suffix_len];\n+\tfor (count = 0; count < TMP_MAX; ++count) {\n+\t\tuint64_t v = value;\n+\t\t/* Fill in the random bits. */\n+\t\ttemplate[0] = letters[v % num_letters]; v/= num_letters;\n+\t\ttemplate[1] = letters[v % num_letters]; v/= num_letters;\n+\t\ttemplate[2] = letters[v % num_letters]; v/= num_letters;\n+\t\ttemplate[3] = letters[v % num_letters]; v/= num_letters;\n+\t\ttemplate[4] = letters[v % num_letters]; v/= num_letters;\n+\t\ttemplate[5] = letters[v % num_letters]; v/= num_letters;\n+\n+\t\tfd = open(pattern, O_CREAT | O_EXCL | O_RDWR, 0600);\n+\t\tif (fd > 0)\n+\t\t\treturn fd;\n+\t\t/* Fatal error (EPERM, ENOSPC etc).\n+\t\t * It doesn't make sense to loop.\n+\t\t */\n+\t\tif (errno != EEXIST)\n+\t\t\tbreak;\n+\t\t/* This is a random value.  It is only necessary that\n+\t\t * the next TMP_MAX values generated by adding 7777 to\n+\t\t * VALUE are different with (module 2^32).\n+\t\t */\n+\t\tvalue += 7777;\n+\t}\n+\t/* We return the null string if we can't find a unique file name.  */\n+\tpattern[0] = '\\0';\n+\terrno = EINVAL;\n+\treturn -1;\n+}\ndiff --git a/config.mak.in b/config.mak.in\nindex 7cce0c1..b6619af 100644\n--- a/config.mak.in\n+++ b/config.mak.in\n@@ -46,6 +46,7 @@ NO_STRTOUMAX=@NO_STRTOUMAX@\n NO_SETENV=@NO_SETENV@\n NO_UNSETENV=@NO_UNSETENV@\n NO_MKDTEMP=@NO_MKDTEMP@\n+NO_MKSTEMPS=@NO_MKSTEMPS@\n NO_ICONV=@NO_ICONV@\n OLD_ICONV=@OLD_ICONV@\n NO_DEFLATE_BOUND=@NO_DEFLATE_BOUND@\ndiff --git a/configure.ac b/configure.ac\nindex 4e728bc..95dccd4 100644\n--- a/configure.ac\n+++ b/configure.ac\n@@ -676,6 +676,12 @@ GIT_CHECK_FUNC(mkdtemp,\n [NO_MKDTEMP=],\n [NO_MKDTEMP=YesPlease])\n AC_SUBST(NO_MKDTEMP)\n+# Define NO_MKSTEMPS if you don't have mkstemps in the C library.\n+GIT_CHECK_FUNC(mkstemps,\n+[NO_MKSTEMPS=],\n+[NO_MKSTEMPS=YesPlease])\n+AC_SUBST(NO_MKSTEMPS)\n+#\n #\n # Define NO_MMAP if you want to avoid mmap.\n #\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex c7cf2d5..f7217ad 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -232,6 +232,11 @@ extern int gitsetenv(const char *, const char *, int);\n extern char *gitmkdtemp(char *);\n #endif\n \n+#ifdef NO_MKSTEMPS\n+#define mkstemps gitmkstemps\n+extern int gitmkstemps(char *, int);\n+#endif\n+\n #ifdef NO_UNSETENV\n #define unsetenv gitunsetenv\n extern void gitunsetenv(const char *);\n-- \n1.6.3.1.178.g4daa97\n"},{"id":"115068","messageId":"1243649890-4522-2-git-send-email-davvid@gmail.com","threadId":"19603","inReplyTo":"1243649890-4522-1-git-send-email-davvid@gmail.com","subject":"[PATCH v5 2/3] path: add a find_basename() portability function","fromName":"David Aguilar","fromEmail":"davvid@gmail.com","sentAt":"2009-05-30T02:18:09Z","receivedAt":"2009-05-30T02:18:09Z","isPatch":true,"sender":{"key":"davvid@gmail.com","avatar":"https://avatars.githubusercontent.com/u/13196?v=4"},"body":"find_basename() is a simpler version of basename().\nIt maintains constness and thus does not require you\nto pass in a copy.  It is only concerned with finding\nthe last directory separator in a string and returning\na pointer.\n\nThis function was written because Windows does not\nhave basename().  It is called \"find_basename()\"\nto avoid name collisions and to provide a hint that\nit is not quite the same thing as POSIX basename().\n\nSigned-off-by: David Aguilar <davvid@gmail.com>\n---\n\nAs suggested by Peff.\n\n cache.h |    1 +\n path.c  |   14 ++++++++++++++\n 2 files changed, 15 insertions(+), 0 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex b8503ad..08b6f42 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -640,6 +640,7 @@ static inline int is_absolute_path(const char *path)\n \treturn path[0] == '/' || has_dos_drive_prefix(path);\n }\n int is_directory(const char *);\n+const char *find_basename(const char *path);\n const char *make_absolute_path(const char *path);\n const char *make_nonrelative_path(const char *path);\n const char *make_relative_path(const char *abs, const char *base);\ndiff --git a/path.c b/path.c\nindex 8a0a674..7a2fe14 100644\n--- a/path.c\n+++ b/path.c\n@@ -358,6 +358,20 @@ int set_shared_perm(const char *path, int mode)\n \treturn 0;\n }\n \n+/* return the basename of a path */\n+const char *find_basename(const char *path)\n+{\n+\tconst char *basename = path + strlen(path) - 1;\n+\twhile(*basename && basename > path) {\n+\t\tbasename--;\n+\t\tif (is_dir_sep(*basename)) {\n+\t\t\tbasename++;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\treturn basename;\n+}\n+\n const char *make_relative_path(const char *abs, const char *base)\n {\n \tstatic char buf[PATH_MAX + 1];\n-- \n1.6.3.1.178.g4daa97\n"},{"id":"115069","messageId":"1243649890-4522-3-git-send-email-davvid@gmail.com","threadId":"19603","inReplyTo":"1243649890-4522-2-git-send-email-davvid@gmail.com","subject":"[PATCH v5 3/3] diff: generate pretty filenames in prep_temp_blob()","fromName":"David Aguilar","fromEmail":"davvid@gmail.com","sentAt":"2009-05-30T02:18:10Z","receivedAt":"2009-05-30T02:18:10Z","isPatch":true,"sender":{"key":"davvid@gmail.com","avatar":"https://avatars.githubusercontent.com/u/13196?v=4"},"body":"Naturally, prep_temp_blob() did not care about filenames.\nAs a result, GIT_EXTERNAL_DIFF and textconv generated\nfilenames such as \".diff_XXXXXX\".\n\nThis modifies prep_temp_blob() to generate user-friendly\nfilenames when creating temporary files.\n\nDiffing \"name.ext\" now generates \"XXXXXX_name.ext\".\n\nSigned-off-by: David Aguilar <davvid@gmail.com>\n---\n\nThe difference since v4 is that find_basename() was\nfactored out into its own function.\n\n cache.h                  |    2 ++\n diff.c                   |   10 +++++++++-\n path.c                   |   16 ++++++++++++++++\n t/t4020-diff-external.sh |    9 +++++++++\n 4 files changed, 36 insertions(+), 1 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 08b6f42..337458d 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -614,6 +614,8 @@ extern int is_empty_blob_sha1(const unsigned char *sha1);\n \n int git_mkstemp(char *path, size_t n, const char *template);\n \n+int git_mkstemps(char *path, size_t n, const char *template, int suffix_len);\n+\n /*\n  * NOTE NOTE NOTE!!\n  *\ndiff --git a/diff.c b/diff.c\nindex dcfbcb0..7edee28 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -1964,8 +1964,15 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp,\n {\n \tint fd;\n \tstruct strbuf buf = STRBUF_INIT;\n+\tstruct strbuf template = STRBUF_INIT;\n+\tconst char *basename = find_basename(path);\n \n-\tfd = git_mkstemp(temp->tmp_path, PATH_MAX, \".diff_XXXXXX\");\n+\t/* Generate \"XXXXXX_basename.ext\" */\n+\tstrbuf_addstr(&template, \"XXXXXX_\");\n+\tstrbuf_addstr(&template, basename);\n+\n+\tfd = git_mkstemps(temp->tmp_path, PATH_MAX, template.buf,\n+\t\t\tstrlen(basename) + 1);\n \tif (fd < 0)\n \t\tdie(\"unable to create temp-file: %s\", strerror(errno));\n \tif (convert_to_working_tree(path,\n@@ -1981,6 +1988,7 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp,\n \ttemp->hex[40] = 0;\n \tsprintf(temp->mode, \"%06o\", mode);\n \tstrbuf_release(&buf);\n+\tstrbuf_release(&template);\n }\n \n static struct diff_tempfile *prepare_temp_file(const char *name,\ndiff --git a/path.c b/path.c\nindex 7a2fe14..4f7fe8f 100644\n--- a/path.c\n+++ b/path.c\n@@ -139,6 +139,22 @@ int git_mkstemp(char *path, size_t len, const char *template)\n \treturn mkstemp(path);\n }\n \n+/* git_mkstemps() - create tmp file with suffix honoring TMPDIR variable. */\n+int git_mkstemps(char *path, size_t len, const char *template, int suffix_len)\n+{\n+\tconst char *tmp;\n+\tsize_t n;\n+\n+\ttmp = getenv(\"TMPDIR\");\n+\tif (!tmp)\n+\t\ttmp = \"/tmp\";\n+\tn = snprintf(path, len, \"%s/%s\", tmp, template);\n+\tif (len <= n) {\n+\t\terrno = ENAMETOOLONG;\n+\t\treturn -1;\n+\t}\n+\treturn mkstemps(path, suffix_len);\n+}\n \n int validate_headref(const char *path)\n {\ndiff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh\nindex 0720001..4ea42e0 100755\n--- a/t/t4020-diff-external.sh\n+++ b/t/t4020-diff-external.sh\n@@ -136,6 +136,15 @@ test_expect_success 'GIT_EXTERNAL_DIFF with more than one changed files' '\n \tGIT_EXTERNAL_DIFF=echo git diff\n '\n \n+test_expect_success 'GIT_EXTERNAL_DIFF generates pretty paths' '\n+\ttouch file.ext &&\n+\tgit add file.ext &&\n+\techo with extension > file.ext &&\n+\tGIT_EXTERNAL_DIFF=echo git diff file.ext | grep ......_file\\.ext &&\n+\tgit update-index --force-remove file.ext &&\n+\trm file.ext\n+'\n+\n echo \"#!$SHELL_PATH\" >fake-diff.sh\n cat >> fake-diff.sh <<\\EOF\n cat $2 >> crlfed.txt\n-- \n1.6.3.1.178.g4daa97\n"},{"id":"115086","messageId":"20090530140519.GA22905@sigill.intra.peff.net","threadId":"19603","inReplyTo":"1243649890-4522-2-git-send-email-davvid@gmail.com","subject":"Re: [PATCH v5 2/3] path: add a find_basename() portability function","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-05-30T14:05:19Z","receivedAt":"2009-05-30T14:05:19Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, May 29, 2009 at 07:18:09PM -0700, David Aguilar wrote:\n\n> +/* return the basename of a path */\n> +const char *find_basename(const char *path)\n> +{\n> +\tconst char *basename = path + strlen(path) - 1;\n> +\twhile(*basename && basename > path) {\n> +\t\tbasename--;\n> +\t\tif (is_dir_sep(*basename)) {\n> +\t\t\tbasename++;\n> +\t\t\tbreak;\n> +\t\t}\n> +\t}\n> +\treturn basename;\n> +}\n\nHmm. Is there any point to the *basename condition in the loop? By using\nstrlen, you are not going to go past any NULs, and you are already\nchecking that you don't go past the beginning of the string.\n\nSpeaking of which, how does this handle an input of \"\"? It seems that it\nwould return a pointer to one character before the string. Given your\nloop, you need to special-case when *path is NUL.\n\nAlso, how should trailing dir_seps be handled? basename() will actually\nreturn \"\" if given \"foo/\". Your implementation, when given \"/foo/bar/\"\nwill return \"bar/\" (and it must keep the trailing bit since we are\nneither reallocating nor munging the input string). But given\n\"/foo/bar//\", it will return simply \"/\". I could see an argument for\neither \"bar//\" or \"\", but I think behaving differently for trailing \"/\"\nversus trailing \"//\" doesn't make sense.\n\n-Peff\n"},{"id":"115100","messageId":"20090530221413.GA10850@gmail.com","threadId":"19603","inReplyTo":"20090530140519.GA22905@sigill.intra.peff.net","subject":"Re: [PATCH v5 2/3] path: add a find_basename() portability function","fromName":"David Aguilar","fromEmail":"davvid@gmail.com","sentAt":"2009-05-30T22:14:14Z","receivedAt":"2009-05-30T22:14:14Z","isPatch":true,"sender":{"key":"davvid@gmail.com","avatar":"https://avatars.githubusercontent.com/u/13196?v=4"},"body":"On Sat, May 30, 2009 at 10:05:19AM -0400, Jeff King wrote:\n> On Fri, May 29, 2009 at 07:18:09PM -0700, David Aguilar wrote:\n> \n> > +/* return the basename of a path */\n> > +const char *find_basename(const char *path)\n> > +{\n> > +\tconst char *basename = path + strlen(path) - 1;\n> > +\twhile(*basename && basename > path) {\n> > +\t\tbasename--;\n> > +\t\tif (is_dir_sep(*basename)) {\n> > +\t\t\tbasename++;\n> > +\t\t\tbreak;\n> > +\t\t}\n> > +\t}\n> > +\treturn basename;\n> > +}\n> \n> Hmm. Is there any point to the *basename condition in the loop? By using\n> strlen, you are not going to go past any NULs, and you are already\n> checking that you don't go past the beginning of the string.\n> \n> Speaking of which, how does this handle an input of \"\"? It seems that it\n> would return a pointer to one character before the string. Given your\n> loop, you need to special-case when *path is NUL.\n> \n> Also, how should trailing dir_seps be handled? basename() will actually\n> return \"\" if given \"foo/\". Your implementation, when given \"/foo/bar/\"\n> will return \"bar/\" (and it must keep the trailing bit since we are\n> neither reallocating nor munging the input string). But given\n> \"/foo/bar//\", it will return simply \"/\". I could see an argument for\n> either \"bar//\" or \"\", but I think behaving differently for trailing \"/\"\n> versus trailing \"//\" doesn't make sense.\n> \n> -Peff\n\nYou know.. going with the compat/basename.c solution is probably\na better idea now that you've pointed out all these issues.\nThen we can just use the system's basename() when available and\nuse our compat/basename.c otherwise (is it only for Windows?).\n\nHere's basename() from libiberty.\n\nIt drops constness (likely to keep in line with the standard)\nand has some #defines that I'll have to translate into git\nequivalents (e.g. IS_DIR_SEPARATOR -> is_dir_sep).\n\nDo we have a cross-platform ISALPHA thing (just thinking out\nloud -- I can check).  I'm under the impression that going with\nsomething like this should get us in a better place.\n\nWhat do you think?\n\n\nchar *basename (const char *name)\n{\n\tconst char *base;\n#if defined (HAVE_DOS_BASED_FILE_SYSTEM)\n\t/* Skip over the disk name in MSDOS pathnames. */\n\tif (ISALPHA (name[0]) && name[1] == ':') \n\t\tname += 2;\n#endif\n\n\tfor (base = name; *name; name++) {\n\t\tif (IS_DIR_SEPARATOR (*name)) {\n\t\t\tbase = name + 1;\n\t\t}\n\t}\n\treturn (char *) base;\n}\n\n-- \n\t\tDavid\n"}]}