Merge branch 'jn/per-repo-object-store-fixes'
authorJunio C Hamano <gitster@pobox.com>
Mon, 25 Sep 2017 06:24:06 +0000 (15:24 +0900)
committerJunio C Hamano <gitster@pobox.com>
Mon, 25 Sep 2017 06:24:07 +0000 (15:24 +0900)
Step #0 of a planned & larger series to make the in-core object
store per in-core repository object.

* jn/per-repo-object-store-fixes:
replace-objects: evaluate replacement refs without using the object store
push, fetch: error out for submodule entries not pointing to commits
pack: make packed_git_mru global a value instead of a pointer

1  2 
refs.c
submodule.c
diff --combined refs.c
index e8b67ddce80c83f8ec0dbfb3adc6d6c10b2f4b2d,cd84ed9710a271e167f91c9b3f8ee629fd58936a..0d5fe7442ae98e5bdc9641b6891cf508e2605453
--- 1/refs.c
--- 2/refs.c
+++ b/refs.c
@@@ -336,6 -336,12 +336,6 @@@ int for_each_tag_ref(each_ref_fn fn, vo
        return refs_for_each_tag_ref(get_main_ref_store(), fn, cb_data);
  }
  
 -int for_each_tag_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
 -{
 -      return refs_for_each_tag_ref(get_submodule_ref_store(submodule),
 -                                   fn, cb_data);
 -}
 -
  int refs_for_each_branch_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
  {
        return refs_for_each_ref_in(refs, "refs/heads/", fn, cb_data);
@@@ -346,6 -352,12 +346,6 @@@ int for_each_branch_ref(each_ref_fn fn
        return refs_for_each_branch_ref(get_main_ref_store(), fn, cb_data);
  }
  
 -int for_each_branch_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
 -{
 -      return refs_for_each_branch_ref(get_submodule_ref_store(submodule),
 -                                      fn, cb_data);
 -}
 -
  int refs_for_each_remote_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
  {
        return refs_for_each_ref_in(refs, "refs/remotes/", fn, cb_data);
@@@ -356,6 -368,12 +356,6 @@@ int for_each_remote_ref(each_ref_fn fn
        return refs_for_each_remote_ref(get_main_ref_store(), fn, cb_data);
  }
  
 -int for_each_remote_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
 -{
 -      return refs_for_each_remote_ref(get_submodule_ref_store(submodule),
 -                                      fn, cb_data);
 -}
 -
  int head_ref_namespaced(each_ref_fn fn, void *cb_data)
  {
        struct strbuf buf = STRBUF_INIT;
@@@ -594,7 -612,7 +594,7 @@@ static int write_pseudoref(const char *
        if (fd < 0) {
                strbuf_addf(err, "could not open '%s' for writing: %s",
                            filename, strerror(errno));
 -              return -1;
 +              goto done;
        }
  
        if (old_sha1) {
                }
        }
  
 -      if (write_in_full(fd, buf.buf, buf.len) != buf.len) {
 +      if (write_in_full(fd, buf.buf, buf.len) < 0) {
                strbuf_addf(err, "could not write to '%s'", filename);
                rollback_lock_file(&lock);
                goto done;
@@@ -1248,13 -1266,19 +1248,13 @@@ int refs_rename_ref_available(struct re
        return ok;
  }
  
 -int head_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
 +int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
  {
        struct object_id oid;
        int flag;
  
 -      if (submodule) {
 -              if (resolve_gitlink_ref(submodule, "HEAD", oid.hash) == 0)
 -                      return fn("HEAD", &oid, 0, cb_data);
 -
 -              return 0;
 -      }
 -
 -      if (!read_ref_full("HEAD", RESOLVE_REF_READING, oid.hash, &flag))
 +      if (!refs_read_ref_full(refs, "HEAD", RESOLVE_REF_READING,
 +                              oid.hash, &flag))
                return fn("HEAD", &oid, flag, cb_data);
  
        return 0;
  
  int head_ref(each_ref_fn fn, void *cb_data)
  {
 -      return head_ref_submodule(NULL, fn, cb_data);
 +      return refs_head_ref(get_main_ref_store(), fn, cb_data);
  }
  
  struct ref_iterator *refs_ref_iterator_begin(
@@@ -1320,6 -1344,11 +1320,6 @@@ int for_each_ref(each_ref_fn fn, void *
        return refs_for_each_ref(get_main_ref_store(), fn, cb_data);
  }
  
 -int for_each_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
 -{
 -      return refs_for_each_ref(get_submodule_ref_store(submodule), fn, cb_data);
 -}
 -
  int refs_for_each_ref_in(struct ref_store *refs, const char *prefix,
                         each_ref_fn fn, void *cb_data)
  {
@@@ -1341,15 -1370,23 +1341,15 @@@ int for_each_fullref_in(const char *pre
                               prefix, fn, 0, flag, cb_data);
  }
  
 -int for_each_ref_in_submodule(const char *submodule, const char *prefix,
 -                            each_ref_fn fn, void *cb_data)
 -{
 -      return refs_for_each_ref_in(get_submodule_ref_store(submodule),
 -                                  prefix, fn, cb_data);
 -}
 -
 -int for_each_fullref_in_submodule(const char *submodule, const char *prefix,
 -                                each_ref_fn fn, void *cb_data,
 -                                unsigned int broken)
 +int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
 +                           each_ref_fn fn, void *cb_data,
 +                           unsigned int broken)
  {
        unsigned int flag = 0;
  
        if (broken)
                flag = DO_FOR_EACH_INCLUDE_BROKEN;
 -      return do_for_each_ref(get_submodule_ref_store(submodule),
 -                             prefix, fn, 0, flag, cb_data);
 +      return do_for_each_ref(refs, prefix, fn, 0, flag, cb_data);
  }
  
  int for_each_replace_ref(each_ref_fn fn, void *cb_data)
        return do_for_each_ref(get_main_ref_store(),
                               git_replace_ref_base, fn,
                               strlen(git_replace_ref_base),
-                              0, cb_data);
+                              DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
  }
  
  int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)
@@@ -1484,10 -1521,25 +1484,10 @@@ const char *resolve_ref_unsafe(const ch
  int resolve_gitlink_ref(const char *submodule, const char *refname,
                        unsigned char *sha1)
  {
 -      size_t len = strlen(submodule);
        struct ref_store *refs;
        int flags;
  
 -      while (len && submodule[len - 1] == '/')
 -              len--;
 -
 -      if (!len)
 -              return -1;
 -
 -      if (submodule[len]) {
 -              /* We need to strip off one or more trailing slashes */
 -              char *stripped = xmemdupz(submodule, len);
 -
 -              refs = get_submodule_ref_store(stripped);
 -              free(stripped);
 -      } else {
 -              refs = get_submodule_ref_store(submodule);
 -      }
 +      refs = get_submodule_ref_store(submodule);
  
        if (!refs)
                return -1;
@@@ -1602,32 -1654,31 +1602,32 @@@ struct ref_store *get_submodule_ref_sto
  {
        struct strbuf submodule_sb = STRBUF_INIT;
        struct ref_store *refs;
 -      int ret;
 +      char *to_free = NULL;
 +      size_t len;
  
 -      if (!submodule || !*submodule) {
 -              /*
 -               * FIXME: This case is ideally not allowed. But that
 -               * can't happen until we clean up all the callers.
 -               */
 -              return get_main_ref_store();
 -      }
 +      if (!submodule)
 +              return NULL;
 +
 +      len = strlen(submodule);
 +      while (len && is_dir_sep(submodule[len - 1]))
 +              len--;
 +      if (!len)
 +              return NULL;
 +
 +      if (submodule[len])
 +              /* We need to strip off one or more trailing slashes */
 +              submodule = to_free = xmemdupz(submodule, len);
  
        refs = lookup_ref_store_map(&submodule_ref_stores, submodule);
        if (refs)
 -              return refs;
 +              goto done;
  
        strbuf_addstr(&submodule_sb, submodule);
 -      ret = is_nonbare_repository_dir(&submodule_sb);
 -      strbuf_release(&submodule_sb);
 -      if (!ret)
 -              return NULL;
 +      if (!is_nonbare_repository_dir(&submodule_sb))
 +              goto done;
  
 -      ret = submodule_to_gitdir(&submodule_sb, submodule);
 -      if (ret) {
 -              strbuf_release(&submodule_sb);
 -              return NULL;
 -      }
 +      if (submodule_to_gitdir(&submodule_sb, submodule))
 +              goto done;
  
        /* assume that add_submodule_odb() has been called */
        refs = ref_store_init(submodule_sb.buf,
        register_ref_store_map(&submodule_ref_stores, "submodule",
                               refs, submodule);
  
 +done:
        strbuf_release(&submodule_sb);
 +      free(to_free);
 +
        return refs;
  }
  
diff --combined submodule.c
index 075c55f3ca8101e06731ef3b45e51d11ec00c7f6,e0da55920d45fb508097d598acda37ae6e5f3c9f..b12600fc798f4427c8ad3bff1384c6fb5a6f4bc5
@@@ -69,13 -69,6 +69,13 @@@ int is_staging_gitmodules_ok(const stru
        return 1;
  }
  
 +static int for_each_remote_ref_submodule(const char *submodule,
 +                                       each_ref_fn fn, void *cb_data)
 +{
 +      return refs_for_each_remote_ref(get_submodule_ref_store(submodule),
 +                                      fn, cb_data);
 +}
 +
  /*
   * Try to update the "path" entry in the "submodule.<name>" section of the
   * .gitmodules file. Return 0 only if a .gitmodules file was found, a section
@@@ -774,19 -767,36 +774,36 @@@ static int append_oid_to_argv(const str
        return 0;
  }
  
+ struct has_commit_data {
+       int result;
+       const char *path;
+ };
  static int check_has_commit(const struct object_id *oid, void *data)
  {
-       int *has_commit = data;
+       struct has_commit_data *cb = data;
  
-       if (!lookup_commit_reference(oid))
-               *has_commit = 0;
+       enum object_type type = sha1_object_info(oid->hash, NULL);
  
-       return 0;
+       switch (type) {
+       case OBJ_COMMIT:
+               return 0;
+       case OBJ_BAD:
+               /*
+                * Object is missing or invalid. If invalid, an error message
+                * has already been printed.
+                */
+               cb->result = 0;
+               return 0;
+       default:
+               die(_("submodule entry '%s' (%s) is a %s, not a commit"),
+                   cb->path, oid_to_hex(oid), typename(type));
+       }
  }
  
  static int submodule_has_commits(const char *path, struct oid_array *commits)
  {
-       int has_commit = 1;
+       struct has_commit_data has_commit = { 1, path };
  
        /*
         * Perform a cheap, but incorrect check for the existence of 'commits'.
  
        oid_array_for_each_unique(commits, check_has_commit, &has_commit);
  
-       if (has_commit) {
+       if (has_commit.result) {
                /*
                 * Even if the submodule is checked out and the commit is
                 * present, make sure it exists in the submodule's object store
                cp.dir = path;
  
                if (capture_command(&cp, &out, GIT_MAX_HEXSZ + 1) || out.len)
-                       has_commit = 0;
+                       has_commit.result = 0;
  
                strbuf_release(&out);
        }
  
-       return has_commit;
+       return has_commit.result;
  }
  
  static int submodule_needs_pushing(const char *path, struct oid_array *commits)
@@@ -1634,8 -1644,6 +1651,8 @@@ static int find_first_merges(struct obj
                        oid_to_hex(&a->object.oid));
        init_revisions(&revs, NULL);
        rev_opts.submodule = path;
 +      /* FIXME: can't handle linked worktrees in submodules yet */
 +      revs.single_worktree = path != NULL;
        setup_revisions(ARRAY_SIZE(rev_args)-1, rev_args, &revs, &rev_opts);
  
        /* save all revisions from the above list that contain b */