Subject: [RFC PATCH 06/15] Automatically reuse sparse limiting arguments in revision walking

From: Elijah Newren <[email-masked]>
Date: Sat, 4 Sep 2010 18:13:58 -0600

In a sparse repository, by automatically making use of sparse limits
specified at clone time, we can avoid walking uninteresting commits and
prevent access to missing trees and blobs.  Note that this means that if
you created a sparse clone with
  git clone <repo> <dest_dir> -- PATH1 PATH2 PATH3 PATH4 PATH5
then
  git log
implicitly runs as though you had manually specified
  git log -- PATH1 PATH2 PATH3 PATH4 PATH5
Similarly, running
  git diff
implicitly runs as though you had manually specified
  git diff -- PATH1 PATH2 PATH3 PATH4 PATH5

This is necessary for proper operation of git diff in a sparse clone to
avoid accessing missing objects.  In the case of a plain git log, this
merely serves as an additional convenience, but for more complicated log
operations (e.g. when passing -p or -S options) it becomes necessary.

Signed-off-by: Elijah Newren <[email-masked]>
---
 revision.c                          |   16 +++++++++++++++-
 t/t5720-sparse-repository-basics.sh |    6 +++---
 2 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/revision.c b/revision.c
index a962b77..67b1a1d 100644
--- a/revision.c
+++ b/revision.c
@@ -1492,6 +1492,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
 	const char *submodule = NULL;
 	const char *optarg;
 	int argcount;
+	const char *arg;
 
 	if (opt)
 		submodule = opt->submodule;
@@ -1514,7 +1515,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
 	flags = 0;
 	read_from_stdin = 0;
 	for (left = i = 1; i < argc; i++) {
-		const char *arg = argv[i];
+		arg = argv[i];
 		if (*arg == '-') {
 			int opts;
 
@@ -1624,6 +1625,19 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
 			got_rev_arg = 1;
 	}
 
+	/*
+	 * FIXME: This disallows things like --all, --stdin, --not, although
+	 * some of those like --stdin may not make sense anyway.
+	 */
+	for (arg = git_sparse_limits ? *git_sparse_limits : NULL; arg; arg++) {
+		const int flags = 0;
+		const int cant_be_filename = 1;
+		if (handle_revision_arg(arg, revs, flags, cant_be_filename))
+			die("bad revision '%s'", arg);
+	}
+	if (git_sparse_pathspecs)
+		append_prune_data(&prune_data, git_sparse_pathspecs);
+
 	if (prune_data)
 		revs->prune_data = get_pathspec(revs->prefix, prune_data);
 
diff --git a/t/t5720-sparse-repository-basics.sh b/t/t5720-sparse-repository-basics.sh
index b11c5ab..d04e171 100755
--- a/t/t5720-sparse-repository-basics.sh
+++ b/t/t5720-sparse-repository-basics.sh
@@ -60,7 +60,7 @@ test_expect_success 'plumbing: ls-files works' '
 	test "sub/b/file" = "$(cat output)"
 '
 
-test_expect_failure 'plumbing: rev-list works' '
+test_expect_success 'plumbing: rev-list works' '
 	test "$(git rev-list HEAD)" = \
 	     "$(git $srcgit rev-list HEAD -- sub/b/)" &&
 	test "$(git rev-list --objects HEAD)" = \
@@ -87,13 +87,13 @@ for i in $(git $srcgit rev-list HEAD | xargs git name-rev | cut -b 42-); do
 	"
 done
 
-test_expect_failure 'basic: log works' '
+test_expect_success 'basic: log works' '
 	git log > /dev/null &&
 	git log -p > /dev/null &&
 	git log -Scontent > /dev/null
 '
 
-test_expect_failure 'basic: diff works' '
+test_expect_success 'basic: diff works' '
 	git diff master~3 master &&
 	git diff master~3
 '
-- 
1.7.2.2.140.gd06af