* [PATCH v1 19/45] checkout: convert to use parse_pathspec
From: Nguyễn Thái Ngọc Duy @ 2013-03-15 6:06 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1363327620-29017-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
builtin/checkout.c | 40 ++++++++++++++++++++++++----------------
1 file changed, 24 insertions(+), 16 deletions(-)
diff --git a/builtin/checkout.c b/builtin/checkout.c
index a9c1b5a..8dc5f51 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -45,7 +45,7 @@ struct checkout_opts {
int branch_exists;
const char *prefix;
- const char **pathspec;
+ struct pathspec pathspec;
struct tree *source_tree;
};
@@ -256,39 +256,37 @@ static int checkout_paths(const struct checkout_opts *opts,
if (opts->patch_mode)
return run_add_interactive(revision, "--patch=checkout",
- opts->pathspec);
+ opts->pathspec.raw);
lock_file = xcalloc(1, sizeof(struct lock_file));
newfd = hold_locked_index(lock_file, 1);
- if (read_cache_preload(opts->pathspec) < 0)
+ if (read_cache_preload(opts->pathspec.raw) < 0)
return error(_("corrupt index file"));
if (opts->source_tree)
- read_tree_some(opts->source_tree, opts->pathspec);
+ read_tree_some(opts->source_tree, opts->pathspec.raw);
- for (pos = 0; opts->pathspec[pos]; pos++)
- ;
- ps_matched = xcalloc(1, pos);
+ ps_matched = xcalloc(1, opts->pathspec.nr);
for (pos = 0; pos < active_nr; pos++) {
struct cache_entry *ce = active_cache[pos];
if (opts->source_tree && !(ce->ce_flags & CE_UPDATE))
continue;
- match_pathspec(opts->pathspec, ce->name, ce_namelen(ce), 0, ps_matched);
+ match_pathspec_depth(&opts->pathspec, ce->name, ce_namelen(ce), 0, ps_matched);
}
- if (report_path_error(ps_matched, opts->pathspec, opts->prefix))
+ if (report_path_error(ps_matched, opts->pathspec.raw, opts->prefix))
return 1;
/* "checkout -m path" to recreate conflicted state */
if (opts->merge)
- unmerge_cache(opts->pathspec);
+ unmerge_cache(opts->pathspec.raw);
/* Any unmerged paths? */
for (pos = 0; pos < active_nr; pos++) {
struct cache_entry *ce = active_cache[pos];
- if (match_pathspec(opts->pathspec, ce->name, ce_namelen(ce), 0, NULL)) {
+ if (match_pathspec_depth(&opts->pathspec, ce->name, ce_namelen(ce), 0, NULL)) {
if (!ce_stage(ce))
continue;
if (opts->force) {
@@ -315,7 +313,7 @@ static int checkout_paths(const struct checkout_opts *opts,
struct cache_entry *ce = active_cache[pos];
if (opts->source_tree && !(ce->ce_flags & CE_UPDATE))
continue;
- if (match_pathspec(opts->pathspec, ce->name, ce_namelen(ce), 0, NULL)) {
+ if (match_pathspec_depth(&opts->pathspec, ce->name, ce_namelen(ce), 0, NULL)) {
if (!ce_stage(ce)) {
errs |= checkout_entry(ce, &state, NULL);
continue;
@@ -960,7 +958,7 @@ static int switch_unborn_to_new_branch(const struct checkout_opts *opts)
static int checkout_branch(struct checkout_opts *opts,
struct branch_info *new)
{
- if (opts->pathspec)
+ if (opts->pathspec.nr)
die(_("paths cannot be used with switching branches"));
if (opts->patch_mode)
@@ -1110,9 +1108,19 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
}
if (argc) {
- opts.pathspec = get_pathspec(prefix, argv);
+ /*
+ * In patch mode (opts.patch_mode != 0), we pass the
+ * pathspec to an external program, git-add--interactive.
+ * Do not accept any kind of magic that that program
+ * cannot handle. Magic mask is pretty safe to be
+ * lifted for new magic when opts.patch_mode == 0.
+ */
+ parse_pathspec(&opts.pathspec,
+ opts.patch_mode == 0 ? 0 :
+ (PATHSPEC_ALL_MAGIC & ~PATHSPEC_FROMTOP),
+ 0, prefix, argv);
- if (!opts.pathspec)
+ if (!opts.pathspec.nr)
die(_("invalid path specification"));
/*
@@ -1144,7 +1152,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
strbuf_release(&buf);
}
- if (opts.patch_mode || opts.pathspec)
+ if (opts.patch_mode || opts.pathspec.nr)
return checkout_paths(&opts, new.name);
else
return checkout_branch(&opts, &new);
--
1.8.0.rc0.19.g7bbb31d
^ permalink raw reply related
* [PATCH v1 18/45] rerere: convert to use parse_pathspec
From: Nguyễn Thái Ngọc Duy @ 2013-03-15 6:06 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1363327620-29017-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
builtin/rerere.c | 8 +++++---
rerere.c | 9 +++++----
rerere.h | 4 +++-
3 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/builtin/rerere.c b/builtin/rerere.c
index dc1708e..4e51add 100644
--- a/builtin/rerere.c
+++ b/builtin/rerere.c
@@ -6,6 +6,7 @@
#include "rerere.h"
#include "xdiff/xdiff.h"
#include "xdiff-interface.h"
+#include "pathspec.h"
static const char * const rerere_usage[] = {
N_("git rerere [clear | forget path... | status | remaining | diff | gc]"),
@@ -68,11 +69,12 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
return rerere(flags);
if (!strcmp(argv[0], "forget")) {
- const char **pathspec;
+ struct pathspec pathspec;
if (argc < 2)
warning("'git rerere forget' without paths is deprecated");
- pathspec = get_pathspec(prefix, argv + 1);
- return rerere_forget(pathspec);
+ parse_pathspec(&pathspec, 0, PATHSPEC_PREFER_CWD,
+ prefix, argv + 1);
+ return rerere_forget(&pathspec);
}
fd = setup_rerere(&merge_rr, flags);
diff --git a/rerere.c b/rerere.c
index a6a5cd5..c52c1f2 100644
--- a/rerere.c
+++ b/rerere.c
@@ -6,6 +6,7 @@
#include "resolve-undo.h"
#include "ll-merge.h"
#include "attr.h"
+#include "pathspec.h"
#define RESOLVED 0
#define PUNTED 1
@@ -655,7 +656,7 @@ static int rerere_forget_one_path(const char *path, struct string_list *rr)
return 0;
}
-int rerere_forget(const char **pathspec)
+int rerere_forget(struct pathspec *pathspec)
{
int i, fd;
struct string_list conflict = STRING_LIST_INIT_DUP;
@@ -666,12 +667,12 @@ int rerere_forget(const char **pathspec)
fd = setup_rerere(&merge_rr, RERERE_NOAUTOUPDATE);
- unmerge_cache(pathspec);
+ unmerge_cache(pathspec->raw);
find_conflict(&conflict);
for (i = 0; i < conflict.nr; i++) {
struct string_list_item *it = &conflict.items[i];
- if (!match_pathspec(pathspec, it->string, strlen(it->string),
- 0, NULL))
+ if (!match_pathspec_depth(pathspec, it->string, strlen(it->string),
+ 0, NULL))
continue;
rerere_forget_one_path(it->string, &merge_rr);
}
diff --git a/rerere.h b/rerere.h
index 156d2aa..4aa06c9 100644
--- a/rerere.h
+++ b/rerere.h
@@ -3,6 +3,8 @@
#include "string-list.h"
+struct pathspec;
+
#define RERERE_AUTOUPDATE 01
#define RERERE_NOAUTOUPDATE 02
@@ -16,7 +18,7 @@ extern void *RERERE_RESOLVED;
extern int setup_rerere(struct string_list *, int);
extern int rerere(int);
extern const char *rerere_path(const char *hex, const char *file);
-extern int rerere_forget(const char **);
+extern int rerere_forget(struct pathspec *);
extern int rerere_remaining(struct string_list *);
extern void rerere_clear(struct string_list *);
extern void rerere_gc(struct string_list *);
--
1.8.0.rc0.19.g7bbb31d
^ permalink raw reply related
* [PATCH v1 17/45] status: convert to use parse_pathspec
From: Nguyễn Thái Ngọc Duy @ 2013-03-15 6:06 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1363327620-29017-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
builtin/commit.c | 9 +++++----
wt-status.c | 18 ++++++++----------
wt-status.h | 2 +-
3 files changed, 14 insertions(+), 15 deletions(-)
diff --git a/builtin/commit.c b/builtin/commit.c
index ba6731b..d8e6b28 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1195,11 +1195,12 @@ int cmd_status(int argc, const char **argv, const char *prefix)
handle_untracked_files_arg(&s);
if (show_ignored_in_status)
s.show_ignored_files = 1;
- if (*argv)
- s.pathspec = get_pathspec(prefix, argv);
+ parse_pathspec(&s.pathspec, 0,
+ PATHSPEC_PREFER_FULL,
+ prefix, argv);
- read_cache_preload(s.pathspec);
- refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, s.pathspec, NULL, NULL);
+ read_cache_preload(s.pathspec.raw);
+ refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, s.pathspec.raw, NULL, NULL);
fd = hold_locked_index(&index_lock, 0);
if (0 <= fd)
diff --git a/wt-status.c b/wt-status.c
index ef405d0..5dec9af 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -1,4 +1,5 @@
#include "cache.h"
+#include "pathspec.h"
#include "wt-status.h"
#include "object.h"
#include "dir.h"
@@ -434,7 +435,7 @@ static void wt_status_collect_changes_worktree(struct wt_status *s)
}
rev.diffopt.format_callback = wt_status_collect_changed_cb;
rev.diffopt.format_callback_data = s;
- init_pathspec(&rev.prune_data, s->pathspec);
+ copy_pathspec(&rev.prune_data, &s->pathspec);
run_diff_files(&rev, 0);
}
@@ -459,22 +460,20 @@ static void wt_status_collect_changes_index(struct wt_status *s)
rev.diffopt.detect_rename = 1;
rev.diffopt.rename_limit = 200;
rev.diffopt.break_opt = 0;
- init_pathspec(&rev.prune_data, s->pathspec);
+ copy_pathspec(&rev.prune_data, &s->pathspec);
run_diff_index(&rev, 1);
}
static void wt_status_collect_changes_initial(struct wt_status *s)
{
- struct pathspec pathspec;
int i;
- init_pathspec(&pathspec, s->pathspec);
for (i = 0; i < active_nr; i++) {
struct string_list_item *it;
struct wt_status_change_data *d;
struct cache_entry *ce = active_cache[i];
- if (!ce_path_match(ce, &pathspec))
+ if (!ce_path_match(ce, &s->pathspec))
continue;
it = string_list_insert(&s->change, ce->name);
d = it->util;
@@ -489,7 +488,6 @@ static void wt_status_collect_changes_initial(struct wt_status *s)
else
d->index_status = DIFF_STATUS_ADDED;
}
- free_pathspec(&pathspec);
}
static void wt_status_collect_untracked(struct wt_status *s)
@@ -505,11 +503,11 @@ static void wt_status_collect_untracked(struct wt_status *s)
DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES;
setup_standard_excludes(&dir);
- fill_directory(&dir, s->pathspec);
+ fill_directory(&dir, s->pathspec.raw);
for (i = 0; i < dir.nr; i++) {
struct dir_entry *ent = dir.entries[i];
if (cache_name_is_other(ent->name, ent->len) &&
- match_pathspec(s->pathspec, ent->name, ent->len, 0, NULL))
+ match_pathspec_depth(&s->pathspec, ent->name, ent->len, 0, NULL))
string_list_insert(&s->untracked, ent->name);
free(ent);
}
@@ -519,11 +517,11 @@ static void wt_status_collect_untracked(struct wt_status *s)
dir.flags = DIR_SHOW_IGNORED;
if (s->show_untracked_files != SHOW_ALL_UNTRACKED_FILES)
dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
- fill_directory(&dir, s->pathspec);
+ fill_directory(&dir, s->pathspec.raw);
for (i = 0; i < dir.nr; i++) {
struct dir_entry *ent = dir.entries[i];
if (cache_name_is_other(ent->name, ent->len) &&
- match_pathspec(s->pathspec, ent->name, ent->len, 0, NULL))
+ match_pathspec_depth(&s->pathspec, ent->name, ent->len, 0, NULL))
string_list_insert(&s->ignored, ent->name);
free(ent);
}
diff --git a/wt-status.h b/wt-status.h
index 81e1dcf..bb01c23 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -44,7 +44,7 @@ struct wt_status {
int is_initial;
char *branch;
const char *reference;
- const char **pathspec;
+ struct pathspec pathspec;
int verbose;
int amend;
enum commit_whence whence;
--
1.8.0.rc0.19.g7bbb31d
^ permalink raw reply related
* [PATCH v1 16/45] commit: convert to use parse_pathspec
From: Nguyễn Thái Ngọc Duy @ 2013-03-15 6:06 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1363327620-29017-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
builtin/commit.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/builtin/commit.c b/builtin/commit.c
index 3348aa1..ba6731b 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -277,17 +277,17 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
{
int fd;
struct string_list partial;
- const char **pathspec = NULL;
+ struct pathspec pathspec;
char *old_index_env = NULL;
int refresh_flags = REFRESH_QUIET;
if (is_status)
refresh_flags |= REFRESH_UNMERGED;
+ parse_pathspec(&pathspec, 0,
+ PATHSPEC_PREFER_FULL,
+ prefix, argv);
- if (*argv)
- pathspec = get_pathspec(prefix, argv);
-
- if (read_cache_preload(pathspec) < 0)
+ if (read_cache_preload(pathspec.raw) < 0)
die(_("index file corrupt"));
if (interactive) {
@@ -329,9 +329,9 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
* (A) if all goes well, commit the real index;
* (B) on failure, rollback the real index.
*/
- if (all || (also && pathspec && *pathspec)) {
+ if (all || (also && pathspec.nr)) {
fd = hold_locked_index(&index_lock, 1);
- add_files_to_cache(also ? prefix : NULL, pathspec, 0);
+ add_files_to_cache(also ? prefix : NULL, pathspec.raw, 0);
refresh_cache_or_die(refresh_flags);
update_main_cache_tree(WRITE_TREE_SILENT);
if (write_cache(fd, active_cache, active_nr) ||
@@ -350,7 +350,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
* and create commit from the_index.
* We still need to refresh the index here.
*/
- if (!only && (!pathspec || !*pathspec)) {
+ if (!only && !pathspec.nr) {
fd = hold_locked_index(&index_lock, 1);
refresh_cache_or_die(refresh_flags);
if (active_cache_changed) {
@@ -395,7 +395,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
memset(&partial, 0, sizeof(partial));
partial.strdup_strings = 1;
- if (list_paths(&partial, !current_head ? NULL : "HEAD", prefix, pathspec))
+ if (list_paths(&partial, !current_head ? NULL : "HEAD", prefix, pathspec.raw))
exit(1);
discard_cache();
--
1.8.0.rc0.19.g7bbb31d
^ permalink raw reply related
* [PATCH v1 15/45] clean: convert to use parse_pathspec
From: Nguyễn Thái Ngọc Duy @ 2013-03-15 6:06 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1363327620-29017-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
builtin/clean.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/builtin/clean.c b/builtin/clean.c
index f955a40..fdd4980 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -13,6 +13,7 @@
#include "refs.h"
#include "string-list.h"
#include "quote.h"
+#include "pathspec.h"
static int force = -1; /* unset */
@@ -150,7 +151,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
int rm_flags = REMOVE_DIR_KEEP_NESTED_GIT;
struct strbuf directory = STRBUF_INIT;
struct dir_struct dir;
- static const char **pathspec;
+ struct pathspec pathspec;
struct strbuf buf = STRBUF_INIT;
struct string_list exclude_list = STRING_LIST_INIT_NODUP;
struct exclude_list *el;
@@ -209,9 +210,11 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
for (i = 0; i < exclude_list.nr; i++)
add_exclude(exclude_list.items[i].string, "", 0, el, -(i+1));
- pathspec = get_pathspec(prefix, argv);
+ parse_pathspec(&pathspec, 0,
+ PATHSPEC_PREFER_CWD,
+ prefix, argv);
- fill_directory(&dir, pathspec);
+ fill_directory(&dir, pathspec.raw);
for (i = 0; i < dir.nr; i++) {
struct dir_entry *ent = dir.entries[i];
@@ -246,9 +249,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
if (lstat(ent->name, &st))
continue;
- if (pathspec)
- matches = match_pathspec(pathspec, ent->name, len,
- 0, NULL);
+ if (pathspec.nr)
+ matches = match_pathspec_depth(&pathspec, ent->name,
+ len, 0, NULL);
if (S_ISDIR(st.st_mode)) {
strbuf_addstr(&directory, ent->name);
@@ -262,7 +265,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
}
strbuf_reset(&directory);
} else {
- if (pathspec && !matches)
+ if (pathspec.nr && !matches)
continue;
res = dry_run ? 0 : unlink(ent->name);
if (res) {
--
1.8.0.rc0.19.g7bbb31d
^ permalink raw reply related
* [PATCH v1 14/45] Guard against new pathspec magic in pathspec matching code
From: Nguyễn Thái Ngọc Duy @ 2013-03-15 6:06 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1363327620-29017-1-git-send-email-pclouds@gmail.com>
GUARD_PATHSPEC() marks pathspec-sensitive code (basically anything in
'struct pathspec' except fields "nr" and "original"). GUARD_PATHSPEC()
is not supposed to fail. The steps for a new pathspec magic or
optimization would be:
- update parse_pathspec, add extra information to struct pathspec
- grep GUARD_PATHSPEC() and update all relevant code (or note those
that won't work with your new stuff). Update GUARD_PATHSPEC mask
accordingly.
- update parse_pathspec calls to disable new magic early at command
parsing level. Make sure parse_pathspec() catches unsupported
syntax, not until GUARD_PATHSPEC catches it.
- add tests to verify supported/unsupported commands both work as
expected.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
builtin/diff.c | 2 ++
dir.c | 2 ++
pathspec.h | 7 +++++++
tree-diff.c | 19 +++++++++++++++++++
tree-walk.c | 2 ++
5 files changed, 32 insertions(+)
diff --git a/builtin/diff.c b/builtin/diff.c
index 8c2af6c..d237e0a 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -371,6 +371,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
die(_("unhandled object '%s' given."), name);
}
if (rev.prune_data.nr) {
+ /* builtin_diff_b_f() */
+ GUARD_PATHSPEC(&rev.prune_data, PATHSPEC_FROMTOP);
if (!path)
path = rev.prune_data.items[0].match;
paths += rev.prune_data.nr;
diff --git a/dir.c b/dir.c
index 1e9db41..6094ba8 100644
--- a/dir.c
+++ b/dir.c
@@ -297,6 +297,8 @@ int match_pathspec_depth(const struct pathspec *ps,
{
int i, retval = 0;
+ GUARD_PATHSPEC(ps, PATHSPEC_FROMTOP | PATHSPEC_MAXDEPTH);
+
if (!ps->nr) {
if (!ps->recursive ||
!(ps->magic & PATHSPEC_MAXDEPTH) ||
diff --git a/pathspec.h b/pathspec.h
index 1cef9c6..ed5d3a6 100644
--- a/pathspec.h
+++ b/pathspec.h
@@ -27,6 +27,13 @@ struct pathspec {
} *items;
};
+#define GUARD_PATHSPEC(ps, mask) \
+ do { \
+ if ((ps)->magic & ~(mask)) \
+ die("BUG:%s:%d: unsupported magic %x", \
+ __FILE__, __LINE__, (ps)->magic & ~(mask)); \
+ } while (0)
+
/* parse_pathspec flags */
#define PATHSPEC_PREFER_CWD (1<<0) /* No args means match cwd */
#define PATHSPEC_PREFER_FULL (1<<1) /* No args means match everything */
diff --git a/tree-diff.c b/tree-diff.c
index 826512e..5a87614 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -198,6 +198,25 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co
const char *paths[1];
int i;
+ /*
+ * follow-rename code is very specific, we need exactly one
+ * path. Magic that matches more than one path is not
+ * supported.
+ */
+ GUARD_PATHSPEC(&opt->pathspec, PATHSPEC_FROMTOP);
+#if 0
+ /*
+ * We should reject wildcards as well. Unfortunately we
+ * haven't got a reliable way to detect that 'foo\*bar' in
+ * fact has no wildcards. nowildcard_len is merely a hint for
+ * optimization. Let it slip for now until wildmatch is taught
+ * about dry-run mode and returns wildcard info.
+ */
+ if (opt->pathspec.has_wildcard)
+ die("BUG:%s:%d: wildcards are not supported",
+ __FILE__, __LINE__);
+#endif
+
/* Remove the file creation entry from the diff queue, and remember it */
choice = q->queue[0];
q->nr = 0;
diff --git a/tree-walk.c b/tree-walk.c
index d399ca9..37b157e 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -636,6 +636,8 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
enum interesting never_interesting = ps->has_wildcard ?
entry_not_interesting : all_entries_not_interesting;
+ GUARD_PATHSPEC(ps, PATHSPEC_FROMTOP | PATHSPEC_MAXDEPTH);
+
if (!ps->nr) {
if (!ps->recursive ||
!(ps->magic & PATHSPEC_MAXDEPTH) ||
--
1.8.0.rc0.19.g7bbb31d
^ permalink raw reply related
* [PATCH v1 13/45] parse_pathspec: support prefixing original patterns
From: Nguyễn Thái Ngọc Duy @ 2013-03-15 6:06 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1363327620-29017-1-git-send-email-pclouds@gmail.com>
This makes 'original' suitable for passing to an external command
because all pathspec magic is left in place, provided that the
external command understands pathspec. The prefixing is needed because
we usually launch a subcommand at worktree's top directory and the
subcommand can no longer calculate the prefix itself.
This slightly affects the original purpose of 'original'
(i.e. reporting). We should report without prefixing. So only turn
this flag on when you know you are about to pass the result straight
away to an external command.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
pathspec.c | 12 +++++++++++-
pathspec.h | 1 +
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/pathspec.c b/pathspec.c
index 834db80..9a57c0c 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -202,7 +202,17 @@ static unsigned prefix_pathspec(struct pathspec_item *item,
else
match = prefix_path(prefix, prefixlen, copyfrom);
*raw = item->match = match;
- item->original = elt;
+ /*
+ * Prefix the pathspec (keep all magic) and put to
+ * original. Useful for passing to another command.
+ */
+ if (flags & PATHSPEC_PREFIX_ORIGIN) {
+ struct strbuf sb = STRBUF_INIT;
+ strbuf_add(&sb, elt, copyfrom - elt);
+ strbuf_addstr(&sb, match);
+ item->original = strbuf_detach(&sb, NULL);
+ } else
+ item->original = elt;
item->len = strlen(item->match);
if ((flags & PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP) &&
diff --git a/pathspec.h b/pathspec.h
index 6ffd09d..1cef9c6 100644
--- a/pathspec.h
+++ b/pathspec.h
@@ -34,6 +34,7 @@ struct pathspec {
#define PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP (1<<3)
#define PATHSPEC_SYMLINK_LEADING_PATH (1<<4)
#define PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE (1<<5)
+#define PATHSPEC_PREFIX_ORIGIN (1<<6)
extern int init_pathspec(struct pathspec *, const char **);
extern void parse_pathspec(struct pathspec *pathspec,
--
1.8.0.rc0.19.g7bbb31d
^ permalink raw reply related
* [PATCH v1 12/45] parse_pathspec: support stripping/checking submodule paths
From: Nguyễn Thái Ngọc Duy @ 2013-03-15 6:06 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1363327620-29017-1-git-send-email-pclouds@gmail.com>
PATHSPEC_SYMLINK_LEADING_PATH and _STRIP_SUBMODULE_SLASH_EXPENSIVE are
respectively the alternate implementation of
pathspec.c:die_if_path_beyond_symlink() and
pathspec.c:check_path_for_gitlink(). They are intended to replace
those functions when builtin/add.c and builtin/check-ignore.c are
converted to use parse_pathspec.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
pathspec.c | 26 ++++++++++++++++++++++++++
pathspec.h | 2 ++
2 files changed, 28 insertions(+)
diff --git a/pathspec.c b/pathspec.c
index 2da8bc9..834db80 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -213,6 +213,26 @@ static unsigned prefix_pathspec(struct pathspec_item *item,
match[item->len] = '\0';
}
+ if (flags & PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE)
+ for (i = 0; i < active_nr; i++) {
+ struct cache_entry *ce = active_cache[i];
+ int ce_len = ce_namelen(ce);
+
+ if (!S_ISGITLINK(ce->ce_mode))
+ continue;
+
+ if (item->len <= ce_len || match[ce_len] != '/' ||
+ memcmp(ce->name, match, ce_len))
+ continue;
+ if (item->len == ce_len + 1) {
+ /* strip trailing slash */
+ item->len--;
+ match[item->len] = '\0';
+ } else
+ die (_("Pathspec '%s' is in submodule '%.*s'"),
+ elt, ce_len, ce->name);
+ }
+
if (limit_pathspec_to_literal())
item->nowildcard_len = item->len;
else
@@ -327,6 +347,12 @@ void parse_pathspec(struct pathspec *pathspec,
unsupported_magic(entry,
item[i].magic & magic_mask,
short_magic);
+
+ if ((flags & PATHSPEC_SYMLINK_LEADING_PATH) &&
+ has_symlink_leading_path(item[i].match, item[i].len)) {
+ die(_("pathspec '%s' is beyond a symbolic link"), entry);
+ }
+
if (item[i].nowildcard_len < item[i].len)
pathspec->has_wildcard = 1;
pathspec->magic |= item[i].magic;
diff --git a/pathspec.h b/pathspec.h
index f24b07b..6ffd09d 100644
--- a/pathspec.h
+++ b/pathspec.h
@@ -32,6 +32,8 @@ struct pathspec {
#define PATHSPEC_PREFER_FULL (1<<1) /* No args means match everything */
#define PATHSPEC_MAXDEPTH_VALID (1<<2) /* max_depth field is valid */
#define PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP (1<<3)
+#define PATHSPEC_SYMLINK_LEADING_PATH (1<<4)
+#define PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE (1<<5)
extern int init_pathspec(struct pathspec *, const char **);
extern void parse_pathspec(struct pathspec *pathspec,
--
1.8.0.rc0.19.g7bbb31d
^ permalink raw reply related
* [PATCH v1 11/45] parse_pathspec: support stripping submodule trailing slashes
From: Nguyễn Thái Ngọc Duy @ 2013-03-15 6:06 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1363327620-29017-1-git-send-email-pclouds@gmail.com>
This flag is equivalent to builtin/ls-files.c:strip_trailing_slashes()
and is intended to replace that function when ls-files is converted to
use parse_pathspec.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
pathspec.c | 9 +++++++++
pathspec.h | 1 +
2 files changed, 10 insertions(+)
diff --git a/pathspec.c b/pathspec.c
index b2446c3..2da8bc9 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -204,6 +204,15 @@ static unsigned prefix_pathspec(struct pathspec_item *item,
*raw = item->match = match;
item->original = elt;
item->len = strlen(item->match);
+
+ if ((flags & PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP) &&
+ (item->len >= 1 && item->match[item->len - 1] == '/') &&
+ (i = cache_name_pos(item->match, item->len - 1)) >= 0 &&
+ S_ISGITLINK(active_cache[i]->ce_mode)) {
+ item->len--;
+ match[item->len] = '\0';
+ }
+
if (limit_pathspec_to_literal())
item->nowildcard_len = item->len;
else
diff --git a/pathspec.h b/pathspec.h
index aa98597..f24b07b 100644
--- a/pathspec.h
+++ b/pathspec.h
@@ -31,6 +31,7 @@ struct pathspec {
#define PATHSPEC_PREFER_CWD (1<<0) /* No args means match cwd */
#define PATHSPEC_PREFER_FULL (1<<1) /* No args means match everything */
#define PATHSPEC_MAXDEPTH_VALID (1<<2) /* max_depth field is valid */
+#define PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP (1<<3)
extern int init_pathspec(struct pathspec *, const char **);
extern void parse_pathspec(struct pathspec *pathspec,
--
1.8.0.rc0.19.g7bbb31d
^ permalink raw reply related
* [PATCH v1 10/45] parse_pathspec: a special flag for max_depth feature
From: Nguyễn Thái Ngọc Duy @ 2013-03-15 6:06 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1363327620-29017-1-git-send-email-pclouds@gmail.com>
match_pathspec_depth() and tree_entry_interesting() check max_depth
field in order to support "git grep --max-depth". The feature
activation is tied to "recursive" field, which led to some unwated
activation, e.g. 5c8eeb8 (diff-index: enable recursive pathspec
matching in unpack_trees - 2012-01-15).
This patch decouples the activation from "recursive" field, puts it in
"magic" field instead. This makes sure that only "git grep" can
activate this feature. And because parse_pathspec knows when the
feature is not used, it does not need to sort pathspec (required for
max_depth to work correctly). A small win for non-grep cases.
Even though a new magic flag is introduced, no magic syntax is. The
magic can be only enabled by parse_pathspec() caller. We might someday
want to support ":(maxdepth:10)src." It all depends on actual use
cases.
max_depth feature cannot be enabled via init_pathspec() anymore. But
that's ok because init_pathspec() is on its way to /dev/null.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
builtin/grep.c | 3 ++-
diff-lib.c | 1 -
dir.c | 8 ++++++--
pathspec.c | 8 ++++++--
pathspec.h | 6 +++++-
tree-diff.c | 1 -
tree-walk.c | 8 ++++++--
7 files changed, 25 insertions(+), 10 deletions(-)
diff --git a/builtin/grep.c b/builtin/grep.c
index 54b089e..1c7397a 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -860,7 +860,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
}
parse_pathspec(&pathspec, 0,
- PATHSPEC_PREFER_CWD,
+ PATHSPEC_PREFER_CWD |
+ (opt.max_depth != -1 ? PATHSPEC_MAXDEPTH_VALID : 0),
prefix, argv + i);
pathspec.max_depth = opt.max_depth;
pathspec.recursive = 1;
diff --git a/diff-lib.c b/diff-lib.c
index f35de0f..4729157 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -474,7 +474,6 @@ static int diff_cache(struct rev_info *revs,
opts.dst_index = NULL;
opts.pathspec = &revs->diffopt.pathspec;
opts.pathspec->recursive = 1;
- opts.pathspec->max_depth = -1;
init_tree_desc(&t, tree->buffer, tree->size);
return unpack_trees(1, &t, &opts);
diff --git a/dir.c b/dir.c
index 8541ea7..1e9db41 100644
--- a/dir.c
+++ b/dir.c
@@ -298,7 +298,9 @@ int match_pathspec_depth(const struct pathspec *ps,
int i, retval = 0;
if (!ps->nr) {
- if (!ps->recursive || ps->max_depth == -1)
+ if (!ps->recursive ||
+ !(ps->magic & PATHSPEC_MAXDEPTH) ||
+ ps->max_depth == -1)
return MATCHED_RECURSIVELY;
if (within_depth(name, namelen, 0, ps->max_depth))
@@ -315,7 +317,9 @@ int match_pathspec_depth(const struct pathspec *ps,
if (seen && seen[i] == MATCHED_EXACTLY)
continue;
how = match_pathspec_item(ps->items+i, prefix, name, namelen);
- if (ps->recursive && ps->max_depth != -1 &&
+ if (ps->recursive &&
+ (ps->magic & PATHSPEC_MAXDEPTH) &&
+ ps->max_depth != -1 &&
how && how != MATCHED_FNMATCH) {
int len = ps->items[i].len;
if (name[len] == '/')
diff --git a/pathspec.c b/pathspec.c
index 6dd944a..b2446c3 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -266,6 +266,9 @@ void parse_pathspec(struct pathspec *pathspec,
memset(pathspec, 0, sizeof(*pathspec));
+ if (flags & PATHSPEC_MAXDEPTH_VALID)
+ pathspec->magic |= PATHSPEC_MAXDEPTH;
+
/* No arguments, no prefix -> no pathspec */
if (!entry && !prefix)
return;
@@ -320,8 +323,9 @@ void parse_pathspec(struct pathspec *pathspec,
pathspec->magic |= item[i].magic;
}
- qsort(pathspec->items, pathspec->nr,
- sizeof(struct pathspec_item), pathspec_item_cmp);
+ if (pathspec->magic & PATHSPEC_MAXDEPTH)
+ qsort(pathspec->items, pathspec->nr,
+ sizeof(struct pathspec_item), pathspec_item_cmp);
}
/*
diff --git a/pathspec.h b/pathspec.h
index d630e8b..aa98597 100644
--- a/pathspec.h
+++ b/pathspec.h
@@ -3,7 +3,10 @@
/* Pathspec magic */
#define PATHSPEC_FROMTOP (1<<0)
-#define PATHSPEC_ALL_MAGIC PATHSPEC_FROMTOP
+#define PATHSPEC_MAXDEPTH (1<<1)
+#define PATHSPEC_ALL_MAGIC \
+ (PATHSPEC_FROMTOP | \
+ PATHSPEC_MAXDEPTH)
#define PATHSPEC_ONESTAR 1 /* the pathspec pattern sastisfies GFNM_ONESTAR */
@@ -27,6 +30,7 @@ struct pathspec {
/* parse_pathspec flags */
#define PATHSPEC_PREFER_CWD (1<<0) /* No args means match cwd */
#define PATHSPEC_PREFER_FULL (1<<1) /* No args means match everything */
+#define PATHSPEC_MAXDEPTH_VALID (1<<2) /* max_depth field is valid */
extern int init_pathspec(struct pathspec *, const char **);
extern void parse_pathspec(struct pathspec *pathspec,
diff --git a/tree-diff.c b/tree-diff.c
index ba01563..826512e 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -138,7 +138,6 @@ int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
/* Enable recursion indefinitely */
opt->pathspec.recursive = DIFF_OPT_TST(opt, RECURSIVE);
- opt->pathspec.max_depth = -1;
strbuf_init(&base, PATH_MAX);
strbuf_add(&base, base_str, baselen);
diff --git a/tree-walk.c b/tree-walk.c
index 72a9613..d399ca9 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -637,7 +637,9 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
entry_not_interesting : all_entries_not_interesting;
if (!ps->nr) {
- if (!ps->recursive || ps->max_depth == -1)
+ if (!ps->recursive ||
+ !(ps->magic & PATHSPEC_MAXDEPTH) ||
+ ps->max_depth == -1)
return all_entries_interesting;
return within_depth(base->buf + base_offset, baselen,
!!S_ISDIR(entry->mode),
@@ -658,7 +660,9 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
if (!match_dir_prefix(base_str, match, matchlen))
goto match_wildcards;
- if (!ps->recursive || ps->max_depth == -1)
+ if (!ps->recursive ||
+ !(ps->magic & PATHSPEC_MAXDEPTH) ||
+ ps->max_depth == -1)
return all_entries_interesting;
return within_depth(base_str + matchlen + 1,
--
1.8.0.rc0.19.g7bbb31d
^ permalink raw reply related
* [PATCH v1 09/45] Convert some get_pathspec() calls to parse_pathspec()
From: Nguyễn Thái Ngọc Duy @ 2013-03-15 6:06 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1363327620-29017-1-git-send-email-pclouds@gmail.com>
These call sites follow the pattern:
paths = get_pathspec(prefix, argv);
init_pathspec(&pathspec, paths);
which can be converted into a single parse_pathspec() call.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
builtin/grep.c | 6 +++---
builtin/ls-tree.c | 10 +++++++++-
builtin/update-index.c | 5 +++--
revision.c | 4 ++--
4 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/builtin/grep.c b/builtin/grep.c
index 3701c2e..54b089e 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -631,7 +631,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
const char *show_in_pager = NULL, *default_pager = "dummy";
struct grep_opt opt;
struct object_array list = OBJECT_ARRAY_INIT;
- const char **paths = NULL;
struct pathspec pathspec;
struct string_list path_list = STRING_LIST_INIT_NODUP;
int i;
@@ -860,8 +859,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
verify_filename(prefix, argv[j], j == i);
}
- paths = get_pathspec(prefix, argv + i);
- init_pathspec(&pathspec, paths);
+ parse_pathspec(&pathspec, 0,
+ PATHSPEC_PREFER_CWD,
+ prefix, argv + i);
pathspec.max_depth = opt.max_depth;
pathspec.recursive = 1;
diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
index 93fc3a0..bdb03f3 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -167,7 +167,15 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
if (get_sha1(argv[0], sha1))
die("Not a valid object name %s", argv[0]);
- init_pathspec(&pathspec, get_pathspec(prefix, argv + 1));
+ /*
+ * show_recursive() rolls its own matching code and is
+ * generally ignorant of 'struct pathspec'. The magic mask
+ * cannot be lifted until it is converted to use
+ * match_pathspec_depth() or tree_entry_interesting()
+ */
+ parse_pathspec(&pathspec, 0,
+ PATHSPEC_PREFER_CWD,
+ prefix, argv + 1);
for (i = 0; i < pathspec.nr; i++)
pathspec.items[i].nowildcard_len = pathspec.items[i].len;
pathspec.has_wildcard = 0;
diff --git a/builtin/update-index.c b/builtin/update-index.c
index ffae585..3c6905d 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -547,10 +547,11 @@ static int do_reupdate(int ac, const char **av,
*/
int pos;
int has_head = 1;
- const char **paths = get_pathspec(prefix, av + 1);
struct pathspec pathspec;
- init_pathspec(&pathspec, paths);
+ parse_pathspec(&pathspec, 0,
+ PATHSPEC_PREFER_CWD,
+ prefix, av + 1);
if (read_ref("HEAD", head_sha1))
/* If there is no HEAD, that means it is an initial
diff --git a/revision.c b/revision.c
index ef60205..e257614 100644
--- a/revision.c
+++ b/revision.c
@@ -1852,8 +1852,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
*/
ALLOC_GROW(prune_data.path, prune_data.nr+1, prune_data.alloc);
prune_data.path[prune_data.nr++] = NULL;
- init_pathspec(&revs->prune_data,
- get_pathspec(revs->prefix, prune_data.path));
+ parse_pathspec(&revs->prune_data, 0, 0,
+ revs->prefix, prune_data.path);
}
if (revs->def == NULL)
--
1.8.0.rc0.19.g7bbb31d
^ permalink raw reply related
* [PATCH v1 08/45] parse_pathspec: add PATHSPEC_PREFER_{CWD,FULL}
From: Nguyễn Thái Ngọc Duy @ 2013-03-15 6:06 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1363327620-29017-1-git-send-email-pclouds@gmail.com>
We have two ways of dealing with empty pathspec:
1. limit it to current prefix
2. match the entire working directory
Some commands go with #1, some #2. get_pathspec() and parse_pathspec()
only support #1. Make parse_pathspec() reject empty pathspec by
default. #1 and #2 can be specified via new flags. This makes it more
expressive about default behavior at command level.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
pathspec.c | 13 ++++++++++++-
pathspec.h | 4 ++++
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/pathspec.c b/pathspec.c
index 2bda633..6dd944a 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -270,10 +270,20 @@ void parse_pathspec(struct pathspec *pathspec,
if (!entry && !prefix)
return;
+ if ((flags & PATHSPEC_PREFER_CWD) &&
+ (flags & PATHSPEC_PREFER_FULL))
+ die("BUG: PATHSPEC_PREFER_CWD and PATHSPEC_PREFER_FULL are incompatible");
+
/* No arguments with prefix -> prefix pathspec */
if (!entry) {
static const char *raw[2];
+ if (flags & PATHSPEC_PREFER_FULL)
+ return;
+
+ if (!(flags & PATHSPEC_PREFER_CWD))
+ die("BUG: parse_pathspec cannot take no arguments in this case");
+
pathspec->items = item = xmalloc(sizeof(*item));
item->match = prefix;
item->original = prefix;
@@ -338,7 +348,8 @@ const char **get_pathspec(const char *prefix, const char **pathspec)
struct pathspec ps;
parse_pathspec(&ps,
PATHSPEC_ALL_MAGIC & ~PATHSPEC_FROMTOP,
- 0, prefix, pathspec);
+ PATHSPEC_PREFER_CWD,
+ prefix, pathspec);
return ps.raw;
}
diff --git a/pathspec.h b/pathspec.h
index cc5841b..d630e8b 100644
--- a/pathspec.h
+++ b/pathspec.h
@@ -24,6 +24,10 @@ struct pathspec {
} *items;
};
+/* parse_pathspec flags */
+#define PATHSPEC_PREFER_CWD (1<<0) /* No args means match cwd */
+#define PATHSPEC_PREFER_FULL (1<<1) /* No args means match everything */
+
extern int init_pathspec(struct pathspec *, const char **);
extern void parse_pathspec(struct pathspec *pathspec,
unsigned magic_mask,
--
1.8.0.rc0.19.g7bbb31d
^ permalink raw reply related
* [PATCH v1 07/45] parse_pathspec: save original pathspec for reporting
From: Nguyễn Thái Ngọc Duy @ 2013-03-15 6:06 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1363327620-29017-1-git-send-email-pclouds@gmail.com>
We usually use pathspec_item's match field for pathspec error
reporting. However "match" (or "raw") does not show the magic part,
which will play more important role later on. Preserve exact user
input for reporting.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
dir.c | 1 +
pathspec.c | 2 ++
pathspec.h | 1 +
3 files changed, 4 insertions(+)
diff --git a/dir.c b/dir.c
index a442467..8541ea7 100644
--- a/dir.c
+++ b/dir.c
@@ -1649,6 +1649,7 @@ int init_pathspec(struct pathspec *pathspec, const char **paths)
const char *path = paths[i];
item->match = path;
+ item->original = path;
item->len = strlen(path);
item->flags = 0;
if (limit_pathspec_to_literal()) {
diff --git a/pathspec.c b/pathspec.c
index bc9d9ac..2bda633 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -202,6 +202,7 @@ static unsigned prefix_pathspec(struct pathspec_item *item,
else
match = prefix_path(prefix, prefixlen, copyfrom);
*raw = item->match = match;
+ item->original = elt;
item->len = strlen(item->match);
if (limit_pathspec_to_literal())
item->nowildcard_len = item->len;
@@ -275,6 +276,7 @@ void parse_pathspec(struct pathspec *pathspec,
pathspec->items = item = xmalloc(sizeof(*item));
item->match = prefix;
+ item->original = prefix;
item->nowildcard_len = item->len = strlen(prefix);
raw[0] = prefix;
raw[1] = NULL;
diff --git a/pathspec.h b/pathspec.h
index 937ec91..cc5841b 100644
--- a/pathspec.h
+++ b/pathspec.h
@@ -16,6 +16,7 @@ struct pathspec {
int max_depth;
struct pathspec_item {
const char *match;
+ const char *original;
unsigned magic;
int len;
int nowildcard_len;
--
1.8.0.rc0.19.g7bbb31d
^ permalink raw reply related
* [PATCH v1 06/45] Add parse_pathspec() that converts cmdline args to struct pathspec
From: Nguyễn Thái Ngọc Duy @ 2013-03-15 6:06 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1363327620-29017-1-git-send-email-pclouds@gmail.com>
Currently to fill a struct pathspec, we do:
const char **paths;
paths = get_pathspec(prefix, argv);
...
init_pathspec(&pathspec, paths);
"paths" can only carry bare strings, which loses information from
command line arguments such as pathspec magic or the prefix part's
length for each argument.
parse_pathspec() is introduced to combine the two calls into one. The
plan is gradually replace all get_pathspec() and init_pathspec() with
parse_pathspec(). get_pathspec() now becomes a thin wrapper of
parse_pathspec().
parse_pathspec() allows the caller to reject the pathspec magics that
it does not support. When a new pathspec magic is introduced, we can
enable it per command after making sure that all underlying code has no
problem with the new magic.
"flags" parameter is currently unused. But it would allow callers to
pass certain instructions to parse_pathspec, for example forcing
literal pathspec when no magic is used.
With the introduction of parse_pathspec, there are now two functions
that can initialize struct pathspec: init_pathspec and
parse_pathspec. Any semantic changes in struct pathspec must be
reflected in both functions. init_pathspec() will be phased out in
favor of parse_pathspec().
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
dir.c | 4 +-
dir.h | 2 +
pathspec.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++--------------
pathspec.h | 11 ++++
4 files changed, 144 insertions(+), 40 deletions(-)
diff --git a/dir.c b/dir.c
index 97ad45b..a442467 100644
--- a/dir.c
+++ b/dir.c
@@ -338,7 +338,7 @@ int match_pathspec_depth(const struct pathspec *ps,
/*
* Return the length of the "simple" part of a path match limiter.
*/
-static int simple_length(const char *match)
+int simple_length(const char *match)
{
int len = -1;
@@ -350,7 +350,7 @@ static int simple_length(const char *match)
}
}
-static int no_wildcard(const char *string)
+int no_wildcard(const char *string)
{
return string[simple_length(string)] == '\0';
}
diff --git a/dir.h b/dir.h
index c3eb4b5..89427fd 100644
--- a/dir.h
+++ b/dir.h
@@ -125,6 +125,8 @@ struct dir_struct {
#define MATCHED_RECURSIVELY 1
#define MATCHED_FNMATCH 2
#define MATCHED_EXACTLY 3
+extern int simple_length(const char *match);
+extern int no_wildcard(const char *string);
extern char *common_prefix(const char **pathspec);
extern int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen);
extern int match_pathspec_depth(const struct pathspec *pathspec,
diff --git a/pathspec.c b/pathspec.c
index ab53b8a..bc9d9ac 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -103,10 +103,6 @@ void die_if_path_beyond_symlink(const char *path, const char *prefix)
/*
* Magic pathspec
*
- * NEEDSWORK: These need to be moved to dir.h or even to a new
- * pathspec.h when we restructure get_pathspec() users to use the
- * "struct pathspec" interface.
- *
* Possible future magic semantics include stuff like:
*
* { PATHSPEC_NOGLOB, '!', "noglob" },
@@ -115,7 +111,6 @@ void die_if_path_beyond_symlink(const char *path, const char *prefix)
* { PATHSPEC_REGEXP, '\0', "regexp" },
*
*/
-#define PATHSPEC_FROMTOP (1<<0)
static struct pathspec_magic {
unsigned bit;
@@ -127,7 +122,7 @@ static struct pathspec_magic {
/*
* Take an element of a pathspec and check for magic signatures.
- * Append the result to the prefix.
+ * Append the result to the prefix. Return the magic bitmap.
*
* For now, we only parse the syntax and throw out anything other than
* "top" magic.
@@ -138,10 +133,15 @@ static struct pathspec_magic {
* the prefix part must always match literally, and a single stupid
* string cannot express such a case.
*/
-static const char *prefix_pathspec(const char *prefix, int prefixlen, const char *elt)
+static unsigned prefix_pathspec(struct pathspec_item *item,
+ unsigned *p_short_magic,
+ const char **raw, unsigned flags,
+ const char *prefix, int prefixlen,
+ const char *elt)
{
- unsigned magic = 0;
+ unsigned magic = 0, short_magic = 0;
const char *copyfrom = elt;
+ char *match;
int i;
if (elt[0] != ':') {
@@ -183,7 +183,7 @@ static const char *prefix_pathspec(const char *prefix, int prefixlen, const char
break;
for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++)
if (pathspec_magic[i].mnemonic == ch) {
- magic |= pathspec_magic[i].bit;
+ short_magic |= pathspec_magic[i].bit;
break;
}
if (ARRAY_SIZE(pathspec_magic) <= i)
@@ -194,15 +194,127 @@ static const char *prefix_pathspec(const char *prefix, int prefixlen, const char
copyfrom++;
}
+ magic |= short_magic;
+ *p_short_magic = short_magic;
+
if (magic & PATHSPEC_FROMTOP)
- return xstrdup(copyfrom);
+ match = xstrdup(copyfrom);
else
- return prefix_path(prefix, prefixlen, copyfrom);
+ match = prefix_path(prefix, prefixlen, copyfrom);
+ *raw = item->match = match;
+ item->len = strlen(item->match);
+ if (limit_pathspec_to_literal())
+ item->nowildcard_len = item->len;
+ else
+ item->nowildcard_len = simple_length(item->match);
+ item->flags = 0;
+ if (item->nowildcard_len < item->len &&
+ item->match[item->nowildcard_len] == '*' &&
+ no_wildcard(item->match + item->nowildcard_len + 1))
+ item->flags |= PATHSPEC_ONESTAR;
+ return magic;
+}
+
+static int pathspec_item_cmp(const void *a_, const void *b_)
+{
+ struct pathspec_item *a, *b;
+
+ a = (struct pathspec_item *)a_;
+ b = (struct pathspec_item *)b_;
+ return strcmp(a->match, b->match);
+}
+
+static void NORETURN unsupported_magic(const char *pattern,
+ unsigned magic,
+ unsigned short_magic)
+{
+ struct strbuf sb = STRBUF_INIT;
+ int i, n;
+ for (n = 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 (short_magic & m->bit)
+ strbuf_addf(&sb, "'%c'", m->mnemonic);
+ else
+ strbuf_addf(&sb, "'%s'", m->name);
+ n++;
+ }
+ /*
+ * We may want to substitue "this command" with a command
+ * name. E.g. when add--interactive dies when running
+ * "checkout -p"
+ */
+ die(_("%s: pathspec magic not supported by this command: %s"),
+ pattern, sb.buf);
+}
+
+/*
+ * Given command line arguments and a prefix, convert the input to
+ * pathspec. die() any magic in magic_mask is used.
+ */
+void parse_pathspec(struct pathspec *pathspec,
+ unsigned magic_mask, unsigned flags,
+ const char *prefix, const char **argv)
+{
+ struct pathspec_item *item;
+ const char *entry = argv ? *argv : NULL;
+ int i, n, prefixlen;
+
+ memset(pathspec, 0, sizeof(*pathspec));
+
+ /* No arguments, no prefix -> no pathspec */
+ if (!entry && !prefix)
+ return;
+
+ /* No arguments with prefix -> prefix pathspec */
+ if (!entry) {
+ static const char *raw[2];
+
+ pathspec->items = item = xmalloc(sizeof(*item));
+ item->match = prefix;
+ item->nowildcard_len = item->len = strlen(prefix);
+ raw[0] = prefix;
+ raw[1] = NULL;
+ pathspec->nr = 1;
+ pathspec->raw = raw;
+ return;
+ }
+
+ n = 0;
+ while (argv[n])
+ n++;
+
+ pathspec->nr = n;
+ pathspec->items = item = xmalloc(sizeof(*item) * n);
+ pathspec->raw = argv;
+ prefixlen = prefix ? strlen(prefix) : 0;
+
+ for (i = 0; i < n; i++) {
+ unsigned short_magic;
+ entry = argv[i];
+
+ item[i].magic = prefix_pathspec(item + i, &short_magic,
+ argv + i, flags,
+ prefix, prefixlen, entry);
+ if (item[i].magic & magic_mask)
+ unsupported_magic(entry,
+ item[i].magic & magic_mask,
+ short_magic);
+ if (item[i].nowildcard_len < item[i].len)
+ pathspec->has_wildcard = 1;
+ pathspec->magic |= item[i].magic;
+ }
+
+ qsort(pathspec->items, pathspec->nr,
+ sizeof(struct pathspec_item), pathspec_item_cmp);
}
/*
* N.B. get_pathspec() is deprecated in favor of the "struct pathspec"
- * based interface - see pathspec_magic above.
+ * based interface - see pathspec.c:parse_pathspec().
*
* Arguments:
* - prefix - a path relative to the root of the working tree
@@ -221,32 +333,11 @@ static const char *prefix_pathspec(const char *prefix, int prefixlen, const char
*/
const char **get_pathspec(const char *prefix, const char **pathspec)
{
- const char *entry = *pathspec;
- const char **src, **dst;
- int prefixlen;
-
- if (!prefix && !entry)
- return NULL;
-
- if (!entry) {
- static const char *spec[2];
- spec[0] = prefix;
- spec[1] = NULL;
- return spec;
- }
-
- /* Otherwise we have to re-write the entries.. */
- src = pathspec;
- dst = pathspec;
- prefixlen = prefix ? strlen(prefix) : 0;
- while (*src) {
- *(dst++) = prefix_pathspec(prefix, prefixlen, *src);
- src++;
- }
- *dst = NULL;
- if (!*pathspec)
- return NULL;
- return pathspec;
+ struct pathspec ps;
+ parse_pathspec(&ps,
+ PATHSPEC_ALL_MAGIC & ~PATHSPEC_FROMTOP,
+ 0, prefix, pathspec);
+ return ps.raw;
}
void copy_pathspec(struct pathspec *dst, const struct pathspec *src)
diff --git a/pathspec.h b/pathspec.h
index a621676..937ec91 100644
--- a/pathspec.h
+++ b/pathspec.h
@@ -1,6 +1,10 @@
#ifndef PATHSPEC_H
#define PATHSPEC_H
+/* Pathspec magic */
+#define PATHSPEC_FROMTOP (1<<0)
+#define PATHSPEC_ALL_MAGIC PATHSPEC_FROMTOP
+
#define PATHSPEC_ONESTAR 1 /* the pathspec pattern sastisfies GFNM_ONESTAR */
struct pathspec {
@@ -8,9 +12,11 @@ struct pathspec {
int nr;
unsigned int has_wildcard:1;
unsigned int recursive:1;
+ unsigned magic;
int max_depth;
struct pathspec_item {
const char *match;
+ unsigned magic;
int len;
int nowildcard_len;
int flags;
@@ -18,6 +24,11 @@ struct pathspec {
};
extern int init_pathspec(struct pathspec *, const char **);
+extern void parse_pathspec(struct pathspec *pathspec,
+ unsigned magic_mask,
+ unsigned flags,
+ const char *prefix,
+ const char **args);
extern void copy_pathspec(struct pathspec *dst, const struct pathspec *src);
extern void free_pathspec(struct pathspec *);
--
1.8.0.rc0.19.g7bbb31d
^ permalink raw reply related
* [PATCH v1 05/45] pathspec: add copy_pathspec
From: Nguyễn Thái Ngọc Duy @ 2013-03-15 6:06 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1363327620-29017-1-git-send-email-pclouds@gmail.com>
The function is made to use with free_pathspec() because a simple
struct assignment is not enough (free_pathspec wants to free "items"
pointer).
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
builtin/mv.c | 13 +++++++------
pathspec.c | 8 ++++++++
pathspec.h | 1 +
3 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/builtin/mv.c b/builtin/mv.c
index 034fec9..16ce99b 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -15,8 +15,9 @@ static const char * const builtin_mv_usage[] = {
NULL
};
-static const char **copy_pathspec(const char *prefix, const char **pathspec,
- int count, int base_name)
+static const char **internal_copy_pathspec(const char *prefix,
+ const char **pathspec,
+ int count, int base_name)
{
int i;
const char **result = xmalloc((count + 1) * sizeof(const char *));
@@ -81,17 +82,17 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
if (read_cache() < 0)
die(_("index file corrupt"));
- source = copy_pathspec(prefix, argv, argc, 0);
+ source = internal_copy_pathspec(prefix, argv, argc, 0);
modes = xcalloc(argc, sizeof(enum update_mode));
- dest_path = copy_pathspec(prefix, argv + argc, 1, 0);
+ dest_path = internal_copy_pathspec(prefix, argv + argc, 1, 0);
if (dest_path[0][0] == '\0')
/* special case: "." was normalized to "" */
- destination = copy_pathspec(dest_path[0], argv, argc, 1);
+ destination = internal_copy_pathspec(dest_path[0], argv, argc, 1);
else if (!lstat(dest_path[0], &st) &&
S_ISDIR(st.st_mode)) {
dest_path[0] = add_slash(dest_path[0]);
- destination = copy_pathspec(dest_path[0], argv, argc, 1);
+ destination = internal_copy_pathspec(dest_path[0], argv, argc, 1);
} else {
if (argc != 1)
die("destination '%s' is not a directory", dest_path[0]);
diff --git a/pathspec.c b/pathspec.c
index 94d64d2..ab53b8a 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -248,3 +248,11 @@ const char **get_pathspec(const char *prefix, const char **pathspec)
return NULL;
return pathspec;
}
+
+void copy_pathspec(struct pathspec *dst, const struct pathspec *src)
+{
+ *dst = *src;
+ dst->items = xmalloc(sizeof(struct pathspec_item) * dst->nr);
+ memcpy(dst->items, src->items,
+ sizeof(struct pathspec_item) * dst->nr);
+}
diff --git a/pathspec.h b/pathspec.h
index 7884068..a621676 100644
--- a/pathspec.h
+++ b/pathspec.h
@@ -18,6 +18,7 @@ struct pathspec {
};
extern int init_pathspec(struct pathspec *, const char **);
+extern void copy_pathspec(struct pathspec *dst, const struct pathspec *src);
extern void free_pathspec(struct pathspec *);
extern int limit_pathspec_to_literal(void);
--
1.8.0.rc0.19.g7bbb31d
^ permalink raw reply related
* [PATCH v1 04/45] pathspec: i18n-ize error strings in pathspec parsing code
From: Nguyễn Thái Ngọc Duy @ 2013-03-15 6:06 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1363327620-29017-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
pathspec.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/pathspec.c b/pathspec.c
index aa3e4d0..94d64d2 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -166,11 +166,11 @@ static const char *prefix_pathspec(const char *prefix, int prefixlen, const char
break;
}
if (ARRAY_SIZE(pathspec_magic) <= i)
- die("Invalid pathspec magic '%.*s' in '%s'",
+ die(_("Invalid pathspec magic '%.*s' in '%s'"),
(int) len, copyfrom, elt);
}
if (*copyfrom != ')')
- die("Missing ')' at the end of pathspec magic in '%s'", elt);
+ die(_("Missing ')' at the end of pathspec magic in '%s'"), elt);
copyfrom++;
} else {
/* shorthand */
@@ -187,7 +187,7 @@ static const char *prefix_pathspec(const char *prefix, int prefixlen, const char
break;
}
if (ARRAY_SIZE(pathspec_magic) <= i)
- die("Unimplemented pathspec magic '%c' in '%s'",
+ die(_("Unimplemented pathspec magic '%c' in '%s'"),
ch, elt);
}
if (*copyfrom == ':')
--
1.8.0.rc0.19.g7bbb31d
^ permalink raw reply related
* [PATCH v1 03/45] Move struct pathspec and related functions to pathspec.[ch]
From: Nguyễn Thái Ngọc Duy @ 2013-03-15 6:06 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1363327620-29017-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
archive.c | 1 +
builtin/grep.c | 1 +
builtin/ls-files.c | 1 +
builtin/ls-tree.c | 1 +
builtin/update-index.c | 1 +
cache.h | 22 +-------
diff.h | 1 +
dir.c | 1 +
pathspec.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++
pathspec.h | 21 +++++++
preload-index.c | 1 +
setup.c | 149 -------------------------------------------------
tree-walk.c | 1 +
13 files changed, 181 insertions(+), 169 deletions(-)
diff --git a/archive.c b/archive.c
index 93e00bb..72c6b0f 100644
--- a/archive.c
+++ b/archive.c
@@ -5,6 +5,7 @@
#include "archive.h"
#include "parse-options.h"
#include "unpack-trees.h"
+#include "pathspec.h"
static char const * const archive_usage[] = {
N_("git archive [options] <tree-ish> [<path>...]"),
diff --git a/builtin/grep.c b/builtin/grep.c
index 8025964..3701c2e 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -17,6 +17,7 @@
#include "grep.h"
#include "quote.h"
#include "dir.h"
+#include "pathspec.h"
static char const * const grep_usage[] = {
N_("git grep [options] [-e] <pattern> [<rev>...] [[--] <path>...]"),
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 175e6e3..752570b 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -13,6 +13,7 @@
#include "parse-options.h"
#include "resolve-undo.h"
#include "string-list.h"
+#include "pathspec.h"
static int abbrev;
static int show_deleted;
diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
index fb76e38..93fc3a0 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -10,6 +10,7 @@
#include "quote.h"
#include "builtin.h"
#include "parse-options.h"
+#include "pathspec.h"
static int line_termination = '\n';
#define LS_RECURSIVE 1
diff --git a/builtin/update-index.c b/builtin/update-index.c
index ada1dff..ffae585 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -11,6 +11,7 @@
#include "refs.h"
#include "resolve-undo.h"
#include "parse-options.h"
+#include "pathspec.h"
/*
* Default to not allowing changes to the list of files. The
diff --git a/cache.h b/cache.h
index e493563..5115c1b 100644
--- a/cache.h
+++ b/cache.h
@@ -182,6 +182,8 @@ struct cache_entry {
#error "CE_EXTENDED_FLAGS out of range"
#endif
+struct pathspec;
+
/*
* Copy the sha1 and stat state of a cache entry from one to
* another. But we never change the name, or the hash state!
@@ -474,28 +476,8 @@ extern int index_name_is_other(const struct index_state *, const char *, int);
extern int ie_match_stat(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);
extern int ie_modified(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);
-#define PATHSPEC_ONESTAR 1 /* the pathspec pattern sastisfies GFNM_ONESTAR */
-
-struct pathspec {
- const char **raw; /* get_pathspec() result, not freed by free_pathspec() */
- int nr;
- unsigned int has_wildcard:1;
- unsigned int recursive:1;
- int max_depth;
- struct pathspec_item {
- const char *match;
- int len;
- int nowildcard_len;
- int flags;
- } *items;
-};
-
-extern int init_pathspec(struct pathspec *, const char **);
-extern void free_pathspec(struct pathspec *);
extern int ce_path_match(const struct cache_entry *ce, const struct pathspec *pathspec);
-extern int limit_pathspec_to_literal(void);
-
#define HASH_WRITE_OBJECT 1
#define HASH_FORMAT_CHECK 2
extern int index_fd(unsigned char *sha1, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
diff --git a/diff.h b/diff.h
index 78b4091..d1bc914 100644
--- a/diff.h
+++ b/diff.h
@@ -5,6 +5,7 @@
#define DIFF_H
#include "tree-walk.h"
+#include "pathspec.h"
struct rev_info;
struct diff_options;
diff --git a/dir.c b/dir.c
index 57394e4..97ad45b 100644
--- a/dir.c
+++ b/dir.c
@@ -11,6 +11,7 @@
#include "dir.h"
#include "refs.h"
#include "wildmatch.h"
+#include "pathspec.h"
struct path_simplify {
int len;
diff --git a/pathspec.c b/pathspec.c
index 284f397..aa3e4d0 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -99,3 +99,152 @@ void die_if_path_beyond_symlink(const char *path, const char *prefix)
die(_("'%s' is beyond a symbolic link"), path + len);
}
}
+
+/*
+ * Magic pathspec
+ *
+ * NEEDSWORK: These need to be moved to dir.h or even to a new
+ * pathspec.h when we restructure get_pathspec() users to use the
+ * "struct pathspec" interface.
+ *
+ * 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)
+
+static struct pathspec_magic {
+ unsigned bit;
+ char mnemonic; /* this cannot be ':'! */
+ const char *name;
+} pathspec_magic[] = {
+ { PATHSPEC_FROMTOP, '/', "top" },
+};
+
+/*
+ * Take an element of a pathspec and check for magic signatures.
+ * Append the result to the prefix.
+ *
+ * For now, we only parse the syntax and throw out anything other than
+ * "top" magic.
+ *
+ * NEEDSWORK: This needs to be rewritten when we start migrating
+ * get_pathspec() users to use the "struct pathspec" interface. For
+ * example, a pathspec element may be marked as case-insensitive, but
+ * the prefix part must always match literally, and a single stupid
+ * string cannot express such a case.
+ */
+static const char *prefix_pathspec(const char *prefix, int prefixlen, const char *elt)
+{
+ unsigned magic = 0;
+ const char *copyfrom = elt;
+ int i;
+
+ if (elt[0] != ':') {
+ ; /* nothing to do */
+ } else if (elt[1] == '(') {
+ /* longhand */
+ const char *nextat;
+ for (copyfrom = elt + 2;
+ *copyfrom && *copyfrom != ')';
+ copyfrom = nextat) {
+ size_t len = strcspn(copyfrom, ",)");
+ if (copyfrom[len] == ')')
+ nextat = copyfrom + len;
+ else
+ nextat = copyfrom + len + 1;
+ if (!len)
+ continue;
+ for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++)
+ if (strlen(pathspec_magic[i].name) == len &&
+ !strncmp(pathspec_magic[i].name, copyfrom, len)) {
+ magic |= pathspec_magic[i].bit;
+ break;
+ }
+ if (ARRAY_SIZE(pathspec_magic) <= i)
+ die("Invalid pathspec magic '%.*s' in '%s'",
+ (int) len, copyfrom, elt);
+ }
+ if (*copyfrom != ')')
+ die("Missing ')' at the end of pathspec magic in '%s'", elt);
+ copyfrom++;
+ } else {
+ /* shorthand */
+ for (copyfrom = elt + 1;
+ *copyfrom && *copyfrom != ':';
+ copyfrom++) {
+ char ch = *copyfrom;
+
+ if (!is_pathspec_magic(ch))
+ break;
+ for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++)
+ if (pathspec_magic[i].mnemonic == ch) {
+ magic |= pathspec_magic[i].bit;
+ break;
+ }
+ if (ARRAY_SIZE(pathspec_magic) <= i)
+ die("Unimplemented pathspec magic '%c' in '%s'",
+ ch, elt);
+ }
+ if (*copyfrom == ':')
+ copyfrom++;
+ }
+
+ if (magic & PATHSPEC_FROMTOP)
+ return xstrdup(copyfrom);
+ else
+ return prefix_path(prefix, prefixlen, copyfrom);
+}
+
+/*
+ * N.B. get_pathspec() is deprecated in favor of the "struct pathspec"
+ * based interface - see pathspec_magic above.
+ *
+ * Arguments:
+ * - prefix - a path relative to the root of the working tree
+ * - pathspec - a list of paths underneath the prefix path
+ *
+ * Iterates over pathspec, prepending each path with prefix,
+ * and return the resulting list.
+ *
+ * If pathspec is empty, return a singleton list containing prefix.
+ *
+ * If pathspec and prefix are both empty, return an empty list.
+ *
+ * This is typically used by built-in commands such as add.c, in order
+ * to normalize argv arguments provided to the built-in into a list of
+ * paths to process, all relative to the root of the working tree.
+ */
+const char **get_pathspec(const char *prefix, const char **pathspec)
+{
+ const char *entry = *pathspec;
+ const char **src, **dst;
+ int prefixlen;
+
+ if (!prefix && !entry)
+ return NULL;
+
+ if (!entry) {
+ static const char *spec[2];
+ spec[0] = prefix;
+ spec[1] = NULL;
+ return spec;
+ }
+
+ /* Otherwise we have to re-write the entries.. */
+ src = pathspec;
+ dst = pathspec;
+ prefixlen = prefix ? strlen(prefix) : 0;
+ while (*src) {
+ *(dst++) = prefix_pathspec(prefix, prefixlen, *src);
+ src++;
+ }
+ *dst = NULL;
+ if (!*pathspec)
+ return NULL;
+ return pathspec;
+}
diff --git a/pathspec.h b/pathspec.h
index db0184a..7884068 100644
--- a/pathspec.h
+++ b/pathspec.h
@@ -1,6 +1,27 @@
#ifndef PATHSPEC_H
#define PATHSPEC_H
+#define PATHSPEC_ONESTAR 1 /* the pathspec pattern sastisfies GFNM_ONESTAR */
+
+struct pathspec {
+ const char **raw; /* get_pathspec() result, not freed by free_pathspec() */
+ int nr;
+ unsigned int has_wildcard:1;
+ unsigned int recursive:1;
+ int max_depth;
+ struct pathspec_item {
+ const char *match;
+ int len;
+ int nowildcard_len;
+ int flags;
+ } *items;
+};
+
+extern int init_pathspec(struct pathspec *, const char **);
+extern void free_pathspec(struct pathspec *);
+
+extern int limit_pathspec_to_literal(void);
+
extern char *find_pathspecs_matching_against_index(const char **pathspec);
extern void add_pathspec_matches_against_index(const char **pathspec, char *seen, int specs);
extern const char *check_path_for_gitlink(const char *path);
diff --git a/preload-index.c b/preload-index.c
index 49cb08d..cddfffa 100644
--- a/preload-index.c
+++ b/preload-index.c
@@ -2,6 +2,7 @@
* Copyright (C) 2008 Linus Torvalds
*/
#include "cache.h"
+#include "pathspec.h"
#ifdef NO_PTHREADS
static void preload_index(struct index_state *index, const char **pathspec)
diff --git a/setup.c b/setup.c
index d0cd784..acdc634 100644
--- a/setup.c
+++ b/setup.c
@@ -155,155 +155,6 @@ void verify_non_filename(const char *prefix, const char *arg)
}
/*
- * Magic pathspec
- *
- * NEEDSWORK: These need to be moved to dir.h or even to a new
- * pathspec.h when we restructure get_pathspec() users to use the
- * "struct pathspec" interface.
- *
- * 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)
-
-static struct pathspec_magic {
- unsigned bit;
- char mnemonic; /* this cannot be ':'! */
- const char *name;
-} pathspec_magic[] = {
- { PATHSPEC_FROMTOP, '/', "top" },
-};
-
-/*
- * Take an element of a pathspec and check for magic signatures.
- * Append the result to the prefix.
- *
- * For now, we only parse the syntax and throw out anything other than
- * "top" magic.
- *
- * NEEDSWORK: This needs to be rewritten when we start migrating
- * get_pathspec() users to use the "struct pathspec" interface. For
- * example, a pathspec element may be marked as case-insensitive, but
- * the prefix part must always match literally, and a single stupid
- * string cannot express such a case.
- */
-static const char *prefix_pathspec(const char *prefix, int prefixlen, const char *elt)
-{
- unsigned magic = 0;
- const char *copyfrom = elt;
- int i;
-
- if (elt[0] != ':') {
- ; /* nothing to do */
- } else if (elt[1] == '(') {
- /* longhand */
- const char *nextat;
- for (copyfrom = elt + 2;
- *copyfrom && *copyfrom != ')';
- copyfrom = nextat) {
- size_t len = strcspn(copyfrom, ",)");
- if (copyfrom[len] == ')')
- nextat = copyfrom + len;
- else
- nextat = copyfrom + len + 1;
- if (!len)
- continue;
- for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++)
- if (strlen(pathspec_magic[i].name) == len &&
- !strncmp(pathspec_magic[i].name, copyfrom, len)) {
- magic |= pathspec_magic[i].bit;
- break;
- }
- if (ARRAY_SIZE(pathspec_magic) <= i)
- die("Invalid pathspec magic '%.*s' in '%s'",
- (int) len, copyfrom, elt);
- }
- if (*copyfrom != ')')
- die("Missing ')' at the end of pathspec magic in '%s'", elt);
- copyfrom++;
- } else {
- /* shorthand */
- for (copyfrom = elt + 1;
- *copyfrom && *copyfrom != ':';
- copyfrom++) {
- char ch = *copyfrom;
-
- if (!is_pathspec_magic(ch))
- break;
- for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++)
- if (pathspec_magic[i].mnemonic == ch) {
- magic |= pathspec_magic[i].bit;
- break;
- }
- if (ARRAY_SIZE(pathspec_magic) <= i)
- die("Unimplemented pathspec magic '%c' in '%s'",
- ch, elt);
- }
- if (*copyfrom == ':')
- copyfrom++;
- }
-
- if (magic & PATHSPEC_FROMTOP)
- return xstrdup(copyfrom);
- else
- return prefix_path(prefix, prefixlen, copyfrom);
-}
-
-/*
- * N.B. get_pathspec() is deprecated in favor of the "struct pathspec"
- * based interface - see pathspec_magic above.
- *
- * Arguments:
- * - prefix - a path relative to the root of the working tree
- * - pathspec - a list of paths underneath the prefix path
- *
- * Iterates over pathspec, prepending each path with prefix,
- * and return the resulting list.
- *
- * If pathspec is empty, return a singleton list containing prefix.
- *
- * If pathspec and prefix are both empty, return an empty list.
- *
- * This is typically used by built-in commands such as add.c, in order
- * to normalize argv arguments provided to the built-in into a list of
- * paths to process, all relative to the root of the working tree.
- */
-const char **get_pathspec(const char *prefix, const char **pathspec)
-{
- const char *entry = *pathspec;
- const char **src, **dst;
- int prefixlen;
-
- if (!prefix && !entry)
- return NULL;
-
- if (!entry) {
- static const char *spec[2];
- spec[0] = prefix;
- spec[1] = NULL;
- return spec;
- }
-
- /* Otherwise we have to re-write the entries.. */
- src = pathspec;
- dst = pathspec;
- prefixlen = prefix ? strlen(prefix) : 0;
- while (*src) {
- *(dst++) = prefix_pathspec(prefix, prefixlen, *src);
- src++;
- }
- *dst = NULL;
- if (!*pathspec)
- return NULL;
- return pathspec;
-}
-
-/*
* Test if it looks like we're at a git directory.
* We want to see:
*
diff --git a/tree-walk.c b/tree-walk.c
index 6e30ef9..72a9613 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -3,6 +3,7 @@
#include "unpack-trees.h"
#include "dir.h"
#include "tree.h"
+#include "pathspec.h"
static const char *get_mode(const char *str, unsigned int *modep)
{
--
1.8.0.rc0.19.g7bbb31d
^ permalink raw reply related
* [PATCH v1 02/45] clean: remove unused variable "seen"
From: Nguyễn Thái Ngọc Duy @ 2013-03-15 6:06 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1363327620-29017-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
builtin/clean.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/builtin/clean.c b/builtin/clean.c
index 04e396b..f955a40 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -155,7 +155,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
struct string_list exclude_list = STRING_LIST_INIT_NODUP;
struct exclude_list *el;
const char *qname;
- char *seen = NULL;
struct option options[] = {
OPT__QUIET(&quiet, N_("do not print names of files removed")),
OPT__DRY_RUN(&dry_run, N_("dry run")),
@@ -214,9 +213,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
fill_directory(&dir, pathspec);
- if (pathspec)
- seen = xmalloc(argc > 0 ? argc : 1);
-
for (i = 0; i < dir.nr; i++) {
struct dir_entry *ent = dir.entries[i];
int len, pos;
@@ -250,11 +246,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
if (lstat(ent->name, &st))
continue;
- if (pathspec) {
- memset(seen, 0, argc > 0 ? argc : 1);
+ if (pathspec)
matches = match_pathspec(pathspec, ent->name, len,
- 0, seen);
- }
+ 0, NULL);
if (S_ISDIR(st.st_mode)) {
strbuf_addstr(&directory, ent->name);
@@ -281,7 +275,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
}
}
}
- free(seen);
strbuf_release(&directory);
string_list_clear(&exclude_list, 0);
--
1.8.0.rc0.19.g7bbb31d
^ permalink raw reply related
* [PATCH v1 01/45] setup.c: check that the pathspec magic ends with ")"
From: Nguyễn Thái Ngọc Duy @ 2013-03-15 6:06 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Andrew Wong,
Nguyễn Thái Ngọc Duy
In-Reply-To: <1363327620-29017-1-git-send-email-pclouds@gmail.com>
From: Andrew Wong <andrew.kw.w@gmail.com>
The previous code did not diagnose an incorrectly spelled ":(top"
as an error.
Signed-off-by: Andrew Wong <andrew.kw.w@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
setup.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/setup.c b/setup.c
index 1dee47e..d0cd784 100644
--- a/setup.c
+++ b/setup.c
@@ -223,8 +223,9 @@ static const char *prefix_pathspec(const char *prefix, int prefixlen, const char
die("Invalid pathspec magic '%.*s' in '%s'",
(int) len, copyfrom, elt);
}
- if (*copyfrom == ')')
- copyfrom++;
+ if (*copyfrom != ')')
+ die("Missing ')' at the end of pathspec magic in '%s'", elt);
+ copyfrom++;
} else {
/* shorthand */
for (copyfrom = elt + 1;
--
1.8.0.rc0.19.g7bbb31d
^ permalink raw reply related
* [PATCH v1 00/45] nd/parse-pathspec and :(glob) pathspec magic
From: Nguyễn Thái Ngọc Duy @ 2013-03-15 6:06 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
Probably not much to say. A big portion of this series is the
conversion to struct pathspec, which enables more use of pathspec
magic. :(glob) magic is added to verify that the conversion makes
sense.
Andrew Wong (1):
setup.c: check that the pathspec magic ends with ")"
Nguyễn Thái Ngọc Duy (44):
clean: remove unused variable "seen"
Move struct pathspec and related functions to pathspec.[ch]
pathspec: i18n-ize error strings in pathspec parsing code
pathspec: add copy_pathspec
Add parse_pathspec() that converts cmdline args to struct pathspec
parse_pathspec: save original pathspec for reporting
parse_pathspec: add PATHSPEC_PREFER_{CWD,FULL}
Convert some get_pathspec() calls to parse_pathspec()
parse_pathspec: a special flag for max_depth feature
parse_pathspec: support stripping submodule trailing slashes
parse_pathspec: support stripping/checking submodule paths
parse_pathspec: support prefixing original patterns
Guard against new pathspec magic in pathspec matching code
clean: convert to use parse_pathspec
commit: convert to use parse_pathspec
status: convert to use parse_pathspec
rerere: convert to use parse_pathspec
checkout: convert to use parse_pathspec
rm: convert to use parse_pathspec
ls-files: convert to use parse_pathspec
archive: convert to use parse_pathspec
check-ignore: convert to use parse_pathspec
add: convert to use parse_pathspec
reset: convert to use parse_pathspec
Convert read_cache_preload() to take struct pathspec
Convert run_add_interactive to use struct pathspec
Convert unmerge_cache to take struct pathspec
checkout: convert read_tree_some to take struct pathspec
Convert report_path_error to take struct pathspec
Convert refresh_index to take struct pathspec
Convert {read,fill}_directory to take struct pathspec
Convert add_files_to_cache to take struct pathspec
Convert common_prefix() to use struct pathspec
Remove diff_tree_{setup,release}_paths
Remove init_pathspec() in favor of parse_pathspec()
Remove match_pathspec() in favor of match_pathspec_depth()
tree-diff: remove the use of pathspec's raw[] in follow-rename codepath
parse_pathspec: make sure the prefix part is wildcard-free
parse_pathspec: preserve prefix length via PATHSPEC_PREFIX_ORIGIN
Kill limit_pathspec_to_literal() as it's only used by parse_pathspec()
pathspec: support :(literal) syntax for noglob pathspec
pathspec: make --literal-pathspecs disable pathspec magic
pathspec: support :(glob) syntax
Rename field "raw" to "_raw" in struct pathspec
Documentation/git.txt | 23 +-
Documentation/glossary-content.txt | 33 +++
archive.c | 18 +-
archive.h | 4 +-
builtin/add.c | 156 ++++++--------
builtin/blame.c | 14 +-
builtin/check-ignore.c | 34 +--
builtin/checkout.c | 46 ++--
builtin/clean.c | 24 +--
builtin/commit.c | 37 ++--
builtin/diff-files.c | 2 +-
builtin/diff-index.c | 2 +-
builtin/diff.c | 6 +-
builtin/grep.c | 10 +-
builtin/log.c | 2 +-
builtin/ls-files.c | 75 +++----
builtin/ls-tree.c | 13 +-
builtin/mv.c | 13 +-
builtin/rerere.c | 8 +-
builtin/reset.c | 33 +--
builtin/rm.c | 24 +--
builtin/update-index.c | 6 +-
cache.h | 34 +--
commit.h | 2 +-
diff-lib.c | 3 +-
diff.h | 3 +-
dir.c | 261 +++++-----------------
dir.h | 18 +-
git.c | 8 +
merge-recursive.c | 2 +-
notes-merge.c | 4 +-
path.c | 15 +-
pathspec.c | 431 +++++++++++++++++++++++++++++++++----
pathspec.h | 59 ++++-
preload-index.c | 21 +-
read-cache.c | 5 +-
rerere.c | 7 +-
rerere.h | 4 +-
resolve-undo.c | 4 +-
resolve-undo.h | 2 +-
revision.c | 11 +-
setup.c | 157 +-------------
t/t0008-ignores.sh | 8 +-
t/t6130-pathspec-noglob.sh | 18 ++
tree-diff.c | 48 +++--
tree-walk.c | 21 +-
tree.c | 4 +-
tree.h | 2 +-
wt-status.c | 18 +-
wt-status.h | 2 +-
50 files changed, 983 insertions(+), 772 deletions(-)
--
1.8.0.rc0.19.g7bbb31d
^ permalink raw reply
* Re: [RFD] Combine diff improvements
From: Junio C Hamano @ 2013-03-15 5:54 UTC (permalink / raw)
To: Antoine Pelisse; +Cc: git
In-Reply-To: <CALWbr2zY3uo==QTd69t1eXNS4-CX1w3T-AaMjOLVmxj-SMJyvg@mail.gmail.com>
Antoine Pelisse <apelisse@gmail.com> writes:
> While if we invert the two parents order we will have:
> - 3
> --1
> --2
> - 4
> -3
> -4
>
> While clearly, in both cases, the optimal solution would be close to:
> - 3
> --1
> --2
> -3
> --4
We should shoot for better readability as the primary goal. When I
am viewing "--cc" output, I find it easier to read if the lines for
the same parent are consecutive. That is, I find the right one far
easier to grok than the left one:
- 1 - 1
-2 - 3
- 3 -2
-4 -4
when trying to see what got changed from the first parent (we had 1
and then 3 and whatever comes after this block; 2 and 4 are noise
and it makes it easier to skip them because they are together).
This can probably be done as a post-process phase after you find the
coalescing matches to express the result in the smallest number of
lines, but I thought it is worth mentioning that not all solutions
with the same number of lines are equally good.
^ permalink raw reply
* Re: Tag peeling peculiarities
From: Michael Haggerty @ 2013-03-15 5:12 UTC (permalink / raw)
To: Jeff King; +Cc: Junio C Hamano, git discussion list
In-Reply-To: <20130314134032.GA9222@sigill.intra.peff.net>
On 03/14/2013 02:40 PM, Jeff King wrote:
> On Thu, Mar 14, 2013 at 12:28:53PM +0100, Michael Haggerty wrote:
>
>> Perhaps if peel_ref() *were* 100% reliable, we might be able to use it
>> to avoid object lookups in some other places.
>
> In theory, some of the many uses of deref_tag could be adopted. However,
> we do not always have the refname handy at that point (and I believe
> peel_ref's optimization only kicks in during for_each_ref traversals
> anyway).
>
> It may still be a win to check the packed-refs file before peeling a
> random sha1, as looking up there should be cheaper than actually loading
> the object. But right now, the way the optimization is used is always
> O(1) to just check the last ref loaded. With your recent ref
> refactoring, I think we should be able to do lookups in O(lg n).
There are more conceptual problems in the handling of peeled references
and current_ref. I want to document them here for future reference and
to get other people thinking about whether other parts of the code might
be making wrong assumptions about this stuff.
What is stored in ref_value.peeled? Is it the peeled version of
ref_value.sha1, or is it the peeled version of the associated refname?
Because they are not necessarily the same thing: an entry in the packed
ref_cache *might* be overridden by a loose reference with the same
refname but a different SHA1 which peels to a different value.
Obviously we cannot always guarantee that ref_value.peeled is the peeled
version of the refname, because it is read from a packed-refs file that
might be old. So the only sane policy is that ref_value.peeled should
be the peeled version of ref_value.sha1 regardless of whether the
refname now points elsewhere.
It follows that the only time we can be sure that ref_value.peeled is
the correct peeled version of refname is if we know that there is no
loose reference overriding it.
This leads to some subtleties when reading and writing ref_value.peeled.
When reading ref_value.peeled:
When we iterate over references using do_for_each_ref(), then we only
present a packed ref if there is no loose ref with the same refname. So
in that case it is OK to point current_ref at the packed ref entry, and
if somebody calls peel_ref() for the current reference then (modulo race
conditions?) current_ref->u.value.peeled is indeed the correct peeled
value for that refname.
But if we iterate over *only* the packed refs using
do_for_each_ref_in_dir() (as, for example, in repack_without_ref()),
then the iteration doesn't even look at the loose refs, so we don't know
whether the packed ref_entry being iterated over is authoritative. But
we nevertheless set current_ref to that entry. So if somebody would
call peel_ref() on the current refname during such an iteration, they
could get the peeled version of the packed ref rather than the correct
peeled version for the refname.
Currently, nobody calls peel_ref() during such an iteration, so I don't
think it causes any bugs. But it is an unmarked landmine.
When setting ref_value.peeled:
When determining the value to write to ref_value.peeled (which I believe
only happens in pack-refs), we should record the peeled version of
ref_entry.sha1, and *not* the peeled version of refname. This is indeed
what pack-refs does. But if somebody were to get the clever and
reasonable-sounding idea of using peel_ref() in the implementation of
pack-refs.c:handle_one_ref(), then it would be easy to accidentally get
a peeled value for the current refname rather than for the SHA1 being
recorded in the file.
I am trying to change repack_without_refs() to write the peeled refs to
the packed-refs file (currently the peeled refs are lost if a packed ref
is deleted). For this I would like to reuse the pre-peeled values from
the old version of the packed-refs file to avoid having to resolve them
all again. So all of the issues mentioned above are coming together for me.
I think my solution will be to add a static function in refs.c that
passes pointers to the ref_entries to its callback, so that the function
has direct access to the peeled member rather than having to access it
via the information-losing peel_ref().
Michael
--
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
^ permalink raw reply
* [PATCH] pull: Apply -q and -v options to rebase mode as well
From: Peter Eisentraut @ 2013-03-15 2:26 UTC (permalink / raw)
To: gitster; +Cc: git
git pull passed -q and -v only to git merge, but they can be useful for
git rebase as well, so pass them there, too. In particular, using -q
shuts up the "Already up-to-date." message. Add test cases to prove it.
Signed-off-by: Peter Eisentraut <peter@eisentraut.org>
---
git-pull.sh | 2 +-
t/t5521-pull-options.sh | 27 +++++++++++++++++++++++++++
2 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/git-pull.sh b/git-pull.sh
index 266e682..5d97e97 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -279,7 +279,7 @@ fi
merge_name=$(git fmt-merge-msg $log_arg <"$GIT_DIR/FETCH_HEAD") || exit
case "$rebase" in
true)
- eval="git-rebase $diffstat $strategy_args $merge_args"
+ eval="git-rebase $diffstat $strategy_args $merge_args $verbosity"
eval="$eval --onto $merge_head ${oldremoteref:-$merge_head}"
;;
*)
diff --git a/t/t5521-pull-options.sh b/t/t5521-pull-options.sh
index 1b06691..aa31abe 100755
--- a/t/t5521-pull-options.sh
+++ b/t/t5521-pull-options.sh
@@ -19,6 +19,17 @@ test_expect_success 'git pull -q' '
test ! -s out)
'
+test_expect_success 'git pull -q --rebase' '
+ mkdir clonedqrb &&
+ (cd clonedqrb && git init &&
+ git pull -q --rebase "../parent" >out 2>err &&
+ test ! -s err &&
+ test ! -s out &&
+ git pull -q --rebase "../parent" >out 2>err &&
+ test ! -s err &&
+ test ! -s out)
+'
+
test_expect_success 'git pull' '
mkdir cloned &&
(cd cloned && git init &&
@@ -27,6 +38,14 @@ test_expect_success 'git pull' '
test ! -s out)
'
+test_expect_success 'git pull --rebase' '
+ mkdir clonedrb &&
+ (cd clonedrb && git init &&
+ git pull --rebase "../parent" >out 2>err &&
+ test -s err &&
+ test ! -s out)
+'
+
test_expect_success 'git pull -v' '
mkdir clonedv &&
(cd clonedv && git init &&
@@ -35,6 +54,14 @@ test_expect_success 'git pull -v' '
test ! -s out)
'
+test_expect_success 'git pull -v --rebase' '
+ mkdir clonedvrb &&
+ (cd clonedvrb && git init &&
+ git pull -v --rebase "../parent" >out 2>err &&
+ test -s err &&
+ test ! -s out)
+'
+
test_expect_success 'git pull -v -q' '
mkdir clonedvq &&
(cd clonedvq && git init &&
--
1.7.10.4
^ permalink raw reply related
* Re: [ANN] git-arr 0.11
From: Alberto Bertogli @ 2013-03-15 1:16 UTC (permalink / raw)
To: Matthieu Moy; +Cc: git
In-Reply-To: <vpqppz22luj.fsf@grenoble-inp.fr>
On Thu, Mar 14, 2013 at 01:43:16PM +0100, Matthieu Moy wrote:
> Alberto Bertogli <albertito@blitiri.com.ar> writes:
>
> > I wanted to let you know about git-arr, which is a git repository
> > browser that can generate static HTML instead of having to run
> > dynamically.
>
> Can it run incrementally? I mean, if you have launched it for one
> revision, does re-running it on the next revision regenerate the whole
> set of pages, or does it only generate new pages?
Yes, you can run it incrementally, and it will only generate new pages.
> If so, that could be a nice way to replace dynamic browsers for people
> who do not have/want dynamic webpages, by just setting a hook or cron
> job that generate the new pages when an update is made.
That's my main intended use. I'm using a hook
(http://blitiri.com.ar/git/r/git-arr/b/master/t/hooks/f=post-receive.html)
to update repos when I push to them and it's been working fine for me so
far. I never tried the cron approach but it should work well too.
Thanks!
Alberto
^ permalink raw reply
* Re: Delivery Status Notification (Failure)
From: Harring Figueiredo @ 2013-03-14 23:36 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vsj3xwrzn.fsf@alter.siamese.dyndns.org>
Got it!
From the recommended site:
--
In the English singular case, the number – always 1 – can be replaced
with "one":
printf (ngettext ("One file removed", "%d files removed", n), n);
This works because the ‘printf’ function discards excess arguments
that are not consumed by the format string.
--
Junio, thank you so much for the reply and link to the docs.
-hff
On Thu, Mar 14, 2013 at 6:12 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Harring Figueiredo <harringf@gmail.com> writes:
>
>> Just want to confirm that this is not a bug:
>> ...
>> printf_ln(Q_("The bundle requires this ref",
>> "The bundle requires these %d refs",
>> r->nr),
>> r->nr);
>> ...
>> seems to be missing %d parameter on the first message.
>
> Perhaps visit
>
> http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms
>
> look for "In the English singular case,..." and read the
> explanation there?
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox