[RFC/PATCH] Introduce branch.<name>.pushremote

Subsystems: documentation, the rest

6 messages, 2 authors, 2016-06-15 · open the first message on its own page

[RFC/PATCH] Introduce branch.<name>.pushremote

From: Ramkumar Ramachandra <hidden>
Date: 2016-06-15 22:56:05

This new configuration variable overrides the remote in
`branch.<name>.remote` for pushes.  It is useful in the typical
scenario, where the remote I'm pulling from is not the remote I'm
pushing to.  Although `remote.<name>.pushurl` is similar, it does not
serve the purpose as the URL would lack corresponding remote tracking
branches.

Signed-off-by: Ramkumar Ramachandra <redacted>
---
 This is a first cut.  There's code duplication at the moment, but I'm
 currently trying to figure out which other remote_get() calls to
 replace with pushremote_get().  Comments are welcome.

 I will leave it to future patches to do the following things:
 1. Fix the status output to be more meaningful when pushremote is
 set.  At the moment, I'm thinking statuses like [pull: 4 behind,
 push: 3 ahead] will make sense.
 2. Introduce a remote.pushDefault (peff)
 3. Introduce a remote.default (peff)

 Documentation/config.txt |  6 ++++++
 builtin/push.c           |  2 +-
 remote.c                 | 41 +++++++++++++++++++++++++++++++++++++++++
 remote.h                 |  2 ++
 4 files changed, 50 insertions(+), 1 deletion(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 9b11597..0b3b1f8 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -727,6 +727,12 @@ branch.<name>.remote::
 	remote to fetch from/push to.  It defaults to `origin` if no remote is
 	configured. `origin` is also used if you are not on any branch.
 
+branch.<name>.pushremote::
+	When in branch <name>, it tells 'git push' which remote to
+	push to.  It falls back to `branch.<name>.remote`, and
+	defaults to `origin` if no remote is configured. `origin` is
+	also used if you are not on any branch.
+
 branch.<name>.merge::
 	Defines, together with branch.<name>.remote, the upstream branch
 	for the given branch. It tells 'git fetch'/'git pull'/'git rebase' which
diff --git a/builtin/push.c b/builtin/push.c
index 42b129d..d447a80 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -322,7 +322,7 @@ static int push_with_options(struct transport *transport, int flags)
 static int do_push(const char *repo, int flags)
 {
 	int i, errs;
-	struct remote *remote = remote_get(repo);
+	struct remote *remote = pushremote_get(repo);
 	const char **url;
 	int url_nr;
 
diff --git a/remote.c b/remote.c
index e53a6eb..d6fcfc0 100644
--- a/remote.c
+++ b/remote.c
@@ -48,6 +48,7 @@ static int branches_nr;
 
 static struct branch *current_branch;
 static const char *default_remote_name;
+static const char *pushremote_name;
 static int explicit_default_remote_name;
 
 static struct rewrites rewrites;
@@ -363,6 +364,12 @@ static int handle_config(const char *key, const char *value, void *cb)
 				default_remote_name = branch->remote_name;
 				explicit_default_remote_name = 1;
 			}
+		} else if (!strcmp(subkey, ".pushremote")) {
+			if (!value)
+				return config_error_nonbool(key);
+			branch->pushremote_name = xstrdup(value);
+			if (branch == current_branch)
+				pushremote_name = branch->pushremote_name;
 		} else if (!strcmp(subkey, ".merge")) {
 			if (!value)
 				return config_error_nonbool(key);
@@ -700,6 +707,40 @@ struct remote *remote_get(const char *name)
 	return ret;
 }
 
