Skip to content

Commit 9a86b89

Browse files
committed
Merge branch 'bk/refs-multi-update'
Give "update-refs" a "--stdin" option to read multiple update requests and perform them in an all-or-none fashion. * bk/refs-multi-update: update-ref: add test cases covering --stdin signature update-ref: support multiple simultaneous updates refs: add update_refs for multiple simultaneous updates refs: add function to repack without multiple refs refs: factor delete_ref loose ref step into a helper refs: factor update_ref steps into helpers refs: report ref type from lock_any_ref_for_update reset: rename update_refs to reset_refs
2 parents 0873503 + c6268bc commit 9a86b89

File tree

15 files changed

+1139
-41
lines changed

15 files changed

+1139
-41
lines changed

Documentation/git-update-ref.txt

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ git-update-ref - Update the object name stored in a ref safely
88
SYNOPSIS
99
--------
1010
[verse]
11-
'git update-ref' [-m <reason>] (-d <ref> [<oldvalue>] | [--no-deref] <ref> <newvalue> [<oldvalue>])
11+
'git update-ref' [-m <reason>] (-d <ref> [<oldvalue>] | [--no-deref] <ref> <newvalue> [<oldvalue>] | --stdin [-z])
1212

1313
DESCRIPTION
1414
-----------
@@ -58,6 +58,58 @@ archive by creating a symlink tree).
5858
With `-d` flag, it deletes the named <ref> after verifying it
5959
still contains <oldvalue>.
6060

61+
With `--stdin`, update-ref reads instructions from standard input and
62+
performs all modifications together. Specify commands of the form:
63+
64+
update SP <ref> SP <newvalue> [SP <oldvalue>] LF
65+
create SP <ref> SP <newvalue> LF
66+
delete SP <ref> [SP <oldvalue>] LF
67+
verify SP <ref> [SP <oldvalue>] LF
68+
option SP <opt> LF
69+
70+
Quote fields containing whitespace as if they were strings in C source
71+
code. Alternatively, use `-z` to specify commands without quoting:
72+
73+
update SP <ref> NUL <newvalue> NUL [<oldvalue>] NUL
74+
create SP <ref> NUL <newvalue> NUL
75+
delete SP <ref> NUL [<oldvalue>] NUL
76+
verify SP <ref> NUL [<oldvalue>] NUL
77+
option SP <opt> NUL
78+
79+
Lines of any other format or a repeated <ref> produce an error.
80+
Command meanings are:
81+
82+
update::
83+
Set <ref> to <newvalue> after verifying <oldvalue>, if given.
84+
Specify a zero <newvalue> to ensure the ref does not exist
85+
after the update and/or a zero <oldvalue> to make sure the
86+
ref does not exist before the update.
87+
88+
create::
89+
Create <ref> with <newvalue> after verifying it does not
90+
exist. The given <newvalue> may not be zero.
91+
92+
delete::
93+
Delete <ref> after verifying it exists with <oldvalue>, if
94+
given. If given, <oldvalue> may not be zero.
95+
96+
verify::
97+
Verify <ref> against <oldvalue> but do not change it. If
98+
<oldvalue> zero or missing, the ref must not exist.
99+
100+
option::
101+
Modify behavior of the next command naming a <ref>.
102+
The only valid option is `no-deref` to avoid dereferencing
103+
a symbolic ref.
104+
105+
Use 40 "0" or the empty string to specify a zero value, except that
106+
with `-z` an empty <oldvalue> is considered missing.
107+
108+
If all <ref>s can be locked with matching <oldvalue>s
109+
simultaneously, all modifications are performed. Otherwise, no
110+
modifications are performed. Note that while each individual
111+
<ref> is updated or deleted atomically, a concurrent reader may
112+
still see a subset of the modifications.
61113

62114
Logging Updates
63115
---------------

branch.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ void create_branch(const char *head,
290290
hashcpy(sha1, commit->object.sha1);
291291

292292
if (!dont_change_ref) {
293-
lock = lock_any_ref_for_update(ref.buf, NULL, 0);
293+
lock = lock_any_ref_for_update(ref.buf, NULL, 0, NULL);
294294
if (!lock)
295295
die_errno(_("Failed to lock ref for update"));
296296
}

builtin/commit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1631,7 +1631,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
16311631
!current_head
16321632
? NULL
16331633
: current_head->object.sha1,
1634-
0);
1634+
0, NULL);
16351635

16361636
nl = strchr(sb.buf, '\n');
16371637
if (nl)

builtin/fetch.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,8 @@ static int s_update_ref(const char *action,
262262
rla = default_rla.buf;
263263
snprintf(msg, sizeof(msg), "%s: %s", rla, action);
264264
lock = lock_any_ref_for_update(ref->name,
265-
check_old ? ref->old_sha1 : NULL, 0);
265+
check_old ? ref->old_sha1 : NULL,
266+
0, NULL);
266267
if (!lock)
267268
return errno == ENOTDIR ? STORE_REF_ERROR_DF_CONFLICT :
268269
STORE_REF_ERROR_OTHER;

builtin/receive-pack.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,8 @@ static const char *update(struct command *cmd)
526526
return NULL; /* good */
527527
}
528528
else {
529-
lock = lock_any_ref_for_update(namespaced_name, old_sha1, 0);
529+
lock = lock_any_ref_for_update(namespaced_name, old_sha1,
530+
0, NULL);
530531
if (!lock) {
531532
rp_error("failed to lock %s", name);
532533
return "failed to lock";

builtin/reflog.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused,
365365
* we take the lock for the ref itself to prevent it from
366366
* getting updated.
367367
*/
368-
lock = lock_any_ref_for_update(ref, sha1, 0);
368+
lock = lock_any_ref_for_update(ref, sha1, 0, NULL);
369369
if (!lock)
370370
return error("cannot lock ref '%s'", ref);
371371
log_file = git_pathdup("logs/%s", ref);

builtin/replace.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ static int replace_object(const char *object_ref, const char *replace_ref,
105105
else if (!force)
106106
die("replace ref '%s' already exists", ref);
107107

108-
lock = lock_any_ref_for_update(ref, prev, 0);
108+
lock = lock_any_ref_for_update(ref, prev, 0, NULL);
109109
if (!lock)
110110
die("%s: cannot lock the ref", ref);
111111
if (write_ref_sha1(lock, repl, NULL) < 0)

builtin/reset.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ static void parse_args(struct pathspec *pathspec,
226226
prefix, argv);
227227
}
228228

229-
static int update_refs(const char *rev, const unsigned char *sha1)
229+
static int reset_refs(const char *rev, const unsigned char *sha1)
230230
{
231231
int update_ref_status;
232232
struct strbuf msg = STRBUF_INIT;
@@ -354,7 +354,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
354354
if (!pathspec.nr && !unborn) {
355355
/* Any resets without paths update HEAD to the head being
356356
* switched to, saving the previous head in ORIG_HEAD before. */
357-
update_ref_status = update_refs(rev, sha1);
357+
update_ref_status = reset_refs(rev, sha1);
358358

359359
if (reset_type == HARD && !update_ref_status && !quiet)
360360
print_new_head_line(lookup_commit_reference(sha1));

builtin/tag.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
574574
if (annotate)
575575
create_tag(object, tag, &buf, &opt, prev, object);
576576

577-
lock = lock_any_ref_for_update(ref.buf, prev, 0);
577+
lock = lock_any_ref_for_update(ref.buf, prev, 0, NULL);
578578
if (!lock)
579579
die(_("%s: cannot lock the ref"), ref.buf);
580580
if (write_ref_sha1(lock, object, NULL) < 0)

0 commit comments

Comments
 (0)