git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH] Add support for figuring out where in the git archive we are
@ 2005-08-16 22:45 Linus Torvalds
  2005-08-16 23:10 ` Yasushi SHOJI
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Linus Torvalds @ 2005-08-16 22:45 UTC (permalink / raw)
  To: Junio C Hamano, Git Mailing List

    
This does only "git-diff-cache" and "git-diff-files", but the concept
should work for any command that uses the working tree.

Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
This is really partly a serious patch, but also just a query whether 
people would want git to work in subdirectories, not just the top-level 
directory.

So you can be in linux/drivers, and if you do a

	git-diff-files -p char

then it will automatically be turned into the full pathname, and do the
right thing (ie do a diff of drivers/char only).

I didn't want to do it originally, but that was largely a complexity
issue, and an issue of there being many more things up in the air at that
time. Now, things have calmed down a bit, the interfaces are fairly
stable, and it turns out to be not that difficult to just walk up the
chain of directories until we hit the one that has the ".git" directory in
it.

I only converted "git-diff-files" and "git-diff-cache" to do this, because
so far it's a technology demo. And the "git-diff-script" file (and the
git-sh-setup-script in particular) does _not_ accept this "automatically 
figure out where we are" thing, so it's really only the native git diff 
commands that do it.

But if people think it's a good idea, I can pretty trivially convert the 
rest. It's done in a way that makes it very easy to convert programs to 
take advantage of the auto-git-directory-finding thing.

If you use the GIT_DIR environment variable approach, it assumes that all
filenames you give it are absolute and acts the way it always did before.

Comments? Like? Dislike?

		Linus

diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -97,7 +97,7 @@ LIB_H=cache.h object.h blob.h tree.h com
 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
diff --git a/cache.h b/cache.h
--- a/cache.h
+++ b/cache.h
@@ -140,6 +140,8 @@ extern char *get_graft_file(void);
 
 #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
 
+extern char **setup_git_directory(char **pathspec);
+
 #define alloc_nr(x) (((x)+16)*3/2)
 
 /* Initialize and use the cache information */
diff --git a/diff-cache.c b/diff-cache.c
--- a/diff-cache.c
+++ b/diff-cache.c
@@ -179,15 +179,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 +262,16 @@ int main(int argc, const char **argv)
 		usage(diff_cache_usage);
 	}
 
+	pathspec = setup_git_directory(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
--- a/diff-files.c
+++ b/diff-files.c
@@ -45,8 +45,7 @@ int main(int argc, const char **argv)
 {
 	static const unsigned char null_sha1[20] = { 0, };
 	const char **pathspec;
-	int entries = read_cache();
-	int i;
+	int entries, i;
 
 	while (1 < argc && argv[1][0] == '-') {
 		if (!strcmp(argv[1], "-p") || !strcmp(argv[1], "-u"))
@@ -95,8 +94,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 = setup_git_directory(argv + 1);
+	entries = read_cache();
 
 	if (find_copies_harder && detect_rename != DIFF_DETECT_COPY)
 		usage(diff_files_usage);
diff --git a/setup.c b/setup.c
new file mode 100644
--- /dev/null
+++ b/setup.c
@@ -0,0 +1,66 @@
+#include "cache.h"
+
+char **setup_git_directory(char **pathspec)
+{
+	static char *spec[2], **p;
+	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 *pathspec ? pathspec : 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 *pathspec ? pathspec : NULL;
+
+	/* Make "offset" point to past the '/', and add a '/' at the end */
+	offset++;
+	cwd[len++] = '/';
+	cwd[len] = 0;
+
+	/* An empty pathspec gets turned into the directory we were in */
+	if (!*pathspec) {
+		spec[0] = cwd + offset;
+		spec[1] = NULL;
+		return spec;
+	}
+
+	/* Otherwise we have to re-write the entries.. */
+	p = pathspec;
+	do {
+		int speclen = strlen(*p);
+		char *n = xmalloc(speclen + len - offset + 1);
+		memcpy(n, cwd + offset, len - offset);
+		memcpy(n + len - offset, *p, speclen+1);
+		*p = n;
+	} while (*++p);
+	return pathspec;
+}
+

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2005-08-17  4:30 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-08-16 22:45 [RFC PATCH] Add support for figuring out where in the git archive we are Linus Torvalds
2005-08-16 23:10 ` Yasushi SHOJI
2005-08-16 23:40 ` Junio C Hamano
2005-08-17  0:01   ` Linus Torvalds
2005-08-17  0:16     ` Junio C Hamano
2005-08-17  1:06       ` Linus Torvalds
2005-08-17  2:00         ` Junio C Hamano
2005-08-17  2:50           ` Linus Torvalds
2005-08-17  4:30             ` Junio C Hamano
2005-08-17  0:25 ` Daniel Barkalow

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).