Instead of a custom commit walker like get_shallow_commits(), this new
function uses rev-list to mark SHALLOW to all reachable commits. 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 not-shallow as boundary.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
---
 commit.h  |  2 ++
 shallow.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 67 insertions(+)

diff --git a/commit.h b/commit.h
index 9f189cb..5c80eea 100644
--- a/commit.h
+++ b/commit.h
@@ -254,6 +254,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 d8bf40a..1db2768 100644
--- a/shallow.c
+++ b/shallow.c
@@ -10,6 +10,8 @@
 #include "revision.h"
 #include "commit-slab.h"
 #include "sigchain.h"
+#include "revision.h"
+#include "list-objects.h"
 
 static int is_shallow = -1;
 static struct stat_validity shallow_stat;
@@ -137,6 +139,69 @@ 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;
+}
+
+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;
+       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);
+               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 SHALLOW */
+       if (prepare_revision_walk(&revs))
+               die("revision walk setup failed");
+       traverse_commit_list(&revs, show_commit, NULL, &shallow_flag);
+
+       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_not_shallow = 0;
+
+               if (o->type != OBJ_COMMIT || !(o->flags & shallow_flag))
+                       continue;
+
+               if (parse_commit(c))
+                       die("unable to parse commit %s",
+                           sha1_to_hex(c->object.sha1));
+
+               for (p = c->parents; p; p = p->next) {
+                       if (p->item->object.flags & shallow_flag)
+                               continue;
+                       parent_is_not_shallow = 1;
+                       if (p->item->object.flags & not_shallow_flag)
+                               continue;
+                       p->item->object.flags |= not_shallow_flag;
+                       commit_list_insert(p->item, &result);
+               }
+
+               if (parent_is_not_shallow)
+                       commit_list_insert(c, &result);
+       }
+       return result;
+}
+
 static void check_shallow_file_for_update(void)
 {
        if (is_shallow == -1)
-- 
2.3.0.rc1.137.g477eb31

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to