git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 05/20] shallow.c: implement a generic shallow boundary finder based on rev-list

From
Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Date
Dec 29, 2015, 12:10 UTC
Message-ID
<1451391043-28093-6-git-send-email-pclouds@gmail.com>
In-Reply-To
<1451391043-28093-1-git-send-email-pclouds@gmail.com>

Instead of a custom commit walker like get_shallow_commits(), this new function uses rev-list to mark NOT_SHALLOW to all reachable commits, except borders. The definition of reachable is to be defined by the protocol later. This makes it more flexible to define shallow boundary.

Note: if a commit has one NOT_SHALLOW parent and one SHALLOW parent,
then it's considered the boundary. Which means in the client side, this
commit has _no_ parents. This could lead to surprising cuts if we're not
careful.

Another option is to include more commits and only mark commits whose all parents are SHALLOW as boundary.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 commit.h  |  2 ++
 shallow.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 94 insertions(+)
diff --git a/commit.h b/commit.h
index 5d58be0..b717be1 100644
--- a/commit.h
+++ b/commit.h
@@ -258,6 +258,8 @@ extern int for_each_commit_graft(each_commit_graft_fn, void *);
 extern int is_repository_shallow(void);
 extern struct commit_list *get_shallow_commits(struct object_array *heads,
 		int depth, int shallow_flag, int not_shallow_flag);
+extern struct commit_list *get_shallow_commits_by_rev_list(
+		int ac, const char **av, int shallow_flag, int not_shallow_flag);
 extern void set_alternate_shallow_file(const char *path, int override);
 extern int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
 				 const struct sha1_array *extra);
diff --git a/shallow.c b/shallow.c
index 60f1505..45dffaa 100644
--- a/shallow.c
+++ b/shallow.c
@@ -10,6 +10,8 @@
 #include "diff.h"
 #include "revision.h"
 #include "commit-slab.h"
+#include "revision.h"
+#include "list-objects.h"
 
 static int is_shallow = -1;
 static struct stat_validity shallow_stat;
@@ -137,6 +139,96 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
 	return result;
 }
 
