From: Dana How <danahow@gmail•com>
To: Junio C Hamano <junkio@cox•net>
Cc: Git Mailing List <git@vger•kernel.org>, danahow@gmail•com
Subject: [PATCH v3] Support ent:relative_path
Date: Fri, 04 May 2007 17:47:08 -0700 [thread overview]
Message-ID: <463BD40C.6080909@gmail.com> (raw)
Most commands accept relative paths, but this is
not true of arguments in ent:path format. This
patch makes all of the following git-show commands
work in the git source tree (not just the first):
% cd xdiff
% git-show v1.5.2-rc0:xdiff/xemit.h
% git-show v1.5.2-rc0:./xemit.h
% git-show v1.5.2-rc0:../sha1_name.c
It also adds ent:?string as a synonym for ent:/string .
This makes the following changes possible later:
ent:/path is an absolute path and ent:path is relative.
Signed-off-by: Dana L. How <danahow@gmail•com>
---
cache.h | 1 +
setup.c | 5 +++-
sha1_name.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 79 insertions(+), 5 deletions(-)
diff --git a/cache.h b/cache.h
index 8e76152..53507d9 100644
--- a/cache.h
+++ b/cache.h
@@ -215,6 +215,7 @@ extern char *get_graft_file(void);
#define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
+extern const char *prefix_to_cwd;
extern const char **get_pathspec(const char *prefix, const char **pathspec);
extern const char *setup_git_directory_gently(int *);
extern const char *setup_git_directory(void);
diff --git a/setup.c b/setup.c
index a45ea83..46ae6e3 100644
--- a/setup.c
+++ b/setup.c
@@ -1,5 +1,7 @@
#include "cache.h"
+const char *prefix_to_cwd;
+
const char *prefix_path(const char *prefix, int len, const char *path)
{
const char *orig = path;
@@ -252,7 +254,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
cwd[len++] = '/';
cwd[len] = 0;
inside_git_dir = !prefixcmp(cwd + offset, ".git/");
- return cwd + offset;
+ prefix_to_cwd = cwd + offset;
+ return prefix_to_cwd;
}
int git_config_perm(const char *var, const char *value)
diff --git a/sha1_name.c b/sha1_name.c
index 55f25a2..dd415c1 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -593,6 +593,67 @@ static int handle_one_ref(const char *path,
}
/*
+ * Future: nonzero to assume relative paths
+ */
+#define ENT_COLON_ASSUME_RELATIVE 0
+
+/*
+ * Modify path into a full absolute path with no leading "/"
+ * and no "." or "..". If we can't,
+ * leave input unaltered for client's error message.
+ */
+static void prepend_prefix(const char **cp, int *namelen)
+{
+ char *t, *t2;
+ const char *cp2 = *cp;
+ int type, namelen2 = *namelen;
+ static char fullpath[PATH_MAX];
+ int fixup = strstr(cp2, "/./") || strstr(cp2, "/../");
+ for (type = 4; --type > 0; )
+ if (namelen2 > type && !memcmp(cp2, "../" + 3 - type, type))
+ break;
+
+ /* handle simple cases else create absolute path */
+ fullpath[0] = 0;
+ if ((type == 0 && !ENT_COLON_ASSUME_RELATIVE) || type == 1) {
+ if (!fixup) goto done;
+ } else
+ if (prefix_to_cwd) {
+ namelen2 += strlen(prefix_to_cwd);
+ if (namelen2 >= PATH_MAX)
+ die("path too long");
+ strcpy(fullpath, prefix_to_cwd);
+ type = 0;
+ } else
+ if (type == 2) {
+ if (!fixup) goto done;
+ } else
+ if (type == 3)
+ return; /* client will complain */
+ cp2 = strcat(fullpath, cp2);
+
+ while ((t = strstr(cp2, "/./")) != NULL)
+ memmove(t, t + 2, (namelen2 -= 2) - (t - cp2) + 1);
+
+ while ((t = strstr(cp2, "/../")) != NULL) {
+ if (t == cp2 || (t == cp2 + 1 && t[-1] == '.'))
+ return; /* client will complain */
+ for (t2 = t; --t2 >= cp2 && *t2 != '/'; )
+ /* nothing */;
+ if (t2 < cp2) {
+ namelen2 -= t + 4 - cp2;
+ cp2 = t + 4;
+ } else {
+ memmove(t2, t + 3, namelen2 - (t + 3 - cp2) + 1);
+ namelen2 -= t + 3 - t2;
+ }
+ }
+
+done: *cp = cp2 + type;
+ *namelen = namelen2 - type;
+}
+
+/*
* This interprets names like ':/Initial revision of "git"' by searching
* through history and returning the first commit whose message starts
* with the given string.
@@ -647,6 +708,11 @@ int get_sha1(const char *name, unsigned char *sha1)
return get_sha1_with_mode(name, sha1, &unused);
}
+/*
+ * Future: change to '?'
+ */
+#define ENT_COLON_OLD_SEARCH '/'
+
int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)
{
int ret, bracket_depth;
@@ -666,7 +732,8 @@ int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)
int stage = 0;
struct cache_entry *ce;
int pos;
- if (namelen > 2 && name[1] == '/')
+ if (namelen > 2 &&
+ (name[1] == ENT_COLON_OLD_SEARCH || name[1] == '?'))
return get_sha1_oneline(name + 2, sha1);
if (namelen < 3 ||
name[2] != ':' ||
@@ -681,6 +748,7 @@ int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)
read_cache();
if (active_nr < 0)
return -1;
+ prepend_prefix(&cp, &namelen);
pos = cache_name_pos(cp, namelen);
if (pos < 0)
pos = -pos - 1;
@@ -708,9 +776,11 @@ 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)) {
+ namelen -= ++cp - name;
+ prepend_prefix(&cp, &namelen);
+ return get_tree_entry(tree_sha1, cp, sha1, mode);
+ }
}
return ret;
}
--
1.5.2.rc0.787.g0014
next reply other threads:[~2007-05-05 0:47 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-05-05 0:47 Dana How [this message]
2007-05-05 1:11 ` [PATCH v3] Support ent:relative_path Jakub Narebski
2007-05-05 1:29 ` Johannes Schindelin
2007-05-05 3:30 ` Shawn O. Pearce
2007-05-05 19:32 ` Martin Waitz
2007-05-05 20:17 ` Junio C Hamano
2007-05-05 21:18 ` Martin Waitz
2007-05-06 0:59 ` Johannes Schindelin
2007-05-06 18:52 ` Martin Waitz
2007-05-06 23:09 ` Johannes Schindelin
2007-05-05 20:37 ` Alex Riesen
2007-05-05 3:38 ` Junio C Hamano
2007-05-05 6:46 ` Dana How
2007-05-05 8:03 ` Alex Riesen
2007-05-05 14:39 ` Johannes Schindelin
2007-05-06 6:38 ` Junio C Hamano
2007-05-06 15:14 ` Johannes Schindelin
2007-05-06 17:35 ` Junio C Hamano
2007-05-06 23:12 ` Johannes Schindelin
2007-05-07 0:18 ` Junio C Hamano
2007-05-07 0:37 ` Dana How
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=463BD40C.6080909@gmail.com \
--to=danahow@gmail$(echo .)com \
--cc=git@vger$(echo .)kernel.org \
--cc=junkio@cox$(echo .)net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox