Merge branch 'jk/help-unknown-ref-fix'
[gitweb.git] / builtin / prune.c
index 1ec9ddd751df6644d2c39ace41a1494800082638..97613eccb54dcba31d9fb35df54673fdf1f57817 100644 (file)
@@ -31,16 +31,39 @@ static int prune_tmp_file(const char *fullpath)
        return 0;
 }
 
+static void perform_reachability_traversal(struct rev_info *revs)
+{
+       static int initialized;
+       struct progress *progress = NULL;
+
+       if (initialized)
+               return;
+
+       if (show_progress)
+               progress = start_delayed_progress(_("Checking connectivity"), 0);
+       mark_reachable_objects(revs, 1, expire, progress);
+       stop_progress(&progress);
+       initialized = 1;
+}
+
+static int is_object_reachable(const struct object_id *oid,
+                              struct rev_info *revs)
+{
+       struct object *obj;
+
+       perform_reachability_traversal(revs);
+
+       obj = lookup_object(the_repository, oid->hash);
+       return obj && (obj->flags & SEEN);
+}
+
 static int prune_object(const struct object_id *oid, const char *fullpath,
                        void *data)
 {
+       struct rev_info *revs = data;
        struct stat st;
 
-       /*
-        * Do we know about this object?
-        * It must have been reachable
-        */
-       if (lookup_object(the_repository, oid->hash))
+       if (is_object_reachable(oid, revs))
                return 0;
 
        if (lstat(fullpath, &st)) {
@@ -102,7 +125,6 @@ static void remove_temporary_files(const char *path)
 int cmd_prune(int argc, const char **argv, const char *prefix)
 {
        struct rev_info revs;
-       struct progress *progress = NULL;
        int exclude_promisor_objects = 0;
        const struct option options[] = {
                OPT__DRY_RUN(&show_only, N_("do not remove, show only")),
@@ -142,17 +164,13 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
 
        if (show_progress == -1)
                show_progress = isatty(2);
-       if (show_progress)
-               progress = start_delayed_progress(_("Checking connectivity"), 0);
        if (exclude_promisor_objects) {
                fetch_if_missing = 0;
                revs.exclude_promisor_objects = 1;
        }
 
-       mark_reachable_objects(&revs, 1, expire, progress);
-       stop_progress(&progress);
        for_each_loose_file_in_objdir(get_object_directory(), prune_object,
-                                     prune_cruft, prune_subdir, NULL);
+                                     prune_cruft, prune_subdir, &revs);
 
        prune_packed_objects(show_only ? PRUNE_PACKED_DRY_RUN : 0);
        remove_temporary_files(get_object_directory());
@@ -160,8 +178,10 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
        remove_temporary_files(s);
        free(s);
 
-       if (is_repository_shallow(the_repository))
+       if (is_repository_shallow(the_repository)) {
+               perform_reachability_traversal(&revs);
                prune_shallow(show_only ? PRUNE_SHOW_ONLY : 0);
+       }
 
        return 0;
 }