Re: [PATCH v2] Add push --set-upstream

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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
<ilari.liusvaara@xxxxxxxxxxx> 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 <peff@xxxxxxxx>
> Signed-off-by: Ilari Liusvaara <ilari.liusvaara@xxxxxxxxxxx>
> ---
> Changes from v1:
> - Handle 'git push -u <remote> 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=<git-receive-pack>]
> -          [--repo=<repository>] [-f | --force] [-v | --verbose]
> +          [--repo=<repository>] [-f | --force] [-v | --verbose] [-u | --set-upstream]
>           [<repository> <refspec>...]
>
>  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.<name>.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@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]