This patch teaches "prune" to remove shallow roots that are no longer
reachable from any refs (e.g. when the relevant refs are removed).

Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
---
 builtin/gc.c    |  1 +
 builtin/prune.c |  4 ++++
 commit.h        |  1 +
 shallow.c       | 43 +++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/builtin/gc.c b/builtin/gc.c
index c14190f..cec8ecd 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -16,6 +16,7 @@
 #include "run-command.h"
 #include "sigchain.h"
 #include "argv-array.h"
+#include "commit.h"
 
 #define FAILED_RUN "failed to run %s"
 
diff --git a/builtin/prune.c b/builtin/prune.c
index 6366917..023aea8 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -170,5 +170,9 @@ int cmd_prune(int argc, const char **argv, const char 
*prefix)
        s = mkpathdup("%s/pack", get_object_directory());
        remove_temporary_files(s);
        free(s);
+
+       if (!show_only && is_repository_shallow())
+               prune_shallow();
+
        return 0;
 }
diff --git a/commit.h b/commit.h
index 0ff70fa..ff93a59 100644
--- a/commit.h
+++ b/commit.h
@@ -215,6 +215,7 @@ extern void remove_reachable_shallow_points(struct 
extra_have_objects *out,
 extern int mark_new_shallow_refs(const struct extra_have_objects *ref,
                                 int *ref_status, uint32_t **used,
                                 const struct extra_have_objects *shallow);
+extern void prune_shallow(void);
 
 int is_descendant_of(struct commit *, struct commit_list *);
 int in_merge_bases(struct commit *, struct commit *);
diff --git a/shallow.c b/shallow.c
index abb04db..0eda40f 100644
--- a/shallow.c
+++ b/shallow.c
@@ -157,6 +157,7 @@ struct write_shallow_data {
        struct strbuf *out;
        int use_pack_protocol;
        int count;
+       int seen_only;
 };
 
 static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
@@ -165,6 +166,11 @@ 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->seen_only) {
+               struct commit *c = lookup_commit(graft->sha1);
+               if (!c || !(c->object.flags & SEEN))
+                       return 0;
+       }
        data->count++;
        if (data->use_pack_protocol)
                packet_buf_write(data->out, "shallow %s", hex);
@@ -175,14 +181,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 extra_have_objects *extra)
+static int write_shallow_commits_1(struct strbuf *out, int use_pack_protocol,
+                                  const struct extra_have_objects *extra,
+                                  int seen_only)
 {
        struct write_shallow_data data;
        int i;
        data.out = out;
        data.use_pack_protocol = use_pack_protocol;
        data.count = 0;
+       data.seen_only = seen_only;
        for_each_commit_graft(write_one_shallow, &data);
        if (!extra)
                return data.count;
@@ -194,6 +202,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 extra_have_objects *extra)
+{
+       return write_shallow_commits_1(out, use_pack_protocol, extra, 0);
+}
+
 char *setup_temporary_shallow(const struct extra_have_objects *extra)
 {
        struct strbuf sb = STRBUF_INIT;
@@ -515,3 +529,28 @@ int mark_new_shallow_refs(const struct extra_have_objects 
*ref,
 
        return ret;
 }
+
+/*
+ * mark_reachable_objects() should have been run prior to this and all
+ * reachable commits marked as "SEEN".
+ */
+void prune_shallow(void)
+{
+       static struct lock_file shallow_lock;
+       struct strbuf sb = STRBUF_INIT;
+       int fd;
+
+       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, 1)) {
+               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);
+}
-- 
1.8.2.83.gc99314b

--
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