builtin/am: introduce write_state_*() helper functions
[gitweb.git] / builtin / update-ref.c
index 54a48c0cfaab57122fc7ce57c525638c2c95408c..6763cf1837db99442a7140fe5bb87a0b3a1248fd 100644 (file)
@@ -6,14 +6,15 @@
 #include "argv-array.h"
 
 static const char * const git_update_ref_usage[] = {
-       N_("git update-ref [options] -d <refname> [<oldval>]"),
-       N_("git update-ref [options]    <refname> <newval> [<oldval>]"),
-       N_("git update-ref [options] --stdin [-z]"),
+       N_("git update-ref [<options>] -d <refname> [<old-val>]"),
+       N_("git update-ref [<options>]    <refname> <new-val> [<old-val>]"),
+       N_("git update-ref [<options>] --stdin [-z]"),
        NULL
 };
 
 static char line_termination = '\n';
 static int update_flags;
+static const char *msg;
 
 /*
  * Parse one whitespace- or NUL-terminated, possibly C-quoted argument
@@ -197,8 +198,9 @@ static const char *parse_cmd_update(struct ref_transaction *transaction,
        if (*next != line_termination)
                die("update %s: extra input: %s", refname, next);
 
-       if (ref_transaction_update(transaction, refname, new_sha1, old_sha1,
-                                  update_flags, have_old, &err))
+       if (ref_transaction_update(transaction, refname,
+                                  new_sha1, have_old ? old_sha1 : NULL,
+                                  update_flags, msg, &err))
                die("%s", err.buf);
 
        update_flags = 0;
@@ -229,7 +231,7 @@ static const char *parse_cmd_create(struct ref_transaction *transaction,
                die("create %s: extra input: %s", refname, next);
 
        if (ref_transaction_create(transaction, refname, new_sha1,
-                                  update_flags, &err))
+                                  update_flags, msg, &err))
                die("%s", err.buf);
 
        update_flags = 0;
@@ -263,8 +265,9 @@ static const char *parse_cmd_delete(struct ref_transaction *transaction,
        if (*next != line_termination)
                die("delete %s: extra input: %s", refname, next);
 
-       if (ref_transaction_delete(transaction, refname, old_sha1,
-                                  update_flags, have_old, &err))
+       if (ref_transaction_delete(transaction, refname,
+                                  have_old ? old_sha1 : NULL,
+                                  update_flags, msg, &err))
                die("%s", err.buf);
 
        update_flags = 0;
@@ -279,28 +282,21 @@ static const char *parse_cmd_verify(struct ref_transaction *transaction,
 {
        struct strbuf err = STRBUF_INIT;
        char *refname;
-       unsigned char new_sha1[20];
        unsigned char old_sha1[20];
-       int have_old;
 
        refname = parse_refname(input, &next);
        if (!refname)
                die("verify: missing <ref>");
 
        if (parse_next_sha1(input, &next, old_sha1, "verify", refname,
-                           PARSE_SHA1_OLD)) {
-               hashclr(new_sha1);
-               have_old = 0;
-       } else {
-               hashcpy(new_sha1, old_sha1);
-               have_old = 1;
-       }
+                           PARSE_SHA1_OLD))
+               hashclr(old_sha1);
 
        if (*next != line_termination)
                die("verify %s: extra input: %s", refname, next);
 
-       if (ref_transaction_update(transaction, refname, new_sha1, old_sha1,
-                                  update_flags, have_old, &err))
+       if (ref_transaction_verify(transaction, refname, old_sha1,
+                                  update_flags, &err))
                die("%s", err.buf);
 
        update_flags = 0;
@@ -354,9 +350,10 @@ static void update_refs_stdin(struct ref_transaction *transaction)
 
 int cmd_update_ref(int argc, const char **argv, const char *prefix)
 {
-       const char *refname, *oldval, *msg = NULL;
+       const char *refname, *oldval;
        unsigned char sha1[20], oldsha1[20];
-       int delete = 0, no_deref = 0, read_stdin = 0, end_null = 0, flags = 0;
+       int delete = 0, no_deref = 0, read_stdin = 0, end_null = 0;
+       unsigned int flags = 0;
        struct option options[] = {
                OPT_STRING( 'm', NULL, &msg, N_("reason"), N_("reason of the update")),
                OPT_BOOL('d', NULL, &delete, N_("delete the reference")),
@@ -385,7 +382,7 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
                if (end_null)
                        line_termination = '\0';
                update_refs_stdin(transaction);
-               if (ref_transaction_commit(transaction, msg, &err))
+               if (ref_transaction_commit(transaction, &err))
                        die("%s", err.buf);
                ref_transaction_free(transaction);
                strbuf_release(&err);
@@ -411,14 +408,27 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
                        die("%s: not a valid SHA1", value);
        }
 
-       hashclr(oldsha1); /* all-zero hash in case oldval is the empty string */
-       if (oldval && *oldval && get_sha1(oldval, oldsha1))
-               die("%s: not a valid old SHA1", oldval);
+       if (oldval) {
+               if (!*oldval)
+                       /*
+                        * The empty string implies that the reference
+                        * must not already exist:
+                        */
+                       hashclr(oldsha1);
+               else if (get_sha1(oldval, oldsha1))
+                       die("%s: not a valid old SHA1", oldval);
+       }
 
        if (no_deref)
                flags = REF_NODEREF;
        if (delete)
-               return delete_ref(refname, oldval ? oldsha1 : NULL, flags);
+               /*
+                * For purposes of backwards compatibility, we treat
+                * NULL_SHA1 as "don't care" here:
+                */
+               return delete_ref(refname,
+                                 (oldval && !is_null_sha1(oldsha1)) ? oldsha1 : NULL,
+                                 flags);
        else
                return update_ref(msg, refname, sha1, oldval ? oldsha1 : NULL,
                                  flags, UPDATE_REFS_DIE_ON_ERR);