Merge branch 'jt/fsck-code-cleanup' into next
authorJunio C Hamano <gitster@pobox.com>
Thu, 8 Feb 2018 23:08:25 +0000 (15:08 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 8 Feb 2018 23:08:25 +0000 (15:08 -0800)
Plug recently introduced leaks in fsck.

* jt/fsck-code-cleanup:
fsck: fix leak when traversing trees

1  2 
builtin/fsck.c
diff --combined builtin/fsck.c
index 7a8a679d4f3d0cf6d95991927947cbd00359868c,5aa4a1b336563313f1e17e57c9049699442a8a63..9981db22637c027019c206583f24dc2b665deeff
@@@ -15,7 -15,6 +15,7 @@@
  #include "progress.h"
  #include "streaming.h"
  #include "decorate.h"
 +#include "packfile.h"
  
  #define REACHABLE 0x0001
  #define SEEN      0x0002
@@@ -149,15 -148,6 +149,15 @@@ static int mark_object(struct object *o
        if (obj->flags & REACHABLE)
                return 0;
        obj->flags |= REACHABLE;
 +
 +      if (is_promisor_object(&obj->oid))
 +              /*
 +               * Further recursion does not need to be performed on this
 +               * object since it is a promisor object (so it does not need to
 +               * be added to "pending").
 +               */
 +              return 0;
 +
        if (!(obj->flags & HAS_OBJ)) {
                if (parent && !has_object_file(&obj->oid)) {
                        printf("broken link from %7s %s\n",
@@@ -180,7 -170,13 +180,13 @@@ static void mark_object_reachable(struc
  
  static int traverse_one_object(struct object *obj)
  {
-       return fsck_walk(obj, obj, &fsck_walk_options);
+       int result = fsck_walk(obj, obj, &fsck_walk_options);
+       if (obj->type == OBJ_TREE) {
+               struct tree *tree = (struct tree *)obj;
+               free_tree_buffer(tree);
+       }
+       return result;
  }
  
  static int traverse_reachable(void)
        unsigned int nr = 0;
        int result = 0;
        if (show_progress)
 -              progress = start_progress_delay(_("Checking connectivity"), 0, 0, 2);
 +              progress = start_delayed_progress(_("Checking connectivity"), 0);
        while (pending.nr) {
 -              struct object_array_entry *entry;
 -              struct object *obj;
 -
 -              entry = pending.objects + --pending.nr;
 -              obj = entry->item;
 -              result |= traverse_one_object(obj);
 +              result |= traverse_one_object(object_array_pop(&pending));
                display_progress(progress, ++nr);
        }
        stop_progress(&progress);
@@@ -217,8 -218,6 +223,8 @@@ static void check_reachable_object(stru
         * do a full fsck
         */
        if (!(obj->flags & HAS_OBJ)) {
 +              if (is_promisor_object(&obj->oid))
 +                      return;
                if (has_sha1_pack(obj->oid.hash))
                        return; /* it is in pack - forget about it */
                printf("missing %s %s\n", printable_type(obj),
@@@ -333,8 -332,6 +339,8 @@@ static void check_connectivity(void
  
  static int fsck_obj(struct object *obj)
  {
 +      int err;
 +
        if (obj->flags & SEEN)
                return 0;
        obj->flags |= SEEN;
  
        if (fsck_walk(obj, NULL, &fsck_obj_options))
                objerror(obj, "broken links");
 -      if (fsck_object(obj, NULL, 0, &fsck_obj_options))
 -              return -1;
 -
 -      if (obj->type == OBJ_TREE) {
 -              struct tree *item = (struct tree *) obj;
 -
 -              free_tree_buffer(item);
 -      }
 +      err = fsck_object(obj, NULL, 0, &fsck_obj_options);
 +      if (err)
 +              goto out;
  
        if (obj->type == OBJ_COMMIT) {
                struct commit *commit = (struct commit *) obj;
  
 -              free_commit_buffer(commit);
 -
                if (!commit->parents && show_root)
                        printf("root %s\n", describe_object(&commit->object));
        }
                }
        }
  
 -      return 0;
 +out:
 +      if (obj->type == OBJ_TREE)
 +              free_tree_buffer((struct tree *)obj);
 +      if (obj->type == OBJ_COMMIT)
 +              free_commit_buffer((struct commit *)obj);
 +      return err;
  }
  
  static int fsck_obj_buffer(const struct object_id *oid, enum object_type type,
@@@ -409,7 -408,7 +415,7 @@@ static void fsck_handle_reflog_oid(cons
                                        xstrfmt("%s@{%"PRItime"}", refname, timestamp));
                        obj->flags |= USED;
                        mark_object_reachable(obj);
 -              } else {
 +              } else if (!is_promisor_object(oid)) {
                        error("%s: invalid reflog entry %s", refname, oid_to_hex(oid));
                        errors_found |= ERROR_REACHABLE;
                }
@@@ -445,14 -444,6 +451,14 @@@ static int fsck_handle_ref(const char *
  
        obj = parse_object(oid);
        if (!obj) {
 +              if (is_promisor_object(oid)) {
 +                      /*
 +                       * Increment default_refs anyway, because this is a
 +                       * valid ref.
 +                       */
 +                       default_refs++;
 +                       return 0;
 +              }
                error("%s: invalid sha1 pointer %s", refname, oid_to_hex(oid));
                errors_found |= ERROR_REACHABLE;
                /* We'll continue with the rest despite the error.. */
@@@ -574,7 -565,7 +580,7 @@@ static int fsck_head_link(void
        if (verbose)
                fprintf(stderr, "Checking HEAD link\n");
  
 -      head_points_at = resolve_ref_unsafe("HEAD", 0, head_oid.hash, NULL);
 +      head_points_at = resolve_ref_unsafe("HEAD", 0, &head_oid, NULL);
        if (!head_points_at) {
                errors_found |= ERROR_REFS;
                return error("Invalid HEAD");
@@@ -678,9 -669,6 +684,9 @@@ int cmd_fsck(int argc, const char **arg
        int i;
        struct alternate_object_database *alt;
  
 +      /* fsck knows how to handle missing promisor objects */
 +      fetch_if_missing = 0;
 +
        errors_found = 0;
        check_replace_refs = 0;
  
  
        for (i = 0; i < argc; i++) {
                const char *arg = argv[i];
 -              unsigned char sha1[20];
 -              if (!get_sha1(arg, sha1)) {
 -                      struct object *obj = lookup_object(sha1);
 +              struct object_id oid;
 +              if (!get_oid(arg, &oid)) {
 +                      struct object *obj = lookup_object(oid.hash);
  
                        if (!obj || !(obj->flags & HAS_OBJ)) {
 -                              error("%s: object missing", sha1_to_hex(sha1));
 +                              if (is_promisor_object(&oid))
 +                                      continue;
 +                              error("%s: object missing", oid_to_hex(&oid));
                                errors_found |= ERROR_OBJECT;
                                continue;
                        }
  
        if (keep_cache_objects) {
                verify_index_checksum = 1;
 +              verify_ce_order = 1;
                read_cache();
                for (i = 0; i < active_nr; i++) {
                        unsigned int mode;