Skip to content

Commit 952c8c5

Browse files
committed
Merge branch 'jc/remote'
* jc/remote: git-push: Update description of refspecs and add examples remote.c: "git-push frotz" should update what matches at the source. remote.c: fix "git push" weak match disambiguation remote.c: minor clean-up of match_explicit() remote.c: refactor creation of new dst ref remote.c: refactor match_explicit_refs()
2 parents 5c088a2 + bb9fca8 commit 952c8c5

File tree

3 files changed

+275
-85
lines changed

3 files changed

+275
-85
lines changed

Documentation/git-push.txt

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,8 @@ side are updated.
5353
+
5454
`tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`.
5555
+
56-
A parameter <ref> without a colon is equivalent to
57-
<ref>`:`<ref>, hence updates <ref> in the destination from <ref>
58-
in the source.
56+
A parameter <ref> without a colon pushes the <ref> from the source
57+
repository to the destination repository under the same name.
5958
+
6059
Pushing an empty <src> allows you to delete the <dst> ref from
6160
the remote repository.
@@ -98,6 +97,26 @@ the remote repository.
9897

9998
include::urls.txt[]
10099

100+
101+
Examples
102+
--------
103+
104+
git push origin master::
105+
Find a ref that matches `master` in the source repository
106+
(most likely, it would find `refs/heads/master`), and update
107+
the same ref (e.g. `refs/heads/master`) in `origin` repository
108+
with it.
109+
110+
git push origin :experimental::
111+
Find a ref that matches `experimental` in the `origin` repository
112+
(e.g. `refs/heads/experimental`), and delete it.
113+
114+
git push origin master:satellite/master::
115+
Find a ref that matches `master` in the source repository
116+
(most likely, it would find `refs/heads/master`), and update
117+
the ref that matches `satellite/master` (most likely, it would
118+
be `refs/remotes/satellite/master`) in `origin` repository with it.
119+
101120
Author
102121
------
103122
Written by Junio C Hamano <junkio@cox.net>, later rewritten in C

remote.c

