diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | cache.h | 3 | ||||
-rw-r--r-- | diff-cache.c | 12 | ||||
-rw-r--r-- | diff-files.c | 11 | ||||
-rw-r--r-- | diff-tree.c | 17 | ||||
-rwxr-xr-x | git-diff-script | 4 | ||||
-rw-r--r-- | rev-parse.c | 7 | ||||
-rw-r--r-- | setup.c | 110 |
8 files changed, 147 insertions, 19 deletions
@@ -97,7 +97,7 @@ LIB_H=cache.h object.h blob.h tree.h commit.h tag.h delta.h epoch.h csum-file.h LIB_OBJS=read-cache.o sha1_file.o usage.o object.o commit.o tree.o blob.o \ tag.o date.o index.o diff-delta.o patch-delta.o entry.o path.o \ refs.o csum-file.o pack-check.o pkt-line.o connect.o ident.o \ - sha1_name.o + sha1_name.o setup.o LIB_H += rev-cache.h LIB_OBJS += rev-cache.o @@ -140,6 +140,9 @@ extern char *get_graft_file(void); #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES" +extern const char **get_pathspec(const char *prefix, char **pathspec); +extern const char *setup_git_directory(void); + #define alloc_nr(x) (((x)+16)*3/2) /* Initialize and use the cache information */ diff --git a/diff-cache.c b/diff-cache.c index 47a4e09ecc..400a4cb2ad 100644 --- a/diff-cache.c +++ b/diff-cache.c @@ -168,10 +168,11 @@ static const char diff_cache_usage[] = "[<common diff options>] <tree-ish> [<path>...]" COMMON_DIFF_OPTIONS_HELP; -int main(int argc, const char **argv) +int main(int argc, char **argv) { const char *tree_name = NULL; unsigned char sha1[20]; + const char *prefix = setup_git_directory(); const char **pathspec = NULL; void *tree; unsigned long size; @@ -179,15 +180,12 @@ int main(int argc, const char **argv) int allow_options = 1; int i; - read_cache(); for (i = 1; i < argc; i++) { const char *arg = argv[i]; if (!allow_options || *arg != '-') { - if (tree_name) { - pathspec = argv + i; + if (tree_name) break; - } tree_name = arg; continue; } @@ -265,12 +263,16 @@ int main(int argc, const char **argv) usage(diff_cache_usage); } + pathspec = get_pathspec(prefix, argv + i); + if (find_copies_harder && detect_rename != DIFF_DETECT_COPY) usage(diff_cache_usage); if (!tree_name || get_sha1(tree_name, sha1)) usage(diff_cache_usage); + read_cache(); + /* The rest is for paths restriction. */ diff_setup(diff_setup_opt); diff --git a/diff-files.c b/diff-files.c index 2e6416e386..89eb29b3e2 100644 --- a/diff-files.c +++ b/diff-files.c @@ -41,12 +41,12 @@ static void show_modified(int oldmode, int mode, diff_change(oldmode, mode, old_sha1, sha1, path, NULL); } -int main(int argc, const char **argv) +int main(int argc, char **argv) { static const unsigned char null_sha1[20] = { 0, }; const char **pathspec; - int entries = read_cache(); - int i; + const char *prefix = setup_git_directory(); + int entries, i; while (1 < argc && argv[1][0] == '-') { if (!strcmp(argv[1], "-p") || !strcmp(argv[1], "-u")) @@ -95,8 +95,9 @@ int main(int argc, const char **argv) argv++; argc--; } - /* Do we have a pathspec? */ - pathspec = (argc > 1) ? argv + 1 : NULL; + /* Find the directory, and set up the pathspec */ + pathspec = get_pathspec(prefix, argv + 1); + entries = read_cache(); if (find_copies_harder && detect_rename != DIFF_DETECT_COPY) usage(diff_files_usage); diff --git a/diff-tree.c b/diff-tree.c index 0dd3cdacb2..fc87902a3d 100644 --- a/diff-tree.c +++ b/diff-tree.c @@ -395,16 +395,25 @@ static int diff_tree_stdin(char *line) return diff_tree_commit(commit, line); } +static int count_paths(const char **paths) +{ + int i = 0; + while (*paths++) + i++; + return i; +} + static const char diff_tree_usage[] = "git-diff-tree [--stdin] [-m] [-s] [-v] [--pretty] [-t] " "[<common diff options>] <tree-ish> <tree-ish>" COMMON_DIFF_OPTIONS_HELP; -int main(int argc, const char **argv) +int main(int argc, char **argv) { int nr_sha1; char line[1000]; unsigned char sha1[2][20]; + const char *prefix = setup_git_directory(); nr_sha1 = 0; for (;;) { @@ -523,11 +532,11 @@ int main(int argc, const char **argv) if (find_copies_harder && detect_rename != DIFF_DETECT_COPY) usage(diff_tree_usage); - if (argc > 0) { + paths = get_pathspec(prefix, argv); + if (paths) { int i; - paths = argv; - nr_paths = argc; + nr_paths = count_paths(paths); pathlens = xmalloc(nr_paths * sizeof(int)); for (i=0; i<nr_paths; i++) pathlens[i] = strlen(paths[i]); diff --git a/git-diff-script b/git-diff-script index 03ed555e77..926f594be4 100755 --- a/git-diff-script +++ b/git-diff-script @@ -1,7 +1,5 @@ #!/bin/sh -. git-sh-setup-script || die "Not a git archive" - -rev=($(git-rev-parse --revs-only "$@")) +rev=($(git-rev-parse --revs-only "$@")) || exit flags=($(git-rev-parse --no-revs --flags "$@")) files=($(git-rev-parse --no-revs --no-flags "$@")) case "${#rev[*]}" in diff --git a/rev-parse.c b/rev-parse.c index 1c6ae76f9a..39cf63540e 100644 --- a/rev-parse.c +++ b/rev-parse.c @@ -134,7 +134,8 @@ int main(int argc, char **argv) { int i, as_is = 0; unsigned char sha1[20]; - + const char *prefix = setup_git_directory(); + for (i = 1; i < argc; i++) { char *arg = argv[i]; char *dotdot; @@ -189,6 +190,10 @@ int main(int argc, char **argv) for_each_ref(show_reference); continue; } + if (!strcmp(arg, "--show-prefix")) { + puts(prefix); + continue; + } show_arg(arg); continue; } diff --git a/setup.c b/setup.c new file mode 100644 index 0000000000..453bddbb17 --- /dev/null +++ b/setup.c @@ -0,0 +1,110 @@ +#include "cache.h" + +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 (!entry) { + static const char *spec[2]; + spec[0] = prefix; + spec[1] = NULL; + return spec; + } + + /* Otherwise we have to re-write the entries.. */ + prefixlen = strlen(prefix); + p = pathspec; + 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; + } while ((entry = *++p) != NULL); + return (const char **) pathspec; +} + +const char *setup_git_directory(void) +{ + static char cwd[PATH_MAX+1]; + int len, offset; + + /* + * If GIT_DIR is set explicitly, we're not going + * to do any discovery + */ + if (gitenv(GIT_DIR_ENVIRONMENT)) + return NULL; + + if (!getcwd(cwd, sizeof(cwd)) || cwd[0] != '/') + die("Unable to read current working directory"); + + offset = len = strlen(cwd); + for (;;) { + /* + * We always want to see a .git/HEAD and a .git/refs/ + * subdirectory + */ + if (!access(".git/HEAD", R_OK) && !access(".git/refs/", X_OK)) { + /* + * Then we need either a GIT_OBJECT_DIRECTORY define + * or a .git/objects/ directory + */ + if (gitenv(DB_ENVIRONMENT) || !access(".git/objects/", X_OK)) + break; + } + chdir(".."); + do { + if (!offset) + die("Not a git repository"); + } while (cwd[--offset] != '/'); + } + + if (offset == len) + return NULL; + + /* Make "offset" point to past the '/', and add a '/' at the end */ + offset++; + cwd[len++] = '/'; + cwd[len] = 0; + return cwd + offset; +} |