All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michael Haggerty <mhagger@alum.mit.edu>
To: Brad King <brad.king@kitware.com>
Cc: git@vger.kernel.org, gitster@pobox.com,
	Martin Fick <mfick@codeaurora.org>
Subject: Re: [PATCH v2 7/8] update-ref: support multiple simultaneous updates
Date: Sat, 31 Aug 2013 20:42:32 +0200	[thread overview]
Message-ID: <52223918.6040603@alum.mit.edu> (raw)
In-Reply-To: <ba564b6566b54d780a24355ca893294d814d8d24.1377885441.git.brad.king@kitware.com>

On 08/30/2013 08:12 PM, Brad King wrote:
> 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 <brad.king@kitware.com>
> ---
>  Documentation/git-update-ref.txt |   21 ++++++-
>  builtin/update-ref.c             |  121 +++++++++++++++++++++++++++++++++++++-
>  2 files changed, 140 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt
> index 0df13ff..295d0bb 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 <reason>] (-d <ref> [<oldvalue>] | [--no-deref] <ref> <newvalue> [<oldvalue>])
> +'git update-ref' [-m <reason>] (-d <ref> [<oldvalue>] | [--no-deref] <ref> <newvalue> [<oldvalue>] | --stdin)
>  
>  DESCRIPTION
>  -----------
> @@ -58,6 +58,25 @@ archive by creating a symlink tree).
>  With `-d` flag, it deletes the named <ref> after verifying it
>  still contains <oldvalue>.
>  
> +With `--stdin`, update-ref reads instructions from standard input and
> +performs all modifications together.  Empty lines are ignored.
> +Each non-empty line is parsed as whitespace-separated arguments.
> +Use single-quotes to enclose whitespace and backslashes and an
> +unquoted backslash to escape a single quote.  Specify updates with
> +lines of the form:
> +
> +	[--no-deref] [--] <ref> <newvalue> [<oldvalue>]
> +
> +Lines of any other format or a repeated <ref> produce an error.
> +Specify a zero <newvalue> to delete a ref and/or a zero <oldvalue>
> +to make sure that a ref not exist.  Use either 40 "0" or the
> +empty string (written as '') to specify a zero value.
> +
> +If all <ref>s can be locked with matching <oldvalue>s
> +simultaneously all modifications are performed.  Otherwise, no

Comma after "simultaneously".

