{"thread":{"id":"1542","subject":"[RFC PATCH] Add support for figuring out where in the git archive we are","startedAt":"2005-08-16T22:45:35Z","lastAt":"2005-08-17T04:30:03Z","messageCount":10,"participants":["Linus Torvalds","Yasushi SHOJI","Junio C Hamano","Daniel Barkalow"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"7395","messageId":"Pine.LNX.4.58.0508161536390.3553@g5.osdl.org","threadId":"1542","inReplyTo":null,"subject":"[RFC PATCH] Add support for figuring out where in the git archive we are","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-08-16T22:45:35Z","receivedAt":"2005-08-16T22:45:35Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"    \nThis does only \"git-diff-cache\" and \"git-diff-files\", but the concept\nshould work for any command that uses the working tree.\n\nSigned-off-by: Linus Torvalds <torvalds@osdl.org>\n---\nThis is really partly a serious patch, but also just a query whether \npeople would want git to work in subdirectories, not just the top-level \ndirectory.\n\nSo you can be in linux/drivers, and if you do a\n\n\tgit-diff-files -p char\n\nthen it will automatically be turned into the full pathname, and do the\nright thing (ie do a diff of drivers/char only).\n\nI didn't want to do it originally, but that was largely a complexity\nissue, and an issue of there being many more things up in the air at that\ntime. Now, things have calmed down a bit, the interfaces are fairly\nstable, and it turns out to be not that difficult to just walk up the\nchain of directories until we hit the one that has the \".git\" directory in\nit.\n\nI only converted \"git-diff-files\" and \"git-diff-cache\" to do this, because\nso far it's a technology demo. And the \"git-diff-script\" file (and the\ngit-sh-setup-script in particular) does _not_ accept this \"automatically \nfigure out where we are\" thing, so it's really only the native git diff \ncommands that do it.\n\nBut if people think it's a good idea, I can pretty trivially convert the \nrest. It's done in a way that makes it very easy to convert programs to \ntake advantage of the auto-git-directory-finding thing.\n\nIf you use the GIT_DIR environment variable approach, it assumes that all\nfilenames you give it are absolute and acts the way it always did before.\n\nComments? Like? Dislike?\n\n\t\tLinus\n\ndiff --git a/Makefile b/Makefile\n--- a/Makefile\n+++ b/Makefile\n@@ -97,7 +97,7 @@ LIB_H=cache.h object.h blob.h tree.h com\n LIB_OBJS=read-cache.o sha1_file.o usage.o object.o commit.o tree.o blob.o \\\n \t tag.o date.o index.o diff-delta.o patch-delta.o entry.o path.o \\\n \t refs.o csum-file.o pack-check.o pkt-line.o connect.o ident.o \\\n-\t sha1_name.o\n+\t sha1_name.o setup.o\n \n LIB_H += rev-cache.h\n LIB_OBJS += rev-cache.o\ndiff --git a/cache.h b/cache.h\n--- a/cache.h\n+++ b/cache.h\n@@ -140,6 +140,8 @@ extern char *get_graft_file(void);\n \n #define ALTERNATE_DB_ENVIRONMENT \"GIT_ALTERNATE_OBJECT_DIRECTORIES\"\n \n+extern char **setup_git_directory(char **pathspec);\n+\n #define alloc_nr(x) (((x)+16)*3/2)\n \n /* Initialize and use the cache information */\ndiff --git a/diff-cache.c b/diff-cache.c\n--- a/diff-cache.c\n+++ b/diff-cache.c\n@@ -179,15 +179,12 @@ int main(int argc, const char **argv)\n \tint allow_options = 1;\n \tint i;\n \n-\tread_cache();\n \tfor (i = 1; i < argc; i++) {\n \t\tconst char *arg = argv[i];\n \n \t\tif (!allow_options || *arg != '-') {\n-\t\t\tif (tree_name) {\n-\t\t\t\tpathspec = argv + i;\n+\t\t\tif (tree_name)\n \t\t\t\tbreak;\n-\t\t\t}\n \t\t\ttree_name = arg;\n \t\t\tcontinue;\n \t\t}\n@@ -265,12 +262,16 @@ int main(int argc, const char **argv)\n \t\tusage(diff_cache_usage);\n \t}\n \n+\tpathspec = setup_git_directory(argv + i);\n+\n \tif (find_copies_harder && detect_rename != DIFF_DETECT_COPY)\n \t\tusage(diff_cache_usage);\n \n \tif (!tree_name || get_sha1(tree_name, sha1))\n \t\tusage(diff_cache_usage);\n \n+\tread_cache();\n+\n \t/* The rest is for paths restriction. */\n \tdiff_setup(diff_setup_opt);\n \ndiff --git a/diff-files.c b/diff-files.c\n--- a/diff-files.c\n+++ b/diff-files.c\n@@ -45,8 +45,7 @@ int main(int argc, const char **argv)\n {\n \tstatic const unsigned char null_sha1[20] = { 0, };\n \tconst char **pathspec;\n-\tint entries = read_cache();\n-\tint i;\n+\tint entries, i;\n \n \twhile (1 < argc && argv[1][0] == '-') {\n \t\tif (!strcmp(argv[1], \"-p\") || !strcmp(argv[1], \"-u\"))\n@@ -95,8 +94,9 @@ int main(int argc, const char **argv)\n \t\targv++; argc--;\n \t}\n \n-\t/* Do we have a pathspec? */\n-\tpathspec = (argc > 1) ? argv + 1 : NULL;\n+\t/* Find the directory, and set up the pathspec */\n+\tpathspec = setup_git_directory(argv + 1);\n+\tentries = read_cache();\n \n \tif (find_copies_harder && detect_rename != DIFF_DETECT_COPY)\n \t\tusage(diff_files_usage);\ndiff --git a/setup.c b/setup.c\nnew file mode 100644\n--- /dev/null\n+++ b/setup.c\n@@ -0,0 +1,66 @@\n+#include \"cache.h\"\n+\n+char **setup_git_directory(char **pathspec)\n+{\n+\tstatic char *spec[2], **p;\n+\tstatic char cwd[PATH_MAX+1];\n+\tint len, offset;\n+\n+\t/*\n+\t * If GIT_DIR is set explicitly, we're not going\n+\t * to do any discovery\n+\t */\n+\tif (gitenv(GIT_DIR_ENVIRONMENT))\n+\t\treturn *pathspec ? pathspec : NULL;\n+\n+\tif (!getcwd(cwd, sizeof(cwd)) || cwd[0] != '/')\n+\t\tdie(\"Unable to read current working directory\");\n+\n+\toffset = len = strlen(cwd);\n+\tfor (;;) {\n+\t\t/*\n+\t\t * We always want to see a .git/HEAD and a .git/refs/\n+\t\t * subdirectory\n+\t\t */\n+\t\tif (!access(\".git/HEAD\", R_OK) && !access(\".git/refs/\", X_OK)) {\n+\t\t\t/*\n+\t\t\t * Then we need either a GIT_OBJECT_DIRECTORY define\n+\t\t\t * or a .git/objects/ directory\n+\t\t\t */\n+\t\t\tif (gitenv(DB_ENVIRONMENT) || !access(\".git/objects/\", X_OK))\n+\t\t\t\tbreak;\n+\t\t}\n+\t\tchdir(\"..\");\n+\t\tdo {\n+\t\t\tif (!offset)\n+\t\t\t\tdie(\"Not a git repository\");\n+\t\t} while (cwd[--offset] != '/');\n+\t}\n+\n+\tif (offset == len)\n+\t\treturn *pathspec ? pathspec : NULL;\n+\n+\t/* Make \"offset\" point to past the '/', and add a '/' at the end */\n+\toffset++;\n+\tcwd[len++] = '/';\n+\tcwd[len] = 0;\n+\n+\t/* An empty pathspec gets turned into the directory we were in */\n+\tif (!*pathspec) {\n+\t\tspec[0] = cwd + offset;\n+\t\tspec[1] = NULL;\n+\t\treturn spec;\n+\t}\n+\n+\t/* Otherwise we have to re-write the entries.. */\n+\tp = pathspec;\n+\tdo {\n+\t\tint speclen = strlen(*p);\n+\t\tchar *n = xmalloc(speclen + len - offset + 1);\n+\t\tmemcpy(n, cwd + offset, len - offset);\n+\t\tmemcpy(n + len - offset, *p, speclen+1);\n+\t\t*p = n;\n+\t} while (*++p);\n+\treturn pathspec;\n+}\n+\n"},{"id":"7397","messageId":"873bp9xytd.wl@mail2.atmark-techno.com","threadId":"1542","inReplyTo":"Pine.LNX.4.58.0508161536390.3553@g5.osdl.org","subject":"Re: [RFC PATCH] Add support for figuring out where in the git archive we are","fromName":"Yasushi SHOJI","fromEmail":"yashi@atmark-techno.com","sentAt":"2005-08-16T23:10:54Z","receivedAt":"2005-08-16T23:10:54Z","isPatch":true,"sender":{"key":"yashi@atmark-techno.com","avatar":"https://gravatar.com/avatar/4817e8703ac4379935834d87453faa9d0c94b9dc19d83fcc54c67875eb133e59?d=mp&s=160"},"body":"At Tue, 16 Aug 2005 15:45:35 -0700 (PDT),\nLinus Torvalds wrote:\n> \n> This is really partly a serious patch, but also just a query whether \n> people would want git to work in subdirectories, not just the top-level \n> directory.\n> \n> So you can be in linux/drivers, and if you do a\n> \n> \tgit-diff-files -p char\n> \n> then it will automatically be turned into the full pathname, and do the\n> right thing (ie do a diff of drivers/char only).\n\nI've had missed this feature a lot, since quilt has been working this\nway.  now I can close just-for-git terminal.(tm)\n\nregards,\n--\n          yashi\n"},{"id":"7399","messageId":"7vll315u3w.fsf@assigned-by-dhcp.cox.net","threadId":"1542","inReplyTo":"Pine.LNX.4.58.0508161536390.3553@g5.osdl.org","subject":"Re: [RFC PATCH] Add support for figuring out where in the git archive we are","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-16T23:40:03Z","receivedAt":"2005-08-16T23:40:03Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> If you use the GIT_DIR environment variable approach, it assumes that all\n> filenames you give it are absolute and acts the way it always did before.\n\n> Comments? Like? Dislike?\n\nComments: Wouldn't that mean git-*-scripts would not benefit from this\n          because git-sh-setup would set GIT_DIR for you even if\n          you don't?\n\n\t  Even if you do not have to do discovery, it may make\n\t  more sense to do the pathname translation (making them\n\t  all relative to the project root) for consistency.\n\n\t  If you can do \"cd drivers && git-diff-files ../net\"\n\t  that would be very useful.  More realistically, people\n\t  would very much appreciate if stripping the leading ./ in\n          \"find . -type f -print0 | xargs -0 git-blah-command\".\n\nLike:\t  Yes, you finally saw the light ;-).\n\nDislike:  I believe I was one of the original proponent for this\n          kind of thing, so no.\n"},{"id":"7400","messageId":"Pine.LNX.4.58.0508161655460.3553@g5.osdl.org","threadId":"1542","inReplyTo":"7vll315u3w.fsf@assigned-by-dhcp.cox.net","subject":"Re: [RFC PATCH] Add support for figuring out where in the git archive we are","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-08-17T00:01:23Z","receivedAt":"2005-08-17T00:01:23Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 16 Aug 2005, Junio C Hamano wrote:\n> \n> Comments: Wouldn't that mean git-*-scripts would not benefit from this\n>           because git-sh-setup would set GIT_DIR for you even if\n>           you don't?\n\nAs it stands now, yes. But the point being that if people like this, then \nI'll just change the git-sh-setup-script accordingly. For example, once \ngit-diff-tree also does the same thing, then \"git-diff-script\" would have \nno reason left to even call the current git-sh-setup-script at all, since \nthe git-diff-* commands would basically do the setup _and_ report the \nerrors that git-sh-setup-script does now.\n\n> \t  If you can do \"cd drivers && git-diff-files ../net\"\n> \t  that would be very useful.\n\nI don't do that right now, but it's actually very easy to do in the \nsetup_git_directory() function. It falls out very simply there - both the \n\"./\" and the \"../\" prefix would make tons of sense to handle there.\n\nDo you want to take the current patch (which buys you very little because \nnot a lot of stuff has been set up to deal with it, but is the basis for \nall future work anyway) or do you want me to polish it up a bit and \nre-submit the whole thing?\n\nI'd do at least the \"git-diff-tree\" part and the \"./\" and \"../\" handling,\nand convert at least the \"git diff\" thing to the new world order and away\nfrom git-sh-setup-script?\n\n\t\tLinus\n"},{"id":"7402","messageId":"7vhddp5sfz.fsf@assigned-by-dhcp.cox.net","threadId":"1542","inReplyTo":"Pine.LNX.4.58.0508161655460.3553@g5.osdl.org","subject":"Re: [RFC PATCH] Add support for figuring out where in the git archive we are","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-17T00:16:00Z","receivedAt":"2005-08-17T00:16:00Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> Do you want to take the current patch (which buys you very little because \n> not a lot of stuff has been set up to deal with it, but is the basis for \n> all future work anyway) or do you want me to polish it up a bit and \n> re-submit the whole thing?\n\nThe developement history would look nicer if you did the latter,\nbut I am easy and can go either way.\n\n> I'd do at least the \"git-diff-tree\" part and the \"./\" and \"../\" handling,\n> and convert at least the \"git diff\" thing to the new world order and away\n> from git-sh-setup-script?\n\nSounds like fun.\n"},{"id":"7404","messageId":"Pine.LNX.4.63.0508162005070.23242@iabervon.org","threadId":"1542","inReplyTo":"Pine.LNX.4.58.0508161536390.3553@g5.osdl.org","subject":"Re: [RFC PATCH] Add support for figuring out where in the git archive we are","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-08-17T00:25:37Z","receivedAt":"2005-08-17T00:25:37Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Tue, 16 Aug 2005, Linus Torvalds wrote:\n\n> If you use the GIT_DIR environment variable approach, it assumes that all\n> filenames you give it are absolute and acts the way it always did before.\n>\n> Comments? Like? Dislike?\n\nI'm all in favor, at least in the general case. I suspect there'll be some\nthings where we have to discuss the behavior, but we can argue that when\nit comes up.\n\nI think, slightly before 1.0, we should sort the library functions into a\nnew set of object files with matching header files, because \"setup\" is not\nreally distinctive, and there's at least one duplicate implementation\n(the ssh subprocess code in your connect.c is the same as my rsh.c in what\nit does, although yours uses two pipes and mine uses a socket).\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"7407","messageId":"Pine.LNX.4.58.0508161803250.3553@g5.osdl.org","threadId":"1542","inReplyTo":"7vhddp5sfz.fsf@assigned-by-dhcp.cox.net","subject":"Re: [RFC PATCH] Add support for figuring out where in the git archive we are","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-08-17T01:06:34Z","receivedAt":"2005-08-17T01:06:34Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 16 Aug 2005, Junio C Hamano wrote:\n> \n> The developement history would look nicer if you did the latter,\n> but I am easy and can go either way.\n\nHere is.\n\n> > I'd do at least the \"git-diff-tree\" part and the \"./\" and \"../\" handling,\n> > and convert at least the \"git diff\" thing to the new world order and away\n> > from git-sh-setup-script?\n> \n> Sounds like fun.\n\nMostly done. It actually works from inside subdirectories, but \".\" at the\ntop-level is still not done. Small detail. Will fix later. But it would\nhelp if you would apply this, since I'm going to be off for dinner..\n\nThe \"../\" handling was pretty straightforward.\n\n\t\tLinus\n\n----\nMake \"git diff\" work inside relative subdirectories\n\nWe always show the diff as an absolute path, but pathnames to diff are\ntaken relative to the current working directory (and if no pathnames are\ngiven, the default ends up being all of the current working directory).\n\nNote that \"../xyz\" also works, so you can do\n\n\tcd linux/drivers/char\n\tgit diff ../block\n\nand it will generate a diff of the linux/drivers/block changes.\n\nSigned-off-by: Linus Torvalds <torvalds@osdl.org>\n---\n\ndiff --git a/Makefile b/Makefile\n--- a/Makefile\n+++ b/Makefile\n@@ -97,7 +97,7 @@ LIB_H=cache.h object.h blob.h tree.h com\n LIB_OBJS=read-cache.o sha1_file.o usage.o object.o commit.o tree.o blob.o \\\n \t tag.o date.o index.o diff-delta.o patch-delta.o entry.o path.o \\\n \t refs.o csum-file.o pack-check.o pkt-line.o connect.o ident.o \\\n-\t sha1_name.o\n+\t sha1_name.o setup.o\n \n LIB_H += rev-cache.h\n LIB_OBJS += rev-cache.o\ndiff --git a/cache.h b/cache.h\n--- a/cache.h\n+++ b/cache.h\n@@ -140,6 +140,9 @@ extern char *get_graft_file(void);\n \n #define ALTERNATE_DB_ENVIRONMENT \"GIT_ALTERNATE_OBJECT_DIRECTORIES\"\n \n+extern const char **get_pathspec(const char *prefix, char **pathspec);\n+extern const char *setup_git_directory(void);\n+\n #define alloc_nr(x) (((x)+16)*3/2)\n \n /* Initialize and use the cache information */\ndiff --git a/diff-cache.c b/diff-cache.c\n--- a/diff-cache.c\n+++ b/diff-cache.c\n@@ -168,10 +168,11 @@ static const char diff_cache_usage[] =\n \"[<common diff options>] <tree-ish> [<path>...]\"\n COMMON_DIFF_OPTIONS_HELP;\n \n-int main(int argc, const char **argv)\n+int main(int argc, char **argv)\n {\n \tconst char *tree_name = NULL;\n \tunsigned char sha1[20];\n+\tconst char *prefix = setup_git_directory();\n \tconst char **pathspec = NULL;\n \tvoid *tree;\n \tunsigned long size;\n@@ -179,15 +180,12 @@ int main(int argc, const char **argv)\n \tint allow_options = 1;\n \tint i;\n \n-\tread_cache();\n \tfor (i = 1; i < argc; i++) {\n \t\tconst char *arg = argv[i];\n \n \t\tif (!allow_options || *arg != '-') {\n-\t\t\tif (tree_name) {\n-\t\t\t\tpathspec = argv + i;\n+\t\t\tif (tree_name)\n \t\t\t\tbreak;\n-\t\t\t}\n \t\t\ttree_name = arg;\n \t\t\tcontinue;\n \t\t}\n@@ -265,12 +263,16 @@ int main(int argc, const char **argv)\n \t\tusage(diff_cache_usage);\n \t}\n \n+\tpathspec = get_pathspec(prefix, argv + i);\n+\n \tif (find_copies_harder && detect_rename != DIFF_DETECT_COPY)\n \t\tusage(diff_cache_usage);\n \n \tif (!tree_name || get_sha1(tree_name, sha1))\n \t\tusage(diff_cache_usage);\n \n+\tread_cache();\n+\n \t/* The rest is for paths restriction. */\n \tdiff_setup(diff_setup_opt);\n \ndiff --git a/diff-files.c b/diff-files.c\n--- a/diff-files.c\n+++ b/diff-files.c\n@@ -41,12 +41,12 @@ static void show_modified(int oldmode, i\n \tdiff_change(oldmode, mode, old_sha1, sha1, path, NULL);\n }\n \n-int main(int argc, const char **argv)\n+int main(int argc, char **argv)\n {\n \tstatic const unsigned char null_sha1[20] = { 0, };\n \tconst char **pathspec;\n-\tint entries = read_cache();\n-\tint i;\n+\tconst char *prefix = setup_git_directory();\n+\tint entries, i;\n \n \twhile (1 < argc && argv[1][0] == '-') {\n \t\tif (!strcmp(argv[1], \"-p\") || !strcmp(argv[1], \"-u\"))\n@@ -95,8 +95,9 @@ int main(int argc, const char **argv)\n \t\targv++; argc--;\n \t}\n \n-\t/* Do we have a pathspec? */\n-\tpathspec = (argc > 1) ? argv + 1 : NULL;\n+\t/* Find the directory, and set up the pathspec */\n+\tpathspec = get_pathspec(prefix, argv + 1);\n+\tentries = read_cache();\n \n \tif (find_copies_harder && detect_rename != DIFF_DETECT_COPY)\n \t\tusage(diff_files_usage);\ndiff --git a/diff-tree.c b/diff-tree.c\n--- a/diff-tree.c\n+++ b/diff-tree.c\n@@ -395,16 +395,25 @@ static int diff_tree_stdin(char *line)\n \treturn diff_tree_commit(commit, line);\n }\n \n+static int count_paths(const char **paths)\n+{\n+\tint i = 0;\n+\twhile (*paths++)\n+\t\ti++;\n+\treturn i;\n+}\n+\n static const char diff_tree_usage[] =\n \"git-diff-tree [--stdin] [-m] [-s] [-v] [--pretty] [-t] \"\n \"[<common diff options>] <tree-ish> <tree-ish>\"\n COMMON_DIFF_OPTIONS_HELP;\n \n-int main(int argc, const char **argv)\n+int main(int argc, char **argv)\n {\n \tint nr_sha1;\n \tchar line[1000];\n \tunsigned char sha1[2][20];\n+\tconst char *prefix = setup_git_directory();\n \n \tnr_sha1 = 0;\n \tfor (;;) {\n@@ -523,11 +532,11 @@ int main(int argc, const char **argv)\n \tif (find_copies_harder && detect_rename != DIFF_DETECT_COPY)\n \t\tusage(diff_tree_usage);\n \n-\tif (argc > 0) {\n+\tpaths = get_pathspec(prefix, argv);\n+\tif (paths) {\n \t\tint i;\n \n-\t\tpaths = argv;\n-\t\tnr_paths = argc;\n+\t\tnr_paths = count_paths(paths);\n \t\tpathlens = xmalloc(nr_paths * sizeof(int));\n \t\tfor (i=0; i<nr_paths; i++)\n \t\t\tpathlens[i] = strlen(paths[i]);\ndiff --git a/git-diff-script b/git-diff-script\n--- a/git-diff-script\n+++ b/git-diff-script\n@@ -1,7 +1,5 @@\n #!/bin/sh\n-. git-sh-setup-script || die \"Not a git archive\"\n-\n-rev=($(git-rev-parse --revs-only \"$@\"))\n+rev=($(git-rev-parse --revs-only \"$@\")) || exit\n flags=($(git-rev-parse --no-revs --flags \"$@\"))\n files=($(git-rev-parse --no-revs --no-flags \"$@\"))\n case \"${#rev[*]}\" in\ndiff --git a/rev-parse.c b/rev-parse.c\n--- a/rev-parse.c\n+++ b/rev-parse.c\n@@ -134,7 +134,8 @@ int main(int argc, char **argv)\n {\n \tint i, as_is = 0;\n \tunsigned char sha1[20];\n-\n+\tconst char *prefix = setup_git_directory();\n+\t\n \tfor (i = 1; i < argc; i++) {\n \t\tchar *arg = argv[i];\n \t\tchar *dotdot;\n@@ -189,6 +190,10 @@ int main(int argc, char **argv)\n \t\t\t\tfor_each_ref(show_reference);\n \t\t\t\tcontinue;\n \t\t\t}\n+\t\t\tif (!strcmp(arg, \"--show-prefix\")) {\n+\t\t\t\tputs(prefix);\n+\t\t\t\tcontinue;\n+\t\t\t}\n \t\t\tshow_arg(arg);\n \t\t\tcontinue;\n \t\t}\ndiff --git a/setup.c b/setup.c\nnew file mode 100644\n--- /dev/null\n+++ b/setup.c\n@@ -0,0 +1,110 @@\n+#include \"cache.h\"\n+\n+const char **get_pathspec(const char *prefix, char **pathspec)\n+{\n+\tchar *entry = *pathspec;\n+\tchar **p;\n+\tint prefixlen;\n+\n+\tif (!prefix) {\n+\t\tchar **p;\n+\t\tif (!entry)\n+\t\t\treturn NULL;\n+\t\tp = pathspec;\n+\t\tdo {\n+\t\t\tif (*entry != '.')\n+\t\t\t\tcontinue;\n+\t\t\t/* fixup ? */\n+\t\t} while ((entry = *++p) != NULL);\n+\t\treturn (const char **) pathspec;\n+\t}\n+\n+\tif (!entry) {\n+\t\tstatic const char *spec[2];\n+\t\tspec[0] = prefix;\n+\t\tspec[1] = NULL;\n+\t\treturn spec;\n+\t}\n+\n+\t/* Otherwise we have to re-write the entries.. */\n+\tprefixlen = strlen(prefix);\n+\tp = pathspec;\n+\tdo {\n+\t\tint speclen, len = prefixlen;\n+\t\tchar *n;\n+\n+\t\tfor (;;) {\n+\t\t\tif (!strcmp(entry, \".\")) {\n+\t\t\t\tentry++;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tif (!strncmp(entry, \"./\", 2)) {\n+\t\t\t\tentry += 2;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif (!strncmp(entry, \"../\", 3)) {\n+\t\t\t\tdo {\n+\t\t\t\t\tif (!len)\n+\t\t\t\t\t\tdie(\"'%s' is outside repository\", *p);\n+\t\t\t\t\tlen--;\n+\t\t\t\t} while (len && prefix[len-1] != '/');\n+\t\t\t\tentry += 3;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t\tspeclen = strlen(entry);\n+\t\tn = xmalloc(speclen + len + 1);\n+\t\t\n+\t\tmemcpy(n, prefix, len);\n+\t\tmemcpy(n + len, entry, speclen+1);\n+\t\t*p = n;\n+\t} while ((entry = *++p) != NULL);\n+\treturn (const char **) pathspec;\n+}\n+\n+const char *setup_git_directory(void)\n+{\n+\tstatic char cwd[PATH_MAX+1];\n+\tint len, offset;\n+\n+\t/*\n+\t * If GIT_DIR is set explicitly, we're not going\n+\t * to do any discovery\n+\t */\n+\tif (gitenv(GIT_DIR_ENVIRONMENT))\n+\t\treturn NULL;\n+\n+\tif (!getcwd(cwd, sizeof(cwd)) || cwd[0] != '/')\n+\t\tdie(\"Unable to read current working directory\");\n+\n+\toffset = len = strlen(cwd);\n+\tfor (;;) {\n+\t\t/*\n+\t\t * We always want to see a .git/HEAD and a .git/refs/\n+\t\t * subdirectory\n+\t\t */\n+\t\tif (!access(\".git/HEAD\", R_OK) && !access(\".git/refs/\", X_OK)) {\n+\t\t\t/*\n+\t\t\t * Then we need either a GIT_OBJECT_DIRECTORY define\n+\t\t\t * or a .git/objects/ directory\n+\t\t\t */\n+\t\t\tif (gitenv(DB_ENVIRONMENT) || !access(\".git/objects/\", X_OK))\n+\t\t\t\tbreak;\n+\t\t}\n+\t\tchdir(\"..\");\n+\t\tdo {\n+\t\t\tif (!offset)\n+\t\t\t\tdie(\"Not a git repository\");\n+\t\t} while (cwd[--offset] != '/');\n+\t}\n+\n+\tif (offset == len)\n+\t\treturn NULL;\n+\n+\t/* Make \"offset\" point to past the '/', and add a '/' at the end */\n+\toffset++;\n+\tcwd[len++] = '/';\n+\tcwd[len] = 0;\n+\treturn cwd + offset;\n+}\n"},{"id":"7408","messageId":"7vwtml490s.fsf@assigned-by-dhcp.cox.net","threadId":"1542","inReplyTo":"Pine.LNX.4.58.0508161803250.3553@g5.osdl.org","subject":"Re: [RFC PATCH] Add support for figuring out where in the git archive we are","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-17T02:00:51Z","receivedAt":"2005-08-17T02:00:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> Mostly done. It actually works from inside subdirectories, but \".\" at the\n> top-level is still not done. Small detail. Will fix later. But it would\n> help if you would apply this, since I'm going to be off for dinner..\n\nMerged, pushed out, and tested.  Ouch.  Fails on t0000 test.\n\nNext time I'll do merge, test, reject and push out, in that\norder.\n"},{"id":"7411","messageId":"Pine.LNX.4.58.0508161946350.3553@g5.osdl.org","threadId":"1542","inReplyTo":"7vwtml490s.fsf@assigned-by-dhcp.cox.net","subject":"Re: [RFC PATCH] Add support for figuring out where in the git archive we are","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-08-17T02:50:37Z","receivedAt":"2005-08-17T02:50:37Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 16 Aug 2005, Junio C Hamano wrote:\n> \n> Merged, pushed out, and tested.  Ouch.  Fails on t0000 test.\n\nIt's because the new git-diff-files expects there to be a valid readable \n.git/HEAD, and is unhappy since the test hasn't updated HEAD.\n\nThis trivial patch fixes it.\n\n\t\tLinus\n----\nFix test failure due to overly strict .git directory tests\n\nWe may not actually have a valid HEAD at all times, so relax the validity \ntests for a .git subdirectory accordingly.\n\nSigned-off-by: Linus Torvalds <torvalds@osdl.org>\n-----\ndiff --git a/setup.c b/setup.c\n--- a/setup.c\n+++ b/setup.c\n@@ -81,10 +81,9 @@ const char *setup_git_directory(void)\n \toffset = len = strlen(cwd);\n \tfor (;;) {\n \t\t/*\n-\t\t * We always want to see a .git/HEAD and a .git/refs/\n-\t\t * subdirectory\n+\t\t * We always want to see a .git/refs/ subdirectory\n \t\t */\n-\t\tif (!access(\".git/HEAD\", R_OK) && !access(\".git/refs/\", X_OK)) {\n+\t\tif (!access(\".git/refs/\", X_OK)) {\n \t\t\t/*\n \t\t\t * Then we need either a GIT_OBJECT_DIRECTORY define\n \t\t\t * or a .git/objects/ directory\n"},{"id":"7418","messageId":"7vmznh4244.fsf@assigned-by-dhcp.cox.net","threadId":"1542","inReplyTo":"Pine.LNX.4.58.0508161946350.3553@g5.osdl.org","subject":"Re: [RFC PATCH] Add support for figuring out where in the git archive we are","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-17T04:30:03Z","receivedAt":"2005-08-17T04:30:03Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> On Tue, 16 Aug 2005, Junio C Hamano wrote:\n>> \n>> Merged, pushed out, and tested.  Ouch.  Fails on t0000 test.\n>\n> It's because the new git-diff-files expects there to be a valid readable \n> .git/HEAD, and is unhappy since the test hasn't updated HEAD.\n\nAh, good catch.  So with this the beginning of the tutorial\nshould work; I think we introduce diff-files before making a\ncommit.  Thanks.\n"}]}