git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v0] sha1_name: grok <revision>:./<relative-path>

From
Johannes Schindelin <johannes.schindelin@gmx.de>
Date
Dec 19, 2007, 13:40 UTC
Message-ID
<Pine.LNX.4.64.0712191334460.23902@racer.site>
In-Reply-To
<56b7f5510712181752s7ecebca9m32794c635cba9fd@mail.gmail.com>

When you are in a deeply-nested directory structure, and just want to reference a blob in a past revision, it can be pretty slow to type out "HEAD~29:/bla/blub/.../that-file".

This patch makes "HEAD~29:./that-file" substitute the current prefix for "./". If there is not working directory, the prefix is empty.

Note that this patch does not handle "../", and neither do I plan to.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
	On Tue, 18 Dec 2007, Dana How wrote:
	> On Dec 18, 2007 5:16 PM, Linus Torvalds 
	>			<torvalds@linux-foundation.org> wrote:
	> > On Tue, 18 Dec 2007, Dana How wrote:
	> >
	> > > The cases we are talking about are all subtrees of the 
	> > > working tree. There is a useful cwd suffix.
	> >
	> > No.
	> >
	> > The cases we're talking of are *not* subtrees of the working 
	> > tree.
	> >
	> > The SHA1 of a commit may well be a totally disjoint tree. Try 
	> > it in the git repository with something like
	> 
	> Agreed,  but note you wrote *may*.
	Okay, this is a proposed patch.  It leaves the existing 
	"HEAD:<path>" handling alone, and only touches "HEAD:./<path>", 
	which would have been invalid anyway (except if you hacked your 
	objects database to include a tree named ".").
	Note: this patch is not meant for application directly.  It should 
	be split into get_current_prefix() as one patch, and the 
	sha1_name.c stuff as the second.  (Not only to boost my ohloh 
	statistics, but because they are logically two separate things.)
	Note, too: this is a quick and little-bit-dirty patch, not well 
	tested.  Particularly, I was unable to trigger the "No <path> in 
	<rev>" error path, so I am not confident that this handling is 
	correct.
	Note also: in contrast to Alex' approach, this will not only work 
	for git-show, but for all callers of get_sha1().
 cache.h     |    1 +
 setup.c     |   16 +++++++++++++---
 sha1_name.c |   17 ++++++++++++++---
 3 files changed, 28 insertions(+), 6 deletions(-)
diff --git a/cache.h b/cache.h
index 39331c2..83a2c31 100644
--- a/cache.h
+++ b/cache.h
@@ -225,6 +225,7 @@ extern char *get_index_file(void);
 extern char *get_graft_file(void);
 extern int set_git_dir(const char *path);
 extern const char *get_git_work_tree(void);
+extern const char *get_current_prefix(void);
 
 #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
 
diff --git a/setup.c b/setup.c
index b59dbe7..fb9b680 100644
--- a/setup.c
+++ b/setup.c
@@ -3,6 +3,12 @@
 
 static int inside_git_dir = -1;
 static int inside_work_tree = -1;
+static const char *current_prefix;
+
+const char *get_current_prefix()
+{
+	return current_prefix;
+}
 
 const char *prefix_path(const char *prefix, int len, const char *path)
 {
@@ -267,6 +273,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
 				/* config may override worktree */
 				if (check_repository_format_gently(nongit_ok))
 					return NULL;
+				current_prefix = retval;
 				return retval;
 			}
 			if (check_repository_format_gently(nongit_ok))
@@ -279,7 +286,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
 			if (chdir(work_tree_env) < 0)
 				die ("Could not chdir to %s", work_tree_env);
 			strcat(buffer, "/");
-			return retval;
+			current_prefix = retval;
+			return current_prefix;
 		}
 		if (nongit_ok) {
 			*nongit_ok = 1;
@@ -339,7 +347,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
 	offset++;
 	cwd[len++] = '/';
 	cwd[len] = 0;
-	return cwd + offset;
+	current_prefix = cwd + offset;
+	return current_prefix;
 }
 
 int git_config_perm(const char *var, const char *value)
