Merge branch 'js/pack-objects-mutex-init-fix' into maint
[gitweb.git] / refs.c
diff --git a/refs.c b/refs.c
index 0eb379f9312fd9f167fea2e0f148c85c47cd2ff0..9a318c8456c3fe8d157cf6c7c6aca5b635d75230 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -9,6 +9,7 @@
 #include "iterator.h"
 #include "refs.h"
 #include "refs/refs-internal.h"
+#include "object-store.h"
 #include "object.h"
 #include "tag.h"
 #include "submodule.h"
@@ -188,7 +189,7 @@ int ref_resolves_to_object(const char *refname,
        if (flags & REF_ISBROKEN)
                return 0;
        if (!has_sha1_file(oid->hash)) {
-               error("%s does not point to a valid object!", refname);
+               error(_("%s does not point to a valid object!"), refname);
                return 0;
        }
        return 1;
@@ -304,7 +305,7 @@ enum peel_status peel_object(const struct object_id *name, struct object_id *oid
 
        if (o->type == OBJ_NONE) {
                int type = oid_object_info(the_repository, name, NULL);
-               if (type < 0 || !object_as_type(o, type, 0))
+               if (type < 0 || !object_as_type(the_repository, o, type, 0))
                        return PEEL_INVALID;
        }
 
@@ -489,16 +490,24 @@ static const char *ref_rev_parse_rules[] = {
        NULL
 };
 
+#define NUM_REV_PARSE_RULES (ARRAY_SIZE(ref_rev_parse_rules) - 1)
+
+/*
+ * Is it possible that the caller meant full_name with abbrev_name?
+ * If so return a non-zero value to signal "yes"; the magnitude of
+ * the returned value gives the precedence used for disambiguation.
+ *
+ * If abbrev_name cannot mean full_name, return 0.
+ */
 int refname_match(const char *abbrev_name, const char *full_name)
 {
        const char **p;
        const int abbrev_name_len = strlen(abbrev_name);
+       const int num_rules = NUM_REV_PARSE_RULES;
 
-       for (p = ref_rev_parse_rules; *p; p++) {
-               if (!strcmp(full_name, mkpath(*p, abbrev_name_len, abbrev_name))) {
-                       return 1;
-               }
-       }
+       for (p = ref_rev_parse_rules; *p; p++)
+               if (!strcmp(full_name, mkpath(*p, abbrev_name_len, abbrev_name)))
+                       return &ref_rev_parse_rules[num_rules] - p;
 
        return 0;
 }
@@ -567,9 +576,9 @@ int expand_ref(const char *str, int len, struct object_id *oid, char **ref)
                        if (!warn_ambiguous_refs)
                                break;
                } else if ((flag & REF_ISSYMREF) && strcmp(fullref.buf, "HEAD")) {
-                       warning("ignoring dangling symref %s.", fullref.buf);
+                       warning(_("ignoring dangling symref %s"), fullref.buf);
                } else if ((flag & REF_ISBROKEN) && strchr(fullref.buf, '/')) {
-                       warning("ignoring broken ref %s.", fullref.buf);
+                       warning(_("ignoring broken ref %s"), fullref.buf);
                }
        }
        strbuf_release(&fullref);
