* [PATCH] fast-export: Allow pruned-references in mark file
From: Antoine Pelisse @ 2012-11-24 9:47 UTC (permalink / raw)
To: git; +Cc: Antoine Pelisse
fast-export can fail because of some pruned-reference when importing a
mark file.
The problem happens in the following scenario:
$ git fast-export --export-marks=MARKS master
(rewrite master)
$ git prune
$ git fast-export --import-marks=MARKS master
This might fail if some references have been removed by prune
because some marks will refer to non-existing commits.
Let's warn when we have a mark for a commit we don't know.
Also, increment the last_idnum before, so we don't override
the mark.
Signed-off-by: Antoine Pelisse <apelisse@gmail.com>
---
builtin/fast-export.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 12220ad..141b245 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -607,16 +607,19 @@ static void import_marks(char *input_file)
|| *mark_end != ' ' || get_sha1(mark_end + 1, sha1))
die("corrupt mark line: %s", line);
+ if (last_idnum < mark)
+ last_idnum = mark;
+
object = parse_object(sha1);
- if (!object)
- die ("Could not read blob %s", sha1_to_hex(sha1));
+ if (!object) {
+ warning("Could not read blob %s", sha1_to_hex(sha1));
+ continue;
+ }
if (object->flags & SHOWN)
error("Object %s already has a mark", sha1_to_hex(sha1));
mark_object(object, mark);
- if (last_idnum < mark)
- last_idnum = mark;
object->flags |= SHOWN;
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 4/4] tree_entry_interesting: do basedir compare on wildcard patterns when possible
From: Nguyễn Thái Ngọc Duy @ 2012-11-24 4:33 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1353731631-20593-1-git-send-email-pclouds@gmail.com>
Currently we treat "*.c" and "path/to/*.c" the same way. Which means
we check all possible paths in repo against "path/to/*.c". One could
see that "path/elsewhere/foo.c" obviously cannot match "path/to/*.c"
and we only need to check all paths _inside_ "path/to/" against that
pattern.
This patch checks the leading fixed part of a pathspec against base
directory and exit early if possible. We could even optimize further
in "path/to/something*.c" case (i.e. check the fixed part against
name_entry as well) but that's more complicated and probably does not
gain us much.
-O2 build on linux-2.6, without and with this patch respectively:
$ time git rev-list --quiet HEAD -- 'drivers/*.c'
real 1m9.484s
user 1m9.128s
sys 0m0.181s
$ time ~/w/git/git rev-list --quiet HEAD -- 'drivers/*.c'
real 0m15.710s
user 0m15.564s
sys 0m0.107s
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
tree-walk.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 62 insertions(+), 1 deletion(-)
diff --git a/tree-walk.c b/tree-walk.c
index 585899e..9d6e59b 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -573,6 +573,52 @@ static int match_dir_prefix(const char *base,
}
/*
+ * Perform matching on the leading non-wildcard part of
+ * pathspec. item->nowildcard_len must be greater than zero. Return
+ * non-zero if base is matched.
+ */
+static int match_wildcard_base(const struct pathspec_item *item,
+ const char *base, int baselen,
+ int *matched)
+{
+ const char *match = item->match;
+ /* the wildcard part is not considered in this function */
+ int matchlen = item->nowildcard_len;
+
+ if (baselen) {
+ int dirlen;
+ /*
+ * Return early if base is longer than the
+ * non-wildcard part but it does not match.
+ */
+ if (baselen >= matchlen) {
+ *matched = matchlen;
+ return !strncmp(base, match, matchlen);
+ }
+
+ dirlen = matchlen;
+ while (dirlen && match[dirlen - 1] != '/')
+ dirlen--;
+
+ /* Return early if base is shorter than the
+ non-wildcard part but it does not match. Note that
+ base ends with '/' so we are sure it really matches
+ directory */
+ if (strncmp(base, match, baselen))
+ return 0;
+ *matched = baselen;
+ } else
+ *matched = 0;
+ /*
+ * we could have checked entry against the non-wildcard part
+ * that is not in base and does similar never_interesting
+ * optimization as in match_entry. For now just be happy with
+ * base comparison.
+ */
+ return entry_interesting;
+}
+
+/*
* Is a tree entry interesting given the pathspec we have?
*
* Pre-condition: either baselen == base_offset (i.e. empty path)
@@ -602,7 +648,7 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
const struct pathspec_item *item = ps->items+i;
const char *match = item->match;
const char *base_str = base->buf + base_offset;
- int matchlen = item->len;
+ int matchlen = item->len, matched = 0;
if (baselen >= matchlen) {
/* If it doesn't match, move along... */
@@ -647,9 +693,24 @@ match_wildcards:
if (item->nowildcard_len == item->len)
continue;
+ if (item->nowildcard_len &&
+ !match_wildcard_base(item, base_str, baselen, &matched))
+ return entry_not_interesting;
+
/*
* Concatenate base and entry->path into one and do
* fnmatch() on it.
+ *
+ * While we could avoid concatenation in certain cases
+ * [1], which saves a memcpy and potentially a
+ * realloc, it turns out not worth it. Measurement on
+ * linux-2.6 does not show any clear improvements,
+ * partly because of the nowildcard_len optimization
+ * in git_fnmatch(). Avoid micro-optimizations here.
+ *
+ * [1] if match_wildcard_base() says the base
+ * directory is already matched, we only need to match
+ * the rest, which is shorter so _in theory_ faster.
*/
strbuf_add(base, entry->path, pathlen);
--
1.8.0.rc2.23.g1fb49df
^ permalink raw reply related
* [PATCH v2 3/4] pathspec: apply "*.c" optimization from exclude
From: Nguyễn Thái Ngọc Duy @ 2012-11-24 4:33 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1353731631-20593-1-git-send-email-pclouds@gmail.com>
When a pattern contains only a single asterisk as wildcard,
e.g. "foo*bar", after literally comparing the leading part "foo" with
the string, we can compare the tail of the string and make sure it
matches "bar", instead of running fnmatch() on "*bar" against the
remainder of the string.
-O2 build on linux-2.6, without the patch:
$ time git rev-list --quiet HEAD -- '*.c'
real 0m40.770s
user 0m40.290s
sys 0m0.256s
With the patch
$ time ~/w/git/git rev-list --quiet HEAD -- '*.c'
real 0m34.288s
user 0m33.997s
sys 0m0.205s
The above command is not supposed to be widely popular. It's chosen
because it exercises pathspec matching a lot. The point is it cuts
down matching time for popular patterns like *.c, which could be used
as pathspec in other places.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
The optimization's condition could be loosen to "only one asterisk"
(iow, fixed-length wildcards are OK, e.g. "abc[de]gh*.[ch]") when we
have a custom fnmatch implementation that supports dry-run, so it can
parse the pattern and determine the actual string length of
"abc[de]gh" and ".[ch]". We would have something similar to regcomp in
addition to git_fnmatch().
cache.h | 3 +++
dir.c | 18 ++++++++++++++++--
dir.h | 1 +
tree-walk.c | 6 ++++--
4 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/cache.h b/cache.h
index bf031f1..babf9e5 100644
--- a/cache.h
+++ b/cache.h
@@ -473,6 +473,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;
@@ -483,6 +485,7 @@ struct pathspec {
const char *match;
int len;
int nowildcard_len;
+ int flags;
} *items;
};
diff --git a/dir.c b/dir.c
index f81e1d2..9afd388 100644
--- a/dir.c
+++ b/dir.c
@@ -46,6 +46,13 @@ inline int git_fnmatch(const char *pattern, const char *string,
pattern += prefix;
string += prefix;
}
+ if (flags & GFNM_ONESTAR) {
+ int pattern_len = strlen(++pattern);
+ int string_len = strlen(string);
+ return string_len < pattern_len ||
+ strcmp(pattern,
+ string + string_len - pattern_len);
+ }
return fnmatch(pattern, string, fnm_flags);
}
@@ -246,7 +253,9 @@ static int match_pathspec_item(const struct pathspec_item *item, int prefix,
}
if (item->nowildcard_len < item->len &&
- !git_fnmatch(match, name, 0, item->nowildcard_len - prefix))
+ !git_fnmatch(match, name,
+ item->flags & PATHSPEC_ONESTAR ? GFNM_ONESTAR : 0,
+ item->nowildcard_len - prefix))
return MATCHED_FNMATCH;
return 0;
@@ -1446,8 +1455,13 @@ int init_pathspec(struct pathspec *pathspec, const char **paths)
item->match = path;
item->len = strlen(path);
item->nowildcard_len = simple_length(path);
- if (item->nowildcard_len < item->len)
+ item->flags = 0;
+ if (item->nowildcard_len < item->len) {
pathspec->has_wildcard = 1;
+ if (path[item->nowildcard_len] == '*' &&
+ no_wildcard(path + item->nowildcard_len + 1))
+ item->flags |= PATHSPEC_ONESTAR;
+ }
}
qsort(pathspec->items, pathspec->nr,
diff --git a/dir.h b/dir.h
index 0e8ae84..ab5af42 100644
--- a/dir.h
+++ b/dir.h
@@ -143,6 +143,7 @@ extern int fnmatch_icase(const char *pattern, const char *string, int flags);
* The prefix part of pattern must not contains wildcards.
*/
#define GFNM_PATHNAME 1 /* similar to FNM_PATHNAME */
+#define GFNM_ONESTAR 2 /* there is only _one_ wildcard, a star */
extern int git_fnmatch(const char *pattern, const char *string,
int flags, int prefix);
diff --git a/tree-walk.c b/tree-walk.c
index 2fcf3c0..585899e 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -628,7 +628,8 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
if (item->nowildcard_len < item->len) {
if (!git_fnmatch(match + baselen, entry->path,
- 0, item->nowildcard_len - baselen))
+ item->flags & PATHSPEC_ONESTAR ? GFNM_ONESTAR : 0,
+ item->nowildcard_len - baselen))
return entry_interesting;
/*
@@ -654,7 +655,8 @@ match_wildcards:
strbuf_add(base, entry->path, pathlen);
if (!git_fnmatch(match, base->buf + base_offset,
- 0, item->nowildcard_len)) {
+ item->flags & PATHSPEC_ONESTAR ? GFNM_ONESTAR : 0,
+ item->nowildcard_len)) {
strbuf_setlen(base, base_offset + baselen);
return entry_interesting;
}
--
1.8.0.rc2.23.g1fb49df
^ permalink raw reply related
* [PATCH v2 1/4] pathspec: save the non-wildcard length part
From: Nguyễn Thái Ngọc Duy @ 2012-11-24 4:33 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1353731631-20593-1-git-send-email-pclouds@gmail.com>
We mark pathspec with wildcards with the field use_wildcard. We
could do better by saving the length of the non-wildcard part, which
can be used for optimizations such as f9f6e2c (exclude: do strcmp as
much as possible before fnmatch - 2012-06-07).
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
builtin/ls-files.c | 2 +-
builtin/ls-tree.c | 2 +-
cache.h | 2 +-
dir.c | 6 +++---
tree-walk.c | 4 ++--
5 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index b5434af..4a9ee69 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -337,7 +337,7 @@ void overlay_tree_on_cache(const char *tree_name, const char *prefix)
matchbuf[0] = prefix;
matchbuf[1] = NULL;
init_pathspec(&pathspec, matchbuf);
- pathspec.items[0].use_wildcard = 0;
+ pathspec.items[0].nowildcard_len = pathspec.items[0].len;
} else
init_pathspec(&pathspec, NULL);
if (read_tree(tree, 1, &pathspec))
diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
index 235c17c..fb76e38 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -168,7 +168,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
init_pathspec(&pathspec, get_pathspec(prefix, argv + 1));
for (i = 0; i < pathspec.nr; i++)
- pathspec.items[i].use_wildcard = 0;
+ pathspec.items[i].nowildcard_len = pathspec.items[i].len;
pathspec.has_wildcard = 0;
tree = parse_tree_indirect(sha1);
if (!tree)
diff --git a/cache.h b/cache.h
index dbd8018..bf031f1 100644
--- a/cache.h
+++ b/cache.h
@@ -482,7 +482,7 @@ struct pathspec {
struct pathspec_item {
const char *match;
int len;
- unsigned int use_wildcard:1;
+ int nowildcard_len;
} *items;
};
diff --git a/dir.c b/dir.c
index 5a83aa7..c391d46 100644
--- a/dir.c
+++ b/dir.c
@@ -230,7 +230,7 @@ static int match_pathspec_item(const struct pathspec_item *item, int prefix,
return MATCHED_RECURSIVELY;
}
- if (item->use_wildcard && !fnmatch(match, name, 0))
+ if (item->nowildcard_len < item->len && !fnmatch(match, name, 0))
return MATCHED_FNMATCH;
return 0;
@@ -1429,8 +1429,8 @@ int init_pathspec(struct pathspec *pathspec, const char **paths)
item->match = path;
item->len = strlen(path);
- item->use_wildcard = !no_wildcard(path);
- if (item->use_wildcard)
+ item->nowildcard_len = simple_length(path);
+ if (item->nowildcard_len < item->len)
pathspec->has_wildcard = 1;
}
diff --git a/tree-walk.c b/tree-walk.c
index 3f54c02..af871c5 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -626,7 +626,7 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
&never_interesting))
return entry_interesting;
- if (item->use_wildcard) {
+ if (item->nowildcard_len < item->len) {
if (!fnmatch(match + baselen, entry->path, 0))
return entry_interesting;
@@ -642,7 +642,7 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
}
match_wildcards:
- if (!item->use_wildcard)
+ if (item->nowildcard_len == item->len)
continue;
/*
--
1.8.0.rc2.23.g1fb49df
^ permalink raw reply related
* [PATCH v2 2/4] pathspec: do exact comparison on the leading non-wildcard part
From: Nguyễn Thái Ngọc Duy @ 2012-11-24 4:33 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1353731631-20593-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
dir.c | 18 +++++++++++++++++-
dir.h | 8 ++++++++
tree-walk.c | 6 ++++--
3 files changed, 29 insertions(+), 3 deletions(-)
diff --git a/dir.c b/dir.c
index c391d46..f81e1d2 100644
--- a/dir.c
+++ b/dir.c
@@ -34,6 +34,21 @@ int fnmatch_icase(const char *pattern, const char *string, int flags)
return fnmatch(pattern, string, flags | (ignore_case ? FNM_CASEFOLD : 0));
}
+inline int git_fnmatch(const char *pattern, const char *string,
+ int flags, int prefix)
+{
+ int fnm_flags = 0;
+ if (flags & GFNM_PATHNAME)
+ fnm_flags |= FNM_PATHNAME;
+ if (prefix > 0) {
+ if (strncmp(pattern, string, prefix))
+ return FNM_NOMATCH;
+ pattern += prefix;
+ string += prefix;
+ }
+ return fnmatch(pattern, string, fnm_flags);
+}
+
static size_t common_prefix_len(const char **pathspec)
{
const char *n, *first;
@@ -230,7 +245,8 @@ static int match_pathspec_item(const struct pathspec_item *item, int prefix,
return MATCHED_RECURSIVELY;
}
- if (item->nowildcard_len < item->len && !fnmatch(match, name, 0))
+ if (item->nowildcard_len < item->len &&
+ !git_fnmatch(match, name, 0, item->nowildcard_len - prefix))
return MATCHED_FNMATCH;
return 0;
diff --git a/dir.h b/dir.h
index f5c89e3..0e8ae84 100644
--- a/dir.h
+++ b/dir.h
@@ -139,4 +139,12 @@ extern int strcmp_icase(const char *a, const char *b);
extern int strncmp_icase(const char *a, const char *b, size_t count);
extern int fnmatch_icase(const char *pattern, const char *string, int flags);
+/*
+ * The prefix part of pattern must not contains wildcards.
+ */
+#define GFNM_PATHNAME 1 /* similar to FNM_PATHNAME */
+
+extern int git_fnmatch(const char *pattern, const char *string,
+ int flags, int prefix);
+
#endif
diff --git a/tree-walk.c b/tree-walk.c
index af871c5..2fcf3c0 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -627,7 +627,8 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
return entry_interesting;
if (item->nowildcard_len < item->len) {
- if (!fnmatch(match + baselen, entry->path, 0))
+ if (!git_fnmatch(match + baselen, entry->path,
+ 0, item->nowildcard_len - baselen))
return entry_interesting;
/*
@@ -652,7 +653,8 @@ match_wildcards:
strbuf_add(base, entry->path, pathlen);
- if (!fnmatch(match, base->buf + base_offset, 0)) {
+ if (!git_fnmatch(match, base->buf + base_offset,
+ 0, item->nowildcard_len)) {
strbuf_setlen(base, base_offset + baselen);
return entry_interesting;
}
--
1.8.0.rc2.23.g1fb49df
^ permalink raw reply related
* [PATCH v2 0/4] nd/pathspec-wildcard
From: Nguyễn Thái Ngọc Duy @ 2012-11-24 4:33 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
The only change (apart from what Junio's made after I sent the series)
is rename GF_* to GFNM_* and PSF_* to PATHSPEC_* with a brief explanation
for each flag.
.gitignore code does not have "foo*oob" bug that the original series has.
Nguyễn Thái Ngọc Duy (4):
pathspec: save the non-wildcard length part
pathspec: do exact comparison on the leading non-wildcard part
pathspec: apply "*.c" optimization from exclude
tree_entry_interesting: do basedir compare on wildcard patterns when
possible
builtin/ls-files.c | 2 +-
builtin/ls-tree.c | 2 +-
cache.h | 5 +++-
dir.c | 36 +++++++++++++++++++++++---
dir.h | 9 +++++++
tree-walk.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++----
6 files changed, 118 insertions(+), 11 deletions(-)
--
1.8.0.rc2.23.g1fb49df
^ permalink raw reply
* Re: [PATCH v6 p2 1/9] transport-helper: update remote helper namespace
From: Felipe Contreras @ 2012-11-24 3:28 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Ilari Liusvaara, Sverre Rabbelier,
Felipe Contreras, Elijah Newren, Thiago Farina
In-Reply-To: <1353727520-26039-2-git-send-email-felipe.contreras@gmail.com>
On Sat, Nov 24, 2012 at 4:25 AM, Felipe Contreras
<felipe.contreras@gmail.com> wrote:
> @@ -673,11 +675,23 @@ static void push_update_refs_status(struct helper_data *data,
> struct strbuf buf = STRBUF_INIT;
> struct ref *ref = remote_refs;
> for (;;) {
> + char *private;
> +
> recvline(data, &buf);
> if (!buf.len)
> break;
>
> - push_update_ref_status(&buf, &ref, remote_refs);
> + if (push_update_ref_status(&buf, &ref, remote_refs))
> + continue;
> +
> + if (!data->refspecs)
> + continue;
> +
> + /* propagate back the update to the remote namespace */
> + private = apply_refspecs(data->refspecs, data->refspec_nr, ref->name);
> + if (!private)
> + continue;
> + update_ref("update by helper", private, ref->new_sha1, NULL, 0, 0);
free(private); I guess
--
Felipe Contreras
^ permalink raw reply
* Re: [PATCH v6 p2 2/9] fast-export: don't handle uninteresting refs
From: Felipe Contreras @ 2012-11-24 3:27 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Ilari Liusvaara, Sverre Rabbelier,
Felipe Contreras, Elijah Newren, Thiago Farina
In-Reply-To: <1353727520-26039-3-git-send-email-felipe.contreras@gmail.com>
On Sat, Nov 24, 2012 at 4:25 AM, Felipe Contreras
<felipe.contreras@gmail.com> wrote:
> +cat > expected << EOF
> +blob
> +mark :13
> +data 5
> +bump
> +
> +commit refs/heads/master
> +mark :14
> +author A U Thor <author@example.com> 1112912773 -0700
> +committer C O Mitter <committer@example.com> 1112912773 -0700
> +data 5
> +bump
> +from :12
> +M 100644 :13 file
> +
> +EOF
> +
> +test_expect_success 'refs are updated even if no commits need to be exported' '
The title should be updated: 'avoid uninteresting refs'
--
Felipe Contreras
^ permalink raw reply
* [PATCH v6 p2 9/9] fast-export: trivial cleanups
From: Felipe Contreras @ 2012-11-24 3:25 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Ilari Liusvaara, Sverre Rabbelier,
Felipe Contreras, Elijah Newren, Thiago Farina
In-Reply-To: <1353727520-26039-1-git-send-email-felipe.contreras@gmail.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
builtin/fast-export.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index d88fa10..bf5c822 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -548,7 +548,6 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
static void handle_tags_and_duplicates(void)
{
- struct commit *commit;
int i;
for (i = extra_refs.nr - 1; i >= 0; i--) {
@@ -560,9 +559,7 @@ static void handle_tags_and_duplicates(void)
break;
case OBJ_COMMIT:
/* create refs pointing to already seen commits */
- commit = (struct commit *)object;
- printf("reset %s\nfrom :%d\n\n", name,
- get_object_mark(&commit->object));
+ printf("reset %s\nfrom :%d\n\n", name, get_object_mark(object));
show_progress();
break;
}
--
1.8.0
^ permalink raw reply related
* [PATCH v6 p2 8/9] fast-export: refactor get_tags_and_duplicates()
From: Felipe Contreras @ 2012-11-24 3:25 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Ilari Liusvaara, Sverre Rabbelier,
Felipe Contreras, Elijah Newren, Thiago Farina
In-Reply-To: <1353727520-26039-1-git-send-email-felipe.contreras@gmail.com>
Split into a separate helper function get_commit() so that the part that
finds the relevant commit, and the part that does something with it
(handle tag object, etc.) are in different places.
No functional changes.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
builtin/fast-export.c | 68 ++++++++++++++++++++++++++++-----------------------
1 file changed, 38 insertions(+), 30 deletions(-)
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 5035382..d88fa10 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -475,9 +475,32 @@ static void handle_tag(const char *name, struct tag *tag)
(int)message_size, (int)message_size, message ? message : "");
}
+static struct commit *get_commit(struct rev_cmdline_entry *e, char *full_name)
+{
+ switch (e->item->type) {
+ case OBJ_COMMIT:
+ return (struct commit *)e->item;
+ case OBJ_TAG: {
+ struct tag *tag = (struct tag *)e->item;
+
+ /* handle nested tags */
+ while (tag && tag->object.type == OBJ_TAG) {
+ parse_object(tag->object.sha1);
+ string_list_append(&extra_refs, full_name)->util = tag;
+ tag = (struct tag *)tag->tagged;
+ }
+ if (!tag)
+ die("Tag %s points nowhere?", e->name);
+ return (struct commit *)tag;
+ break;
+ }
+ default:
+ return NULL;
+ }
+}
+
static void get_tags_and_duplicates(struct rev_cmdline_info *info)
{
- struct tag *tag;
int i;
for (i = 0; i < info->nr; i++) {
@@ -492,41 +515,26 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
if (dwim_ref(e->name, strlen(e->name), sha1, &full_name) != 1)
continue;
- switch (e->item->type) {
- case OBJ_COMMIT:
- commit = (struct commit *)e->item;
- break;
- case OBJ_TAG:
- tag = (struct tag *)e->item;
-
- /* handle nested tags */
- while (tag && tag->object.type == OBJ_TAG) {
- parse_object(tag->object.sha1);
- string_list_append(&extra_refs, full_name)->util = tag;
- tag = (struct tag *)tag->tagged;
- }
- if (!tag)
- die ("Tag %s points nowhere?", e->name);
- switch(tag->object.type) {
- case OBJ_COMMIT:
- commit = (struct commit *)tag;
- break;
- case OBJ_BLOB:
- handle_object(tag->object.sha1);
- continue;
- default: /* OBJ_TAG (nested tags) is already handled */
- warning("Tag points to object of unexpected type %s, skipping.",
- typename(tag->object.type));
- continue;
- }
- break;
- default:
+ commit = get_commit(e, full_name);
+ if (!commit) {
warning("%s: Unexpected object of type %s, skipping.",
e->name,
typename(e->item->type));
continue;
}
+ switch(commit->object.type) {
+ case OBJ_COMMIT:
+ break;
+ case OBJ_BLOB:
+ handle_object(commit->object.sha1);
+ continue;
+ default: /* OBJ_TAG (nested tags) is already handled */
+ warning("Tag points to object of unexpected type %s, skipping.",
+ typename(commit->object.type));
+ continue;
+ }
+
/*
* This ref will not be updated through a commit, lets make
* sure it gets properly updated eventually.
--
1.8.0
^ permalink raw reply related
* [PATCH v6 p2 6/9] transport-helper: fix push without marks
From: Felipe Contreras @ 2012-11-24 3:25 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Ilari Liusvaara, Sverre Rabbelier,
Felipe Contreras, Elijah Newren, Thiago Farina
In-Reply-To: <1353727520-26039-1-git-send-email-felipe.contreras@gmail.com>
There's not much to do when marks are not available, except pushing
everything, so let's do so by avoiding the negative refs (e.g.
^refs/testgit/origin/master).
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
t/t5801-remote-helpers.sh | 2 +-
transport-helper.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh
index 9c7871b..456303b 100755
--- a/t/t5801-remote-helpers.sh
+++ b/t/t5801-remote-helpers.sh
@@ -141,7 +141,7 @@ test_expect_success 'pulling without marks' '
compare_refs local2 HEAD server HEAD
'
-test_expect_failure 'pushing without marks' '
+test_expect_success 'pushing without marks' '
test_when_finished "(cd local2 && git reset --hard origin)" &&
(cd local2 &&
echo content >>file &&
diff --git a/transport-helper.c b/transport-helper.c
index 6dbb72e..78e4e82 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -781,7 +781,7 @@ static int push_refs_with_export(struct transport *transport,
if (ref->peer_ref)
string_list_append(&revlist_args, ref->peer_ref->name);
- if (!data->refspecs)
+ if (!data->refspecs || !data->import_marks)
continue;
private = apply_refspecs(data->refspecs, data->refspec_nr, ref->name);
if (private && strcmp(private, ref->name) && !get_sha1(private, sha1)) {
--
1.8.0
^ permalink raw reply related
* [PATCH v6 p2 7/9] fast-export: make extra_refs global
From: Felipe Contreras @ 2012-11-24 3:25 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Ilari Liusvaara, Sverre Rabbelier,
Felipe Contreras, Elijah Newren, Thiago Farina
In-Reply-To: <1353727520-26039-1-git-send-email-felipe.contreras@gmail.com>
There's no need to pass it around everywhere. This would make easier
further refactoring that makes use of this variable.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
builtin/fast-export.c | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 77dffd1..5035382 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -30,6 +30,7 @@ static int fake_missing_tagger;
static int use_done_feature;
static int no_data;
static int full_tree;
+static struct string_list extra_refs = STRING_LIST_INIT_NODUP;
static int parse_opt_signed_tag_mode(const struct option *opt,
const char *arg, int unset)
@@ -474,8 +475,7 @@ static void handle_tag(const char *name, struct tag *tag)
(int)message_size, (int)message_size, message ? message : "");
}
-static void get_tags_and_duplicates(struct rev_cmdline_info *info,
- struct string_list *extra_refs)
+static void get_tags_and_duplicates(struct rev_cmdline_info *info)
{
struct tag *tag;
int i;
@@ -502,7 +502,7 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info,
/* handle nested tags */
while (tag && tag->object.type == OBJ_TAG) {
parse_object(tag->object.sha1);
- string_list_append(extra_refs, full_name)->util = tag;
+ string_list_append(&extra_refs, full_name)->util = tag;
tag = (struct tag *)tag->tagged;
}
if (!tag)
@@ -532,20 +532,20 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info,
* sure it gets properly updated eventually.
*/
if (commit->util || commit->object.flags & SHOWN)
- string_list_append(extra_refs, full_name)->util = commit;
+ string_list_append(&extra_refs, full_name)->util = commit;
if (!commit->util)
commit->util = full_name;
}
}
-static void handle_tags_and_duplicates(struct string_list *extra_refs)
+static void handle_tags_and_duplicates(void)
{
struct commit *commit;
int i;
- for (i = extra_refs->nr - 1; i >= 0; i--) {
- const char *name = extra_refs->items[i].string;
- struct object *object = extra_refs->items[i].util;
+ for (i = extra_refs.nr - 1; i >= 0; i--) {
+ const char *name = extra_refs.items[i].string;
+ struct object *object = extra_refs.items[i].util;
switch (object->type) {
case OBJ_TAG:
handle_tag(name, (struct tag *)object);
@@ -638,7 +638,6 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
{
struct rev_info revs;
struct object_array commits = OBJECT_ARRAY_INIT;
- struct string_list extra_refs = STRING_LIST_INIT_NODUP;
struct commit *commit;
char *export_filename = NULL, *import_filename = NULL;
struct option options[] = {
@@ -688,7 +687,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
if (import_filename && revs.prune_data.nr)
full_tree = 1;
- get_tags_and_duplicates(&revs.cmdline, &extra_refs);
+ get_tags_and_duplicates(&revs.cmdline);
if (prepare_revision_walk(&revs))
die("revision walk setup failed");
@@ -704,7 +703,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
}
}
- handle_tags_and_duplicates(&extra_refs);
+ handle_tags_and_duplicates();
if (export_filename)
export_marks(export_filename);
--
1.8.0
^ permalink raw reply related
* [PATCH v6 p2 5/9] transport-helper: fix pushing with straight refspec
From: Felipe Contreras @ 2012-11-24 3:25 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Ilari Liusvaara, Sverre Rabbelier,
Felipe Contreras, Elijah Newren, Thiago Farina
In-Reply-To: <1353727520-26039-1-git-send-email-felipe.contreras@gmail.com>
For example '*:*'.
Obviously '^refs/heads/master refs/heads/master' is not going to work,
so lets check that the ref we are negating is not the same we are
pushing.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
t/t5801-remote-helpers.sh | 2 +-
transport-helper.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh
index b268cd2..9c7871b 100755
--- a/t/t5801-remote-helpers.sh
+++ b/t/t5801-remote-helpers.sh
@@ -126,7 +126,7 @@ test_expect_success 'pulling with straight refspec' '
compare_refs local2 HEAD server HEAD
'
-test_expect_failure 'pushing with straight refspec' '
+test_expect_success 'pushing with straight refspec' '
test_when_finished "(cd local2 && git reset --hard origin)" &&
(cd local2 &&
echo content >>file &&
diff --git a/transport-helper.c b/transport-helper.c
index 899eb36..6dbb72e 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -784,7 +784,7 @@ static int push_refs_with_export(struct transport *transport,
if (!data->refspecs)
continue;
private = apply_refspecs(data->refspecs, data->refspec_nr, ref->name);
- if (private && !get_sha1(private, sha1)) {
+ if (private && strcmp(private, ref->name) && !get_sha1(private, sha1)) {
strbuf_addf(&buf, "^%s", private);
string_list_append(&revlist_args, strbuf_detach(&buf, NULL));
}
--
1.8.0
^ permalink raw reply related
* [PATCH v6 p2 4/9] transport-helper: fix push without refspec
From: Felipe Contreras @ 2012-11-24 3:25 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Ilari Liusvaara, Sverre Rabbelier,
Felipe Contreras, Elijah Newren, Thiago Farina
In-Reply-To: <1353727520-26039-1-git-send-email-felipe.contreras@gmail.com>
The refspec feature is not mandatory.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
t/t5801-remote-helpers.sh | 2 +-
transport-helper.c | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh
index 2e027c8..b268cd2 100755
--- a/t/t5801-remote-helpers.sh
+++ b/t/t5801-remote-helpers.sh
@@ -111,7 +111,7 @@ test_expect_success 'pulling without refspecs' '
compare_refs local2 HEAD server HEAD
'
-test_expect_failure 'pushing without refspecs' '
+test_expect_success 'pushing without refspecs' '
test_when_finished "(cd local2 && git reset --hard origin)" &&
(cd local2 &&
echo content >>file &&
diff --git a/transport-helper.c b/transport-helper.c
index 0c95101..899eb36 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -778,6 +778,9 @@ static int push_refs_with_export(struct transport *transport,
if (ref->deletion)
die("remote-helpers do not support ref deletion");
+ if (ref->peer_ref)
+ string_list_append(&revlist_args, ref->peer_ref->name);
+
if (!data->refspecs)
continue;
private = apply_refspecs(data->refspecs, data->refspec_nr, ref->name);
@@ -787,9 +790,6 @@ static int push_refs_with_export(struct transport *transport,
}
free(private);
- if (ref->peer_ref)
- string_list_append(&revlist_args, ref->peer_ref->name);
-
}
if (get_exporter(transport, &exporter, &revlist_args))
--
1.8.0
^ permalink raw reply related
* [PATCH v6 p2 3/9] transport-helper: trivial code shuffle
From: Felipe Contreras @ 2012-11-24 3:25 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Ilari Liusvaara, Sverre Rabbelier,
Felipe Contreras, Elijah Newren, Thiago Farina
In-Reply-To: <1353727520-26039-1-git-send-email-felipe.contreras@gmail.com>
Just shuffle the die() part to make it more explicit, and cleanup the
code-style.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
transport-helper.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/transport-helper.c b/transport-helper.c
index 32ad877..0c95101 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -775,6 +775,9 @@ static int push_refs_with_export(struct transport *transport,
char *private;
unsigned char sha1[20];
+ if (ref->deletion)
+ die("remote-helpers do not support ref deletion");
+
if (!data->refspecs)
continue;
private = apply_refspecs(data->refspecs, data->refspec_nr, ref->name);
@@ -784,10 +787,6 @@ static int push_refs_with_export(struct transport *transport,
}
free(private);
- if (ref->deletion) {
- die("remote-helpers do not support ref deletion");
- }
-
if (ref->peer_ref)
string_list_append(&revlist_args, ref->peer_ref->name);
--
1.8.0
^ permalink raw reply related
* [PATCH v6 p2 2/9] fast-export: don't handle uninteresting refs
From: Felipe Contreras @ 2012-11-24 3:25 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Ilari Liusvaara, Sverre Rabbelier,
Felipe Contreras, Elijah Newren, Thiago Farina
In-Reply-To: <1353727520-26039-1-git-send-email-felipe.contreras@gmail.com>
They have been marked as UNINTERESTING for a reason, lets respect that.
Currently the first ref is handled properly, but not the rest:
% git fast-export master ^uninteresting ^foo ^bar
reset refs/heads/bar
from :0
reset refs/heads/foo
from :0
reset refs/heads/uninteresting
from :0
% git fast-export ^uninteresting ^foo ^bar master
reset refs/heads/master
from :0
reset refs/heads/bar
from :0
reset refs/heads/foo
from :0
Clearly this is wrong; the negative refs should be ignored.
After this patch:
% git fast-export ^uninteresting ^foo ^bar master
# nothing
% git fast-export master ^uninteresting ^foo ^bar
# nothing
And even more, it would only happen if the ref is pointing to exactly
the same commit, but not otherwise:
% git fast-export ^next next
reset refs/heads/next
from :0
% git fast-export ^next next^{commit}
# nothing
% git fast-export ^next next~0
# nothing
% git fast-export ^next next~1
# nothing
% git fast-export ^next next~2
# nothing
The reason this happens is that before traversing the commits,
fast-export checks if any of the refs point to the same object, and any
duplicated ref gets added to a list in order to issue 'reset' commands
after the traversing. Unfortunately, it's not even checking if the
commit is flagged as UNINTERESTING. The fix of course, is to do
precisely that.
However, in order to do it properly we need to get the UNINTERESTING flag
from the command line ref, not from the commit object. Fortunately we
can simply use revs.pending, which contains all the information we need
for get_tags_and_duplicates(), plus the ref flag. This way the rest of
the positive refs will remain untouched; it's only the negative ones
that change in behavior.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
The difference with the previous version is that now '^uninteresting ^bad
master new' would handle 'master' and 'new', while the previous one would not
do anything. The current behavior would handle 'bad', 'master', and 'new'.
builtin/fast-export.c | 11 +++++++----
t/t5801-remote-helpers.sh | 8 ++++++++
t/t9350-fast-export.sh | 30 ++++++++++++++++++++++++++++++
3 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 31bfbee..77dffd1 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -474,18 +474,21 @@ static void handle_tag(const char *name, struct tag *tag)
(int)message_size, (int)message_size, message ? message : "");
}
-static void get_tags_and_duplicates(struct object_array *pending,
+static void get_tags_and_duplicates(struct rev_cmdline_info *info,
struct string_list *extra_refs)
{
struct tag *tag;
int i;
- for (i = 0; i < pending->nr; i++) {
- struct object_array_entry *e = pending->objects + i;
+ for (i = 0; i < info->nr; i++) {
+ struct rev_cmdline_entry *e = info->rev + i;
unsigned char sha1[20];
struct commit *commit;
char *full_name;
+ if (e->flags & UNINTERESTING)
+ continue;
+
if (dwim_ref(e->name, strlen(e->name), sha1, &full_name) != 1)
continue;
@@ -685,7 +688,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
if (import_filename && revs.prune_data.nr)
full_tree = 1;
- get_tags_and_duplicates(&revs.pending, &extra_refs);
+ get_tags_and_duplicates(&revs.cmdline, &extra_refs);
if (prepare_revision_walk(&revs))
die("revision walk setup failed");
diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh
index b2782a2..2e027c8 100755
--- a/t/t5801-remote-helpers.sh
+++ b/t/t5801-remote-helpers.sh
@@ -158,4 +158,12 @@ test_expect_success 'push ref with existing object' '
compare_refs local dup server dup
'
+test_expect_success 'push all with existing object' '
+ (cd local &&
+ git branch dup2 master &&
+ git push origin --all
+ ) &&
+ compare_refs local dup2 server dup2
+'
+
test_done
diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh
index 237d2e5..2e7187e 100755
--- a/t/t9350-fast-export.sh
+++ b/t/t9350-fast-export.sh
@@ -469,4 +469,34 @@ test_expect_success 'refs are updated even if no commits need to be exported' '
test_cmp expected actual
'
+cat > expected << EOF
+blob
+mark :13
+data 5
+bump
+
+commit refs/heads/master
+mark :14
+author A U Thor <author@example.com> 1112912773 -0700
+committer C O Mitter <committer@example.com> 1112912773 -0700
+data 5
+bump
+from :12
+M 100644 :13 file
+
+EOF
+
+test_expect_success 'refs are updated even if no commits need to be exported' '
+ > tmp-marks &&
+ git fast-export --import-marks=tmp-marks \
+ --export-marks=tmp-marks master > /dev/null &&
+ git tag v1.0 &&
+ git branch uninteresting &&
+ echo bump > file &&
+ git commit -a -m bump &&
+ git fast-export --import-marks=tmp-marks \
+ --export-marks=tmp-marks ^uninteresting ^v1.0 master > actual &&
+ test_cmp expected actual
+'
+
test_done
--
1.8.0
^ permalink raw reply related
* [PATCH v6 p2 1/9] transport-helper: update remote helper namespace
From: Felipe Contreras @ 2012-11-24 3:25 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Ilari Liusvaara, Sverre Rabbelier,
Felipe Contreras, Elijah Newren, Thiago Farina
In-Reply-To: <1353727520-26039-1-git-send-email-felipe.contreras@gmail.com>
When pushing, the remote namespace is updated correctly
(e.g. refs/origin/master), but not the remote helper's
(e.g. refs/testgit/origin/master).
This alone should not cause any regressions, but combined with other
patches to handle negative refs correctly (upcoming patch), it might.
However, that's a good thing; otherwise those issues would go
unnoticed.
For the moment though, this patch alone shouldn't cause any issues, in
fact the rest of the code seems to rely on this happening.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
transport-helper.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/transport-helper.c b/transport-helper.c
index cfe0988..32ad877 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -10,6 +10,7 @@
#include "string-list.h"
#include "thread-utils.h"
#include "sigchain.h"
+#include "refs.h"
static int debug;
@@ -600,7 +601,7 @@ static int fetch(struct transport *transport,
return -1;
}
-static void push_update_ref_status(struct strbuf *buf,
+static int push_update_ref_status(struct strbuf *buf,
struct ref **ref,
struct ref *remote_refs)
{
@@ -651,7 +652,7 @@ static void push_update_ref_status(struct strbuf *buf,
*ref = find_ref_by_name(remote_refs, refname);
if (!*ref) {
warning("helper reported unexpected status of %s", refname);
- return;
+ return 1;
}
if ((*ref)->status != REF_STATUS_NONE) {
@@ -660,11 +661,12 @@ static void push_update_ref_status(struct strbuf *buf,
* status reported by the remote helper if the latter is 'no match'.
*/
if (status == REF_STATUS_NONE)
- return;
+ return 1;
}
(*ref)->status = status;
(*ref)->remote_status = msg;
+ return 0;
}
static void push_update_refs_status(struct helper_data *data,
@@ -673,11 +675,23 @@ static void push_update_refs_status(struct helper_data *data,
struct strbuf buf = STRBUF_INIT;
struct ref *ref = remote_refs;
for (;;) {
+ char *private;
+
recvline(data, &buf);
if (!buf.len)
break;
- push_update_ref_status(&buf, &ref, remote_refs);
+ if (push_update_ref_status(&buf, &ref, remote_refs))
+ continue;
+
+ if (!data->refspecs)
+ continue;
+
+ /* propagate back the update to the remote namespace */
+ private = apply_refspecs(data->refspecs, data->refspec_nr, ref->name);
+ if (!private)
+ continue;
+ update_ref("update by helper", private, ref->new_sha1, NULL, 0, 0);
}
strbuf_release(&buf);
}
--
1.8.0
^ permalink raw reply related
* [PATCH v6 p2 0/9] transport-helper and fast-export fixes
From: Felipe Contreras @ 2012-11-24 3:25 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Ilari Liusvaara, Sverre Rabbelier,
Felipe Contreras, Elijah Newren, Thiago Farina
Hi,
Trying to fix the remaining issues with transport-helper I stumbled upon a
problem with the first patch attached. Now that the namespaced refs of the
remote helper are properly tracked, there's a problem when pushing more than
one ref at the same time *and* the last patch on the v5 patch series is
applied.
The second patch here tries to solve that problem.
The rest are cleanups and trivial fixes.
Felipe Contreras (9):
transport-helper: update remote helper namespace
fast-export: don't handle uninteresting refs
transport-helper: trivial code shuffle
transport-helper: fix push without refspec
transport-helper: fix pushing with straight refspec
transport-helper: fix push without marks
fast-export: make extra_refs global
fast-export: refactor get_tags_and_duplicates()
fast-export: trivial cleanups
builtin/fast-export.c | 99 +++++++++++++++++++++++++----------------------
t/t5801-remote-helpers.sh | 14 +++++--
t/t9350-fast-export.sh | 30 ++++++++++++++
transport-helper.c | 39 ++++++++++++-------
4 files changed, 120 insertions(+), 62 deletions(-)
--
1.8.0
^ permalink raw reply
* [PATCH v6 p1.1 14/14] fast-export: make sure updated refs get updated
From: Felipe Contreras @ 2012-11-24 3:17 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Johannes Sixt, Johannes Schindelin,
Max Horn, Sverre Rabbelier, Brandon Casey, Brandon Casey,
Jonathan Nieder, Ilari Liusvaara, Pete Wyckoff, Ben Walton,
Matthieu Moy, Julian Phillips, Felipe Contreras
In-Reply-To: <1353727034-24698-1-git-send-email-felipe.contreras@gmail.com>
When an object has already been exported (and thus is in the marks) it's
flagged as SHOWN, so it will not be exported again, even if in a later
time it's exported through a different ref.
We don't need the object to be exported again, but we want the ref
updated, which doesn't happen.
Since we can't know if a ref was exported or not, let's just assume that
if the commit was marked (flags & SHOWN), the user still wants the ref
updated.
IOW: If it's specified in the command line, it will get updated,
regardless of whether or not the object was marked.
So:
% git branch test master
% git fast-export $mark_flags master
% git fast-export $mark_flags test
Would export 'test' properly.
Additionally, this fixes issues with remote helpers; now they can push
refs whose objects have already been exported, and a few other issues as
well. Update the tests accordingly.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
builtin/fast-export.c | 10 +++++++---
t/t5801-remote-helpers.sh | 20 ++++++++------------
t/t9350-fast-export.sh | 15 +++++++++++++++
3 files changed, 30 insertions(+), 15 deletions(-)
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 191936c..31bfbee 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -523,10 +523,14 @@ static void get_tags_and_duplicates(struct object_array *pending,
typename(e->item->type));
continue;
}
- if (commit->util)
- /* more than one name for the same object */
+
+ /*
+ * This ref will not be updated through a commit, lets make
+ * sure it gets properly updated eventually.
+ */
+ if (commit->util || commit->object.flags & SHOWN)
string_list_append(extra_refs, full_name)->util = commit;
- else
+ if (!commit->util)
commit->util = full_name;
}
}
diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh
index 12ae256..b2782a2 100755
--- a/t/t5801-remote-helpers.sh
+++ b/t/t5801-remote-helpers.sh
@@ -63,18 +63,6 @@ test_expect_success 'fetch new branch' '
compare_refs server HEAD local FETCH_HEAD
'
-#
-# This is only needed because of a bug not detected by this script. It will be
-# fixed shortly, but for now lets not cause regressions.
-#
-test_expect_success 'bump commit in server' '
- (cd server &&
- git checkout master &&
- echo content >>file &&
- git commit -a -m four) &&
- compare_refs server HEAD server HEAD
-'
-
test_expect_success 'fetch multiple branches' '
(cd local &&
git fetch
@@ -162,4 +150,12 @@ test_expect_failure 'pushing without marks' '
compare_refs local2 HEAD server HEAD
'
+test_expect_success 'push ref with existing object' '
+ (cd local &&
+ git branch dup master &&
+ git push origin dup
+ ) &&
+ compare_refs local dup server dup
+'
+
test_done
diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh
index 1f59862..237d2e5 100755
--- a/t/t9350-fast-export.sh
+++ b/t/t9350-fast-export.sh
@@ -454,4 +454,19 @@ test_expect_success 'test bidirectionality' '
git fast-import --export-marks=marks-cur --import-marks=marks-cur
'
+cat > expected << EOF
+reset refs/heads/master
+from :12
+
+EOF
+
+test_expect_success 'refs are updated even if no commits need to be exported' '
+ > tmp-marks &&
+ git fast-export --import-marks=tmp-marks \
+ --export-marks=tmp-marks master > /dev/null &&
+ git fast-export --import-marks=tmp-marks \
+ --export-marks=tmp-marks master > actual &&
+ test_cmp expected actual
+'
+
test_done
--
1.8.0
^ permalink raw reply related
* [PATCH v6 p1.1 13/14] fast-export: fix comparison in tests
From: Felipe Contreras @ 2012-11-24 3:17 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Johannes Sixt, Johannes Schindelin,
Max Horn, Sverre Rabbelier, Brandon Casey, Brandon Casey,
Jonathan Nieder, Ilari Liusvaara, Pete Wyckoff, Ben Walton,
Matthieu Moy, Julian Phillips, Felipe Contreras
In-Reply-To: <1353727034-24698-1-git-send-email-felipe.contreras@gmail.com>
First the expected, then the actual, otherwise the diff would be the
opposite of what we want.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
t/t9350-fast-export.sh | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh
index 5948b65..1f59862 100755
--- a/t/t9350-fast-export.sh
+++ b/t/t9350-fast-export.sh
@@ -303,7 +303,7 @@ test_expect_success 'dropping tag of filtered out object' '
(
cd limit-by-paths &&
git fast-export --tag-of-filtered-object=drop mytag -- there > output &&
- test_cmp output expected
+ test_cmp expected output
)
'
@@ -320,7 +320,7 @@ test_expect_success 'rewriting tag of filtered out object' '
(
cd limit-by-paths &&
git fast-export --tag-of-filtered-object=rewrite mytag -- there > output &&
- test_cmp output expected
+ test_cmp expected output
)
'
@@ -351,7 +351,7 @@ test_expect_failure 'no exact-ref revisions included' '
(
cd limit-by-paths &&
git fast-export master~2..master~1 > output &&
- test_cmp output expected
+ test_cmp expected output
)
'
--
1.8.0
^ permalink raw reply related
* [PATCH v6 p1.1 12/14] fast-export: trivial cleanup
From: Felipe Contreras @ 2012-11-24 3:17 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Johannes Sixt, Johannes Schindelin,
Max Horn, Sverre Rabbelier, Brandon Casey, Brandon Casey,
Jonathan Nieder, Ilari Liusvaara, Pete Wyckoff, Ben Walton,
Matthieu Moy, Julian Phillips, Felipe Contreras
In-Reply-To: <1353727034-24698-1-git-send-email-felipe.contreras@gmail.com>
Setting 'commit' to 'commit' is a no-op. It might have been there to
avoid a compiler warning, but if so, it was the compiler to blame, and
it's certainly not there any more.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
builtin/fast-export.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 9b70ec1..191936c 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -483,7 +483,7 @@ static void get_tags_and_duplicates(struct object_array *pending,
for (i = 0; i < pending->nr; i++) {
struct object_array_entry *e = pending->objects + i;
unsigned char sha1[20];
- struct commit *commit = commit;
+ struct commit *commit;
char *full_name;
if (dwim_ref(e->name, strlen(e->name), sha1, &full_name) != 1)
--
1.8.0
^ permalink raw reply related
* [PATCH v6 p1.1 11/14] remote-testgit: implement the "done" feature manually
From: Felipe Contreras @ 2012-11-24 3:17 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Johannes Sixt, Johannes Schindelin,
Max Horn, Sverre Rabbelier, Brandon Casey, Brandon Casey,
Jonathan Nieder, Ilari Liusvaara, Pete Wyckoff, Ben Walton,
Matthieu Moy, Julian Phillips, Felipe Contreras
In-Reply-To: <1353727034-24698-1-git-send-email-felipe.contreras@gmail.com>
People who want to write their own remote-helper will find it more
useful to see clearly how they are supposed to advertise and implement
the "done" feature themselves.
Right now we are relying on fast-export to do that by using the
--use-done-feature argument. However, people writing their own
remote-helper would probably not have such an option, as they would
probably be writing the fast-export functionality themselves.
It should now be clearer to them.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
git-remote-testgit | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/git-remote-testgit b/git-remote-testgit
index aba3502..0389545 100755
--- a/git-remote-testgit
+++ b/git-remote-testgit
@@ -61,8 +61,10 @@ do
echo "feature import-marks=$gitmarks"
echo "feature export-marks=$gitmarks"
fi
- git fast-export --use-done-feature "${testgitmarks_args[@]}" $refs |
+ echo "feature done"
+ git fast-export "${testgitmarks_args[@]}" $refs |
sed -e "s#refs/heads/#${prefix}/heads/#g"
+ echo "done"
;;
export)
before=$(git for-each-ref --format='%(refname) %(objectname)')
--
1.8.0
^ permalink raw reply related
* [PATCH v6 p1.1 10/14] remote-testgit: report success after an import
From: Felipe Contreras @ 2012-11-24 3:17 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Johannes Sixt, Johannes Schindelin,
Max Horn, Sverre Rabbelier, Brandon Casey, Brandon Casey,
Jonathan Nieder, Ilari Liusvaara, Pete Wyckoff, Ben Walton,
Matthieu Moy, Julian Phillips, Felipe Contreras
In-Reply-To: <1353727034-24698-1-git-send-email-felipe.contreras@gmail.com>
Doesn't make a difference for the tests, but it does for the ones
seeking reference.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
git-remote-testgit | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/git-remote-testgit b/git-remote-testgit
index e140282..aba3502 100755
--- a/git-remote-testgit
+++ b/git-remote-testgit
@@ -65,7 +65,20 @@ do
sed -e "s#refs/heads/#${prefix}/heads/#g"
;;
export)
+ before=$(git for-each-ref --format='%(refname) %(objectname)')
+
git fast-import "${testgitmarks_args[@]}" --quiet
+
+ after=$(git for-each-ref --format='%(refname) %(objectname)')
+
+ # figure out which refs were updated
+ join -e 0 -o '0 1.2 2.2' -a 2 <(echo "$before") <(echo "$after") |
+ while read ref a b
+ do
+ test $a == $b && continue
+ echo "ok $ref"
+ done
+
echo
;;
'')
--
1.8.0
^ permalink raw reply related
* [PATCH v6 p1.1 09/14] remote-testgit: exercise more features
From: Felipe Contreras @ 2012-11-24 3:17 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Johannes Sixt, Johannes Schindelin,
Max Horn, Sverre Rabbelier, Brandon Casey, Brandon Casey,
Jonathan Nieder, Ilari Liusvaara, Pete Wyckoff, Ben Walton,
Matthieu Moy, Julian Phillips, Felipe Contreras
In-Reply-To: <1353727034-24698-1-git-send-email-felipe.contreras@gmail.com>
Unfortunately a lot of these tests fail.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
git-remote-testgit | 38 +++++++++++++++++++++++-----------
t/t5801-remote-helpers.sh | 52 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 78 insertions(+), 12 deletions(-)
diff --git a/git-remote-testgit b/git-remote-testgit
index bf4d22c..e140282 100755
--- a/git-remote-testgit
+++ b/git-remote-testgit
@@ -6,17 +6,25 @@ url=$2
dir="$GIT_DIR/testgit/$alias"
prefix="refs/testgit/$alias"
-refspec="refs/heads/*:${prefix}/heads/*"
-gitmarks="$dir/git.marks"
-testgitmarks="$dir/testgit.marks"
+default_refspec="refs/heads/*:${prefix}/heads/*"
+
+refspec="${GIT_REMOTE_TESTGIT_REFSPEC-$default_refspec}"
+
+test -z "$refspec" && prefix="refs"
export GIT_DIR="$url/.git"
mkdir -p "$dir"
-test -e "$gitmarks" || > "$gitmarks"
-test -e "$testgitmarks" || > "$testgitmarks"
+if test -z "$GIT_REMOTE_TESTGIT_NO_MARKS"
+then
+ gitmarks="$dir/git.marks"
+ testgitmarks="$dir/testgit.marks"
+ test -e "$gitmarks" || >"$gitmarks"
+ test -e "$testgitmarks" || >"$testgitmarks"
+ testgitmarks_args=( "--"{import,export}"-marks=$testgitmarks" )
+fi
while read line
do
@@ -24,9 +32,12 @@ do
capabilities)
echo 'import'
echo 'export'
- echo "refspec $refspec"
- echo "*import-marks $gitmarks"
- echo "*export-marks $gitmarks"
+ test -n "$refspec" && echo "refspec $refspec"
+ if test -n "$gitmarks"
+ then
+ echo "*import-marks $gitmarks"
+ echo "*export-marks $gitmarks"
+ fi
echo
;;
list)
@@ -45,13 +56,16 @@ do
test "${line%% *}" != "import" && break
done
- echo "feature import-marks=$gitmarks"
- echo "feature export-marks=$gitmarks"
- git fast-export --use-done-feature --{import,export}-marks="$testgitmarks" $refs |
+ if test -n "$gitmarks"
+ then
+ echo "feature import-marks=$gitmarks"
+ echo "feature export-marks=$gitmarks"
+ fi
+ git fast-export --use-done-feature "${testgitmarks_args[@]}" $refs |
sed -e "s#refs/heads/#${prefix}/heads/#g"
;;
export)
- git fast-import --{import,export}-marks="$testgitmarks" --quiet
+ git fast-import "${testgitmarks_args[@]}" --quiet
echo
;;
'')
diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh
index bc0b5f7..12ae256 100755
--- a/t/t5801-remote-helpers.sh
+++ b/t/t5801-remote-helpers.sh
@@ -110,4 +110,56 @@ test_expect_failure 'push new branch with old:new refspec' '
compare_refs local HEAD server refs/heads/new-refspec
'
+test_expect_success 'cloning without refspec' '
+ GIT_REMOTE_TESTGIT_REFSPEC="" \
+ git clone "testgit::${PWD}/server" local2 &&
+ compare_refs local2 HEAD server HEAD
+'
+
+test_expect_success 'pulling without refspecs' '
+ (cd local2 &&
+ git reset --hard &&
+ GIT_REMOTE_TESTGIT_REFSPEC="" git pull) &&
+ compare_refs local2 HEAD server HEAD
+'
+
+test_expect_failure 'pushing without refspecs' '
+ test_when_finished "(cd local2 && git reset --hard origin)" &&
+ (cd local2 &&
+ echo content >>file &&
+ git commit -a -m ten &&
+ GIT_REMOTE_TESTGIT_REFSPEC="" git push) &&
+ compare_refs local2 HEAD server HEAD
+'
+
+test_expect_success 'pulling with straight refspec' '
+ (cd local2 &&
+ GIT_REMOTE_TESTGIT_REFSPEC="*:*" git pull) &&
+ compare_refs local2 HEAD server HEAD
+'
+
+test_expect_failure 'pushing with straight refspec' '
+ test_when_finished "(cd local2 && git reset --hard origin)" &&
+ (cd local2 &&
+ echo content >>file &&
+ git commit -a -m eleven &&
+ GIT_REMOTE_TESTGIT_REFSPEC="*:*" git push) &&
+ compare_refs local2 HEAD server HEAD
+'
+
+test_expect_success 'pulling without marks' '
+ (cd local2 &&
+ GIT_REMOTE_TESTGIT_NO_MARKS=1 git pull) &&
+ compare_refs local2 HEAD server HEAD
+'
+
+test_expect_failure 'pushing without marks' '
+ test_when_finished "(cd local2 && git reset --hard origin)" &&
+ (cd local2 &&
+ echo content >>file &&
+ git commit -a -m twelve &&
+ GIT_REMOTE_TESTGIT_NO_MARKS=1 git push) &&
+ compare_refs local2 HEAD server HEAD
+'
+
test_done
--
1.8.0
^ permalink raw reply related
* [PATCH v6 p1.1 08/14] remote-testgit: cleanup tests
From: Felipe Contreras @ 2012-11-24 3:17 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jeff King, Johannes Sixt, Johannes Schindelin,
Max Horn, Sverre Rabbelier, Brandon Casey, Brandon Casey,
Jonathan Nieder, Ilari Liusvaara, Pete Wyckoff, Ben Walton,
Matthieu Moy, Julian Phillips, Felipe Contreras
In-Reply-To: <1353727034-24698-1-git-send-email-felipe.contreras@gmail.com>
We don't need a bare 'server' and an intermediary 'public'. The repos
can talk to each other directly; that's what we want to exercise.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
t/t5801-remote-helpers.sh | 63 ++++++++++++++++++++++-------------------------
1 file changed, 29 insertions(+), 34 deletions(-)
diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh
index 6801529..bc0b5f7 100755
--- a/t/t5801-remote-helpers.sh
+++ b/t/t5801-remote-helpers.sh
@@ -19,100 +19,95 @@ compare_refs() {
}
test_expect_success 'setup repository' '
- git init --bare server/.git &&
- git clone server public &&
- (cd public &&
+ git init server &&
+ (cd server &&
echo content >file &&
git add file &&
- git commit -m one &&
- git push origin master)
+ git commit -m one)
'
test_expect_success 'cloning from local repo' '
- git clone "testgit::${PWD}/server" localclone &&
- test_cmp public/file localclone/file
+ git clone "testgit::${PWD}/server" local &&
+ test_cmp server/file local/file
'
test_expect_success 'create new commit on remote' '
- (cd public &&
+ (cd server &&
echo content >>file &&
- git commit -a -m two &&
- git push)
+ git commit -a -m two)
'
test_expect_success 'pulling from local repo' '
- (cd localclone && git pull) &&
- test_cmp public/file localclone/file
+ (cd local && git pull) &&
+ test_cmp server/file local/file
'
test_expect_success 'pushing to local repo' '
- (cd localclone &&
+ (cd local &&
echo content >>file &&
git commit -a -m three &&
git push) &&
- compare_refs localclone HEAD server HEAD
+ compare_refs local HEAD server HEAD
'
test_expect_success 'fetch new branch' '
- (cd public &&
+ (cd server &&
+ git reset --hard &&
git checkout -b new &&
echo content >>file &&
- git commit -a -m five &&
- git push origin new
+ git commit -a -m five
) &&
- (cd localclone &&
+ (cd local &&
git fetch origin new
) &&
- compare_refs public HEAD localclone FETCH_HEAD
+ compare_refs server HEAD local FETCH_HEAD
'
#
# This is only needed because of a bug not detected by this script. It will be
# fixed shortly, but for now lets not cause regressions.
#
-test_expect_success 'bump commit in public' '
- (cd public &&
+test_expect_success 'bump commit in server' '
+ (cd server &&
git checkout master &&
- git pull &&
echo content >>file &&
- git commit -a -m four &&
- git push) &&
- compare_refs public HEAD server HEAD
+ git commit -a -m four) &&
+ compare_refs server HEAD server HEAD
'
test_expect_success 'fetch multiple branches' '
- (cd localclone &&
+ (cd local &&
git fetch
) &&
- compare_refs server master localclone refs/remotes/origin/master &&
- compare_refs server new localclone refs/remotes/origin/new
+ compare_refs server master local refs/remotes/origin/master &&
+ compare_refs server new local refs/remotes/origin/new
'
test_expect_success 'push when remote has extra refs' '
- (cd localclone &&
+ (cd local &&
git reset --hard origin/master &&
echo content >>file &&
git commit -a -m six &&
git push
) &&
- compare_refs localclone master server master
+ compare_refs local master server master
'
test_expect_success 'push new branch by name' '
- (cd localclone &&
+ (cd local &&
git checkout -b new-name &&
echo content >>file &&
git commit -a -m seven &&
git push origin new-name
) &&
- compare_refs localclone HEAD server refs/heads/new-name
+ compare_refs local HEAD server refs/heads/new-name
'
test_expect_failure 'push new branch with old:new refspec' '
- (cd localclone &&
+ (cd local &&
git push origin new-name:new-refspec
) &&
- compare_refs localclone HEAD server refs/heads/new-refspec
+ compare_refs local HEAD server refs/heads/new-refspec
'
test_done
--
1.8.0
^ permalink raw reply related
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