Merge branch 'tg/refs-allowed-flags' into next
authorJunio C Hamano <gitster@pobox.com>
Tue, 19 Sep 2017 03:52:28 +0000 (12:52 +0900)
committerJunio C Hamano <gitster@pobox.com>
Tue, 19 Sep 2017 03:52:28 +0000 (12:52 +0900)
API error-proofing which happens to also squelch warnings from GCC.

* tg/refs-allowed-flags:
refs: strip out not allowed flags from ref_transaction_update

1  2 
refs.c
refs.h
diff --combined refs.c
index 0d5fe7442ae98e5bdc9641b6891cf508e2605453,41aec6505d1309fa2efed2bd9aca0a0ef2646444..83f0e687857dfaee3b91ce4d47b16f2f16945ce2
--- 1/refs.c
--- 2/refs.c
+++ b/refs.c
@@@ -174,24 -174,6 +174,24 @@@ int refname_is_safe(const char *refname
        return 1;
  }
  
 +/*
 + * Return true if refname, which has the specified oid and flags, can
 + * be resolved to an object in the database. If the referred-to object
 + * does not exist, emit a warning and return false.
 + */
 +int ref_resolves_to_object(const char *refname,
 +                         const struct object_id *oid,
 +                         unsigned int flags)
 +{
 +      if (flags & REF_ISBROKEN)
 +              return 0;
 +      if (!has_sha1_file(oid->hash)) {
 +              error("%s does not point to a valid object!", refname);
 +              return 0;
 +      }
 +      return 1;
 +}
 +
  char *refs_resolve_refdup(struct ref_store *refs,
                          const char *refname, int resolve_flags,
                          unsigned char *sha1, int *flags)
@@@ -336,6 -318,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 -334,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 -350,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;
@@@ -561,21 -561,6 +561,21 @@@ enum ref_type ref_type(const char *refn
         return REF_TYPE_NORMAL;
  }
  
 +long get_files_ref_lock_timeout_ms(void)
 +{
 +      static int configured = 0;
 +
 +      /* The default timeout is 100 ms: */
 +      static int timeout_ms = 100;
 +
 +      if (!configured) {
 +              git_config_get_int("core.filesreflocktimeout", &timeout_ms);
 +              configured = 1;
 +      }
 +
 +      return timeout_ms;
 +}
 +
  static int write_pseudoref(const char *pseudoref, const unsigned char *sha1,
                           const unsigned char *old_sha1, struct strbuf *err)
  {
        strbuf_addf(&buf, "%s\n", sha1_to_hex(sha1));
  
        filename = git_path("%s", pseudoref);
 -      fd = hold_lock_file_for_update(&lock, filename, LOCK_DIE_ON_ERROR);
 +      fd = hold_lock_file_for_update_timeout(&lock, filename,
 +                                             LOCK_DIE_ON_ERROR,
 +                                             get_files_ref_lock_timeout_ms());
        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;
@@@ -633,9 -616,8 +633,9 @@@ static int delete_pseudoref(const char 
                int fd;
                unsigned char actual_old_sha1[20];
  
 -              fd = hold_lock_file_for_update(&lock, filename,
 -                                             LOCK_DIE_ON_ERROR);
 +              fd = hold_lock_file_for_update_timeout(
 +                              &lock, filename, LOCK_DIE_ON_ERROR,
 +                              get_files_ref_lock_timeout_ms());
                if (fd < 0)
                        die_errno(_("Could not open '%s' for writing"), filename);
                if (read_ref(pseudoref, actual_old_sha1))
@@@ -836,7 -818,7 +836,7 @@@ int read_ref_at(const char *refname, un
        for_each_reflog_ent_reverse(refname, read_ref_at_ent, &cb);
  
        if (!cb.reccnt) {
 -              if (flags & GET_SHA1_QUIETLY)
 +              if (flags & GET_OID_QUIETLY)
                        exit(128);
                else
                        die("Log for %s is empty.", refname);
@@@ -939,6 -921,8 +939,8 @@@ int ref_transaction_update(struct ref_t
                return -1;
        }
  
+       flags &= REF_TRANSACTION_UPDATE_ALLOWED_FLAGS;
        flags |= (new_sha1 ? REF_HAVE_NEW : 0) | (old_sha1 ? REF_HAVE_OLD : 0);
  
        ref_transaction_add_update(transaction, refname, flags,
@@@ -1248,13 -1232,19 +1250,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 -1310,11 +1322,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 -1336,23 +1343,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 -1487,25 +1486,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 -1620,31 +1604,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 refs.h
index 78a26400b61b0046c72a64b985b9aa6443f27021,4d75c207e18bd6504a5613a373adf9dd8c745034..ae33a5f74d65dda62c84deb1eaae1774a0d21214
--- 1/refs.h
--- 2/refs.h
+++ b/refs.h
@@@ -275,8 -275,6 +275,8 @@@ typedef int each_ref_fn(const char *ref
   * modifies the reference also returns a nonzero value to immediately
   * stop the iteration. Returned references are sorted.
   */
 +int refs_head_ref(struct ref_store *refs,
 +                each_ref_fn fn, void *cb_data);
  int refs_for_each_ref(struct ref_store *refs,
                      each_ref_fn fn, void *cb_data);
  int refs_for_each_ref_in(struct ref_store *refs, const char *prefix,
@@@ -291,9 -289,6 +291,9 @@@ int refs_for_each_remote_ref(struct ref
  int head_ref(each_ref_fn fn, void *cb_data);
  int for_each_ref(each_ref_fn fn, void *cb_data);
  int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data);
 +int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
 +                           each_ref_fn fn, void *cb_data,
 +                           unsigned int broken);
  int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data,
                        unsigned int broken);
  int for_each_tag_ref(each_ref_fn fn, void *cb_data);
@@@ -304,6 -299,21 +304,6 @@@ int for_each_glob_ref(each_ref_fn fn, c
  int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
                         const char *prefix, void *cb_data);
  
 -int head_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data);
 -int for_each_ref_submodule(const char *submodule,
 -                         each_ref_fn fn, void *cb_data);
 -int for_each_ref_in_submodule(const char *submodule, const char *prefix,
 -                            each_ref_fn fn, void *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 for_each_tag_ref_submodule(const char *submodule,
 -                             each_ref_fn fn, void *cb_data);
 -int for_each_branch_ref_submodule(const char *submodule,
 -                                each_ref_fn fn, void *cb_data);
 -int for_each_remote_ref_submodule(const char *submodule,
 -                                each_ref_fn fn, void *cb_data);
 -
  int head_ref_namespaced(each_ref_fn fn, void *cb_data);
  int for_each_namespaced_ref(each_ref_fn fn, void *cb_data);
  
@@@ -344,6 -354,14 +344,14 @@@ int refs_pack_refs(struct ref_store *re
  #define REF_NODEREF   0x01
  #define REF_FORCE_CREATE_REFLOG 0x40
  
+ /*
+  * Flags that can be passed in to ref_transaction_update
+  */
+ #define REF_TRANSACTION_UPDATE_ALLOWED_FLAGS \
+       REF_ISPRUNING |                      \
+       REF_FORCE_CREATE_REFLOG |            \
+       REF_NODEREF
  /*
   * Setup reflog before using. Fill in err and return -1 on failure.
   */