#include "bundle.h"
#include "dir.h"
#include "refs.h"
+#include "branch.h"
/* rsync support */
}
}
+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;
args.include_tag = data->options.followtags;
args.verbose = (transport->verbose > 0);
args.quiet = (transport->verbose < 0);
- args.no_progress = args.quiet || (!transport->progress && !isatty(1));
+ args.no_progress = args.quiet || (!transport->progress && !isatty(2));
args.depth = data->options.depth;
for (i = 0; i < nr_heads; i++)
static int print_one_push_status(struct ref *ref, const char *dest, int count, int porcelain)
{
if (!count)
- fprintf(stderr, "To %s\n", dest);
+ fprintf(porcelain ? stdout : stderr, "To %s\n", dest);
switch(ref->status) {
case REF_STATUS_NONE:
args.verbose = !!(flags & TRANSPORT_PUSH_VERBOSE);
args.quiet = !!(flags & TRANSPORT_PUSH_QUIET);
args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN);
+ args.porcelain = !!(flags & TRANSPORT_PUSH_PORCELAIN);
ret = send_pack(&args, data->fd, data->conn, remote_refs,
&data->extra_have);
struct transport *transport_get(struct remote *remote, const char *url)
{
+ const char *helper;
struct transport *ret = xcalloc(1, sizeof(*ret));
if (!remote)
die("No remote provided to transport_get()");
ret->remote = remote;
+ helper = remote->foreign_vcs;
- if (!url && remote && remote->url)
+ if (!url && remote->url)
url = remote->url[0];
ret->url = url;
- /* In case previous URL had helper forced, reset it. */
- remote->foreign_vcs = NULL;
-
/* maybe it is a foreign URL? */
if (url) {
const char *p = url;
while (isalnum(*p))
p++;
if (!prefixcmp(p, "::"))
- remote->foreign_vcs = xstrndup(url, p - url);
+ helper = xstrndup(url, p - url);
}
- if (remote && remote->foreign_vcs) {
- transport_helper_init(ret, remote->foreign_vcs);
+ if (helper) {
+ transport_helper_init(ret, helper);
} else if (!prefixcmp(url, "rsync:")) {
ret->get_refs_list = get_refs_via_rsync;
ret->fetch = fetch_objs_via_rsync;
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 =
int verbose = flags & TRANSPORT_PUSH_VERBOSE;
int quiet = flags & TRANSPORT_PUSH_QUIET;
int porcelain = flags & TRANSPORT_PUSH_PORCELAIN;
- int ret;
+ int pretend = flags & TRANSPORT_PUSH_DRY_RUN;
+ int push_ret, ret, err;
if (flags & TRANSPORT_PUSH_ALL)
match_flags |= MATCH_REFS_ALL;
return -1;
}
- ret = transport->push_refs(transport, remote_refs, flags);
+ set_ref_status_for_push(remote_refs,
+ flags & TRANSPORT_PUSH_MIRROR,
+ flags & TRANSPORT_PUSH_FORCE);
+
+ push_ret = transport->push_refs(transport, remote_refs, flags);
+ err = push_had_errors(remote_refs);
+ ret = push_ret | err;
- if (!quiet || push_had_errors(remote_refs))
+ if (!quiet || err)
print_push_status(transport->url, remote_refs,
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)
update_tracking_ref(transport->remote, ref, verbose);
}
- if (!quiet && !ret && !refs_pushed(remote_refs))
+ if (porcelain && !push_ret)
+ puts("Done");
+ else if (!quiet && !ret && !refs_pushed(remote_refs))
fprintf(stderr, "Everything up-to-date\n");
+
return ret;
}
return 1;