Re: Improve handling of "." and ".." in git-diff-*
- From
Alex Riesen <raa.lkml@gmail.com>
- Date
- Aug 23, 2005, 19:49 UTC
- Message-ID
- <81b0412b050823124938d735bf@mail.gmail.com>
- In-Reply-To
- <Pine.LNX.4.58.0508162037080.3553@g5.osdl.org>
On 8/17/05, Linus Torvalds <torvalds@osdl.org> wrote:
> NOTE! This does _not_ handle ".." or "." in the _middle_ of a pathspec. If > you have people who do
BTW, could this (below) be useful for something?
#include <string.h> #include <stdio.h> #include <stdlib.h>
// an analog of "cd path" from a directory "cwd".
char* pathexpand(const char* cwd, const char* path)
{
static const char SEP[] = "/";
if ( !*path ) // empty path -> "." (don't move)
path = ".";
if ( !*cwd || *SEP == *path ) // no cwd, or path begins with "/"
cwd = SEP; int len = strlen(cwd);
char* out = (char*)malloc(len + 1 + strlen(path) + 1);
char* p = strcpy(out, cwd) + len;if ( *SEP != p[-1] ) *p++ = *SEP;
for ( ; *path; ++path )
{
char * pl = p;
while ( *path && *SEP != *path )
*p++ = *path++;
*p = '\0';if ( p == pl ) /* ..."//"... */ ; // just ignore
/* ..."/./"... */ else if ( p - pl == 1 && '.' == *pl ) --p; // just ignore
/* ..."/../"... */
else if ( p - pl == 2 && '.' == pl[0] && '.' == pl[1] )
{
// drop last element of the resulting path
if ( --pl > out )
for ( --pl; pl > out && *SEP != *pl; --pl );
p = ++pl;
}
/* ..."/path/"... */
else if ( *path )
*p++ = *path; // just add the separator
if ( !*path )
break;
}
if ( p > out+1 && *SEP == p[-1] )
--p;
*p = '\0';
return out;
}#ifdef CHECK_PATHEXPAND
static void check(const char * cwd, const char * path, const char * good)
{
static int n = 0;
printf("%-2d: %s$ cd %s", ++n, cwd, path);
char* t = pathexpand(cwd, path);
if ( strcmp(t, good) )
printf(" failed(%s)\n", t);
else
printf(" \t\t%s\n", t);
free(t);
}int main(int argc, char** argv)
{
/* 1 */ check("/onelevel", "aa", "/onelevel/aa");
/* 2 */ check("/", "..", "/");
/* 3 */ check("/", "../..", "/");
/* 4 */ check("/one", "aa/../bb", "/one/bb");
/* 5 */ check("/one/two", "aa//bb", "/one/two/aa/bb");
/* 6 */ check("", "/aa//bb", "/aa/bb");
/* 7 */ check("/one/two", "", "/one/two");
/* 8 */ check("/one/two", "aa/..bb/x/../cc/", "/one/two/aa/..bb/cc");
/* 9 */ check("/one/two", "aa/x/././cc////", "/one/two/aa/x/cc");
/* 10 */ check("/one/two", "../../../../aa", "/aa");return 0; } #endif