@@ -396,7 +405,8 @@ const char *setup_git_directory(void)
 		if (retval && chdir(retval))
 			die ("Could not jump back into original cwd");
 		rel = get_relative_cwd(buffer, PATH_MAX, get_git_work_tree());
-		return rel && *rel ? strcat(rel, "/") : NULL;
+		current_prefix = rel && *rel ? strcat(rel, "/") : NULL;
+		return current_prefix;
 	}
 
 	return retval;
diff --git a/sha1_name.c b/sha1_name.c
index 13e1164..6f61d26 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -712,9 +712,20 @@ int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)
 	}
 	if (*cp == ':') {
 		unsigned char tree_sha1[20];
-		if (!get_sha1_1(name, cp-name, tree_sha1))
-			return get_tree_entry(tree_sha1, cp+1, sha1,
-					      mode);
+		if (!get_sha1_1(name, cp-name, tree_sha1)) {
+			const char *prefix;
+			if (!prefixcmp(cp + 1, "./") &&
+					(prefix = get_current_prefix())) {
+				unsigned char subtree_sha1[20];
+				if (get_tree_entry(tree_sha1, prefix,
+							subtree_sha1, mode))
+					return error("No '%s' in '%.*s'",
+							prefix, cp-name, name);
+				memcpy(tree_sha1, subtree_sha1, 20);
+				cp += 2;
+			}
+			return get_tree_entry(tree_sha1, cp+1, sha1, mode);
+		}
 	}
 	return ret;
 }
-- 
1.5.4.rc0.72.g536e9
Previous: Jakub NarebskiNext: Jeff King
Message 29 of 43 in “log/show: relative pathnames do not work in rev:path”
  1. Alex RiesenDec 18, 2007
  2. Jakub NarebskiDec 18, 2007
  3. Alex RiesenDec 18, 2007
  4. Simple support for tree entry specification with relative pathnamesAlex Riesen, Dec 18, 2007
  5. Introduce pathexpand: syntax-level chdir into the given cwdAlex Riesen, Dec 18, 2007
  6. Use pathexpand to preparse the relative pathnames in blob referencesAlex Riesen, Dec 18, 2007
  7. Dana HowDec 18, 2007
  8. Jeff KingDec 19, 2007
  9. Dana HowDec 18, 2007
  10. Alex RiesenDec 18, 2007
  11. Jakub NarebskiDec 18, 2007
  12. Linus TorvaldsDec 18, 2007
  13. Dana HowDec 18, 2007
  14. Alex RiesenDec 18, 2007
  15. Junio C HamanoDec 18, 2007
  16. Dana HowDec 18, 2007
  17. Johannes SchindelinDec 18, 2007
  18. Junio C HamanoDec 19, 2007
  19. Alex RiesenDec 18, 2007
  20. Johannes SchindelinDec 18, 2007
  21. Dana HowDec 18, 2007
  22. Johannes SchindelinDec 18, 2007
  23. Linus TorvaldsDec 19, 2007
  24. Dana HowDec 19, 2007
  25. Alex RiesenDec 19, 2007
  26. Jakub NarebskiDec 19, 2007
  27. Dana HowDec 19, 2007
  28. Jakub NarebskiDec 19, 2007
  29. sha1_name: grok <revision>:./<relative-path>Johannes Schindelin, Dec 19, 2007
  30. Jeff KingDec 19, 2007
  31. Dana HowDec 19, 2007
  32. Alex RiesenDec 19, 2007
  33. Junio C HamanoDec 20, 2007
  34. Johannes SchindelinDec 20, 2007
  35. Nguyen Thai Ngoc DuyDec 21, 2007
  36. Junio C HamanoDec 21, 2007
  37. Nguyen Thai Ngoc DuyDec 21, 2007
  38. Johannes SchindelinDec 22, 2007
  39. Jakub NarebskiDec 18, 2007
  40. Dana HowDec 18, 2007
  41. Junio C HamanoDec 18, 2007
  42. Jakub NarebskiDec 18, 2007
  43. Alex RiesenDec 19, 2007

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.