{
unsigned char sha1[20];
unsigned mode;
- /* try a detailed diagnostic ... */
- get_sha1_with_mode_1(arg, sha1, &mode, 0, prefix);
+
+ /*
+ * Saying "'(icase)foo' does not exist in the index" when the
+ * user gave us ":(icase)foo" is just stupid. A magic pathspec
+ * begins with a colon and is followed by a non-alnum; do not
+ * let get_sha1_with_mode_1(only_to_die=1) to even trigger.
+ */
+ if (!(arg[0] == ':' && !isalnum(arg[1])))
+ /* try a detailed diagnostic ... */
+ get_sha1_with_mode_1(arg, sha1, &mode, 1, prefix);
+
/* ... or fall back the most general message. */
die("ambiguous argument '%s': unknown revision or path not in the working tree.\n"
"Use '--' to separate paths from revisions", arg);
* Possible future magic semantics include stuff like:
*
* { PATHSPEC_NOGLOB, '!', "noglob" },
+ * { PATHSPEC_ICASE, '\0', "icase" },
* { PATHSPEC_RECURSIVE, '*', "recursive" },
* { PATHSPEC_REGEXP, '\0', "regexp" },
*
*/
#define PATHSPEC_FROMTOP (1<<0)
-#define PATHSPEC_ICASE (1<<1)
-struct pathspec_magic {
+static struct pathspec_magic {
unsigned bit;
char mnemonic; /* this cannot be ':'! */
const char *name;
} pathspec_magic[] = {
{ PATHSPEC_FROMTOP, '/', "top" },
- { PATHSPEC_ICASE, '\0', "icase" },
};
/*
* the prefix part must always match literally, and a single stupid
* string cannot express such a case.
*/
-const char *prefix_pathspec(const char *prefix, int prefixlen, const char *elt)
+static const char *prefix_pathspec(const char *prefix, int prefixlen, const char *elt)
{
unsigned magic = 0;
const char *copyfrom = elt;
- const char *retval;
- int i, free_source = 0;
+ int i;
if (elt[0] != ':') {
; /* nothing to do */
}
if (*copyfrom == ')')
copyfrom++;
- } else if (!elt[1]) {
- /* Just ':' -- no element! */
- return NULL;
} else {
/* shorthand */
for (copyfrom = elt + 1;
copyfrom++;
}
- if (magic & PATHSPEC_ICASE) {
- struct strbuf sb = STRBUF_INIT;
- for (i = 0; copyfrom[i]; i++) {
- int ch = copyfrom[i];
- if (('a' <= ch && ch <= 'z') ||
- ('A' <= ch && ch <= 'Z')) {
- strbuf_addf(&sb, "[%c%c]",
- tolower(ch), toupper(ch));
- } else {
- strbuf_addch(&sb, ch);
- }
- }
- if (sb.len) {
- free_source = 1;
- copyfrom = strbuf_detach(&sb, NULL);
- }
- }
-
if (magic & PATHSPEC_FROMTOP)
- retval = xstrdup(copyfrom);
+ return xstrdup(copyfrom);
else
- retval = prefix_path(prefix, prefixlen, copyfrom);
- if (free_source)
- free((char *)copyfrom);
- return retval;
+ return prefix_path(prefix, prefixlen, copyfrom);
}
const char **get_pathspec(const char *prefix, const char **pathspec)
return pathspec;
}
+const char *pathspec_prefix(const char *prefix, const char **pathspec)
+{
+ const char **p, *n, *prev;
+ unsigned long max;
+
+ if (!pathspec)
+ return prefix ? xmemdupz(prefix, strlen(prefix)) : NULL;
+
+ prev = NULL;
+ max = PATH_MAX;
+ for (p = pathspec; (n = *p) != NULL; p++) {
+ int i, len = 0;
+ for (i = 0; i < max; i++) {
+ char c = n[i];
+ if (prev && prev[i] != c)
+ break;
+ if (!c || c == '*' || c == '?')
+ break;
+ if (c == '/')
+ len = i+1;
+ }
+ prev = n;
+ if (len < max) {
+ max = len;
+ if (!max)
+ break;
+ }
+ }
+
+ return max ? xmemdupz(prev, max) : NULL;
+}
+
/*
* Test if it looks like we're at a git directory.
* We want to see:
const char *slash;
struct stat st;
int fd;
- size_t len;
+ ssize_t len;
if (stat(path, &st))
return NULL;
const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);
const char *worktree;
char *gitfile;
+ int offset;
if (PATH_MAX - 40 < strlen(gitdirenv))
die("'$%s' too big", GIT_DIR_ENVIRONMENT);
return NULL;
}
- if (!prefixcmp(cwd, worktree) &&
- cwd[strlen(worktree)] == '/') { /* cwd inside worktree */
+ offset = dir_inside_of(cwd, worktree);
+ if (offset >= 0) { /* cwd inside worktree? */
set_git_dir(real_path(gitdirenv));
if (chdir(worktree))
die_errno("Could not chdir to '%s'", worktree);
cwd[len++] = '/';
cwd[len] = '\0';
free(gitfile);
- return cwd + strlen(worktree) + 1;
+ return cwd + offset;
}
/* cwd outside worktree */
const char *prefix;
prefix = setup_git_directory_gently_1(nongit_ok);
+ if (prefix)
+ setenv("GIT_PREFIX", prefix, 1);
+ else
+ setenv("GIT_PREFIX", "", 1);
+
if (startup_info) {
startup_info->have_repository = !nongit_ok || !*nongit_ok;
startup_info->prefix = prefix;