[RFC/PATCH 3/3] push: add 'prune' option
From: Felipe Contreras <hidden>
Date: 2016-06-15 22:53:06
Subsystem:
the rest · Maintainer:
Linus Torvalds
This will allow us to remove refs from the remote that have been removed locally. It's useful to conveniently synchronize all the local branches to certain remote. Signed-off-by: Felipe Contreras <redacted> --- builtin/push.c | 2 ++ remote.c | 29 ++++++++++++++++++++++++++--- remote.h | 3 ++- transport.c | 2 ++ transport.h | 1 + 5 files changed, 33 insertions(+), 4 deletions(-)
diff --git a/builtin/push.c b/builtin/push.c
index 35cce53..46b99b1 100644
--- a/builtin/push.c
+++ b/builtin/push.c@@ -261,6 +261,8 @@ int cmd_push(int argc, const char **argv, const char *prefix) OPT_BIT('u', "set-upstream", &flags, "set upstream for git pull/status", TRANSPORT_PUSH_SET_UPSTREAM), OPT_BOOLEAN(0, "progress", &progress, "force progress reporting"), + OPT_BIT('p', "prune", &flags, "prune locally removed refs", + TRANSPORT_PUSH_PRUNE), OPT_END() };
diff --git a/remote.c b/remote.c
index 019aafc..0900bb5 100644
--- a/remote.c
+++ b/remote.c@@ -1111,7 +1111,7 @@ static int match_explicit_refs(struct ref *src, struct ref *dst, } static char *check_pattern_match(const struct refspec *rs, int rs_nr, struct ref *ref, - int send_mirror, const struct refspec **ret_pat) + int send_mirror, int dir, const struct refspec **ret_pat) { const struct refspec *pat; char *name;
@@ -1126,7 +1126,12 @@ static char *check_pattern_match(const struct refspec *rs, int rs_nr, 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 (dir == 0) + 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; }
@@ -1173,6 +1178,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);
@@ -1193,7 +1199,7 @@ int match_push_refs(struct ref *src, struct ref **dst, if (ref->peer_ref) continue; - dst_name = check_pattern_match(rs, nr_refspec, ref, send_mirror, &pat); + dst_name = check_pattern_match(rs, nr_refspec, ref, send_mirror, 0, &pat); if (!dst_name) continue;
@@ -1220,6 +1226,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 = check_pattern_match(rs, nr_refspec, ref, send_mirror, 1, NULL); + if (src_name) { + if (!find_ref_by_name(src, src_name)) + ref->peer_ref = try_explicit_object_name(""); + free(src_name); + } + } + } if (errs) return -1; return 0;
diff --git a/remote.h b/remote.h
index b395598..341142c 100644
--- a/remote.h
+++ b/remote.h@@ -145,7 +145,8 @@ int branch_merge_matches(struct branch *, int n, const char *); enum match_refs_flags { MATCH_REFS_NONE = 0, MATCH_REFS_ALL = (1 << 0), - MATCH_REFS_MIRROR = (1 << 1) + MATCH_REFS_MIRROR = (1 << 1), + MATCH_REFS_PRUNE = (1 << 2), }; /* Reporting of tracking info */
diff --git a/transport.c b/transport.c
index cac0c06..c20267c 100644
--- a/transport.c
+++ b/transport.c@@ -1028,6 +1028,8 @@ int transport_push(struct transport *transport, match_flags |= MATCH_REFS_ALL; if (flags & TRANSPORT_PUSH_MIRROR) match_flags |= MATCH_REFS_MIRROR; + if (flags & TRANSPORT_PUSH_PRUNE) + match_flags |= MATCH_REFS_PRUNE; if (match_push_refs(local_refs, &remote_refs, refspec_nr, refspec, match_flags)) {
diff --git a/transport.h b/transport.h
index 059b330..5d30328 100644
--- a/transport.h
+++ b/transport.h@@ -101,6 +101,7 @@ struct transport { #define TRANSPORT_PUSH_MIRROR 8 #define TRANSPORT_PUSH_PORCELAIN 16 #define TRANSPORT_PUSH_SET_UPSTREAM 32 +#define TRANSPORT_PUSH_PRUNE 64 #define TRANSPORT_RECURSE_SUBMODULES_CHECK 64 #define TRANSPORT_SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
--
1.7.9.1