Merge branch 'rs/ref-transaction'
authorJunio C Hamano <gitster@pobox.com>
Tue, 21 Oct 2014 20:28:10 +0000 (13:28 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 21 Oct 2014 20:28:10 +0000 (13:28 -0700)
The API to update refs have been restructured to allow introducing
a true transactional updates later. We would even allow storing
refs in backends other than the traditional filesystem-based one.

* rs/ref-transaction: (25 commits)
ref_transaction_commit: bail out on failure to remove a ref
lockfile: remove unable_to_lock_error
refs.c: do not permit err == NULL
remote rm/prune: print a message when writing packed-refs fails
for-each-ref: skip and warn about broken ref names
refs.c: allow listing and deleting badly named refs
test: put tests for handling of bad ref names in one place
packed-ref cache: forbid dot-components in refnames
branch -d: simplify by using RESOLVE_REF_READING
branch -d: avoid repeated symref resolution
reflog test: test interaction with detached HEAD
refs.c: change resolve_ref_unsafe reading argument to be a flags field
refs.c: make write_ref_sha1 static
fetch.c: change s_update_ref to use a ref transaction
refs.c: ref_transaction_commit: distinguish name conflicts from other errors
refs.c: pass a list of names to skip to is_refname_available
refs.c: call lock_ref_sha1_basic directly from commit
refs.c: refuse to lock badly named refs in lock_ref_sha1_basic
rename_ref: don't ask read_ref_full where the ref came from
refs.c: pass the ref log message to _create/delete/update instead of _commit
...

1  2 
builtin/branch.c
builtin/commit.c
builtin/for-each-ref.c
builtin/log.c
builtin/receive-pack.c
diff --combined builtin/branch.c
index 19a93a14d7dd04c2150ff43a8c0751d4a09baabb,7e113d6c7df7ac602333c81aac84aee5a7e35f2d..3b79c5087fbf1157d1bdfa2cccc99547f8abdb09
@@@ -62,19 -62,19 +62,19 @@@ static unsigned char merge_filter_ref[2
  static struct string_list output = STRING_LIST_INIT_DUP;
  static unsigned int colopts;
  
 -static int parse_branch_color_slot(const char *var, int ofs)
 +static int parse_branch_color_slot(const char *slot)
  {
 -      if (!strcasecmp(var+ofs, "plain"))
 +      if (!strcasecmp(slot, "plain"))
                return BRANCH_COLOR_PLAIN;
 -      if (!strcasecmp(var+ofs, "reset"))
 +      if (!strcasecmp(slot, "reset"))
                return BRANCH_COLOR_RESET;
 -      if (!strcasecmp(var+ofs, "remote"))
 +      if (!strcasecmp(slot, "remote"))
                return BRANCH_COLOR_REMOTE;
 -      if (!strcasecmp(var+ofs, "local"))
 +      if (!strcasecmp(slot, "local"))
                return BRANCH_COLOR_LOCAL;
 -      if (!strcasecmp(var+ofs, "current"))
 +      if (!strcasecmp(slot, "current"))
                return BRANCH_COLOR_CURRENT;
 -      if (!strcasecmp(var+ofs, "upstream"))
 +      if (!strcasecmp(slot, "upstream"))
                return BRANCH_COLOR_UPSTREAM;
        return -1;
  }
@@@ -90,12 -90,13 +90,12 @@@ static int git_branch_config(const cha
                return 0;
        }
        if (skip_prefix(var, "color.branch.", &slot_name)) {
 -              int slot = parse_branch_color_slot(var, slot_name - var);
 +              int slot = parse_branch_color_slot(slot_name);
                if (slot < 0)
                        return 0;
                if (!value)
                        return config_error_nonbool(var);
 -              color_parse(value, var, branch_colors[slot]);
 -              return 0;
 +              return color_parse(value, branch_colors[slot]);
        }
        return git_color_default_config(var, value, cb);
  }
@@@ -130,7 -131,8 +130,8 @@@ static int branch_merged(int kind, cons
                    branch->merge[0] &&
                    branch->merge[0]->dst &&
                    (reference_name = reference_name_to_free =
-                    resolve_refdup(branch->merge[0]->dst, sha1, 1, NULL)) != NULL)
+                    resolve_refdup(branch->merge[0]->dst, RESOLVE_REF_READING,
+                                   sha1, NULL)) != NULL)
                        reference_rev = lookup_commit_reference(sha1);
        }
        if (!reference_rev)
