Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/rev-list-options.txt8
-rw-r--r--connected.c1
-rw-r--r--revision.c29
-rwxr-xr-xt/perf/p5600-clone-reference.sh27
-rwxr-xr-xt/t5618-alternate-refs.sh60
5 files changed, 125 insertions, 0 deletions
diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index 71a1fcc093..90a2c027ea 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -182,6 +182,14 @@ explicitly.
Pretend as if all objects mentioned by reflogs are listed on the
command line as `<commit>`.
+--alternate-refs::
+ Pretend as if all objects mentioned as ref tips of alternate
+ repositories were listed on the command line. An alternate
+ repository is any repository whose object directory is specified
+ in `objects/info/alternates`. The set of included objects may
+ be modified by `core.alternateRefsCommand`, etc. See
+ linkgit:git-config[1].
+
--single-worktree::
By default, all working trees will be examined by the
following options when there are more than one (see
diff --git a/connected.c b/connected.c
index 1ab481fed6..cd9b324afa 100644
--- a/connected.c
+++ b/connected.c
@@ -80,6 +80,7 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
argv_array_push(&rev_list.args, "--all");
}
argv_array_push(&rev_list.args, "--quiet");
+ argv_array_push(&rev_list.args, "--alternate-refs");
if (opt->progress)
argv_array_pushf(&rev_list.args, "--progress=%s",
_("Checking connectivity"));
diff --git a/revision.c b/revision.c
index d4aaf0ef25..0d1a30a7d7 100644
--- a/revision.c
+++ b/revision.c
@@ -1552,6 +1552,32 @@ void add_index_objects_to_pending(struct rev_info *revs, unsigned int flags)
free_worktrees(worktrees);
}
+struct add_alternate_refs_data {
+ struct rev_info *revs;
+ unsigned int flags;
+};
+
+static void add_one_alternate_ref(const struct object_id *oid,
+ void *vdata)
+{
+ const char *name = ".alternate";
+ struct add_alternate_refs_data *data = vdata;
+ struct object *obj;
+
+ obj = get_reference(data->revs, name, oid, data->flags);
+ add_rev_cmdline(data->revs, obj, name, REV_CMD_REV, data->flags);
+ add_pending_object(data->revs, obj, name);
+}
+
+static void add_alternate_refs_to_pending(struct rev_info *revs,
+ unsigned int flags)
+{
+ struct add_alternate_refs_data data;
+ data.revs = revs;
+ data.flags = flags;
+ for_each_alternate_ref(add_one_alternate_ref, &data);
+}
+
static int add_parents_only(struct rev_info *revs, const char *arg_, int flags,
int exclude_parent)
{
@@ -1954,6 +1980,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
!strcmp(arg, "--no-walk") || !strcmp(arg, "--do-walk") ||
!strcmp(arg, "--bisect") || starts_with(arg, "--glob=") ||
!strcmp(arg, "--indexed-objects") ||
+ !strcmp(arg, "--alternate-refs") ||
starts_with(arg, "--exclude=") ||
starts_with(arg, "--branches=") || starts_with(arg, "--tags=") ||
starts_with(arg, "--remotes=") || starts_with(arg, "--no-walk="))
@@ -2440,6 +2467,8 @@ static int handle_revision_pseudo_opt(const char *submodule,
add_reflogs_to_pending(revs, *flags);
} else if (!strcmp(arg, "--indexed-objects")) {
add_index_objects_to_pending(revs, *flags);
+ } else if (!strcmp(arg, "--alternate-refs")) {
+ add_alternate_refs_to_pending(revs, *flags);
} else if (!strcmp(arg, "--not")) {
*flags ^= UNINTERESTING | BOTTOM;
} else if (!strcmp(arg, "--no-walk")) {
diff --git a/t/perf/p5600-clone-reference.sh b/t/perf/p5600-clone-reference.sh
new file mode 100755
index 0000000000..68fed66347
--- /dev/null
+++ b/t/perf/p5600-clone-reference.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+test_description='speed of clone --reference'
+. ./perf-lib.sh
+
+test_perf_default_repo
+
+test_expect_success 'create shareable repository' '
+ git clone --bare . shared.git
+'
+
+test_expect_success 'advance base repository' '
+ # Do not use test_commit here; its test_tick will
+ # use some ancient hard-coded date. The resulting clock
+ # skew will cause pack-objects to traverse in a very
+ # sub-optimal order, skewing the results.
+ echo content >new-file-that-does-not-exist &&
+ git add new-file-that-does-not-exist &&
+ git commit -m "new commit"
+'
+
+test_perf 'clone --reference' '
+ rm -rf dst.git &&
+ git clone --no-local --bare --reference shared.git . dst.git
+'
+
+test_done
diff --git a/t/t5618-alternate-refs.sh b/t/t5618-alternate-refs.sh
new file mode 100755
index 0000000000..3353216f09
--- /dev/null
+++ b/t/t5618-alternate-refs.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+test_description='test handling of --alternate-refs traversal'
+. ./test-lib.sh
+
+# Avoid test_commit because we want a specific and known set of refs:
+#
+# base -- one
+# \ \
+# two -- merged
+#
+# where "one" and "two" are on separate refs, and "merged" is available only in
+# the dependent child repository.
+test_expect_success 'set up local refs' '
+ git checkout -b one &&
+ test_tick &&
+ git commit --allow-empty -m base &&
+ test_tick &&
+ git commit --allow-empty -m one &&
+ git checkout -b two HEAD^ &&
+ test_tick &&
+ git commit --allow-empty -m two
+'
+
+# We'll enter the child repository after it's set up since that's where
+# all of the subsequent tests will want to run (and it's easy to forget a
+# "-C child" and get nonsense results).
+test_expect_success 'set up shared clone' '
+ git clone -s . child &&
+ cd child &&
+ git merge origin/one
+'
+
+test_expect_success 'rev-list --alternate-refs' '
+ git rev-list --remotes=origin >expect &&
+ git rev-list --alternate-refs >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'rev-list --not --alternate-refs' '
+ git rev-parse HEAD >expect &&
+ git rev-list HEAD --not --alternate-refs >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'limiting with alternateRefsPrefixes' '
+ test_config core.alternateRefsPrefixes refs/heads/one &&
+ git rev-list origin/one >expect &&
+ git rev-list --alternate-refs >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'log --source shows .alternate marker' '
+ git log --oneline --source --remotes=origin >expect.orig &&
+ sed "s/origin.* /.alternate /" <expect.orig >expect &&
+ git log --oneline --source --alternate-refs >actual &&
+ test_cmp expect actual
+'
+
+test_done