aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@osdl.org>2005-08-16 20:44:32 -0700
committerJunio C Hamano <junkio@cox.net>2005-08-16 21:33:25 -0700
commitf332726eaad74ac2aac0c3fb2dcb662acdbc3a31 (patch)
treeb286ced3860a853e4ebcea7f7e2b10b2571215bd
parenta579defe5a43bdd242d79750039758f319b82a38 (diff)
downloadgit-f332726eaad74ac2aac0c3fb2dcb662acdbc3a31.tar.gz
git-f332726eaad74ac2aac0c3fb2dcb662acdbc3a31.tar.xz
[PATCH] Improve handling of "." and ".." in git-diff-*
This fixes up usage of ".." (without an ending slash) and "." (with or without the ending slash) in the git diff family. It also fixes pathspec matching for the case of an empty pathspec, since a "." in the top-level directory (or enough ".." under subdirectories) will result in an empty pathspec. We used to not match it against anything, but it should in fact match everything. Signed-off-by: Linus Torvalds <torvalds@osdl.org> Signed-off-by: Junio C Hamano <junkio@cox.net>
-rw-r--r--diffcore-pathspec.c2
-rw-r--r--read-cache.c2
-rw-r--r--setup.c93
3 files changed, 55 insertions, 42 deletions
diff --git a/diffcore-pathspec.c b/diffcore-pathspec.c
index a48acbc96..68fe00913 100644
--- a/diffcore-pathspec.c
+++ b/diffcore-pathspec.c
@@ -29,6 +29,8 @@ static int matches_pathspec(const char *name, struct path_spec *s, int cnt)
name[len] == 0 ||
name[len] == '/')
return 1;
+ if (!len)
+ return 1;
}
return 0;
}
diff --git a/read-cache.c b/read-cache.c
index 5820f18d9..ced597318 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -191,6 +191,8 @@ int ce_path_match(const struct cache_entry *ce, const char **pathspec)
return 1;
if (name[matchlen] == '/' || !name[matchlen])
return 1;
+ if (!matchlen)
+ return 1;
}
return 0;
}
diff --git a/setup.c b/setup.c
index 896fca503..1710b1685 100644
--- a/setup.c
+++ b/setup.c
@@ -1,23 +1,60 @@
#include "cache.h"
+static char *prefix_path(const char *prefix, int len, char *path)
+{
+ char *orig = path;
+ for (;;) {
+ char c;
+ if (*path != '.')
+ break;
+ c = path[1];
+ /* "." */
+ if (!c) {
+ path++;
+ break;
+ }
+ /* "./" */
+ if (c == '/') {
+ path += 2;
+ continue;
+ }
+ if (c != '.')
+ break;
+ c = path[2];
+ if (!c)
+ path += 2;
+ else if (c == '/')
+ path += 3;
+ else
+ break;
+ /* ".." and "../" */
+ /* Remove last component of the prefix */
+ do {
+ if (!len)
+ die("'%s' is outside repository", orig);
+ len--;
+ } while (len && prefix[len-1] != '/');
+ continue;
+ }
+ if (len) {
+ int speclen = strlen(path);
+ char *n = xmalloc(speclen + len + 1);
+
+ memcpy(n, prefix, len);
+ memcpy(n + len, path, speclen+1);
+ path = n;
+ }
+ return path;
+}
+
const char **get_pathspec(const char *prefix, char **pathspec)
{
char *entry = *pathspec;
char **p;
int prefixlen;
- if (!prefix) {
- char **p;
- if (!entry)
- return NULL;
- p = pathspec;
- do {
- if (*entry != '.')
- continue;
- /* fixup ? */
- } while ((entry = *++p) != NULL);
- return (const char **) pathspec;
- }
+ if (!prefix && !entry)
+ return NULL;
if (!entry) {
static const char *spec[2];
@@ -27,38 +64,10 @@ const char **get_pathspec(const char *prefix, char **pathspec)
}
/* Otherwise we have to re-write the entries.. */
- prefixlen = strlen(prefix);
p = pathspec;
+ prefixlen = prefix ? strlen(prefix) : 0;
do {
- int speclen, len = prefixlen;
- char *n;
-
- for (;;) {
- if (!strcmp(entry, ".")) {
- entry++;
- break;
- }
- if (!strncmp(entry, "./", 2)) {
- entry += 2;
- continue;
- }
- if (!strncmp(entry, "../", 3)) {
- do {
- if (!len)
- die("'%s' is outside repository", *p);
- len--;
- } while (len && prefix[len-1] != '/');
- entry += 3;
- continue;
- }
- break;
- }
- speclen = strlen(entry);
- n = xmalloc(speclen + len + 1);
-
- memcpy(n, prefix, len);
- memcpy(n + len, entry, speclen+1);
- *p = n;
+ *p = prefix_path(prefix, prefixlen, entry);
} while ((entry = *++p) != NULL);
return (const char **) pathspec;
}