> +modifications are performed.  Note that while each individual
> +<ref> 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 51d2684..eb8db85 100644
> --- a/builtin/update-ref.c
> +++ b/builtin/update-ref.c
> @@ -6,19 +6,129 @@
>  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"),
>  	NULL
>  };
>  
> +static const char blank[] = " \t\r\n";
> +
> +static int updates_size;
> +static int updates_count;
> +static struct ref_update *updates;
> +
> +static const char* update_refs_stdin_next_arg(const char* next,
> +					      struct strbuf *arg)
> +{
> +	/* Skip leading whitespace: */
> +	while (isspace(*next))
> +		++next;
> +
> +	/* Return NULL when no argument is found: */
> +	if (!*next)
> +		return NULL;
> +
> +	/* Parse the argument: */
> +	strbuf_reset(arg);
> +	for (;;) {
> +		char c = *next;
> +		if (!c || isspace(c))
> +			break;
> +		++next;
> +		if (c == '\'') {
> +			size_t len = strcspn(next, "'");

I agree with Junio that your quoting rules are peculiar.

> +			if (!next[len])
> +				die("unterminated single-quote: '%s", next);
> +			strbuf_add(arg, next, len);
> +			next += len + 1;
> +			continue;
> +		}
> +		if (c == '\\') {
> +			if (*next == '\'')
> +				c = *next++;
> +			else
> +				die("unquoted backslash not escaping "
> +				    "single-quote: \\%s", next);
> +		}
> +		strbuf_addch(arg, c);
> +	}
> +	return next;
> +}
> +
> +static void update_refs_stdin(const char *line)
> +{
> +	int options = 1, flags = 0, argc = 0;
> +	char *argv[3] = {0, 0, 0};
> +	struct strbuf arg = STRBUF_INIT;
> +	struct ref_update *update;
> +	const char *next = line;
> +
> +	/* Skip blank lines: */
> +	if (!line[0])
> +		return;
> +
> +	/* Parse arguments on this line: */
> +	while ((next = update_refs_stdin_next_arg(next, &arg)) != NULL) {
> +		if (options && arg.buf[0] == '-')
> +			if (!strcmp(arg.buf, "--no-deref"))
> +				flags |= REF_NODEREF;
> +			else if (!strcmp(arg.buf, "--"))
> +				options = 0;
> +			else
> +				die("unknown option %s", arg.buf);
> +		else if (argc >= 3)
> +			die("too many arguments on line: %s", line);
> +		else {
> +			argv[argc++] = xstrdup(arg.buf);
> +			options = 0;
> +		}
> +	}
> +	strbuf_release(&arg);
> +
> +	/* Allocate and zero-init a struct ref_update: */
> +	if (updates_count == updates_size) {
> +		updates_size = updates_size ? (updates_size * 2) : 16;
> +		updates = xrealloc(updates, sizeof(*updates) * updates_size);
> +		memset(updates + updates_count, 0,
> +		       sizeof(*updates) * (updates_size - updates_count));
> +	}

Here you can use ARRAY_GROW().  See

    Documentation/technical/api-allocation-growing.txt

> +	update = &updates[updates_count++];
> +	update->flags = flags;
> +
> +	/* Set the update ref_name: */
> +	if (!argv[0])
> +		die("no ref on line: %s", line);
> +	if (check_refname_format(argv[0], REFNAME_ALLOW_ONELEVEL))
> +		die("invalid ref format on line: %s", line);
> +	update->ref_name = argv[0];
> +	argv[0] = 0;
> +
> +	/* Set the update new_sha1 and, if specified, old_sha1: */
> +	if (!argv[1])
> +		die("missing new value on line: %s", line);
> +	if (*argv[1] && get_sha1(argv[1], update->new_sha1))
> +		die("invalid new value on line: %s", line);
> +	if (argv[2]) {
> +		update->have_old = 1;
> +		if (*argv[2] && get_sha1(argv[2], update->old_sha1))
> +			die("invalid old value on line: %s", line);
> +	}
> +
> +	while (argc > 0)
> +		free(argv[--argc]);
> +}
> +
>  int cmd_update_ref(int argc, const char **argv, const char *prefix)
>  {
>  	const char *refname, *oldval, *msg = NULL;
>  	unsigned char sha1[20], oldsha1[20];
> -	int delete = 0, no_deref = 0, flags = 0;
> +	int delete = 0, no_deref = 0, read_stdin = 0, flags = 0;
> +	struct strbuf line = STRBUF_INIT;
>  	struct option options[] = {
>  		OPT_STRING( 'm', NULL, &msg, N_("reason"), N_("reason of the update")),
>  		OPT_BOOLEAN('d', NULL, &delete, N_("delete the reference")),
>  		OPT_BOOLEAN( 0 , "no-deref", &no_deref,
>  					N_("update <refname> not the one it points to")),
> +		OPT_BOOLEAN( 0 , "stdin", &read_stdin, N_("read updates from stdin")),
>  		OPT_END(),
>  	};
>  
> @@ -28,6 +138,15 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
>  	if (msg && !*msg)
>  		die("Refusing to perform update with empty message.");
>  
> +	if (read_stdin) {
> +		if (delete || no_deref || argc > 0)
> +			usage_with_options(git_update_ref_usage, options);
> +		while (strbuf_getline(&line, stdin, '\n') != EOF)
> +			update_refs_stdin(line.buf);
> +		strbuf_release(&line);
> +		return update_refs(msg, updates, updates_count, DIE_ON_ERR);
> +	}
> +
>  	if (delete) {
>  		if (argc < 1 || argc > 2)
>  			usage_with_options(git_update_ref_usage, options);
> 


-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/

  parent reply	other threads:[~2013-08-31 18:49 UTC|newest]

Thread overview: 106+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-08-29 14:11 [PATCH/RFC 0/7] Multiple simultaneously locked ref updates Brad King
2013-08-29 14:11 ` [PATCH/RFC 1/7] reset: rename update_refs to reset_refs Brad King
2013-08-29 17:17   ` Junio C Hamano
2013-08-29 18:07     ` Brad King
2013-08-29 14:11 ` [PATCH/RFC 2/7] refs: report ref type from lock_any_ref_for_update Brad King
2013-08-29 17:22   ` Junio C Hamano
2013-08-29 18:08     ` Brad King
2013-08-29 14:11 ` [PATCH/RFC 3/7] refs: factor update_ref steps into helpers Brad King
2013-08-29 14:11 ` [PATCH/RFC 4/7] refs: factor delete_ref loose ref step into a helper Brad King
2013-08-29 17:28   ` Junio C Hamano
2013-08-29 18:08     ` Brad King
2013-08-29 14:11 ` [PATCH/RFC 5/7] refs: add function to repack without multiple refs Brad King
2013-08-29 17:34   ` Junio C Hamano
2013-08-29 18:09     ` Brad King
2013-08-29 14:11 ` [PATCH/RFC 6/7] refs: add update_refs for multiple simultaneous updates Brad King
2013-08-29 17:39   ` Junio C Hamano
2013-08-29 18:20     ` Brad King
2013-08-29 18:32       ` Junio C Hamano
2013-08-29 18:38         ` Brad King
2013-08-29 19:30       ` Brad King
2013-08-29 14:11 ` [PATCH/RFC 7/7] update-ref: support " Brad King
2013-08-29 18:34   ` Junio C Hamano
2013-08-29 18:42     ` Brad King
2013-08-29 15:32 ` [PATCH/RFC 0/7] Multiple simultaneously locked ref updates Martin Fick
2013-08-29 15:46   ` Brad King
2013-08-29 16:21     ` Junio C Hamano
2013-08-29 17:09       ` Brad King
2013-08-29 18:07         ` Junio C Hamano
2013-08-29 18:23           ` Brad King
2013-08-30 18:11 ` [PATCH v2 0/8] " Brad King
2013-08-30 18:11   ` [PATCH v2 1/8] reset: rename update_refs to reset_refs Brad King
2013-08-30 18:12   ` [PATCH v2 2/8] refs: report ref type from lock_any_ref_for_update Brad King
2013-08-30 18:12   ` [PATCH v2 3/8] refs: factor update_ref steps into helpers Brad King
2013-09-01  6:08     ` Junio C Hamano
2013-09-02 17:19       ` Brad King
2013-08-30 18:12   ` [PATCH v2 4/8] refs: factor delete_ref loose ref step into a helper Brad King
2013-08-31 16:30     ` Michael Haggerty
2013-09-02 17:19       ` Brad King
2013-08-30 18:12   ` [PATCH v2 5/8] refs: add function to repack without multiple refs Brad King
2013-08-30 18:12   ` [PATCH v2 6/8] refs: add update_refs for multiple simultaneous updates Brad King
2013-08-31 18:19     ` Michael Haggerty
2013-09-02 17:20       ` Brad King
2013-09-01  6:08     ` Junio C Hamano
2013-09-02 17:20       ` Brad King
2013-09-03  4:43         ` Michael Haggerty
2013-09-03 11:59           ` Brad King
2013-08-30 18:12   ` [PATCH v2 7/8] update-ref: support " Brad King
2013-08-30 22:51     ` Junio C Hamano
2013-09-02 17:23       ` Brad King
2013-08-31 18:42     ` Michael Haggerty [this message]
2013-09-02 17:21       ` Brad King
2013-08-30 18:12   ` [PATCH v2 8/8] update-ref: add test cases covering --stdin signature Brad King
2013-09-01  3:41     ` Eric Sunshine
2013-09-02 17:23       ` Brad King
2013-08-31 19:02   ` [PATCH v2 0/8] Multiple simultaneously locked ref updates Michael Haggerty
2013-09-02 17:48   ` [PATCH v3 " Brad King
2013-09-02 17:48     ` [PATCH v3 1/8] reset: rename update_refs to reset_refs Brad King
2013-09-02 17:48     ` [PATCH v3 2/8] refs: report ref type from lock_any_ref_for_update Brad King
2013-09-02 17:48     ` [PATCH v3 3/8] refs: factor update_ref steps into helpers Brad King
2013-09-02 17:48     ` [PATCH v3 4/8] refs: factor delete_ref loose ref step into a helper Brad King
2013-09-02 17:48     ` [PATCH v3 5/8] refs: add function to repack without multiple refs Brad King
2013-09-02 17:48     ` [PATCH v3 6/8] refs: add update_refs for multiple simultaneous updates Brad King
2013-09-02 17:48     ` [PATCH v3 7/8] update-ref: support " Brad King
2013-09-02 18:37       ` Brad King
2013-09-02 17:48     ` [PATCH v3 8/8] update-ref: add test cases covering --stdin signature Brad King
2013-09-03  8:16       ` Eric Sunshine
2013-09-03 12:15         ` Brad King
2013-09-04 15:22     ` [PATCH v4 0/8] Multiple simultaneously locked ref updates Brad King
2013-09-04 15:22       ` [PATCH v4 1/8] reset: rename update_refs to reset_refs Brad King
2013-09-04 15:22       ` [PATCH v4 2/8] refs: report ref type from lock_any_ref_for_update Brad King
2013-09-04 15:22       ` [PATCH v4 3/8] refs: factor update_ref steps into helpers Brad King
2013-09-04 15:22       ` [PATCH v4 4/8] refs: factor delete_ref loose ref step into a helper Brad King
2013-09-04 15:22       ` [PATCH v4 5/8] refs: add function to repack without multiple refs Brad King
2013-09-04 15:22       ` [PATCH v4 6/8] refs: add update_refs for multiple simultaneous updates Brad King
2013-09-04 15:22       ` [PATCH v4 7/8] update-ref: support " Brad King
2013-09-04 18:23         ` Junio C Hamano
2013-09-04 19:59           ` Brad King
2013-09-04 21:27             ` Junio C Hamano
2013-09-05 20:32               ` Brad King
2013-09-05 21:23                 ` Junio C Hamano
2013-09-05 23:44                   ` Brad King
2013-09-04 19:17         ` Junio C Hamano
2013-09-04 19:16           ` Brad King
2013-09-04 15:22       ` [PATCH v4 8/8] update-ref: add test cases covering --stdin signature Brad King
2013-09-09 13:22       ` [PATCH v5 0/8] Multiple simultaneously locked ref updates Brad King
2013-09-09 13:22         ` [PATCH v5 7/8] update-ref: support multiple simultaneous updates Brad King
2013-09-09 13:22         ` [PATCH v5 8/8] update-ref: add test cases covering --stdin signature Brad King
2013-09-10  0:57         ` [PATCH v6 0/8] Multiple simultaneously locked ref updates Brad King
2013-09-10  0:57           ` [PATCH v6 1/8] reset: rename update_refs to reset_refs Brad King
2013-09-10  3:43             ` Ramkumar Ramachandra
2013-09-10  0:57           ` [PATCH v6 2/8] refs: report ref type from lock_any_ref_for_update Brad King
2013-09-10  0:57           ` [PATCH v6 3/8] refs: factor update_ref steps into helpers Brad King
2013-09-10  0:57           ` [PATCH v6 4/8] refs: factor delete_ref loose ref step into a helper Brad King
2013-09-10  0:57           ` [PATCH v6 5/8] refs: add function to repack without multiple refs Brad King
2013-09-10  0:57           ` [PATCH v6 6/8] refs: add update_refs for multiple simultaneous updates Brad King
2013-09-10  0:57           ` [PATCH v6 7/8] update-ref: support " Brad King
2013-09-10 22:51             ` Eric Sunshine
2013-09-11 12:36               ` Brad King
2013-09-11 16:07                 ` Eric Sunshine
2013-09-10  0:57           ` [PATCH v6 8/8] update-ref: add test cases covering --stdin signature Brad King
2013-09-10 22:46             ` Eric Sunshine
2013-09-10 22:54               ` Junio C Hamano
2013-09-11 12:46               ` [PATCH v6.1 " Brad King
2013-09-10 16:30           ` [PATCH v6 0/8] Multiple simultaneously locked ref updates Junio C Hamano
2013-09-10 16:54             ` Brad King
2013-09-10 20:18               ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=52223918.6040603@alum.mit.edu \
    --to=mhagger@alum.mit.edu \
    --cc=brad.king@kitware.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=mfick@codeaurora.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.