Merge branch 'il/push-set-upstream'
authorJunio C Hamano <gitster@pobox.com>
Wed, 20 Jan 2010 22:40:48 +0000 (14:40 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 20 Jan 2010 22:40:48 +0000 (14:40 -0800)
* il/push-set-upstream:
Add push --set-upstream

Conflicts:
transport.c

1  2 
transport.c
transport.h
diff --combined transport.c
index d7db2941fb135c8d956756ced762dc0a3dd75a4b,8cc287d4429212c385b1359943ba41deb8a0460d..7714fdb6c6578c711dc0b98a2086669a6a797257
@@@ -8,6 -8,7 +8,7 @@@
  #include "bundle.h"
  #include "dir.h"
  #include "refs.h"
+ #include "branch.h"
  
  /* rsync support */
  
@@@ -135,6 -136,53 +136,53 @@@ static void insert_packed_refs(const ch
        }
  }
  
+ 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;
  static struct ref *get_refs_via_rsync(struct transport *transport, int for_push)
  {
        struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
 -      struct ref dummy, *tail = &dummy;
 +      struct ref dummy = {0}, *tail = &dummy;
        struct child_process rsync;
        const char *args[5];
        int temp_dir_len;
@@@ -478,7 -526,7 +526,7 @@@ static int fetch_refs_via_pack(struct t
        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++)
@@@ -974,6 -1022,10 +1022,10 @@@ int transport_push(struct transport *tr
        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 ret, err;
  
                if (flags & TRANSPORT_PUSH_ALL)
                        match_flags |= MATCH_REFS_ALL;
                        return -1;
                }
  
 +              set_ref_status_for_push(remote_refs,
 +                      flags & TRANSPORT_PUSH_MIRROR,
 +                      flags & TRANSPORT_PUSH_FORCE);
 +
                ret = transport->push_refs(transport, remote_refs, flags);
 +              err = push_had_errors(remote_refs);
 +
 +              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)
diff --combined transport.h
index 7a242fe3bd68e55e5807268e5c381c3c89f96a47,c4314dd59b5831996b6ddb92072c629a1f029b2c..7cea5cc7234185b1c37ada818dfa1a9114621ad2
@@@ -74,7 -74,7 +74,7 @@@ struct transport 
        int (*disconnect)(struct transport *connection);
        char *pack_lockfile;
        signed verbose : 3;
 -      /* Force progress even if the output is not a tty */
 +      /* Force progress even if stderr is not a tty */
        unsigned progress : 1;
        /*
         * If transport is at least potentially smart, this points to
@@@ -91,6 -91,7 +91,7 @@@
  #define TRANSPORT_PUSH_VERBOSE 16
  #define TRANSPORT_PUSH_PORCELAIN 32
  #define TRANSPORT_PUSH_QUIET 64
+ #define TRANSPORT_PUSH_SET_UPSTREAM 128
  
  /* Returns a transport suitable for the url */
  struct transport *transport_get(struct remote *, const char *);