diff options
author | Felipe Contreras <felipe.contreras@gmail.com> | 2012-02-23 00:43:41 +0200 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2012-02-22 18:17:39 -0800 |
commit | 6ddba5e241ebe484d53e3573c72386f487e25697 (patch) | |
tree | 836c5b5f1ee5d900e87ea9d60c32e576e219b68f /remote.c | |
parent | 676552464a871564835e1cb9d0484277b1b75e79 (diff) | |
download | git-6ddba5e241ebe484d53e3573c72386f487e25697.tar.gz |
push: add '--prune' optionfc/push-prune
When pushing groups of refs to a remote, there is no simple way to remove
old refs that still exist at the remote that is no longer updated from us.
This will allow us to remove such refs from the remote.
With this change, running this command
$ git push --prune remote refs/heads/*:refs/remotes/laptop/*
removes refs/remotes/laptop/foo from the remote if we do not have branch
"foo" locally anymore.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'remote.c')
-rw-r--r-- | remote.c | 31 |
1 files changed, 28 insertions, 3 deletions
@@ -8,6 +8,8 @@ #include "tag.h" #include "string-list.h" +enum map_direction { FROM_SRC, FROM_DST }; + static struct refspec s_tag_refspec = { 0, 1, @@ -1115,7 +1117,7 @@ static int match_explicit_refs(struct ref *src, struct ref *dst, } static char *get_ref_match(const struct refspec *rs, int rs_nr, const struct ref *ref, - int send_mirror, const struct refspec **ret_pat) + int send_mirror, int direction, const struct refspec **ret_pat) { const struct refspec *pat; char *name; @@ -1130,7 +1132,12 @@ static char *get_ref_match(const struct refspec *rs, int rs_nr, const struct ref if (rs[i].pattern) { const char *dst_side = rs[i].dst ? rs[i].dst : rs[i].src; - if (match_name_with_pattern(rs[i].src, ref->name, dst_side, &name)) { + int match; + if (direction == FROM_SRC) + match = match_name_with_pattern(rs[i].src, ref->name, dst_side, &name); + else + match = match_name_with_pattern(dst_side, ref->name, rs[i].src, &name); + if (match) { matching_refs = i; break; } @@ -1177,6 +1184,7 @@ int match_push_refs(struct ref *src, struct ref **dst, struct refspec *rs; int send_all = flags & MATCH_REFS_ALL; int send_mirror = flags & MATCH_REFS_MIRROR; + int send_prune = flags & MATCH_REFS_PRUNE; int errs; static const char *default_refspec[] = { ":", NULL }; struct ref *ref, **dst_tail = tail_ref(dst); @@ -1197,7 +1205,7 @@ int match_push_refs(struct ref *src, struct ref **dst, if (ref->peer_ref) continue; - dst_name = get_ref_match(rs, nr_refspec, ref, send_mirror, &pat); + dst_name = get_ref_match(rs, nr_refspec, ref, send_mirror, FROM_SRC, &pat); if (!dst_name) continue; @@ -1224,6 +1232,23 @@ int match_push_refs(struct ref *src, struct ref **dst, free_name: free(dst_name); } + if (send_prune) { + /* check for missing refs on the remote */ + for (ref = *dst; ref; ref = ref->next) { + char *src_name; + + if (ref->peer_ref) + /* We're already sending something to this ref. */ + continue; + + src_name = get_ref_match(rs, nr_refspec, ref, send_mirror, FROM_DST, NULL); + if (src_name) { + if (!find_ref_by_name(src, src_name)) + ref->peer_ref = alloc_delete_ref(); + free(src_name); + } + } + } if (errs) return -1; return 0; |