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 don't remember either if the idea was rejected or nobody bothered
to implement it. Anyway, here it is (for demostration only because it
needs two minor patches to work). Comments?
--
Duy
sha1_name.c | 30 +++++++++++++++++++++++++++---
1 files changed, 27 insertions(+), 3 deletions(-)
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;
+ }
+ }
else {
stage = name[1] - '0';
cp = name + 3;
}
- namelen = namelen - (cp - name);
+ namelen = strlen(cp);
strncpy(oc->path, cp,
sizeof(oc->path));@@ -1096,12 +1106,14 @@ int get_sha1_with_context_1(const char *name, unsigned char *sha1,
break;
if (ce_stage(ce) == stage) {
hashcpy(sha1, ce->sha1);
+ free(new_path);
return 0;
}
pos++;
}
if (!gently)
diagnose_invalid_index_path(stage, prefix, cp);
+ free(new_path);
return -1;
}
for (cp = name, bracket_depth = 0; *cp; cp++) {@@ -1122,6 +1134,17 @@ int get_sha1_with_context_1(const char *name, unsigned char *sha1,
}
if (!get_sha1_1(name, cp-name, tree_sha1)) {
const char *filename = cp+1;
+ char *new_filename = NULL;
+
+ if (startup_info &&
+ filename[0] == '.' &&
+ (filename[1] == '/' ||
+ (filename[1] == '.' && filename[2] == '/'))) {
+ new_filename = prefix_path(startup_info->prefix,
+ strlen(startup_info->prefix),
+ filename);
+ filename = new_filename;
+ }
ret = get_tree_entry(tree_sha1, filename, sha1, &oc->mode);
if (!gently) {
diagnose_invalid_sha1_path(prefix, filename,@@ -1133,6 +1156,7 @@ int get_sha1_with_context_1(const char *name, unsigned char *sha1,
sizeof(oc->path));
oc->path[sizeof(oc->path)-1] = '\0';
+ free(new_filename);
return ret;
} else {
if (!gently)--
1.7.3.2.210.g045198