From: Tay Ray Chuan Date: Sat, 16 Jan 2010 01:00:30 GMT Subject: Re: [PATCH v2] Add push --set-upstream Message-ID: In-Reply-To: <1263595630-18962-1-git-send-email-ilari.liusvaara@elisanet.fi> Hi, I'm adding people from the "git push --track" thread here, since this feature is related to what they want. (sorry for any line-wrap mangling in the patch.) -- Cheers, Ray Chuan On Sat, Jan 16, 2010 at 6:47 AM, Ilari Liusvaara wrote: > 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 > Signed-off-by: Ilari Liusvaara > --- > Changes from v1: > - Handle 'git push -u HEAD' correctly. > - Add testsuite (thanks Peff), with some additional tests to test delete. > - Modify documentation for push -u (thanks Matthieu Moy). > >  Documentation/git-push.txt |    9 +++++- >  builtin-push.c             |    1 + >  t/t5523-push-upstream.sh   |   64 ++++++++++++++++++++++++++++++++++++++++++++ >  transport.c                |   49 +++++++++++++++++++++++++++++++++ >  transport.h                |    1 + >  5 files changed, 123 insertions(+), 1 deletions(-) >  create mode 100755 t/t5523-push-upstream.sh > > diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt > index e3eb1e8..2a5394b 100644 > --- a/Documentation/git-push.txt > +++ b/Documentation/git-push.txt > @@ -10,7 +10,7 @@ SYNOPSIS >  -------- >  [verse] >  'git push' [--all | --mirror | --tags] [-n | --dry-run] [--receive-pack=] > -          [--repo=] [-f | --force] [-v | --verbose] > +          [--repo=] [-f | --force] [-v | --verbose] [-u | --set-upstream] >           [ ...] > >  DESCRIPTION > @@ -122,6 +122,13 @@ nor in any Push line of the corresponding remotes file---see below). >        the name "origin" is used. For this latter case, this option >        can be used to override the name "origin". In other words, >        the difference between these two commands > + > +-u:: > +--set-upstream:: > +       For every branch that is up to date or successfully pushed, add > +       upstream (tracking) reference, used by argument-less > +       linkgit:git-pull[1] and other commands. For more information, > +       see 'branch..merge' in linkgit:git-config[1]. >  + >  -------------------------- >  git push public         #1 > diff --git a/builtin-push.c b/builtin-push.c > index 28a26e7..75ddaf4 100644 > --- a/builtin-push.c > +++ b/builtin-push.c > @@ -218,6 +218,7 @@ int cmd_push(int argc, const char **argv, const char *prefix) >                OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"), >                OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"), >                OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"), > +               OPT_BIT('u', "set-upstream", &flags, "Set upstream for git pull", TRANSPORT_PUSH_SET_UPSTREAM), >                OPT_END() >        }; > > diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh > new file mode 100755 > index 0000000..e098d37 > --- /dev/null > +++ b/t/t5523-push-upstream.sh > @@ -0,0 +1,64 @@ > +#!/bin/sh > + > +test_description='push with --set-upstream' > +. ./test-lib.sh > + > +test_expect_success 'setup bare parent' ' > +       git init --bare parent && > +       git remote add upstream parent > +' > + > +test_expect_success 'setup local commit' ' > +       echo content >file && > +       git add file && > +       git commit -m one > +' > + > +check_config() { > +       (echo $2; echo $3) >expect.$1 > +       (git config branch.$1.remote > +        git config branch.$1.merge) >actual.$1 > +       test_cmp expect.$1 actual.$1 > +} > + > +test_expect_success 'push -u master:master' ' > +       git push -u upstream master:master && > +       check_config master upstream refs/heads/master > +' > + > +test_expect_success 'push -u master:other' ' > +       git push -u upstream master:other && > +       check_config master upstream refs/heads/other > +' > + > +test_expect_success 'push -u master2:master2' ' > +       git branch master2 && > +       git push -u upstream master2:master2 && > +       check_config master2 upstream refs/heads/master2 > +' > + > +test_expect_success 'push -u master2:other2' ' > +       git push -u upstream master2:other2 && > +       check_config master2 upstream refs/heads/other2 > +' > + > +test_expect_success 'push -u :master2' ' > +       git push -u upstream :master2 && > +       check_config master2 upstream refs/heads/other2 > +' > + > +test_expect_success 'push -u --all' ' > +       git branch all1 && > +       git branch all2 && > +       git push -u --all && > +       check_config all1 upstream refs/heads/all1 && > +       check_config all2 upstream refs/heads/all2 > +' > + > +test_expect_success 'push -u HEAD' ' > +       git checkout -b headbranch && > +       git push -u upstream HEAD && > +       check_config headbranch upstream refs/heads/headbranch > +' > + > +test_done > diff --git a/transport.c b/transport.c > index b5332c0..e5b462b 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,47 @@ static void insert_packed_refs(const char *packed_refs, struct ref **list) >        } >  } > > +static void set_upstreams(struct transport *trans, struct ref *refs) > +{ > +       struct ref *i; > +       for (i = refs; i; i = i->next) { > +               const char *localname; > +               const char *tmp; > +               const char *remotename; > +               unsigned char sha[20]; > +               int flag = 0; > +               /* > +                * Check suitability for tracking. Must be successful / > +                * alreay up-to-date ref create/modify (not delete). > +                */ > +               if (i->status != REF_STATUS_OK && > +                       i->status != REF_STATUS_UPTODATE) > +                       continue; > +               if (!i->peer_ref) > +                       continue; > +               if (!i->new_sha1 || is_null_sha1(i->new_sha1)) > +                       continue; > + > +               /* Chase symbolic refs (mainly for HEAD). */ > +               localname = i->peer_ref->name; > +               remotename = i->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; > + > +               install_branch_config(BRANCH_CONFIG_VERBOSE, > +                       localname + 11, trans->remote->name, > +                       remotename); > +       } > +} > + >  static const char *rsync_url(const char *url) >  { >        return prefixcmp(url, "rsync://") ? skip_prefix(url, "rsync:") : url; > @@ -974,6 +1016,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 = > @@ -1002,6 +1048,9 @@ int transport_push(struct transport *transport, >                                        verbose | porcelain, porcelain, >                                        nonfastforward); > > +               if (flags & TRANSPORT_PUSH_SET_UPSTREAM) > +                       set_upstreams(transport, remote_refs); > + >                if (!(flags & TRANSPORT_PUSH_DRY_RUN)) { >                        struct ref *ref; >                        for (ref = remote_refs; ref; ref = ref->next) > diff --git a/transport.h b/transport.h > index 97ba251..c4314dd 100644 > --- a/transport.h > +++ b/transport.h > @@ -91,6 +91,7 @@ struct transport { >  #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 *); > -- > 1.6.6.102.gd6f8f.dirty > > -- > To unsubscribe from this list: send the line "unsubscribe git" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at  http://vger.kernel.org/majordomo-info.html >