Re: Incorrect git-blame result if I use full path to file

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On Sun, 2 Dec 2007, Junio C Hamano wrote:
> "Anatol Pomozov" <anatol.pomozov@xxxxxxxxx> writes:
> >
> > I just start learning git and I found a bug (but sorry if the
> > functionality I am trying to blame as a bug not actually bug and it
> > was made by intention)
> 
> I think it is rather a sloppy error checking than a bug.  It should be
> throwing a stone back at you when you feed it a full path, or converting
> it back to work tree relative path before using.

How about this patch?

It makes "get_pathspec()" make all the paths it returns relative, if it 
can. HOWEVER! I think it should actually die() if it sees an absolute path 
that it cannot convert (because it really cannot do anything sane about 
it), but I commented that out for now because that requires some test case 
change: right now we actually have a few test cases for insane filename 
arguments, and they expect the old behaviour.

Comments? This changes behaviour subtly (and if we enable the "die(..)" 
logic, not-so-subtly), but I think that in any case where it changes 
behaviour, the new behaviour would be an improvement, and the old one 
would be nonsensical (ie you get *some* results with an absolute pathname, 
just not the ones you'd expect!)

Note the die() comment in the bad case in "make_relative()".

		Linus
---
 setup.c |   34 +++++++++++++++++++++++++++++++++-
 1 files changed, 33 insertions(+), 1 deletions(-)

diff --git a/setup.c b/setup.c
index 2c7b5cb..fadf4ee 100644
--- a/setup.c
+++ b/setup.c
@@ -111,11 +111,26 @@ void verify_non_filename(const char *prefix, const char *arg)
 		die("'%s': %s", arg, strerror(errno));
 }
 
+static const char *make_relative(const char *file, const char *pwd, int pwdlen)
+{
+	if (strncmp(file, pwd, pwdlen))
+		goto bad;
+	if (file[pwdlen] != '/')
+		goto bad;
+	return file + pwdlen + 1;
+
+bad:
+	/* Should we die() here or just do a "return file"? */
+	/* die("pathname '%s' is not in the repository", file); */
+	return file;
+}
+
 const char **get_pathspec(const char *prefix, const char **pathspec)
 {
+	const char *pwd;
 	const char *entry = *pathspec;
 	const char **p;
-	int prefixlen;
+	int prefixlen, pwdlen;
 
 	if (!prefix && !entry)
 		return NULL;
@@ -127,9 +142,26 @@ const char **get_pathspec(const char *prefix, const char **pathspec)
 		return spec;
 	}
 
+	pwd = NULL;
+	pwdlen = 0;
+	p = pathspec;
+	do {
+		if (*entry == '/') {
+			if (!pwd) {
+				char buffer[PATH_MAX + 1];
+				if (!getcwd(buffer, sizeof(buffer)))
+					break;
+				pwd = buffer;
+				pwdlen = strlen(buffer);
+			}
+			*p = make_relative(entry, pwd, pwdlen);
+		}
+	} while ((entry = *++p) != NULL);
+
 	/* Otherwise we have to re-write the entries.. */
 	p = pathspec;
 	prefixlen = prefix ? strlen(prefix) : 0;
+	entry = *p;
 	do {
 		*p = prefix_path(prefix, prefixlen, entry);
 	} while ((entry = *++p) != NULL);

-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux