From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org, tfransosi@gmail.com,
Junio C Hamano <gitster@pobox.com>
Cc: "Jonathan Niedier" <jrnieder@gmail.com>,
Matthieu.Moy@grenoble-inp.fr,
"Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH] get_sha1: support relative path ":path" syntax
Date: Mon, 15 Nov 2010 10:56:09 +0700 [thread overview]
Message-ID: <1289793369-10653-1-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <AANLkTimJKQ=xc7az+FEM+18aTxQ5zQ24q7pfChnSwt6f@mail.gmail.com>
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 for which startup_info is NULL
(i.e. non-builtin ones).
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
Fixed the error messages in resolve_relative_path()
sha1_name.c | 38 ++++++++++++++++++++++--
t/t1506-rev-parse-diagnosis.sh | 62 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 97 insertions(+), 3 deletions(-)
diff --git a/sha1_name.c b/sha1_name.c
index 484081d..1d227d5 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -1046,6 +1046,24 @@ int get_sha1_with_mode_1(const char *name, unsigned char *sha1, unsigned *mode,
return ret;
}
+static char *resolve_relative_path(const char *rel)
+{
+ if (prefixcmp(rel, "./") && prefixcmp(rel, "../"))
+ return NULL;
+
+ if (!startup_info)
+ die("Relative path syntax is not supported in this command.\n"
+ "Please report to git@vger.kernel.org.");
+
+ if (!is_inside_work_tree())
+ die("Relative path syntax can't be used outside working tree.");
+
+ /* die() inside prefix_path() if resolved path is outside worktree */
+ return prefix_path(startup_info->prefix,
+ startup_info->prefix ? strlen(startup_info->prefix) : 0,
+ rel);
+}
+
int get_sha1_with_context_1(const char *name, unsigned char *sha1,
struct object_context *oc,
int gently, const char *prefix)
@@ -1060,25 +1078,31 @@ 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;
+ new_path = resolve_relative_path(cp);
+ if (new_path)
+ 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 +1120,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 +1148,11 @@ 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;
+
+ new_filename = resolve_relative_path(filename);
+ if (new_filename)
+ filename = new_filename;
ret = get_tree_entry(tree_sha1, filename, sha1, &oc->mode);
if (!gently) {
diagnose_invalid_sha1_path(prefix, filename,
@@ -1133,6 +1164,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)
diff --git a/t/t1506-rev-parse-diagnosis.sh b/t/t1506-rev-parse-diagnosis.sh
index 0eeeb0e..f7a4076 100755
--- a/t/t1506-rev-parse-diagnosis.sh
+++ b/t/t1506-rev-parse-diagnosis.sh
@@ -31,6 +31,43 @@ test_expect_success 'correct file objects' '
test $HASH_file = $(git rev-parse :0:file.txt) )
'
+test_expect_success 'correct relative file objects (0)' '
+ git rev-parse :file.txt >expected &&
+ git rev-parse :./file.txt >result &&
+ test_cmp expected result
+'
+
+test_expect_success 'correct relative file objects (1)' '
+ git rev-parse HEAD:file.txt >expected &&
+ git rev-parse HEAD:./file.txt >result &&
+ test_cmp expected result
+'
+
+test_expect_success 'correct relative file objects (2)' '
+ (
+ cd subdir &&
+ git rev-parse HEAD:../file.txt >result &&
+ test_cmp ../expected result
+ )
+'
+
+test_expect_success 'correct relative file objects (3)' '
+ (
+ cd subdir &&
+ git rev-parse HEAD:../subdir/../file.txt >result &&
+ test_cmp ../expected result
+ )
+'
+
+test_expect_success 'correct relative file objects (4)' '
+ git rev-parse HEAD:subdir/file.txt >expected &&
+ (
+ cd subdir &&
+ git rev-parse HEAD:./file.txt >result &&
+ test_cmp ../expected result
+ )
+'
+
test_expect_success 'incorrect revision id' '
test_must_fail git rev-parse foobar:file.txt 2>error &&
grep "Invalid object name '"'"'foobar'"'"'." error &&
@@ -75,4 +112,29 @@ test_expect_success 'invalid @{n} reference' '
grep "fatal: Log for [^ ]* only has [0-9][0-9]* entries." error
'
+test_expect_success 'relative path not found' '
+ (
+ cd subdir &&
+ test_must_fail git rev-parse HEAD:./nonexistent.txt 2>error &&
+ grep subdir/nonexistent.txt error
+ )
+'
+
+test_expect_success 'relative path outside worktree' '
+ test_must_fail git rev-parse HEAD:../file.txt >output 2>error &&
+ test -z "$(cat output)" &&
+ grep "outside repository" error
+'
+
+test_expect_success 'relative path when cwd is outside worktree' '
+ test_must_fail git --git-dir=.git --work-tree=subdir rev-parse HEAD:./file.txt >output 2>error &&
+ test -z "$(cat output)" &&
+ grep "relative path syntax can.t be used outside working tree." error
+'
+
+test_expect_success 'relative path when startup_info is NULL' '
+ test_must_fail test-match-trees HEAD:./file.txt HEAD:./file.txt 2>error &&
+ grep "Relative path syntax is not supported in this command" error
+'
+
test_done
--
1.7.3.2.210.g045198
next prev parent reply other threads:[~2010-11-15 3:57 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-11-11 14:08 [PATCH 0/3] Support relative path in <blah>:path syntax Nguyễn Thái Ngọc Duy
2010-11-11 14:08 ` [PATCH 1/3] setup: save prefix (original cwd relative to toplevel) in startup_info Nguyễn Thái Ngọc Duy
2010-11-11 14:08 ` [PATCH 2/3] Make prefix_path() return char* without const Nguyễn Thái Ngọc Duy
2010-11-11 14:08 ` [PATCH 3/3] get_sha1: support relative path ":path" syntax Nguyễn Thái Ngọc Duy
2010-11-14 20:22 ` Thiago Farina
2010-11-15 3:56 ` Nguyễn Thái Ngọc Duy [this message]
2010-11-15 14:56 ` [PATCH] " Sverre Rabbelier
2010-11-15 17:29 ` Junio C Hamano
2010-11-15 18:59 ` Junio C Hamano
2010-11-28 3:37 ` Nguyễn Thái Ngọc Duy
2010-11-17 17:54 ` [PATCH 0/3] Support relative path in <blah>:path syntax Junio C Hamano
2010-11-18 1:47 ` Nguyen Thai Ngoc Duy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1289793369-10653-1-git-send-email-pclouds@gmail.com \
--to=pclouds@gmail.com \
--cc=Matthieu.Moy@grenoble-inp.fr \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=jrnieder@gmail.com \
--cc=tfransosi@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.