Lines changed: 89 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,6 @@ static int count_refspec_match(const char *pattern,
333333
for (weak_match = match = 0; refs; refs = refs->next) {
334334
char *name = refs->name;
335335
int namelen = strlen(name);
336-
int weak_match;
337336

338337
if (namelen < patlen ||
339338
memcmp(name + namelen - patlen, pattern, patlen))
@@ -406,90 +405,96 @@ static struct ref *try_explicit_object_name(const char *name)
406405
return ref;
407406
}
408407

409-
static int match_explicit_refs(struct ref *src, struct ref *dst,
410-
struct ref ***dst_tail, struct refspec *rs,
411-
int rs_nr)
408+
static struct ref *make_dst(const char *name, struct ref ***dst_tail)
412409
{
413-
int i, errs;
414-
for (i = errs = 0; i < rs_nr; i++) {
415-
struct ref *matched_src, *matched_dst;
410+
struct ref *dst;
411+
size_t len;
416412

417-
const char *dst_value = rs[i].dst;
413+
len = strlen(name) + 1;
414+
dst = xcalloc(1, sizeof(*dst) + len);
415+
memcpy(dst->name, name, len);
416+
link_dst_tail(dst, dst_tail);
417+
return dst;
418+
}
418419

419-
if (rs[i].pattern)
420-
continue;
420+
static int match_explicit(struct ref *src, struct ref *dst,
421+
struct ref ***dst_tail,
422+
struct refspec *rs,
423+
int errs)
424+
{
425+
struct ref *matched_src, *matched_dst;
421426

422-
if (dst_value == NULL)
423-
dst_value = rs[i].src;
427+
const char *dst_value = rs->dst;
424428

425-
matched_src = matched_dst = NULL;
426-
switch (count_refspec_match(rs[i].src, src, &matched_src)) {
427-
case 1:
428-
break;
429-
case 0:
430-
/* The source could be in the get_sha1() format
431-
* not a reference name. :refs/other is a
432-
* way to delete 'other' ref at the remote end.
433-
*/
434-
matched_src = try_explicit_object_name(rs[i].src);
435-
if (matched_src)
436-
break;
437-
errs = 1;
438-
error("src refspec %s does not match any.",
439-
rs[i].src);
440-
break;
441-
default:
442-
errs = 1;
443-
error("src refspec %s matches more than one.",
444-
rs[i].src);
445-
break;
446-
}
447-
switch (count_refspec_match(dst_value, dst, &matched_dst)) {
448-
case 1:
449-
break;
450-
case 0:
451-
if (!memcmp(dst_value, "refs/", 5)) {
452-
int len = strlen(dst_value) + 1;
453-
matched_dst = xcalloc(1, sizeof(*dst) + len);
454-
memcpy(matched_dst->name, dst_value, len);
455-
link_dst_tail(matched_dst, dst_tail);
456-
}
457-
else if (!strcmp(rs[i].src, dst_value) &&
458-
matched_src) {
459-
/* pushing "master:master" when
460-
* remote does not have master yet.
461-
*/
462-
int len = strlen(matched_src->name) + 1;
463-
matched_dst = xcalloc(1, sizeof(*dst) + len);
464-
memcpy(matched_dst->name, matched_src->name,
465-
len);
466-
link_dst_tail(matched_dst, dst_tail);
467-
}
468-
else {
469-
errs = 1;
470-
error("dst refspec %s does not match any "
471-
"existing ref on the remote and does "
472-
"not start with refs/.", dst_value);
473-
}
474-
break;
475-
default:
476-
errs = 1;
477-
error("dst refspec %s matches more than one.",
478-
dst_value);
429+
if (rs->pattern)
430+
return errs;
431+
432+
matched_src = matched_dst = NULL;
433+
switch (count_refspec_match(rs->src, src, &matched_src)) {
434+
case 1:
435+
break;
436+
case 0:
437+
/* The source could be in the get_sha1() format
438+
* not a reference name. :refs/other is a
439+
* way to delete 'other' ref at the remote end.
440+
*/
441+
matched_src = try_explicit_object_name(rs->src);
442+
if (matched_src)
479443
break;
480-
}
481-
if (errs)
482-
continue;
483-
if (matched_dst->peer_ref) {
484-
errs = 1;
485-
error("dst ref %s receives from more than one src.",
486-
matched_dst->name);
487-
}
488-
else {
489-
matched_dst->peer_ref = matched_src;
490-
matched_dst->force = rs[i].force;
491-
}
444+
error("src refspec %s does not match any.",
445+
rs->src);
446+
break;
447+
default:
448+
matched_src = NULL;
449+
error("src refspec %s matches more than one.",
450+
rs->src);
451+
break;
452+
}
453+
454+
if (!matched_src)
455+
errs = 1;
456+
457+
if (dst_value == NULL)
458+
dst_value = matched_src->name;
459+
460+
switch (count_refspec_match(dst_value, dst, &matched_dst)) {
461+
case 1:
462+
break;
463+
case 0:
464+
if (!memcmp(dst_value, "refs/", 5))
465+
matched_dst = make_dst(dst_value, dst_tail);
466+
else
467+
error("dst refspec %s does not match any "
468+
"existing ref on the remote and does "
469+
"not start with refs/.", dst_value);
470+
break;
471+
default:
472+
matched_dst = NULL;
473+
error("dst refspec %s matches more than one.",
474+
dst_value);
475+
break;
476+
}
477+
if (errs || matched_dst == NULL)
478+
return 1;
479+
if (matched_dst->peer_ref) {
480+
errs = 1;
481+
error("dst ref %s receives from more than one src.",
482+
matched_dst->name);
483+
}
484+
else {
485+
matched_dst->peer_ref = matched_src;
486+
matched_dst->force = rs->force;
492487
}
488+
return errs;
489+
}
490+
491+
static int match_explicit_refs(struct ref *src, struct ref *dst,
492+
struct ref ***dst_tail, struct refspec *rs,
493+
int rs_nr)
494+
{
495+
int i, errs;
496+
for (i = errs = 0; i < rs_nr; i++)
497+
errs |= match_explicit(src, dst, dst_tail, &rs[i], errs);
493498
return -errs;
494499
}
495500

@@ -513,6 +518,11 @@ static const struct refspec *check_pattern_match(const struct refspec *rs,
513518
return NULL;
514519
}
515520

521+
/*
522+
* Note. This is used only by "push"; refspec matching rules for
523+
* push and fetch are subtly different, so do not try to reuse it
524+
* without thinking.
525+
*/
516526
int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
517527
int nr_refspec, char **refspec, int all)
518528
{
@@ -555,11 +565,8 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
555565
goto free_name;
556566
if (!dst_peer) {
557567
/* Create a new one and link it */
558-
int len = strlen(dst_name) + 1;
559-
dst_peer = xcalloc(1, sizeof(*dst_peer) + len);
560-
memcpy(dst_peer->name, dst_name, len);
568+
dst_peer = make_dst(dst_name, dst_tail);
561569
hashcpy(dst_peer->new_sha1, src->new_sha1);
562-
link_dst_tail(dst_peer, dst_tail);
563570
}
564571
dst_peer->peer_ref = src;
565572
free_name:

0 commit comments

Comments
 (0)