summaryrefslogtreecommitdiff
path: root/pathspec.c
diff options
context:
space:
mode:
Diffstat (limited to 'pathspec.c')
-rw-r--r--pathspec.c85
1 files changed, 61 insertions, 24 deletions
diff --git a/pathspec.c b/pathspec.c
index 46e77a85fe..2133b9fe60 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -1,10 +1,18 @@
-#include "cache.h"
-#include "config.h"
+#include "git-compat-util.h"
+#include "abspath.h"
+#include "parse.h"
#include "dir.h"
+#include "environment.h"
+#include "gettext.h"
#include "pathspec.h"
#include "attr.h"
+#include "read-cache.h"
+#include "repository.h"
+#include "setup.h"
#include "strvec.h"
+#include "symlinks.h"
#include "quote.h"
+#include "wildmatch.h"
/*
* Finds which of the given pathspecs match items in the index.
@@ -101,16 +109,37 @@ static struct pathspec_magic {
{ PATHSPEC_ATTR, '\0', "attr" },
};
-static void prefix_magic(struct strbuf *sb, int prefixlen, unsigned magic)
+static void prefix_magic(struct strbuf *sb, int prefixlen,
+ unsigned magic, const char *element)
{
- int i;
- strbuf_addstr(sb, ":(");
- for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++)
- if (magic & pathspec_magic[i].bit) {
- if (sb->buf[sb->len - 1] != '(')
- strbuf_addch(sb, ',');
- strbuf_addstr(sb, pathspec_magic[i].name);
+ /* No magic was found in element, just add prefix magic */
+ if (!magic) {
+ strbuf_addf(sb, ":(prefix:%d)", prefixlen);
+ return;
+ }
+
+ /*
+ * At this point, we know that parse_element_magic() was able
+ * to extract some pathspec magic from element. So we know
+ * element is correctly formatted in either shorthand or
+ * longhand form
+ */
+ if (element[1] != '(') {
+ /* Process an element in shorthand form (e.g. ":!/<match>") */
+ strbuf_addstr(sb, ":(");
+ for (int i = 0; i < ARRAY_SIZE(pathspec_magic); i++) {
+ if ((magic & pathspec_magic[i].bit) &&
+ pathspec_magic[i].mnemonic) {
+ if (sb->buf[sb->len - 1] != '(')
+ strbuf_addch(sb, ',');
+ strbuf_addstr(sb, pathspec_magic[i].name);
+ }
}
+ } else {
+ /* For the longhand form, we copy everything up to the final ')' */
+ size_t len = strchr(element, ')') - element;
+ strbuf_add(sb, element, len);
+ }
strbuf_addf(sb, ",prefix:%d)", prefixlen);
}
@@ -459,7 +488,12 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags,
match = prefix_path_gently(prefix, prefixlen,
&prefixlen, copyfrom);
if (!match) {
- const char *hint_path = get_git_work_tree();
+ const char *hint_path;
+
+ if (!have_git_dir())
+ die(_("'%s' is outside the directory tree"),
+ copyfrom);
+ hint_path = get_git_work_tree();
if (!hint_path)
hint_path = get_git_dir();
die(_("%s: '%s' is outside repository at '%s'"), elt,
@@ -480,7 +514,7 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags,
struct strbuf sb = STRBUF_INIT;
/* Preserve the actual prefix length of each pattern */
- prefix_magic(&sb, prefixlen, element_magic);
+ prefix_magic(&sb, prefixlen, element_magic, elt);
strbuf_addstr(&sb, match);
item->original = strbuf_detach(&sb, NULL);
@@ -525,27 +559,32 @@ static int pathspec_item_cmp(const void *a_, const void *b_)
return strcmp(a->match, b->match);
}
-static void NORETURN unsupported_magic(const char *pattern,
- unsigned magic)
+void pathspec_magic_names(unsigned magic, struct strbuf *out)
{
- struct strbuf sb = STRBUF_INIT;
int i;
for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++) {
const struct pathspec_magic *m = pathspec_magic + i;
if (!(magic & m->bit))
continue;
- if (sb.len)
- strbuf_addstr(&sb, ", ");
+ if (out->len)
+ strbuf_addstr(out, ", ");
if (m->mnemonic)
- strbuf_addf(&sb, _("'%s' (mnemonic: '%c')"),
+ strbuf_addf(out, _("'%s' (mnemonic: '%c')"),
m->name, m->mnemonic);
else
- strbuf_addf(&sb, "'%s'", m->name);
+ strbuf_addf(out, "'%s'", m->name);
}
+}
+
+static void NORETURN unsupported_magic(const char *pattern,
+ unsigned magic)
+{
+ struct strbuf sb = STRBUF_INIT;
+ pathspec_magic_names(magic, &sb);
/*
* We may want to substitute "this command" with a command
- * name. E.g. when add--interactive dies when running
+ * name. E.g. when "git add -p" or "git add -i" dies when running
* "checkout -p"
*/
die(_("%s: pathspec magic not supported by this command: %s"),
@@ -681,8 +720,7 @@ void copy_pathspec(struct pathspec *dst, const struct pathspec *src)
int i, j;
*dst = *src;
- ALLOC_ARRAY(dst->items, dst->nr);
- COPY_ARRAY(dst->items, src->items, dst->nr);
+ DUP_ARRAY(dst->items, src->items, dst->nr);
for (i = 0; i < dst->nr; i++) {
struct pathspec_item *d = &dst->items[i];
@@ -691,8 +729,7 @@ void copy_pathspec(struct pathspec *dst, const struct pathspec *src)
d->match = xstrdup(s->match);
d->original = xstrdup(s->original);
- ALLOC_ARRAY(d->attr_match, d->attr_match_nr);
- COPY_ARRAY(d->attr_match, s->attr_match, d->attr_match_nr);
+ DUP_ARRAY(d->attr_match, s->attr_match, d->attr_match_nr);
for (j = 0; j < d->attr_match_nr; j++) {
const char *value = s->attr_match[j].value;
d->attr_match[j].value = xstrdup_or_null(value);