+struct remote *pushremote_get(const char *name)
+{
+	struct remote *ret;
+	int name_given = 0;
+
+	read_config();
+	if (name)
+		name_given = 1;
+	else {
+		if (pushremote_name) {
+			name = pushremote_name;
+			name_given = 1;
+		} else {
+			name = default_remote_name;
+			name_given = explicit_default_remote_name;
+		}
+	}
+
+	ret = make_remote(name, 0);
+	if (valid_remote_nick(name)) {
+		if (!valid_remote(ret))
+			read_remotes_file(ret);
+		if (!valid_remote(ret))
+			read_branches_file(ret);
+	}
+	if (name_given && !valid_remote(ret))
+		add_url_alias(ret, name);
+	if (!valid_remote(ret))
+		return NULL;
+	ret->fetch = parse_fetch_refspec(ret->fetch_refspec_nr, ret->fetch_refspec);
+	ret->push = parse_push_refspec(ret->push_refspec_nr, ret->push_refspec);
+	return ret;
+}
+
 int remote_is_configured(const char *name)
 {
 	int i;
diff --git a/remote.h b/remote.h
index 251d8fd..aa42ff5 100644
--- a/remote.h
+++ b/remote.h
@@ -51,6 +51,7 @@ struct remote {
 };
 
 struct remote *remote_get(const char *name);
+struct remote *pushremote_get(const char *name);
 int remote_is_configured(const char *name);
 
 typedef int each_remote_fn(struct remote *remote, void *priv);
@@ -130,6 +131,7 @@ struct branch {
 	const char *refname;
 
 	const char *remote_name;
+	const char *pushremote_name;
 	struct remote *remote;
 
 	const char **merge_name;
-- 
1.8.1.2.545.g2f19ada.dirty

Re: [RFC/PATCH] Introduce branch.<name>.pushremote

From: Blind <hidden>
Date: 2016-06-15 22:56:07

If I understand correctly,
in your scenario the branches with branch.<name>.pushremote
will be still included in the $git push <remote> --all?
Are you considering some way to exclude a branch from "push --all"
(branch.<name>.push = always, explicit, never... for example)?
Or maybe, if the branch is already marked as special
with branch.<name>.pushremote,
then it could be logical to push it only when is explicitly specified
on the command line (excluded from --all)?

Thanks,
Blind.

2013/2/8 Ramkumar Ramachandra [off-list ref]:
quoted hunk
This new configuration variable overrides the remote in
`branch.<name>.remote` for pushes.  It is useful in the typical
scenario, where the remote I'm pulling from is not the remote I'm
pushing to.  Although `remote.<name>.pushurl` is similar, it does not
serve the purpose as the URL would lack corresponding remote tracking
branches.

Signed-off-by: Ramkumar Ramachandra <redacted>
---
 This is a first cut.  There's code duplication at the moment, but I'm
 currently trying to figure out which other remote_get() calls to
 replace with pushremote_get().  Comments are welcome.

 I will leave it to future patches to do the following things:
 1. Fix the status output to be more meaningful when pushremote is
 set.  At the moment, I'm thinking statuses like [pull: 4 behind,
 push: 3 ahead] will make sense.
 2. Introduce a remote.pushDefault (peff)
 3. Introduce a remote.default (peff)

 Documentation/config.txt |  6 ++++++
 builtin/push.c           |  2 +-
 remote.c                 | 41 +++++++++++++++++++++++++++++++++++++++++
 remote.h                 |  2 ++
 4 files changed, 50 insertions(+), 1 deletion(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 9b11597..0b3b1f8 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -727,6 +727,12 @@ branch.<name>.remote::
        remote to fetch from/push to.  It defaults to `origin` if no remote is
        configured. `origin` is also used if you are not on any branch.

+branch.<name>.pushremote::
+       When in branch <name>, it tells 'git push' which remote to
+       push to.  It falls back to `branch.<name>.remote`, and
+       defaults to `origin` if no remote is configured. `origin` is
+       also used if you are not on any branch.
+
 branch.<name>.merge::
        Defines, together with branch.<name>.remote, the upstream branch
        for the given branch. It tells 'git fetch'/'git pull'/'git rebase' which
diff --git a/builtin/push.c b/builtin/push.c
index 42b129d..d447a80 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -322,7 +322,7 @@ static int push_with_options(struct transport *transport, int flags)
 static int do_push(const char *repo, int flags)
 {
        int i, errs;
-       struct remote *remote = remote_get(repo);
+       struct remote *remote = pushremote_get(repo);
        const char **url;
        int url_nr;
diff --git a/remote.c b/remote.c
index e53a6eb..d6fcfc0 100644
--- a/remote.c
+++ b/remote.c
@@ -48,6 +48,7 @@ static int branches_nr;

 static struct branch *current_branch;
 static const char *default_remote_name;
+static const char *pushremote_name;
 static int explicit_default_remote_name;

 static struct rewrites rewrites;
@@ -363,6 +364,12 @@ static int handle_config(const char *key, const char *value, void *cb)
                                default_remote_name = branch->remote_name;
                                explicit_default_remote_name = 1;
                        }
+               } else if (!strcmp(subkey, ".pushremote")) {
+                       if (!value)
+                               return config_error_nonbool(key);
+                       branch->pushremote_name = xstrdup(value);
+                       if (branch == current_branch)
+                               pushremote_name = branch->pushremote_name;
                } else if (!strcmp(subkey, ".merge")) {
                        if (!value)
                                return config_error_nonbool(key);
@@ -700,6 +707,40 @@ struct remote *remote_get(const char *name)
        return ret;
 }

+struct remote *pushremote_get(const char *name)
+{
+       struct remote *ret;
+       int name_given = 0;
+
+       read_config();
+       if (name)
+               name_given = 1;
+       else {
+               if (pushremote_name) {
+                       name = pushremote_name;
+                       name_given = 1;
+               } else {
+                       name = default_remote_name;
+                       name_given = explicit_default_remote_name;
+               }
+       }
+
+       ret = make_remote(name, 0);
+       if (valid_remote_nick(name)) {
+               if (!valid_remote(ret))
+                       read_remotes_file(ret);
+               if (!valid_remote(ret))
+                       read_branches_file(ret);
+       }
+       if (name_given && !valid_remote(ret))
+               add_url_alias(ret, name);
+       if (!valid_remote(ret))
+               return NULL;
+       ret->fetch = parse_fetch_refspec(ret->fetch_refspec_nr, ret->fetch_refspec);
+       ret->push = parse_push_refspec(ret->push_refspec_nr, ret->push_refspec);
+       return ret;
+}
+
 int remote_is_configured(const char *name)
 {
        int i;
diff --git a/remote.h b/remote.h
index 251d8fd..aa42ff5 100644
--- a/remote.h
+++ b/remote.h
@@ -51,6 +51,7 @@ struct remote {
 };

 struct remote *remote_get(const char *name);
+struct remote *pushremote_get(const char *name);
 int remote_is_configured(const char *name);

 typedef int each_remote_fn(struct remote *remote, void *priv);
@@ -130,6 +131,7 @@ struct branch {
        const char *refname;

        const char *remote_name;
+       const char *pushremote_name;
        struct remote *remote;

        const char **merge_name;
--
1.8.1.2.545.g2f19ada.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

Re: [RFC/PATCH] Introduce branch.<name>.pushremote

From: Ramkumar Ramachandra <hidden>
Date: 2016-06-15 22:56:12

Blind wrote:
If I understand correctly,
in your scenario the branches with branch.<name>.pushremote
will be still included in the $git push <remote> --all?
Yes, this is correct.
Are you considering some way to exclude a branch from "push --all"
(branch.<name>.push = always, explicit, never... for example)?
No.  I don't see why push.default is limiting.
Or maybe, if the branch is already marked as special
with branch.<name>.pushremote,
then it could be logical to push it only when is explicitly specified
on the command line (excluded from --all)?
Huh?  Why would I treat this as a special case?

Re: [RFC/PATCH] Introduce branch.<name>.pushremote

From: Blind <hidden>
Date: 2016-06-15 22:56:12

2013/2/19 Ramkumar Ramachandra:
No.  I don't see why push.default is limiting.
I just want to find a way to exclude a branch (or infact a group of
branches) from $git push --all.
so when I read your thing, I thought for a second that it could be a
possibility... But seems its not the case.

... or branch.<name>.pushremote can support some kind of a "none" value?

Blind.

Re: [RFC/PATCH] Introduce branch.<name>.pushremote

From: Ramkumar Ramachandra <hidden>
Date: 2016-06-15 22:56:12

Blind wrote:
2013/2/19 Ramkumar Ramachandra:
quoted
No.  I don't see why push.default is limiting.
I just want to find a way to exclude a branch (or infact a group of
branches) from $git push --all.
so when I read your thing, I thought for a second that it could be a
possibility... But seems its not the case.
What is your usecase?  If you have a local branch with the same name
as on the remote, why wouldn't you want to push-to-update it when you
make changes in the branch?  In other words, why doesn't push.default
= matching suffice for most practical purposes.
... or branch.<name>.pushremote can support some kind of a "none" value?
Not a bad idea at all, provided you tell me your usecase.

Re: [RFC/PATCH] Introduce branch.<name>.pushremote

From: Blind <hidden>
Date: 2016-06-15 22:56:12

2013/2/19 Ramkumar Ramachandra:
What is your usecase?  If you have a local branch with the same name
as on the remote, why wouldn't you want to push-to-update it when you
make changes in the branch?  In other words, why doesn't push.default
= matching suffice for most practical purposes.
quoted
... or branch.<name>.pushremote can support some kind of a "none" value?
Not a bad idea at all, provided you tell me your usecase.
The question is infact about branches who are not on the remote.
push.default=matching wouldn't upload the branches which are not there already.
push --all on other hand pushes .. all (as expected :-))...

Its difficult for me to manage quickly, lets say, "news-to-push/*" and
"crazy-ideas/*" branches ...

Blind.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help