Merge branch 'sg/skip-prefix-in-prettify-refname'
authorJunio C Hamano <gitster@pobox.com>
Tue, 28 Mar 2017 21:05:59 +0000 (14:05 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 28 Mar 2017 21:05:59 +0000 (14:05 -0700)
Code cleanup.

* sg/skip-prefix-in-prettify-refname:
refs.c: use skip_prefix() in prettify_refname()

1  2 
refs.c
diff --combined refs.c
index e7606716ddfff47b29f90e4d46cb2d59633cb455,49a7e703d53b3a3ffe7d9f6a006fe1819c9ed5e9..0272e332cc9951497dddcd8b5c57a30e80552b4f
--- 1/refs.c
--- 2/refs.c
+++ b/refs.c
@@@ -3,32 -3,12 +3,32 @@@
   */
  
  #include "cache.h"
 +#include "hashmap.h"
  #include "lockfile.h"
  #include "refs.h"
  #include "refs/refs-internal.h"
  #include "object.h"
  #include "tag.h"
  
 +/*
 + * List of all available backends
 + */
 +static struct ref_storage_be *refs_backends = &refs_be_files;
 +
 +static struct ref_storage_be *find_ref_storage_backend(const char *name)
 +{
 +      struct ref_storage_be *be;
 +      for (be = refs_backends; be; be = be->next)
 +              if (!strcmp(be->name, name))
 +                      return be;
 +      return NULL;
 +}
 +
 +int ref_storage_backend_exists(const char *name)
 +{
 +      return find_ref_storage_backend(name) != NULL;
 +}
 +
  /*
   * How to handle various characters in refnames:
   * 0: An acceptable character for refs
@@@ -366,11 -346,11 +366,11 @@@ int for_each_glob_ref(each_ref_fn fn, c
  
  const char *prettify_refname(const char *name)
  {
-       return name + (
-               starts_with(name, "refs/heads/") ? 11 :
-               starts_with(name, "refs/tags/") ? 10 :
-               starts_with(name, "refs/remotes/") ? 13 :
-               0);
+       if (skip_prefix(name, "refs/heads/", &name) ||
+           skip_prefix(name, "refs/tags/", &name) ||
+           skip_prefix(name, "refs/remotes/", &name))
+               ; /* nothing */
+       return name;
  }
  
  static const char *ref_rev_parse_rules[] = {
@@@ -405,7 -385,7 +405,7 @@@ int refname_match(const char *abbrev_na
  static char *substitute_branch_name(const char **string, int *len)
  {
        struct strbuf buf = STRBUF_INIT;
 -      int ret = interpret_branch_name(*string, *len, &buf);
 +      int ret = interpret_branch_name(*string, *len, &buf, 0);
  
        if (ret == *len) {
                size_t size;
  int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
  {
        char *last_branch = substitute_branch_name(&str, &len);
 +      int   refs_found  = expand_ref(str, len, sha1, ref);
 +      free(last_branch);
 +      return refs_found;
 +}
 +
 +int expand_ref(const char *str, int len, unsigned char *sha1, char **ref)
 +{
        const char **p, *r;
        int refs_found = 0;
  
                        warning("ignoring broken ref %s.", fullref);
                }
        }
 -      free(last_branch);
        return refs_found;
  }
  
@@@ -592,8 -566,8 +592,8 @@@ static int delete_pseudoref(const char 
        return 0;
  }
  
 -int delete_ref(const char *refname, const unsigned char *old_sha1,
 -             unsigned int flags)
 +int delete_ref(const char *msg, const char *refname,
 +             const unsigned char *old_sha1, unsigned int flags)
  {
        struct ref_transaction *transaction;
        struct strbuf err = STRBUF_INIT;
        transaction = ref_transaction_begin(&err);
        if (!transaction ||
            ref_transaction_delete(transaction, refname, old_sha1,
 -                                 flags, NULL, &err) ||
 +                                 flags, msg, &err) ||
            ref_transaction_commit(transaction, &err)) {
                error("%s", err.buf);
                ref_transaction_free(transaction);
@@@ -639,17 -613,12 +639,17 @@@ int copy_reflog_msg(char *buf, const ch
  
  int should_autocreate_reflog(const char *refname)
  {
 -      if (!log_all_ref_updates)
 +      switch (log_all_ref_updates) {
 +      case LOG_REFS_ALWAYS:
 +              return 1;
 +      case LOG_REFS_NORMAL:
 +              return starts_with(refname, "refs/heads/") ||
 +                      starts_with(refname, "refs/remotes/") ||
 +                      starts_with(refname, "refs/notes/") ||
 +                      !strcmp(refname, "HEAD");
 +      default:
                return 0;
 -      return starts_with(refname, "refs/heads/") ||
 -              starts_with(refname, "refs/remotes/") ||
 -              starts_with(refname, "refs/notes/") ||
 -              !strcmp(refname, "HEAD");
 +      }
  }
  
  int is_branch(const char *refname)
@@@ -675,7 -644,7 +675,7 @@@ struct read_ref_at_cb 
        int *cutoff_cnt;
  };
  
 -static int read_ref_at_ent(unsigned char *osha1, unsigned char *nsha1,
 +static int read_ref_at_ent(struct object_id *ooid, struct object_id *noid,
                const char *email, unsigned long timestamp, int tz,
                const char *message, void *cb_data)
  {
                 * hold the values for the previous record.
                 */
                if (!is_null_sha1(cb->osha1)) {
 -                      hashcpy(cb->sha1, nsha1);
 -                      if (hashcmp(cb->osha1, nsha1))
 +                      hashcpy(cb->sha1, noid->hash);
 +                      if (hashcmp(cb->osha1, noid->hash))
                                warning("Log for ref %s has gap after %s.",
                                        cb->refname, show_date(cb->date, cb->tz, DATE_MODE(RFC2822)));
                }
                else if (cb->date == cb->at_time)
 -                      hashcpy(cb->sha1, nsha1);
 -              else if (hashcmp(nsha1, cb->sha1))
 +                      hashcpy(cb->sha1, noid->hash);
 +              else if (hashcmp(noid->hash, cb->sha1))
                        warning("Log for ref %s unexpectedly ended on %s.",
                                cb->refname, show_date(cb->date, cb->tz,
                                                       DATE_MODE(RFC2822)));
 -              hashcpy(cb->osha1, osha1);
 -              hashcpy(cb->nsha1, nsha1);
 +              hashcpy(cb->osha1, ooid->hash);
 +              hashcpy(cb->nsha1, noid->hash);
                cb->found_it = 1;
                return 1;
        }
 -      hashcpy(cb->osha1, osha1);
 -      hashcpy(cb->nsha1, nsha1);
 +      hashcpy(cb->osha1, ooid->hash);
 +      hashcpy(cb->nsha1, noid->hash);
        if (cb->cnt > 0)
                cb->cnt--;
        return 0;
  }
  
 -static int read_ref_at_ent_oldest(unsigned char *osha1, unsigned char *nsha1,
 +static int read_ref_at_ent_oldest(struct object_id *ooid, struct object_id *noid,
                                  const char *email, unsigned long timestamp,
                                  int tz, const char *message, void *cb_data)
  {
                *cb->cutoff_tz = tz;
        if (cb->cutoff_cnt)
                *cb->cutoff_cnt = cb->reccnt;
 -      hashcpy(cb->sha1, osha1);
 +      hashcpy(cb->sha1, ooid->hash);
        if (is_null_sha1(cb->sha1))
 -              hashcpy(cb->sha1, nsha1);
 +              hashcpy(cb->sha1, noid->hash);
        /* We just want the first entry */
        return 1;
  }
@@@ -888,14 -857,6 +888,14 @@@ int ref_transaction_verify(struct ref_t
                                      flags, NULL, err);
  }
  
 +int update_ref_oid(const char *msg, const char *refname,
 +             const struct object_id *new_oid, const struct object_id *old_oid,
 +             unsigned int flags, enum action_on_err onerr)
 +{
 +      return update_ref(msg, refname, new_oid ? new_oid->hash : NULL,
 +              old_oid ? old_oid->hash : NULL, flags, onerr);
 +}
 +
  int update_ref(const char *msg, const char *refname,
               const unsigned char *new_sha1, const unsigned char *old_sha1,
               unsigned int flags, enum action_on_err onerr)
@@@ -1035,10 -996,10 +1035,10 @@@ static struct string_list *hide_refs
  
  int parse_hide_refs_config(const char *var, const char *value, const char *section)
  {
 +      const char *key;
        if (!strcmp("transfer.hiderefs", var) ||
 -          /* NEEDSWORK: use parse_config_key() once both are merged */
 -          (starts_with(var, section) && var[strlen(section)] == '.' &&
 -           !strcmp(var + strlen(section), ".hiderefs"))) {
 +          (!parse_config_key(var, section, NULL, NULL, &key) &&
 +           !strcmp(key, "hiderefs"))) {
                char *ref;
                int len;
  
@@@ -1119,20 -1080,20 +1119,20 @@@ const char *find_descendant_ref(const c
        return NULL;
  }
  
 -int rename_ref_available(const char *oldname, const char *newname)
 +int rename_ref_available(const char *old_refname, const char *new_refname)
  {
        struct string_list skip = STRING_LIST_INIT_NODUP;
        struct strbuf err = STRBUF_INIT;
 -      int ret;
 +      int ok;
  
 -      string_list_insert(&skip, oldname);
 -      ret = !verify_refname_available(newname, NULL, &skip, &err);
 -      if (!ret)
 +      string_list_insert(&skip, old_refname);
 +      ok = !verify_refname_available(new_refname, NULL, &skip, &err);
 +      if (!ok)
                error("%s", err.buf);
  
        string_list_clear(&skip, 0);
        strbuf_release(&err);
 -      return ret;
 +      return ok;
  }
  
  int head_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
@@@ -1170,13 -1131,9 +1170,13 @@@ int head_ref(each_ref_fn fn, void *cb_d
  static int do_for_each_ref(const char *submodule, const char *prefix,
                           each_ref_fn fn, int trim, int flags, void *cb_data)
  {
 +      struct ref_store *refs = get_ref_store(submodule);
        struct ref_iterator *iter;
  
 -      iter = files_ref_iterator_begin(submodule, prefix, flags);
 +      if (!refs)
 +              return 0;
 +
 +      iter = refs->be->iterator_begin(refs, prefix, flags);
        iter = prefix_ref_iterator_begin(iter, prefix, trim);
  
        return do_for_each_ref_iterator(iter, fn, cb_data);
@@@ -1235,10 -1192,8 +1235,10 @@@ int for_each_rawref(each_ref_fn fn, voi
  }
  
  /* This function needs to return a meaningful errno on failure */
 -const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
 -                             unsigned char *sha1, int *flags)
 +const char *resolve_ref_recursively(struct ref_store *refs,
 +                                  const char *refname,
 +                                  int resolve_flags,
 +                                  unsigned char *sha1, int *flags)
  {
        static struct strbuf sb_refname = STRBUF_INIT;
        int unused_flags;
        for (symref_count = 0; symref_count < SYMREF_MAXDEPTH; symref_count++) {
                unsigned int read_flags = 0;
  
 -              if (read_raw_ref(refname, sha1, &sb_refname, &read_flags)) {
 +              if (refs->be->read_raw_ref(refs, refname,
 +                                         sha1, &sb_refname, &read_flags)) {
                        *flags |= read_flags;
                        if (errno != ENOENT || (resolve_flags & RESOLVE_REF_READING))
                                return NULL;
        errno = ELOOP;
        return NULL;
  }
 +
 +/* backend functions */
 +int refs_init_db(struct strbuf *err)
 +{
 +      struct ref_store *refs = get_ref_store(NULL);
 +
 +      return refs->be->init_db(refs, err);
 +}
 +
 +const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
 +                             unsigned char *sha1, int *flags)
 +{
 +      return resolve_ref_recursively(get_ref_store(NULL), refname,
 +                                     resolve_flags, sha1, flags);
 +}
 +
 +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_ref_store(stripped);
 +              free(stripped);
 +      } else {
 +              refs = get_ref_store(submodule);
 +      }
 +
 +      if (!refs)
 +              return -1;
 +
 +      if (!resolve_ref_recursively(refs, refname, 0, sha1, &flags) ||
 +          is_null_sha1(sha1))
 +              return -1;
 +      return 0;
 +}
 +
 +struct submodule_hash_entry
 +{
 +      struct hashmap_entry ent; /* must be the first member! */
 +
 +      struct ref_store *refs;
 +
 +      /* NUL-terminated name of submodule: */
 +      char submodule[FLEX_ARRAY];
 +};
 +
 +static int submodule_hash_cmp(const void *entry, const void *entry_or_key,
 +                            const void *keydata)
 +{
 +      const struct submodule_hash_entry *e1 = entry, *e2 = entry_or_key;
 +      const char *submodule = keydata ? keydata : e2->submodule;
 +
 +      return strcmp(e1->submodule, submodule);
 +}
 +
 +static struct submodule_hash_entry *alloc_submodule_hash_entry(
 +              const char *submodule, struct ref_store *refs)
 +{
 +      struct submodule_hash_entry *entry;
 +
 +      FLEX_ALLOC_STR(entry, submodule, submodule);
 +      hashmap_entry_init(entry, strhash(submodule));
 +      entry->refs = refs;
 +      return entry;
 +}
 +
 +/* A pointer to the ref_store for the main repository: */
 +static struct ref_store *main_ref_store;
 +
 +/* A hashmap of ref_stores, stored by submodule name: */
 +static struct hashmap submodule_ref_stores;
 +
 +/*
 + * Return the ref_store instance for the specified submodule (or the
 + * main repository if submodule is NULL). If that ref_store hasn't
 + * been initialized yet, return NULL.
 + */
 +static struct ref_store *lookup_ref_store(const char *submodule)
 +{
 +      struct submodule_hash_entry *entry;
 +
 +      if (!submodule)
 +              return main_ref_store;
 +
 +      if (!submodule_ref_stores.tablesize)
 +              /* It's initialized on demand in register_ref_store(). */
 +              return NULL;
 +
 +      entry = hashmap_get_from_hash(&submodule_ref_stores,
 +                                    strhash(submodule), submodule);
 +      return entry ? entry->refs : NULL;
 +}
 +
 +/*
 + * Register the specified ref_store to be the one that should be used
 + * for submodule (or the main repository if submodule is NULL). It is
 + * a fatal error to call this function twice for the same submodule.
 + */
 +static void register_ref_store(struct ref_store *refs, const char *submodule)
 +{
 +      if (!submodule) {
 +              if (main_ref_store)
 +                      die("BUG: main_ref_store initialized twice");
 +
 +              main_ref_store = refs;
 +      } else {
 +              if (!submodule_ref_stores.tablesize)
 +                      hashmap_init(&submodule_ref_stores, submodule_hash_cmp, 0);
 +
 +              if (hashmap_put(&submodule_ref_stores,
 +                              alloc_submodule_hash_entry(submodule, refs)))
 +                      die("BUG: ref_store for submodule '%s' initialized twice",
 +                          submodule);
 +      }
 +}
 +
 +/*
 + * Create, record, and return a ref_store instance for the specified
 + * submodule (or the main repository if submodule is NULL).
 + */
 +static struct ref_store *ref_store_init(const char *submodule)
 +{
 +      const char *be_name = "files";
 +      struct ref_storage_be *be = find_ref_storage_backend(be_name);
 +      struct ref_store *refs;
 +
 +      if (!be)
 +              die("BUG: reference backend %s is unknown", be_name);
 +
 +      refs = be->init(submodule);
 +      register_ref_store(refs, submodule);
 +      return refs;
 +}
 +
 +struct ref_store *get_ref_store(const char *submodule)
 +{
 +      struct ref_store *refs;
 +
 +      if (!submodule || !*submodule) {
 +              refs = lookup_ref_store(NULL);
 +
 +              if (!refs)
 +                      refs = ref_store_init(NULL);
 +      } else {
 +              refs = lookup_ref_store(submodule);
 +
 +              if (!refs) {
 +                      struct strbuf submodule_sb = STRBUF_INIT;
 +
 +                      strbuf_addstr(&submodule_sb, submodule);
 +                      if (is_nonbare_repository_dir(&submodule_sb))
 +                              refs = ref_store_init(submodule);
 +                      strbuf_release(&submodule_sb);
 +              }
 +      }
 +
 +      return refs;
 +}
 +
 +void base_ref_store_init(struct ref_store *refs,
 +                       const struct ref_storage_be *be)
 +{
 +      refs->be = be;
 +}
 +
 +/* backend functions */
 +int pack_refs(unsigned int flags)
 +{
 +      struct ref_store *refs = get_ref_store(NULL);
 +
 +      return refs->be->pack_refs(refs, flags);
 +}
 +
 +int peel_ref(const char *refname, unsigned char *sha1)
 +{
 +      struct ref_store *refs = get_ref_store(NULL);
 +
 +      return refs->be->peel_ref(refs, refname, sha1);
 +}
 +
 +int create_symref(const char *ref_target, const char *refs_heads_master,
 +                const char *logmsg)
 +{
 +      struct ref_store *refs = get_ref_store(NULL);
 +
 +      return refs->be->create_symref(refs, ref_target, refs_heads_master,
 +                                     logmsg);
 +}
 +
 +int ref_transaction_commit(struct ref_transaction *transaction,
 +                         struct strbuf *err)
 +{
 +      struct ref_store *refs = get_ref_store(NULL);
 +
 +      return refs->be->transaction_commit(refs, transaction, err);
 +}
 +
 +int verify_refname_available(const char *refname,
 +                           const struct string_list *extra,
 +                           const struct string_list *skip,
 +                           struct strbuf *err)
 +{
 +      struct ref_store *refs = get_ref_store(NULL);
 +
 +      return refs->be->verify_refname_available(refs, refname, extra, skip, err);
 +}
 +
 +int for_each_reflog(each_ref_fn fn, void *cb_data)
 +{
 +      struct ref_store *refs = get_ref_store(NULL);
 +      struct ref_iterator *iter;
 +
 +      iter = refs->be->reflog_iterator_begin(refs);
 +
 +      return do_for_each_ref_iterator(iter, fn, cb_data);
 +}
 +
 +int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn,
 +                              void *cb_data)
 +{
 +      struct ref_store *refs = get_ref_store(NULL);
 +
 +      return refs->be->for_each_reflog_ent_reverse(refs, refname,
 +                                                   fn, cb_data);
 +}
 +
 +int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn,
 +                      void *cb_data)
 +{
 +      struct ref_store *refs = get_ref_store(NULL);
 +
 +      return refs->be->for_each_reflog_ent(refs, refname, fn, cb_data);
 +}
 +
 +int reflog_exists(const char *refname)
 +{
 +      struct ref_store *refs = get_ref_store(NULL);
 +
 +      return refs->be->reflog_exists(refs, refname);
 +}
 +
 +int safe_create_reflog(const char *refname, int force_create,
 +                     struct strbuf *err)
 +{
 +      struct ref_store *refs = get_ref_store(NULL);
 +
 +      return refs->be->create_reflog(refs, refname, force_create, err);
 +}
 +
 +int delete_reflog(const char *refname)
 +{
 +      struct ref_store *refs = get_ref_store(NULL);
 +
 +      return refs->be->delete_reflog(refs, refname);
 +}
 +
 +int reflog_expire(const char *refname, const unsigned char *sha1,
 +                unsigned int flags,
 +                reflog_expiry_prepare_fn prepare_fn,
 +                reflog_expiry_should_prune_fn should_prune_fn,
 +                reflog_expiry_cleanup_fn cleanup_fn,
 +                void *policy_cb_data)
 +{
 +      struct ref_store *refs = get_ref_store(NULL);
 +
 +      return refs->be->reflog_expire(refs, refname, sha1, flags,
 +                                     prepare_fn, should_prune_fn,
 +                                     cleanup_fn, policy_cb_data);
 +}
 +
 +int initial_ref_transaction_commit(struct ref_transaction *transaction,
 +                                 struct strbuf *err)
 +{
 +      struct ref_store *refs = get_ref_store(NULL);
 +
 +      return refs->be->initial_transaction_commit(refs, transaction, err);
 +}
 +
 +int delete_refs(struct string_list *refnames, unsigned int flags)
 +{
 +      struct ref_store *refs = get_ref_store(NULL);
 +
 +      return refs->be->delete_refs(refs, refnames, flags);
 +}
 +
 +int rename_ref(const char *oldref, const char *newref, const char *logmsg)
 +{
 +      struct ref_store *refs = get_ref_store(NULL);
 +
 +      return refs->be->rename_ref(refs, oldref, newref, logmsg);
 +}