@@ -673,7 +682,7 @@ static int write_pseudoref(const char *pseudoref, const struct object_id *oid,
        fd = hold_lock_file_for_update_timeout(&lock, filename, 0,
                                               get_files_ref_lock_timeout_ms());
        if (fd < 0) {
-               strbuf_addf(err, "could not open '%s' for writing: %s",
+               strbuf_addf(err, _("could not open '%s' for writing: %s"),
                            filename, strerror(errno));
                goto done;
        }
@@ -683,18 +692,18 @@ static int write_pseudoref(const char *pseudoref, const struct object_id *oid,
 
                if (read_ref(pseudoref, &actual_old_oid)) {
                        if (!is_null_oid(old_oid)) {
-                               strbuf_addf(err, "could not read ref '%s'",
+                               strbuf_addf(err, _("could not read ref '%s'"),
                                            pseudoref);
                                rollback_lock_file(&lock);
                                goto done;
                        }
                } else if (is_null_oid(old_oid)) {
-                       strbuf_addf(err, "ref '%s' already exists",
+                       strbuf_addf(err, _("ref '%s' already exists"),
                                    pseudoref);
                        rollback_lock_file(&lock);
                        goto done;
                } else if (oidcmp(&actual_old_oid, old_oid)) {
-                       strbuf_addf(err, "unexpected object ID when writing '%s'",
+                       strbuf_addf(err, _("unexpected object ID when writing '%s'"),
                                    pseudoref);
                        rollback_lock_file(&lock);
                        goto done;
@@ -702,7 +711,7 @@ static int write_pseudoref(const char *pseudoref, const struct object_id *oid,
        }
 
        if (write_in_full(fd, buf.buf, buf.len) < 0) {
-               strbuf_addf(err, "could not write to '%s'", filename);
+               strbuf_addf(err, _("could not write to '%s'"), filename);
                rollback_lock_file(&lock);
                goto done;
        }
@@ -734,9 +743,9 @@ static int delete_pseudoref(const char *pseudoref, const struct object_id *old_o
                        return -1;
                }
                if (read_ref(pseudoref, &actual_old_oid))
-                       die("could not read ref '%s'", pseudoref);
+                       die(_("could not read ref '%s'"), pseudoref);
                if (oidcmp(&actual_old_oid, old_oid)) {
-                       error("unexpected object ID when deleting '%s'",
+                       error(_("unexpected object ID when deleting '%s'"),
                              pseudoref);
                        rollback_lock_file(&lock);
                        return -1;
@@ -786,25 +795,21 @@ int delete_ref(const char *msg, const char *refname,
                               old_oid, flags);
 }
 
-int copy_reflog_msg(char *buf, const char *msg)
+void copy_reflog_msg(struct strbuf *sb, const char *msg)
 {
-       char *cp = buf;
        char c;
        int wasspace = 1;
 
-       *cp++ = '\t';
+       strbuf_addch(sb, '\t');
        while ((c = *msg++)) {
                if (wasspace && isspace(c))
                        continue;
                wasspace = isspace(c);
                if (wasspace)
                        c = ' ';
-               *cp++ = c;
+               strbuf_addch(sb, c);
        }
-       while (buf < cp && isspace(cp[-1]))
-               cp--;
-       *cp++ = '\n';
-       return cp - buf;
+       strbuf_rtrim(sb);
 }
 
 int should_autocreate_reflog(const char *refname)
@@ -871,13 +876,13 @@ static int read_ref_at_ent(struct object_id *ooid, struct object_id *noid,
                if (!is_null_oid(&cb->ooid)) {
                        oidcpy(cb->oid, noid);
                        if (oidcmp(&cb->ooid, noid))
-                               warning("Log for ref %s has gap after %s.",
+                               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)
                        oidcpy(cb->oid, noid);
                else if (oidcmp(noid, cb->oid))
-                       warning("Log for ref %s unexpectedly ended on %s.",
+                       warning(_("log for ref %s unexpectedly ended on %s"),
                                cb->refname, show_date(cb->date, cb->tz,
                                                       DATE_MODE(RFC2822)));
                oidcpy(&cb->ooid, ooid);
@@ -935,7 +940,7 @@ int read_ref_at(const char *refname, unsigned int flags, timestamp_t at_time, in
                if (flags & GET_OID_QUIETLY)
                        exit(128);
                else
-                       die("Log for %s is empty.", refname);
+                       die(_("log for %s is empty"), refname);
        }
        if (cb.found_it)
                return 0;
@@ -1027,7 +1032,7 @@ int ref_transaction_update(struct ref_transaction *transaction,
        if ((new_oid && !is_null_oid(new_oid)) ?
            check_refname_format(refname, REFNAME_ALLOW_ONELEVEL) :
            !refname_is_safe(refname)) {
-               strbuf_addf(err, "refusing to update ref with bad name '%s'",
+               strbuf_addf(err, _("refusing to update ref with bad name '%s'"),
                            refname);
                return -1;
        }
@@ -1103,7 +1108,7 @@ int refs_update_ref(struct ref_store *refs, const char *msg,
                }
        }
        if (ret) {
-               const char *str = "update_ref failed for ref '%s': %s";
+               const char *str = _("update_ref failed for ref '%s': %s");
 
                switch (onerr) {
                case UPDATE_REFS_MSG_ON_ERR:
@@ -1389,17 +1394,50 @@ struct ref_iterator *refs_ref_iterator_begin(
  * non-zero value, stop the iteration and return that value;
  * otherwise, return 0.
  */
+static int do_for_each_repo_ref(struct repository *r, const char *prefix,
+                               each_repo_ref_fn fn, int trim, int flags,
+                               void *cb_data)
+{
+       struct ref_iterator *iter;
+       struct ref_store *refs = get_main_ref_store(r);
+
+       if (!refs)
+               return 0;
+
+       iter = refs_ref_iterator_begin(refs, prefix, trim, flags);
+
+       return do_for_each_repo_ref_iterator(r, iter, fn, cb_data);
+}
+
+struct do_for_each_ref_help {
+       each_ref_fn *fn;
+       void *cb_data;
+};
+
+static int do_for_each_ref_helper(struct repository *r,
+                                 const char *refname,
+                                 const struct object_id *oid,
+                                 int flags,
+                                 void *cb_data)
+{
+       struct do_for_each_ref_help *hp = cb_data;
+
+       return hp->fn(refname, oid, flags, hp->cb_data);
+}
+
 static int do_for_each_ref(struct ref_store *refs, const char *prefix,
                           each_ref_fn fn, int trim, int flags, void *cb_data)
 {
        struct ref_iterator *iter;
+       struct do_for_each_ref_help hp = { fn, cb_data };
 
        if (!refs)
                return 0;
 
        iter = refs_ref_iterator_begin(refs, prefix, trim, flags);
 
-       return do_for_each_ref_iterator(iter, fn, cb_data);
+       return do_for_each_repo_ref_iterator(the_repository, iter,
+                                       do_for_each_ref_helper, &hp);
 }
 
 int refs_for_each_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
@@ -1444,12 +1482,11 @@ int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
        return do_for_each_ref(refs, prefix, fn, 0, flag, cb_data);
 }
 
-int for_each_replace_ref(struct repository *r, each_ref_fn fn, void *cb_data)
+int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_data)
 {
-       return do_for_each_ref(get_main_ref_store(r),
-                              git_replace_ref_base, fn,
-                              strlen(git_replace_ref_base),
-                              DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
+       return do_for_each_repo_ref(r, git_replace_ref_base, fn,
+                                   strlen(git_replace_ref_base),
+                                   DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
 }
 
 int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)
@@ -1845,7 +1882,7 @@ int ref_update_reject_duplicates(struct string_list *refnames,
 
                if (!cmp) {
                        strbuf_addf(err,
-                                   "multiple updates for ref '%s' not allowed.",
+                                   _("multiple updates for ref '%s' not allowed"),
                                    refnames->items[i].string);
                        return 1;
                } else if (cmp > 0) {
@@ -1973,13 +2010,13 @@ int refs_verify_refname_available(struct ref_store *refs,
                        continue;
 
                if (!refs_read_raw_ref(refs, dirname.buf, &oid, &referent, &type)) {
-                       strbuf_addf(err, "'%s' exists; cannot create '%s'",
+                       strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
                                    dirname.buf, refname);
                        goto cleanup;
                }
 
                if (extras && string_list_has_string(extras, dirname.buf)) {
-                       strbuf_addf(err, "cannot process '%s' and '%s' at the same time",
+                       strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"),
                                    refname, dirname.buf);
                        goto cleanup;
                }
@@ -2003,7 +2040,7 @@ int refs_verify_refname_available(struct ref_store *refs,
                    string_list_has_string(skip, iter->refname))
                        continue;
 
-               strbuf_addf(err, "'%s' exists; cannot create '%s'",
+               strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
                            iter->refname, refname);
                ref_iterator_abort(iter);
                goto cleanup;
@@ -2014,7 +2051,7 @@ int refs_verify_refname_available(struct ref_store *refs,
 
        extra_refname = find_descendant_ref(dirname.buf, extras, skip);
        if (extra_refname)
-               strbuf_addf(err, "cannot process '%s' and '%s' at the same time",
+               strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"),
                            refname, extra_refname);
        else
                ret = 0;
@@ -2028,10 +2065,12 @@ int refs_verify_refname_available(struct ref_store *refs,
 int refs_for_each_reflog(struct ref_store *refs, each_ref_fn fn, void *cb_data)
 {
        struct ref_iterator *iter;
+       struct do_for_each_ref_help hp = { fn, cb_data };
 
        iter = refs->be->reflog_iterator_begin(refs);
 
-       return do_for_each_ref_iterator(iter, fn, cb_data);
+       return do_for_each_repo_ref_iterator(the_repository, iter,
+                                            do_for_each_ref_helper, &hp);
 }
 
 int for_each_reflog(each_ref_fn fn, void *cb_data)