@@@ -234,9 -236,12 +235,12 @@@ static int delete_branches(int argc, co
                free(name);
  
                name = mkpathdup(fmt, bname.buf);
-               target = resolve_ref_unsafe(name, sha1, 0, &flags);
-               if (!target ||
-                   (!(flags & REF_ISSYMREF) && is_null_sha1(sha1))) {
+               target = resolve_ref_unsafe(name,
+                                           RESOLVE_REF_READING
+                                           | RESOLVE_REF_NO_RECURSE
+                                           | RESOLVE_REF_ALLOW_BAD_NAME,
+                                           sha1, &flags);
+               if (!target) {
                        error(remote_branch
                              ? _("remote branch '%s' not found.")
                              : _("branch '%s' not found."), bname.buf);
                        continue;
                }
  
-               if (!(flags & REF_ISSYMREF) &&
+               if (!(flags & (REF_ISSYMREF|REF_ISBROKEN)) &&
                    check_branch_commit(bname.buf, name, sha1, head_rev, kinds,
                                        force)) {
                        ret = 1;
                               ? _("Deleted remote branch %s (was %s).\n")
                               : _("Deleted branch %s (was %s).\n"),
                               bname.buf,
-                              (flags & REF_ISSYMREF)
-                              ? target
+                              (flags & REF_ISBROKEN) ? "broken"
+                              : (flags & REF_ISSYMREF) ? target
                               : find_unique_abbrev(sha1, DEFAULT_ABBREV));
                }
                delete_branch_config(bname.buf);
@@@ -298,7 -303,7 +302,7 @@@ static char *resolve_symref(const char 
        int flag;
        const char *dst;
  
-       dst = resolve_ref_unsafe(src, sha1, 0, &flag);
+       dst = resolve_ref_unsafe(src, 0, sha1, &flag);
        if (!(dst && (flag & REF_ISSYMREF)))
                return NULL;
        if (prefix)
@@@ -868,7 -873,7 +872,7 @@@ int cmd_branch(int argc, const char **a
  
        track = git_branch_track;
  
-       head = resolve_refdup("HEAD", head_sha1, 0, NULL);
+       head = resolve_refdup("HEAD", 0, head_sha1, NULL);
        if (!head)
                die(_("Failed to resolve HEAD as a valid ref."));
        if (!strcmp(head, "HEAD"))
diff --combined builtin/commit.c
index 60d35d0408c4900dfd86b24c86824a1e90da1f41,aa0940e38f7f2c4e562956e5cdb184392b7c7661..e108c5301564a86d396d72169f40cd24a9916a1f
@@@ -1272,21 -1272,22 +1272,21 @@@ static int dry_run_commit(int argc, con
        return commitable ? 0 : 1;
  }
  
 -static int parse_status_slot(const char *var, int offset)
 +static int parse_status_slot(const char *slot)
  {
 -      if (!strcasecmp(var+offset, "header"))
 +      if (!strcasecmp(slot, "header"))
                return WT_STATUS_HEADER;
 -      if (!strcasecmp(var+offset, "branch"))
 +      if (!strcasecmp(slot, "branch"))
                return WT_STATUS_ONBRANCH;
 -      if (!strcasecmp(var+offset, "updated")
 -              || !strcasecmp(var+offset, "added"))
 +      if (!strcasecmp(slot, "updated") || !strcasecmp(slot, "added"))
                return WT_STATUS_UPDATED;
 -      if (!strcasecmp(var+offset, "changed"))
 +      if (!strcasecmp(slot, "changed"))
                return WT_STATUS_CHANGED;
 -      if (!strcasecmp(var+offset, "untracked"))
 +      if (!strcasecmp(slot, "untracked"))
                return WT_STATUS_UNTRACKED;
 -      if (!strcasecmp(var+offset, "nobranch"))
 +      if (!strcasecmp(slot, "nobranch"))
                return WT_STATUS_NOBRANCH;
 -      if (!strcasecmp(var+offset, "unmerged"))
 +      if (!strcasecmp(slot, "unmerged"))
                return WT_STATUS_UNMERGED;
        return -1;
  }
@@@ -1326,12 -1327,13 +1326,12 @@@ static int git_status_config(const cha
        }
        if (skip_prefix(k, "status.color.", &slot_name) ||
            skip_prefix(k, "color.status.", &slot_name)) {
 -              int slot = parse_status_slot(k, slot_name - k);
 +              int slot = parse_status_slot(slot_name);
                if (slot < 0)
                        return 0;
                if (!v)
                        return config_error_nonbool(k);
 -              color_parse(v, k, s->color_palette[slot]);
 -              return 0;
 +              return color_parse(v, s->color_palette[slot]);
        }
        if (!strcmp(k, "status.relativepaths")) {
                s->relative_paths = git_config_bool(k, v);
@@@ -1513,7 -1515,7 +1513,7 @@@ static void print_summary(const char *p
        rev.diffopt.break_opt = 0;
        diff_setup_done(&rev.diffopt);
  
-       head = resolve_ref_unsafe("HEAD", junk_sha1, 0, NULL);
+       head = resolve_ref_unsafe("HEAD", 0, junk_sha1, NULL);
        if (!strcmp(head, "HEAD"))
                head = _("detached HEAD");
        else
@@@ -1809,8 -1811,8 +1809,8 @@@ int cmd_commit(int argc, const char **a
            ref_transaction_update(transaction, "HEAD", sha1,
                                   current_head
                                   ? current_head->object.sha1 : NULL,
-                                  0, !!current_head, &err) ||
-           ref_transaction_commit(transaction, sb.buf, &err)) {
+                                  0, !!current_head, sb.buf, &err) ||
+           ref_transaction_commit(transaction, &err)) {
                rollback_index_files();
                die("%s", err.buf);
        }
diff --combined builtin/for-each-ref.c
index 7ee86b3ae1f417704d4b1171a7d346dab3cd181e,3ee22b96a561ecba2fcd344379fbfb861530a3ae..603a90e29b808a86fa39f031d13a1ca94f5d236e
@@@ -635,7 -635,8 +635,8 @@@ static void populate_value(struct refin
  
        if (need_symref && (ref->flag & REF_ISSYMREF) && !ref->symref) {
                unsigned char unused1[20];
-               ref->symref = resolve_refdup(ref->refname, unused1, 1, NULL);
+               ref->symref = resolve_refdup(ref->refname, RESOLVE_REF_READING,
+                                            unused1, NULL);
                if (!ref->symref)
                        ref->symref = "";
        }
                } else if (starts_with(name, "color:")) {
                        char color[COLOR_MAXLEN] = "";
  
 -                      color_parse(name + 6, "--format", color);
 +                      if (color_parse(name + 6, color) < 0)
 +                              die(_("unable to parse format"));
                        v->s = xstrdup(color);
                        continue;
                } else if (!strcmp(name, "flag")) {
                        const char *head;
                        unsigned char sha1[20];
  
-                       head = resolve_ref_unsafe("HEAD", sha1, 1, NULL);
+                       head = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
+                                                 sha1, NULL);
                        if (!strcmp(ref->refname, head))
                                v->s = "*";
                        else
@@@ -838,6 -839,11 +840,11 @@@ static int grab_single_ref(const char *
        struct refinfo *ref;
        int cnt;
  
+       if (flag & REF_BAD_NAME) {
+                 warning("ignoring ref with broken name %s", refname);
+                 return 0;
+       }
        if (*cb->grab_pattern) {
                const char **pattern;
                int namelen = strlen(refname);
@@@ -1005,8 -1011,7 +1012,8 @@@ static void show_ref(struct refinfo *in
                struct atom_value resetv;
                char color[COLOR_MAXLEN] = "";
  
 -              color_parse("reset", "--format", color);
 +              if (color_parse("reset", color) < 0)
 +                      die("BUG: couldn't parse 'reset' as a color");
                resetv.s = color;
                print_value(&resetv, quote_style);
        }
diff --combined builtin/log.c
index 68d5d30035442a1d12cf0fbf8a10dca0df2711be,83c0b927070793ed421992a1647e3c0e71721cc3..734aab3a73185964d18c82fe5eb31008bbc409b7
@@@ -391,7 -391,7 +391,7 @@@ static int git_log_config(const char *v
                return 0;
        }
        if (skip_prefix(var, "color.decorate.", &slot_name))
 -              return parse_decorate_color_config(var, slot_name - var, value);
 +              return parse_decorate_color_config(var, slot_name, value);
        if (!strcmp(var, "log.mailmap")) {
                use_mailmap_config = git_config_bool(var, value);
                return 0;
@@@ -1400,7 -1400,8 +1400,8 @@@ int cmd_format_patch(int argc, const ch
                if (check_head) {
                        unsigned char sha1[20];
                        const char *ref, *v;
-                       ref = resolve_ref_unsafe("HEAD", sha1, 1, NULL);
+                       ref = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
+                                                sha1, NULL);
                        if (ref && skip_prefix(ref, "refs/heads/", &v))
                                branch_name = xstrdup(v);
                        else
diff --combined builtin/receive-pack.c
index 6420680bddcd4d9963f5b71e98b09ff5528ec42d,27e9dc2c5b37150da7012a794827d331d90380a6..916315ff5c2f08bed1e52c8188939405c0b7a0e1
@@@ -842,8 -842,9 +842,9 @@@ static const char *update(struct comman
                transaction = ref_transaction_begin(&err);
                if (!transaction ||
                    ref_transaction_update(transaction, namespaced_name,
-                                          new_sha1, old_sha1, 0, 1, &err) ||
-                   ref_transaction_commit(transaction, "push", &err)) {
+                                          new_sha1, old_sha1, 0, 1, "push",
+                                          &err) ||
+                   ref_transaction_commit(transaction, &err)) {
                        ref_transaction_free(transaction);
  
                        rp_error("%s", err.buf);
@@@ -908,7 -909,7 +909,7 @@@ static void check_aliased_update(struc
        int flag;
  
        strbuf_addf(&buf, "%s%s", get_git_namespace(), cmd->ref_name);
-       dst_name = resolve_ref_unsafe(buf.buf, sha1, 0, &flag);
+       dst_name = resolve_ref_unsafe(buf.buf, 0, sha1, &flag);
        strbuf_release(&buf);
  
        if (!(flag & REF_ISSYMREF))
@@@ -1069,7 -1070,7 +1070,7 @@@ static void execute_commands(struct com
        check_aliased_updates(commands);
  
        free(head_name_to_free);
-       head_name = head_name_to_free = resolve_refdup("HEAD", sha1, 0, NULL);
+       head_name = head_name_to_free = resolve_refdup("HEAD", 0, sha1, NULL);
  
        checked_connectivity = 1;
        for (cmd = commands; cmd; cmd = cmd->next) {
@@@ -1230,6 -1231,7 +1231,6 @@@ static const char *pack_lockfile
  static const char *unpack(int err_fd, struct shallow_info *si)
  {
        struct pack_header hdr;
 -      struct argv_array av = ARGV_ARRAY_INIT;
        const char *hdr_err;
        int status;
        char hdr_arg[38];
  
        if (si->nr_ours || si->nr_theirs) {
                alt_shallow_file = setup_temporary_shallow(si->shallow);
 -              argv_array_pushl(&av, "--shallow-file", alt_shallow_file, NULL);
 +              argv_array_push(&child.args, "--shallow-file");
 +              argv_array_push(&child.args, alt_shallow_file);
        }
  
        if (ntohl(hdr.hdr_entries) < unpack_limit) {
 -              argv_array_pushl(&av, "unpack-objects", hdr_arg, NULL);
 +              argv_array_pushl(&child.args, "unpack-objects", hdr_arg, NULL);
                if (quiet)
 -                      argv_array_push(&av, "-q");
 +                      argv_array_push(&child.args, "-q");
                if (fsck_objects)
 -                      argv_array_push(&av, "--strict");
 -              child.argv = av.argv;
 +                      argv_array_push(&child.args, "--strict");
                child.no_stdout = 1;
                child.err = err_fd;
                child.git_cmd = 1;
                if (gethostname(keep_arg + s, sizeof(keep_arg) - s))
                        strcpy(keep_arg + s, "localhost");
  
 -              argv_array_pushl(&av, "index-pack",
 +              argv_array_pushl(&child.args, "index-pack",
                                 "--stdin", hdr_arg, keep_arg, NULL);
                if (fsck_objects)
 -                      argv_array_push(&av, "--strict");
 +                      argv_array_push(&child.args, "--strict");
                if (fix_thin)
 -                      argv_array_push(&av, "--fix-thin");
 -              child.argv = av.argv;
 +                      argv_array_push(&child.args, "--fix-thin");
                child.out = -1;
                child.err = err_fd;
                child.git_cmd = 1;