Merge branch 'fp/submodule-checkout-mode'
[gitweb.git] / shallow.c
index 3c36dd82bc118d78b60832a80df5a2abb6a0d0d8..bbc98b55c07969474b0afb01d9c4da70455f1903 100644 (file)
--- a/shallow.c
+++ b/shallow.c
@@ -99,8 +99,7 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
                                cur_depth = *(int *)commit->util;
                        }
                }
-               if (parse_commit(commit))
-                       die("invalid commit");
+               parse_commit_or_die(commit);
                cur_depth++;
                if ((depth != INFINITE_DEPTH && cur_depth >= depth) ||
                    (is_repository_shallow() && !commit->parents &&
@@ -155,10 +154,14 @@ void check_shallow_file_for_update(void)
                die("shallow file was changed during fetch");
 }
 
+#define SEEN_ONLY 1
+#define VERBOSE   2
+
 struct write_shallow_data {
        struct strbuf *out;
        int use_pack_protocol;
        int count;
+       unsigned flags;
 };
 
 static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
@@ -167,6 +170,15 @@ static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
        const char *hex = sha1_to_hex(graft->sha1);
        if (graft->nr_parent != -1)
                return 0;
+       if (data->flags & SEEN_ONLY) {
+               struct commit *c = lookup_commit(graft->sha1);
+               if (!c || !(c->object.flags & SEEN)) {
+                       if (data->flags & VERBOSE)
+                               printf("Removing %s from .git/shallow\n",
+                                      sha1_to_hex(c->object.sha1));
+                       return 0;
+               }
+       }
        data->count++;
        if (data->use_pack_protocol)
                packet_buf_write(data->out, "shallow %s", hex);
@@ -177,14 +189,16 @@ static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
        return 0;
 }
 
-int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
-                         const struct sha1_array *extra)
+static int write_shallow_commits_1(struct strbuf *out, int use_pack_protocol,
+                                  const struct sha1_array *extra,
+                                  unsigned flags)
 {
        struct write_shallow_data data;
        int i;
        data.out = out;
        data.use_pack_protocol = use_pack_protocol;
        data.count = 0;
+       data.flags = flags;
        for_each_commit_graft(write_one_shallow, &data);
        if (!extra)
                return data.count;
@@ -196,6 +210,12 @@ int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
        return data.count;
 }
 
+int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
+                         const struct sha1_array *extra)
+{
+       return write_shallow_commits_1(out, use_pack_protocol, extra, 0);
+}
+
 char *setup_temporary_shallow(const struct sha1_array *extra)
 {
        struct strbuf sb = STRBUF_INIT;
@@ -258,6 +278,36 @@ void advertise_shallow_grafts(int fd)
        for_each_commit_graft(advertise_shallow_grafts_cb, &fd);
 }
 
+/*
+ * mark_reachable_objects() should have been run prior to this and all
+ * reachable commits marked as "SEEN".
+ */
+void prune_shallow(int show_only)
+{
+       static struct lock_file shallow_lock;
+       struct strbuf sb = STRBUF_INIT;
+       int fd;
+
+       if (show_only) {
+               write_shallow_commits_1(&sb, 0, NULL, SEEN_ONLY | VERBOSE);
+               strbuf_release(&sb);
+               return;
+       }
+       check_shallow_file_for_update();
+       fd = hold_lock_file_for_update(&shallow_lock, git_path("shallow"),
+                                      LOCK_DIE_ON_ERROR);
+       if (write_shallow_commits_1(&sb, 0, NULL, SEEN_ONLY)) {
+               if (write_in_full(fd, sb.buf, sb.len) != sb.len)
+                       die_errno("failed to write to %s",
+                                 shallow_lock.filename);
+               commit_lock_file(&shallow_lock);
+       } else {
+               unlink(git_path("shallow"));
+               rollback_lock_file(&shallow_lock);
+       }
+       strbuf_release(&sb);
+}
+
 #define TRACE_KEY "GIT_TRACE_SHALLOW"
 
 /*
@@ -308,22 +358,6 @@ void remove_nonexistent_theirs_shallow(struct shallow_info *info)
        info->nr_theirs = dst;
 }
 
-/* Step 5, remove non-existent ones in "ours" in the pack */
-void remove_nonexistent_ours_in_pack(struct shallow_info *info,
-                                    struct packed_git *p)
-{
-       unsigned char (*sha1)[20] = info->shallow->sha1;
-       int i, dst;
-       trace_printf_key(TRACE_KEY, "shallow: remove_nonexistent_ours_in_pack\n");
-       for (i = dst = 0; i < info->nr_ours; i++) {
-               if (i != dst)
-                       info->ours[dst] = info->ours[i];
-               if (find_pack_entry_one(sha1[info->ours[i]], p))
-                       dst++;
-       }
-       info->nr_ours = dst;
-}
-
 define_commit_slab(ref_bitmap, uint32_t *);
 
 struct paint_info {