summaryrefslogtreecommitdiff
path: root/transport.c
diff options
context:
space:
mode:
authorIlari Liusvaara <ilari.liusvaara@elisanet.fi>2010-01-16 23:45:31 +0200
committerJunio C Hamano <gitster@pobox.com>2010-01-16 16:39:58 -0800
commite9fcd1e2121100d43d2d212eb6c6f1fc82aade1d (patch)
tree6a1d97f297fa15ee407e395a778c43675c95194f /transport.c
parent1f73566af5bec28cd8489c6139a9ede95817349c (diff)
downloadgit-e9fcd1e2121100d43d2d212eb6c6f1fc82aade1d.tar.gz
Add push --set-upstream
Frequent complaint is lack of easy way to set up upstream (tracking) references for git pull to work as part of push command. So add switch --set-upstream (-u) to do just that. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'transport.c')
-rw-r--r--transport.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/transport.c b/transport.c
index b5332c018b..8cc287d442 100644
--- a/transport.c
+++ b/transport.c
@@ -8,6 +8,7 @@
#include "bundle.h"
#include "dir.h"
#include "refs.h"
+#include "branch.h"
/* rsync support */
@@ -135,6 +136,53 @@ static void insert_packed_refs(const char *packed_refs, struct ref **list)
}
}
+static void set_upstreams(struct transport *transport, struct ref *refs,
+ int pretend)
+{
+ struct ref *ref;
+ for (ref = refs; ref; ref = ref->next) {
+ const char *localname;
+ const char *tmp;
+ const char *remotename;
+ unsigned char sha[20];
+ int flag = 0;
+ /*
+ * Check suitability for tracking. Must be successful /
+ * already up-to-date ref create/modify (not delete).
+ */
+ if (ref->status != REF_STATUS_OK &&
+ ref->status != REF_STATUS_UPTODATE)
+ continue;
+ if (!ref->peer_ref)
+ continue;
+ if (!ref->new_sha1 || is_null_sha1(ref->new_sha1))
+ continue;
+
+ /* Follow symbolic refs (mainly for HEAD). */
+ localname = ref->peer_ref->name;
+ remotename = ref->name;
+ tmp = resolve_ref(localname, sha, 1, &flag);
+ if (tmp && flag & REF_ISSYMREF &&
+ !prefixcmp(tmp, "refs/heads/"))
+ localname = tmp;
+
+ /* Both source and destination must be local branches. */
+ if (!localname || prefixcmp(localname, "refs/heads/"))
+ continue;
+ if (!remotename || prefixcmp(remotename, "refs/heads/"))
+ continue;
+
+ if (!pretend)
+ install_branch_config(BRANCH_CONFIG_VERBOSE,
+ localname + 11, transport->remote->name,
+ remotename);
+ else
+ printf("Would set upstream of '%s' to '%s' of '%s'\n",
+ localname + 11, remotename + 11,
+ transport->remote->name);
+ }
+}
+
static const char *rsync_url(const char *url)
{
return prefixcmp(url, "rsync://") ? skip_prefix(url, "rsync:") : url;
@@ -974,6 +1022,10 @@ int transport_push(struct transport *transport,
verify_remote_names(refspec_nr, refspec);
if (transport->push) {
+ /* Maybe FIXME. But no important transport uses this case. */
+ if (flags & TRANSPORT_PUSH_SET_UPSTREAM)
+ die("This transport does not support using --set-upstream");
+
return transport->push(transport, refspec_nr, refspec, flags);
} else if (transport->push_refs) {
struct ref *remote_refs =
@@ -983,6 +1035,7 @@ int transport_push(struct transport *transport,
int verbose = flags & TRANSPORT_PUSH_VERBOSE;
int quiet = flags & TRANSPORT_PUSH_QUIET;
int porcelain = flags & TRANSPORT_PUSH_PORCELAIN;
+ int pretend = flags & TRANSPORT_PUSH_DRY_RUN;
int ret;
if (flags & TRANSPORT_PUSH_ALL)
@@ -1002,6 +1055,9 @@ int transport_push(struct transport *transport,
verbose | porcelain, porcelain,
nonfastforward);
+ if (flags & TRANSPORT_PUSH_SET_UPSTREAM)
+ set_upstreams(transport, remote_refs, pretend);
+
if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
struct ref *ref;
for (ref = remote_refs; ref; ref = ref->next)