Re: [PATCH v6 7/8] update-ref: support multiple simultaneous updates

2013-09-11 Thread Eric Sunshine
On Wed, Sep 11, 2013 at 8:36 AM, Brad King  wrote:
> On 09/10/2013 06:51 PM, Eric Sunshine wrote:
>> On Mon, Sep 9, 2013 at 8:57 PM, Brad King  wrote:
>>> +Use 40 "0" or the empty string to specify a zero value, except that
>>
>> Did you want an 's' after the "0"?
>
> The same description without 's' already appears in git-update-ref.txt
> above this location in the existing documentation of the command-line

Thanks for the explanation. (I could have checked the surrounding text
but didn't think to do so.)

> option behavior.  I see 0{40} in git-receive-pack.txt and also in
> howto/update-hook-example.txt.  Perhaps a follow-up change can be made
> to choose a consistent way to describe 40 0s.
>
> -Brad
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v6 7/8] update-ref: support multiple simultaneous updates

2013-09-11 Thread Brad King
On 09/10/2013 06:51 PM, Eric Sunshine wrote:
> On Mon, Sep 9, 2013 at 8:57 PM, Brad King  wrote:
>> +Use 40 "0" or the empty string to specify a zero value, except that
> 
> Did you want an 's' after the "0"?

The same description without 's' already appears in git-update-ref.txt
above this location in the existing documentation of the command-line
option behavior.  I see 0{40} in git-receive-pack.txt and also in
howto/update-hook-example.txt.  Perhaps a follow-up change can be made
to choose a consistent way to describe 40 0s.

-Brad
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v6 7/8] update-ref: support multiple simultaneous updates

2013-09-10 Thread Eric Sunshine
On Mon, Sep 9, 2013 at 8:57 PM, Brad King  wrote:
> diff --git a/Documentation/git-update-ref.txt 
> b/Documentation/git-update-ref.txt
> index 0df13ff..0a0a551 100644
> --- a/Documentation/git-update-ref.txt
> +++ b/Documentation/git-update-ref.txt
> @@ -58,6 +58,58 @@ archive by creating a symlink tree).
> +option::
> +   Modify behavior of the next command naming a .
> +   The only valid option is `no-deref` to avoid dereferencing
> +   a symbolic ref.
> +
> +Use 40 "0" or the empty string to specify a zero value, except that

Did you want an 's' after the "0"?

0's
"0"s
"0"'s
zeros
zeroes

> +with `-z` an empty  is considered missing.
> +
> +If all s can be locked with matching s
> +simultaneously, all modifications are performed.  Otherwise, no
> +modifications are performed.  Note that while each individual
> + is updated or deleted atomically, a concurrent reader may
> +still see a subset of the modifications.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 7/8] update-ref: support multiple simultaneous updates

2013-09-09 Thread Brad King
Add a --stdin signature to read update instructions from standard input
and apply multiple ref updates together.  Use an input format that
supports any update that could be specified via the command-line,
including object names like "branch:path with space".

Signed-off-by: Brad King 
---
 Documentation/git-update-ref.txt |  54 -
 builtin/update-ref.c | 252 ++-
 2 files changed, 304 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt
index 0df13ff..0a0a551 100644
--- a/Documentation/git-update-ref.txt
+++ b/Documentation/git-update-ref.txt
@@ -8,7 +8,7 @@ git-update-ref - Update the object name stored in a ref safely
 SYNOPSIS
 
 [verse]
-'git update-ref' [-m ] (-d  [] | [--no-deref]  
 [])
+'git update-ref' [-m ] (-d  [] | [--no-deref]  
 [] | --stdin [-z])
 
 DESCRIPTION
 ---
@@ -58,6 +58,58 @@ archive by creating a symlink tree).
 With `-d` flag, it deletes the named  after verifying it
 still contains .
 
+With `--stdin`, update-ref reads instructions from standard input and
+performs all modifications together.  Specify commands of the form:
+
+   update SP  SP  [SP ] LF
+   create SP  SP  LF
+   delete SP  [SP ] LF
+   verify SP  [SP ] LF
+   option SP  LF
+
+Quote fields containing whitespace as if they were strings in C source
+code.  Alternatively, use `-z` to specify commands without quoting:
+
+   update SP  NUL  NUL [] NUL
+   create SP  NUL  NUL
+   delete SP  NUL [] NUL
+   verify SP  NUL [] NUL
+   option SP  NUL
+
+Lines of any other format or a repeated  produce an error.
+Command meanings are:
+
+update::
+   Set  to  after verifying , if given.
+   Specify a zero  to ensure the ref does not exist
+   after the update and/or a zero  to make sure the
+   ref does not exist before the update.
+
+create::
+   Create  with  after verifying it does not
+   exist.  The given  may not be zero.
+
+delete::
+   Delete  after verifying it exists with , if
+   given.  If given,  may not be zero.
+
+verify::
+   Verify  against  but do not change it.  If
+zero or missing, the ref must not exist.
+
+option::
+   Modify behavior of the next command naming a .
+   The only valid option is `no-deref` to avoid dereferencing
+   a symbolic ref.
+
+Use 40 "0" or the empty string to specify a zero value, except that
+with `-z` an empty  is considered missing.
+
+If all s can be locked with matching s
+simultaneously, all modifications are performed.  Otherwise, no
+modifications are performed.  Note that while each individual
+ is updated or deleted atomically, a concurrent reader may
+still see a subset of the modifications.
 
 Logging Updates
 ---
diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 7484d36..b5479e2 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -2,23 +2,261 @@
 #include "refs.h"
 #include "builtin.h"
 #include "parse-options.h"
+#include "quote.h"
+#include "argv-array.h"
 
 static const char * const git_update_ref_usage[] = {
N_("git update-ref [options] -d  []"),
N_("git update-ref [options]  []"),
+   N_("git update-ref [options] --stdin [-z]"),
NULL
 };
 
+static int updates_alloc;
+static int updates_count;
+static const struct ref_update **updates;
+
+static char line_termination = '\n';
+static int update_flags;
+
+static struct ref_update *update_alloc(void)
+{
+   struct ref_update *update;
+
+   /* Allocate and zero-init a struct ref_update */
+   update = xcalloc(1, sizeof(*update));
+   ALLOC_GROW(updates, updates_count + 1, updates_alloc);
+   updates[updates_count++] = update;
+
+   /* Store and reset accumulated options */
+   update->flags = update_flags;
+   update_flags = 0;
+
+   return update;
+}
+
+static void update_store_ref_name(struct ref_update *update,
+ const char *ref_name)
+{
+   if (check_refname_format(ref_name, REFNAME_ALLOW_ONELEVEL))
+   die("invalid ref format: %s", ref_name);
+   update->ref_name = xstrdup(ref_name);
+}
+
+static void update_store_new_sha1(struct ref_update *update,
+ const char *newvalue)
+{
+   if (*newvalue && get_sha1(newvalue, update->new_sha1))
+   die("invalid new value for ref %s: %s",
+   update->ref_name, newvalue);
+}
+
+static void update_store_old_sha1(struct ref_update *update,
+ const char *oldvalue)
+{
+   if (*oldvalue && get_sha1(oldvalue, update->old_sha1))
+   die("invalid old value for ref %s: %s",
+   update->ref_name, oldvalue);
+
+   /* We have an old value if non-empty, or if empty without -z */
+   update->have_old = *oldvalue || line_termination;
+}
+
+static const char *parse_arg(const char *nex