Thread (1 message) 1 message, 1 author, 2016-06-15

Re: [PATCH] get_sha1: support relative path "<obj>:<sth>" syntax

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:50:13

Nguyễn Thái Ngọc Duy  [off-list ref] writes:
Currently :path and ref:path can be used to refer to a specific object
in index or ref respectively. "path" component is absolute path. This
patch allows "path" to be written as "./path" or "../path", which is
relative to user's original cwd.

This does not work in commands that startup_info is NULL
(i.e. non-builtin ones).
---
 On Wed, Nov 10, 2010 at 07:26:20AM -0800, Jakub Narebski wrote:
 > The <obj>:<sth> is (with single exception of ':/<regexp>') about
 > selecting subitem (path): <tree-ish>:<path>, [:<stage>]:<path>

 I feel the urge of keeping ':./path' and ':../path' out of this
 competition.

 The idea is old although I don't remember if anybody has made any
 attempt to realize it: use './' and '../' to specify the given path
 is relative, not absolute.
I've had this queued for some time, with help from Jonathan, and am happy
about it in general, but after taking another look at it, noticed one
minor thing.
quoted hunk
diff --git a/sha1_name.c b/sha1_name.c
index 484081d..791608d 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -1060,25 +1060,35 @@ int get_sha1_with_context_1(const char *name, unsigned char *sha1,
 	if (!ret)
 		return ret;
 	/* sha1:path --> object name of path in ent sha1
-	 * :path -> object name of path in index
+	 * :path -> object name of absolute path in index
+	 * :./path -> object name of path relative to cwd in index
 	 * :[0-3]:path -> object name of path in index at stage
 	 * :/foo -> recent commit matching foo
 	 */
 	if (name[0] == ':') {
 		int stage = 0;
 		struct cache_entry *ce;
+		char *new_path = NULL;
 		int pos;
 		if (namelen > 2 && name[1] == '/')
 			return get_sha1_oneline(name + 2, sha1);
 		if (namelen < 3 ||
 		    name[2] != ':' ||
-		    name[1] < '0' || '3' < name[1])
+		    name[1] < '0' || '3' < name[1]) {
 			cp = name + 1;
+			if (startup_info && cp[0] == '.' &&
+			    (cp[1] == '/' || (cp[1] == '.' && cp[2] == '/'))) {
+				new_path = prefix_path(startup_info->prefix,
+						       strlen(startup_info->prefix),
+						       cp);
+				cp = new_path;
+			}
+		}
This deals with ":$foo" (path $foo in the index), which is a shorthand for
":0:$foo" (the path $foo at stage #0 in the index).  However...
 		else {
 			stage = name[1] - '0';
 			cp = name + 3;
... this side does not do anything about it, so:

	$ cd Documentation
        ... working for a while ...
        $ git merge another_branch
        ... oops, got conflicts at ../Makefile
	$ git show :2:../Makefile

won't work.

Besides, it is a bad idea to make ":../Makefile" work while leaving
its longhand ":0:../Makefile" not.

I think it is just the matter of moving "if (startup-info)..." logic
outside the "is the :$path lacking an explicit stage number" block and
having it after that if/else, no?
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help