+static void show_commit(struct commit *commit, void *data)
+{
+	commit->object.flags |= *(int *)data;
+}
+
+/*
+ * Given rev-list arguments, run rev-list. All reachable commits
+ * except border ones are marked with not_shallow_flag. Border commits
+ * are marked with shallow_flag. The list of border/shallow commits
+ * are also returned.
+ */
+struct commit_list *get_shallow_commits_by_rev_list(int ac, const char **av,
+						    int shallow_flag,
+						    int not_shallow_flag)
+{
+	struct commit_list *result = NULL, *cl;
+	struct rev_info revs;
+	unsigned int i, nr;
+
+	/*
+	 * SHALLOW and NOT_SHALLOW should not be set at this
+	 * point. But better be safe than sorry.
+	 */
+	nr = get_max_object_index();
+	for (i = 0; i < nr; i++) {
+		struct object *o = get_indexed_object(i);
+		if (!o)
+			continue;
+		o->flags &= ~(shallow_flag | not_shallow_flag);
+	}
+
+	is_repository_shallow(); /* make sure shallows are read */
+
+	init_revisions(&revs, NULL);
+	save_commit_buffer = 0;
+	setup_revisions(ac, av, &revs, NULL);
+
+	/* Mark all reachable commits as NOT_SHALLOW */
+	if (prepare_revision_walk(&revs))
+		die("revision walk setup failed");
+	traverse_commit_list(&revs, show_commit, NULL, &not_shallow_flag);
+
+	/*
+	 * mark border commits SHALLOW + NOT_SHALLOW.
+	 * We cannot clear NOT_SHALLOW right now. Imagine border
+	 * commit A is processed first, then commit B, whose parent is
+	 * A, later. If NOT_SHALLOW on A is cleared at step 1, B
+	 * itself is considered border at step 2, which is incorrect.
+	 */
+	nr = get_max_object_index();
+	for (i = 0; i < nr; i++) {
+		struct object *o = get_indexed_object(i);
+		struct commit *c = (struct commit *)o;
+		struct commit_list *p;
+		int parent_is_shallow = 0;
+
+		if (!o || o->type != OBJ_COMMIT || !(o->flags & not_shallow_flag))
+			continue;
+
+		if (parse_commit(c))
+			die("unable to parse commit %s",
+			    oid_to_hex(&c->object.oid));
+
+		for (p = c->parents; p; p = p->next) {
+			if (p->item->object.flags & not_shallow_flag)
+				continue;
+			parent_is_shallow = 1;
+			if (p->item->object.flags & shallow_flag)
+				continue;
+			p->item->object.flags |= shallow_flag;
+			commit_list_insert(p->item, &result);
+		}
+
+		if (parent_is_shallow) {
+			o->flags |= shallow_flag;
+			commit_list_insert(c, &result);
+		}
+	}
+	/* clean up NOT_SHALLOW on border commits */
+	cl = result;
+	while (cl) {
+		struct object *object = &result->item->object;
+		if ((object->flags & not_shallow_flag) &&
+		    (object->flags & shallow_flag))
+			object->flags &= ~not_shallow_flag;
+		cl = cl->next;
+	}
+	return result;
+}
+
 static void check_shallow_file_for_update(void)
 {
 	if (is_shallow == -1)
-- 
2.3.0.rc1.137.g477eb31
Previous: Nguyễn Thái Ngọc DuyNext: Nguyễn Thái Ngọc Duy
Message 6 of 24 in “More flexibility in making shallow clones”
  1. 00/20 More flexibility in making shallow clonesNguyễn Thái Ngọc Duy, Dec 29, 2015
  2. 01/20 upload-pack: move shallow deepen code out of receive_needs()Nguyễn Thái Ngọc Duy, Dec 29, 2015
  3. 02/20 upload-pack: move "shallow" sending code out of deepen()Nguyễn Thái Ngọc Duy, Dec 29, 2015
  4. 03/20 upload-pack: remove unused variable "backup"Nguyễn Thái Ngọc Duy, Dec 29, 2015
  5. 04/20 upload-pack: move "unshallow" sending code out of deepen()Nguyễn Thái Ngọc Duy, Dec 29, 2015
  6. 05/20 shallow.c: implement a generic shallow boundary finder based on rev-listNguyễn Thái Ngọc Duy, Dec 29, 2015
  7. 06/20 upload-pack: glue code to use get_shallow_commits_by_rev_listNguyễn Thái Ngọc Duy, Dec 29, 2015
  8. 07/20 upload-pack: use skip_prefix() instead of starts_with() when possibleNguyễn Thái Ngọc Duy, Dec 29, 2015
  9. 08/20 upload-pack: tighten number parsing at "deepen" linesNguyễn Thái Ngọc Duy, Dec 29, 2015
  10. 09/20 upload-pack: add deepen-since to cut shallow repos based on timeNguyễn Thái Ngọc Duy, Dec 29, 2015
  11. 10/20 fetch-pack: use a common function for verbose printingNguyễn Thái Ngọc Duy, Dec 29, 2015
  12. 11/20 fetch-pack: use a separate flag for fetch in deepening modeNguyễn Thái Ngọc Duy, Dec 29, 2015
  13. 12/20 fetch: define shallow boundary with --sinceNguyễn Thái Ngọc Duy, Dec 29, 2015
  14. 13/20 clone: define shallow clone boundary based on time with --sinceNguyễn Thái Ngọc Duy, Dec 29, 2015
  15. 14/20 Add test_repo_expect_success for running tests in a new repositoryNguyễn Thái Ngọc Duy, Dec 29, 2015
  16. Duy NguyenDec 29, 2015
  17. 15/20 t5500: test for shallow depth since a specific dateNguyễn Thái Ngọc Duy, Dec 29, 2015
  18. 16/20 upload-pack: support define shallow boundary by excluding revisionsNguyễn Thái Ngọc Duy, Dec 29, 2015
  19. 17/20 fetch: define shallow boundary with --notNguyễn Thái Ngọc Duy, Dec 29, 2015
  20. 18/20 clone: define shallow clone boundary with --notNguyễn Thái Ngọc Duy, Dec 29, 2015
  21. 19/20 t5500: test for shallow depth excluding a refNguyễn Thái Ngọc Duy, Dec 29, 2015
  22. 20/20 fetch: add --deepen=<N> to extend shallow boundary by <N> commitsNguyễn Thái Ngọc Duy, Dec 29, 2015
  23. Eric SunshineJan 4, 2016
  24. Junio C HamanoDec 29, 2015

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.