All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/6] Default remote
@ 2012-07-11 15:33 marcnarc
  2012-07-11 15:33 ` [PATCH 1/6] Rename remote.c's default_remote_name static variables marcnarc
                   ` (6 more replies)
  0 siblings, 7 replies; 22+ messages in thread
From: marcnarc @ 2012-07-11 15:33 UTC (permalink / raw)
  To: git; +Cc: gitster, Jens.Lehmann, peff, phil.hord

Incorporated feedback on the first version of this series[1], and also added
documentation updates.

Note that the documentation changes include 4 minor grammatical fixes (verb
tenses, added a "the" in a couple fo places).  

I also added Phil's "git push" scenario to patch #2's message, rather than
putting it in the documentation as I'd planned.  Explaining the behavior
change in the commit message felt more natural.

The specific differences from v1 are:

Patch #1 (Rename remote.c's default_remote_name static variables.):
  * Expanded the commit message to explain the choice of
    "effective_remote_name".

Patch #2 (Teach remote.c about the remote.default configuration setting.):
  * Added documentation updates.
  * Commit message now describes change in default "git push" behavior.
  * Moved new remote_get_default_name() and remote_count() functions
    to patch #3.

Patch #3 (Teach "git remote" about remote.default.):
  * (Was patch #4 in v1 of this series.)
  * Documented changes to "git remote".
  * The remote_get_default_name() and remote_count() functions are
    now added to remote.[ch] here, with proper declarations.
  * Added a test to ensure that renaming the "origin" remote still
    properly sets remote.default in repos created with an older
    version of git.

Patch #4 (Teach clone to set remote.default.):
  * (Was patch #3 in v1 of this series.)
  * Commit message now justifies changes to "git clone".

Patches 5 & 6 are unchanged.

		M.

[1] http://thread.gmane.org/gmane.comp.version-control.git/201065

Marc Branchaud (6):
      Rename remote.c's default_remote_name static variables.
      Teach remote.c about the remote.default configuration setting.
      Teach "git remote" about remote.default.
      Teach clone to set remote.default.
      Test that plain "git fetch" uses remote.default when on a detached HEAD.
      Teach get_default_remote to respect remote.default.

 Documentation/config.txt           |  8 ++++
 Documentation/git-pull.txt         |  6 ++-
 Documentation/git-push.txt         |  8 +++-
 Documentation/git-remote.txt       | 32 ++++++++++++++--
 Documentation/pull-fetch-param.txt |  6 +++
 builtin/clone.c                    |  2 +
 builtin/remote.c                   | 29 +++++++++++++++
 git-parse-remote.sh                |  5 +--
 remote.c                           | 34 +++++++++++++----
 remote.h                           |  2 +
 t/t5505-remote.sh                  | 76 ++++++++++++++++++++++++++++++++++++++
 t/t5510-fetch.sh                   | 17 +++++++++
 t/t5512-ls-remote.sh               |  8 +++-
 t/t5528-push-default.sh            |  4 +-
 t/t5601-clone.sh                   | 10 +++++
 t/t5702-clone-options.sh           |  7 +++-
 t/t7400-submodule-basic.sh         | 21 +++++++++++
 17 files changed, 253 insertions(+), 22 deletions(-)

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 1/6] Rename remote.c's default_remote_name static variables.
  2012-07-11 15:33 [PATCH v2 0/6] Default remote marcnarc
@ 2012-07-11 15:33 ` marcnarc
  2012-07-11 15:33 ` [PATCH 2/6] Teach remote.c about the remote.default configuration setting marcnarc
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 22+ messages in thread
From: marcnarc @ 2012-07-11 15:33 UTC (permalink / raw)
  To: git; +Cc: gitster, Jens.Lehmann, peff, phil.hord, Marc Branchaud

From: Marc Branchaud <marcnarc@xiplink.com>

This prepares the code to handle a true remote.default configuration value.

Rename two variables:
  default_remote_name          --> effective_remote_name
  explicit_default_remote_name --> explicit_effective_remote_name

effective_remote_name is the remote name that is currently "in effect".
This is the currently checked-out branch's remote (in which case
explicit_effective_remote_name=1), or "origin" if the branch has no remote
(or the working tree is a detached HEAD).

The next commit re-introduces default_remote_name with its new semantics.

Signed-off-by: Marc Branchaud <marcnarc@xiplink.com>
---
 remote.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/remote.c b/remote.c
index 6833538..6f371e0 100644
--- a/remote.c
+++ b/remote.c
@@ -47,8 +47,8 @@ static int branches_alloc;
 static int branches_nr;
 
 static struct branch *current_branch;
-static const char *default_remote_name;
-static int explicit_default_remote_name;
+static const char *effective_remote_name;
+static int explicit_effective_remote_name;
 
 static struct rewrites rewrites;
 static struct rewrites rewrites_push;
@@ -360,8 +360,8 @@ static int handle_config(const char *key, const char *value, void *cb)
 				return config_error_nonbool(key);
 			branch->remote_name = xstrdup(value);
 			if (branch == current_branch) {
-				default_remote_name = branch->remote_name;
-				explicit_default_remote_name = 1;
+				effective_remote_name = branch->remote_name;
+				explicit_effective_remote_name = 1;
 			}
 		} else if (!strcmp(subkey, ".merge")) {
 			if (!value)
@@ -481,9 +481,9 @@ static void read_config(void)
 	unsigned char sha1[20];
 	const char *head_ref;
 	int flag;
-	if (default_remote_name) /* did this already */
+	if (effective_remote_name) /* did this already */
 		return;
-	default_remote_name = xstrdup("origin");
+	effective_remote_name = xstrdup("origin");
 	current_branch = NULL;
 	head_ref = resolve_ref_unsafe("HEAD", sha1, 0, &flag);
 	if (head_ref && (flag & REF_ISSYMREF) &&
@@ -680,8 +680,8 @@ struct remote *remote_get(const char *name)
 	if (name)
 		name_given = 1;
 	else {
-		name = default_remote_name;
-		name_given = explicit_default_remote_name;
+		name = effective_remote_name;
+		name_given = explicit_effective_remote_name;
 	}
 
 	ret = make_remote(name, 0);
-- 
1.7.11.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 2/6] Teach remote.c about the remote.default configuration setting.
  2012-07-11 15:33 [PATCH v2 0/6] Default remote marcnarc
  2012-07-11 15:33 ` [PATCH 1/6] Rename remote.c's default_remote_name static variables marcnarc
@ 2012-07-11 15:33 ` marcnarc
  2012-07-11 18:21   ` Junio C Hamano
  2012-07-11 15:33 ` [PATCH 3/6] Teach "git remote" about remote.default marcnarc
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 22+ messages in thread
From: marcnarc @ 2012-07-11 15:33 UTC (permalink / raw)
  To: git; +Cc: gitster, Jens.Lehmann, peff, phil.hord, Marc Branchaud

From: Marc Branchaud <marcnarc@xiplink.com>

The code now has a default_remote_name and an effective_remote_name:

 - default_remote_name is set by remote.default in the config, or is "origin"
   if remote.default doesn't exist ("origin" was the fallback value before
   this change).

 - effective_remote_name is the name of the remote tracked by the current
   branch, or is default_remote_name if the current branch doesn't have a
   remote.

This has a minor side effect on the default behavior of "git push".  Consider
the following sequence of commands:

      git config remote.default foo                 # Set default remote
      git checkout somelocalbranch                  # Does not track a remote
      git remote add origin ssh://example.com/repo  # Add a new "origin"
      git push

Prior to this change, the above "git push" would attempt to push to the new
"origin" repository at ssh://example.com/repo.  Now instead that "git push"
will attempt to push to the repository named "foo".

Signed-off-by: Marc Branchaud <marcnarc@xiplink.com>
---
 Documentation/config.txt           |  8 ++++++++
 Documentation/git-pull.txt         |  6 +++++-
 Documentation/git-push.txt         |  8 +++++++-
 Documentation/pull-fetch-param.txt |  6 ++++++
 remote.c                           | 14 +++++++++++---
 5 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 915cb5a..7869e1b 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1856,6 +1856,14 @@ remote.<name>.vcs::
 	Setting this to a value <vcs> will cause git to interact with
 	the remote with the git-remote-<vcs> helper.
 
+remote.default::
+	This value is the <name> of a remote.  When Git needs to automatically
+	choose a remote to use, it first tries the 'branch.<branchname>.remote'
+	value of the currently checked-out branch.  If the currently checked-out
+	branch has no remote, Git uses the remote named by 'remote.default', or
+	the remote named "origin" if no value is set (even if there is no
+	actual remote named "origin").
+
 remotes.<group>::
 	The list of remotes which are fetched by "git remote update
 	<group>".  See linkgit:git-remote[1].
diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt
index defb544..2610253 100644
--- a/Documentation/git-pull.txt
+++ b/Documentation/git-pull.txt
@@ -33,7 +33,11 @@ but usually it is the name of a branch in the remote repository.
 
 Default values for <repository> and <branch> are read from the
 "remote" and "merge" configuration for the current branch
-as set by linkgit:git-branch[1] `--track`.
+as set by linkgit:git-branch[1] `--track`.  If the current branch
+has no remote configured, the default for <repository> is read
+from the "remote.default" configuration variable.  If that variable
+is not set, the default <repository> is "origin" even if there is no
+actual remote named "origin".
 
 Assume the following history exists and the current branch is
 "`master`":
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index cb97cc1..fc17d39 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -27,10 +27,16 @@ documentation for linkgit:git-receive-pack[1].
 OPTIONS[[OPTIONS]]
 ------------------
 <repository>::
-	The "remote" repository that is destination of a push
+	The "remote" repository that is the destination of the push
 	operation.  This parameter can be either a URL
 	(see the section <<URLS,GIT URLS>> below) or the name
 	of a remote (see the section <<REMOTES,REMOTES>> below).
+	If this parameter is omitted, git tries to use the remote
+	associated with the currently checked-out branch.  If there
+	is no remote associated with the current branch, git uses
+	the remote named by the "remote.default" configuration variable.
+	If "remote.default" is not set, git uses the name "origin" even
+	if there is no actual remote named "origin".
 
 <refspec>...::
 	The format of a <refspec> parameter is an optional plus
diff --git a/Documentation/pull-fetch-param.txt b/Documentation/pull-fetch-param.txt
index 94a9d32..696f1fb 100644
--- a/Documentation/pull-fetch-param.txt
+++ b/Documentation/pull-fetch-param.txt
@@ -3,6 +3,12 @@
 	or pull operation.  This parameter can be either a URL
 	(see the section <<URLS,GIT URLS>> below) or the name
 	of a remote (see the section <<REMOTES,REMOTES>> below).
+	If this parameter is omitted, git tries to use the remote
+	associated with the currently checked-out branch.  If there
+	is no remote associated with the current branch, git uses
+	the remote named by the "remote.default" configuration variable.
+	If "remote.default" is not set, git uses the name "origin" even
+	if there is no actual remote named "origin".
 
 ifndef::git-pull[]
 <group>::
diff --git a/remote.c b/remote.c
index 6f371e0..2ebdbbd 100644
--- a/remote.c
+++ b/remote.c
@@ -47,6 +47,7 @@ static int branches_alloc;
 static int branches_nr;
 
 static struct branch *current_branch;
+static const char *default_remote_name;
 static const char *effective_remote_name;
 static int explicit_effective_remote_name;
 
@@ -397,8 +398,12 @@ static int handle_config(const char *key, const char *value, void *cb)
 		return 0;
 	}
 	subkey = strrchr(name, '.');
-	if (!subkey)
+	if (!subkey) {
+		/* Look for remote.default */
+		if (!strcmp(name, "default"))
+			default_remote_name = xstrdup(value);
 		return 0;
+	}
 	remote = make_remote(name, subkey - name);
 	remote->origin = REMOTE_CONFIG;
 	if (!strcmp(subkey, ".mirror"))
@@ -481,9 +486,8 @@ static void read_config(void)
 	unsigned char sha1[20];
 	const char *head_ref;
 	int flag;
-	if (effective_remote_name) /* did this already */
+	if (default_remote_name) /* did this already */
 		return;
-	effective_remote_name = xstrdup("origin");
 	current_branch = NULL;
 	head_ref = resolve_ref_unsafe("HEAD", sha1, 0, &flag);
 	if (head_ref && (flag & REF_ISSYMREF) &&
@@ -492,6 +496,10 @@ static void read_config(void)
 			make_branch(head_ref + strlen("refs/heads/"), 0);
 	}
 	git_config(handle_config, NULL);
+	if (!default_remote_name)
+		default_remote_name = "origin";
+	if (!effective_remote_name)
+		effective_remote_name = default_remote_name;
 	alias_all_urls();
 }
 
-- 
1.7.11.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 3/6] Teach "git remote" about remote.default.
  2012-07-11 15:33 [PATCH v2 0/6] Default remote marcnarc
  2012-07-11 15:33 ` [PATCH 1/6] Rename remote.c's default_remote_name static variables marcnarc
  2012-07-11 15:33 ` [PATCH 2/6] Teach remote.c about the remote.default configuration setting marcnarc
@ 2012-07-11 15:33 ` marcnarc
  2012-07-11 18:27   ` Junio C Hamano
  2012-07-11 15:33 ` [PATCH 4/6] Teach clone to set remote.default marcnarc
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 22+ messages in thread
From: marcnarc @ 2012-07-11 15:33 UTC (permalink / raw)
  To: git; +Cc: gitster, Jens.Lehmann, peff, phil.hord, Marc Branchaud

From: Marc Branchaud <marcnarc@xiplink.com>

The "rename" and "rm" commands now handle the case where the remote being
changed is the default remote.

If the "add" command is used to add the repo's first remote, that remote
becomes the default remote.

Also introduce a "default" sub-command to get or set the default remote:

 - "git remote default" (with no parameter) displays the current default remote.

 - "git remote default <remo>" checks if <remo> is a configured remote and if
   so changes remote.default to <remo>.

These changes needed a couple of new helper functions in remote.c:
 - remote_get_default_name() returns default_remote_name.
 - remote_count() returns the number of remotes.

(The test in t5528 had to be changed because now with push.default=matching
a plain "git push" succeeds with "Everything up-to-date".  It used to
fail with "No configured push destination".)

Signed-off-by: Marc Branchaud <marcnarc@xiplink.com>
---
 Documentation/git-remote.txt | 32 ++++++++++++++++---
 builtin/remote.c             | 29 +++++++++++++++++
 remote.c                     | 12 +++++++
 remote.h                     |  2 ++
 t/t5505-remote.sh            | 76 ++++++++++++++++++++++++++++++++++++++++++++
 t/t5512-ls-remote.sh         |  8 ++++-
 t/t5528-push-default.sh      |  4 +--
 7 files changed, 156 insertions(+), 7 deletions(-)

diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt
index a308f4c..f4de21d 100644
--- a/Documentation/git-remote.txt
+++ b/Documentation/git-remote.txt
@@ -11,6 +11,7 @@ SYNOPSIS
 [verse]
 'git remote' [-v | --verbose]
 'git remote add' [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--mirror=<fetch|push>] <name> <url>
+'git remote default' [<name>]
 'git remote rename' <old> <new>
 'git remote rm' <name>
 'git remote set-head' <name> (-a | -d | <branch>)
@@ -75,20 +76,43 @@ because a fetch would overwrite any local commits.
 +
 When a push mirror is created with `--mirror=push`, then `git push`
 will always behave as if `--mirror` was passed.
++
+When the first remote is added to a repository, it becomes the repository's
+default remote.
+
+'default'::
+
+Displays or sets the name of the repository's default remote.  When git needs
+to automatically choose a remote to use, it first tries to use the remote
+associated with the currently checked-out branch.  If the currently
+checked-out branch has no remote, git uses the repository's default remote.
+If the repository has no default remote, git tries to use a remote named
+"origin" even if there is no actual remote named "origin".  (In other words,
+the default value for the default remote name is "origin".)
++
+With no <name> parameter, displays the current default remote name.
++
+With the <name> parameter, sets the repository's default remote to <name>.
 
 'rename'::
 
-Rename the remote named <old> to <new>. All remote-tracking branches and
+Renames the remote named <old> to <new>. All remote-tracking branches and
 configuration settings for the remote are updated.
 +
 In case <old> and <new> are the same, and <old> is a file under
 `$GIT_DIR/remotes` or `$GIT_DIR/branches`, the remote is converted to
 the configuration file format.
++
+If <old> was the repository's default remote name, the default remote name
+changes to <new>.
 
 'rm'::
 
-Remove the remote named <name>. All remote-tracking branches and
-configuration settings for the remote are removed.
+Removes the remote named <name>. All remote-tracking branches and
+configuration settings for the remote are removed.  If the remote was
+the repository's default remote, then the repository's default remote
+name is changed to "origin".  Use 'git remote default <name>' to set
+the repository's default remote name.
 
 'set-head'::
 
@@ -160,7 +184,7 @@ actually prune them.
 
 'update'::
 
-Fetch updates for a named set of remotes in the repository as defined by
+Fetches updates for a named set of remotes in the repository as defined by
 remotes.<group>.  If a named group is not specified on the command line,
 the configuration parameter remotes.default will be used; if
 remotes.default is not defined, all remotes which do not have the
diff --git a/builtin/remote.c b/builtin/remote.c
index 920262d..1fb272c 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -12,6 +12,7 @@ static const char * const builtin_remote_usage[] = {
 	"git remote add [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--mirror=<fetch|push>] <name> <url>",
 	"git remote rename <old> <new>",
 	"git remote rm <name>",
+	"git remote default [<name>]",
 	"git remote set-head <name> (-a | -d | <branch>)",
 	"git remote [-v | --verbose] show [-n] <name>",
 	"git remote prune [-n | --dry-run] <name>",
@@ -198,6 +199,9 @@ static int add(int argc, const char **argv)
 	if (!valid_fetch_refspec(buf2.buf))
 		die(_("'%s' is not a valid remote name"), name);
 
+	if (remote_count() == 1) /* remote_get() adds a remote if it's new */
+		git_config_set("remote.default", name);
+
 	strbuf_addf(&buf, "remote.%s.url", name);
 	if (git_config_set(buf.buf, url))
 		return 1;
@@ -656,6 +660,10 @@ static int mv(int argc, const char **argv)
 		return error(_("Could not rename config section '%s' to '%s'"),
 				buf.buf, buf2.buf);
 
+	if (!strcmp(oldremote->name, remote_get_default_name())) {
+		git_config_set("remote.default", newremote->name);
+	}
+
 	strbuf_reset(&buf);
 	strbuf_addf(&buf, "remote.%s.fetch", rename.new);
 	if (git_config_set_multivar(buf.buf, NULL, NULL, 1))
@@ -798,6 +806,10 @@ static int rm(int argc, const char **argv)
 	if (git_config_rename_section(buf.buf, NULL) < 1)
 		return error(_("Could not remove config section '%s'"), buf.buf);
 
+	if (!strcmp(remote->name, remote_get_default_name())) {
+		git_config_set("remote.default", NULL);
+	}
+
 	read_branches();
 	for (i = 0; i < branch_list.nr; i++) {
 		struct string_list_item *item = branch_list.items + i;
@@ -845,6 +857,21 @@ static int rm(int argc, const char **argv)
 	return result;
 }
 
+static int deflt(int argc, const char **argv)
+{
+	if (argc < 2)
+		printf_ln("%s", remote_get_default_name());
+	else {
+		const char *name = argv[1];
+		if (remote_is_configured(name)) {
+			git_config_set("remote.default", name);
+			printf_ln(_("Default remote set to '%s'."), name);
+		} else
+			return error(_("No remote named '%s'."), name);
+	}
+	return 0;
+}
+
 static void clear_push_info(void *util, const char *string)
 {
 	struct push_info *info = util;
@@ -1582,6 +1609,8 @@ int cmd_remote(int argc, const char **argv, const char *prefix)
 		result = mv(argc, argv);
 	else if (!strcmp(argv[0], "rm"))
 		result = rm(argc, argv);
+	else if (!strcmp(argv[0], "default"))
+		result = deflt(argc, argv);
 	else if (!strcmp(argv[0], "set-head"))
 		result = set_head(argc, argv);
 	else if (!strcmp(argv[0], "set-branches"))
diff --git a/remote.c b/remote.c
index 2ebdbbd..8d9e8a8 100644
--- a/remote.c
+++ b/remote.c
@@ -679,6 +679,18 @@ static int valid_remote_nick(const char *name)
 	return !strchr(name, '/'); /* no slash */
 }
 
+const char *remote_get_default_name(void)
+{
+	read_config();
+	return default_remote_name;
+}
+
+int remote_count(void)
+{
+	read_config();
+	return remotes_nr;
+}
+
 struct remote *remote_get(const char *name)
 {
 	struct remote *ret;
diff --git a/remote.h b/remote.h
index 251d8fd..c8c54e8 100644
--- a/remote.h
+++ b/remote.h
@@ -52,6 +52,8 @@ struct remote {
 
 struct remote *remote_get(const char *name);
 int remote_is_configured(const char *name);
+const char *remote_get_default_name(void);
+int remote_count(void);
 
 typedef int each_remote_fn(struct remote *remote, void *priv);
 int for_each_remote(each_remote_fn fn, void *priv);
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index e8af615..0027a82 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -77,6 +77,15 @@ test_expect_success 'add another remote' '
 )
 '
 
+test_expect_success 'add first remote sets default' '
+(
+	test_create_repo default-first-remote &&
+	cd default-first-remote &&
+	git remote add first /path/to/first &&
+	test "$(git config --get remote.default)" = first
+)
+'
+
 test_expect_success 'remote forces tracking branches' '
 (
 	cd test &&
@@ -107,6 +116,16 @@ test_expect_success 'remove remote' '
 )
 '
 
+test_expect_success 'remove default remote' '
+(
+	git clone one no-default
+	cd no-default &&
+	test "$(git config --get remote.default)" = origin   # Sanity check
+	git remote rm origin &&
+	test_must_fail git config --get remote.default
+)
+'
+
 test_expect_success 'remove remote protects local branches' '
 (
 	cd test &&
@@ -662,6 +681,28 @@ test_expect_success 'rename a remote with name prefix of other remote' '
 
 '
 
+test_expect_success 'rename the default remote' '
+	git clone one default-rename &&
+	(cd default-rename &&
+		test "$(git config --get remote.default)" = origin   # Sanity?
+		git remote rename origin tyrion
+		test "$(git config --get remote.default)" = tyrion
+	)
+
+'
+
+# This test ensures that repos created wth an older version of git and that
+# have a remote named "origin" get remote.default updated properly.
+test_expect_success 'rename the "origin" remote if remote.default is not set' '
+	git clone one default-oldschool &&
+	(cd default-oldschool &&
+		git config --unset remote.default
+		git remote rename origin stark
+		test "$(git config --get remote.default)" = stark
+	)
+'
+
+
 cat > remotes_origin << EOF
 URL: $(pwd)/one
 Push: refs/heads/master:refs/heads/upstream
@@ -997,4 +1038,39 @@ test_expect_success 'remote set-url --delete baz' '
 	cmp expect actual
 '
 
+test_expect_success 'remote default' '
+(
+	git clone -o up one default
+	cd default &&
+	test "$(git remote default)" = up
+)
+'
+
+test_expect_success 'remote default (none)' '
+(
+	test_create_repo default-none &&
+	cd default-none &&
+	test "$(git remote default)" = origin
+)
+'
+
+test_expect_success 'remote default set' '
+(
+	test_create_repo default-set &&
+	cd default-set &&
+	git remote add A /foo-A &&
+	git remote add B /foo-A &&
+	git remote default B &&
+	test "$(git remote default)" = B
+)
+'
+
+test_expect_success 'remote default bad' '
+(
+	git clone one default-bad &&
+	cd default-bad &&
+	test_must_fail git remote default NonExistant
+)
+'
+
 test_done
diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh
index 6764d51..853b045 100755
--- a/t/t5512-ls-remote.sh
+++ b/t/t5512-ls-remote.sh
@@ -40,7 +40,13 @@ test_expect_success 'ls-remote self' '
 '
 
 test_expect_success 'dies when no remote specified and no default remotes found' '
-	test_must_fail git ls-remote
+	test_create_repo no-remotes &&
+	(
+		cd no-remotes &&
+		test_must_fail git ls-remote &&
+		test_config remote.default blop &&
+		test_must_fail git ls-remote
+	)
 '
 
 test_expect_success 'use "origin" when no remote specified' '
diff --git a/t/t5528-push-default.sh b/t/t5528-push-default.sh
index 4736da8..6a08998 100755
--- a/t/t5528-push-default.sh
+++ b/t/t5528-push-default.sh
@@ -71,10 +71,10 @@ test_expect_success '"upstream" does not push when remotes do not match' '
 	test_must_fail git push parent2
 '
 
-test_expect_success 'push from/to new branch with upstream, matching and simple' '
+test_expect_success 'push from/to new remoteless branch with upstream, matching and simple' '
 	git checkout -b new-branch &&
 	test_push_failure simple &&
-	test_push_failure matching &&
+	test_push_success matching master &&
 	test_push_failure upstream
 '
 
-- 
1.7.11.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 4/6] Teach clone to set remote.default.
  2012-07-11 15:33 [PATCH v2 0/6] Default remote marcnarc
                   ` (2 preceding siblings ...)
  2012-07-11 15:33 ` [PATCH 3/6] Teach "git remote" about remote.default marcnarc
@ 2012-07-11 15:33 ` marcnarc
  2012-07-11 15:34 ` [PATCH 5/6] Test that plain "git fetch" uses remote.default when on a detached HEAD marcnarc
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 22+ messages in thread
From: marcnarc @ 2012-07-11 15:33 UTC (permalink / raw)
  To: git; +Cc: gitster, Jens.Lehmann, peff, phil.hord, Marc Branchaud

From: Marc Branchaud <marcnarc@xiplink.com>

This makes git-clone consistent with the remote.default support implemented in
git-remote.  Specifically, since "git remote add" sets remote.default if
it's adding the first remote to the repository, when clone itself adds the
first remote it should do the same.

This also makes "git clone -o" work without a special case in the code (so
"git clone /some/repo" and "git clone -o origin /some/repo" produce the same
result).

Signed-off-by: Marc Branchaud <marcnarc@xiplink.com>
---
 builtin/clone.c          |  2 ++
 t/t5601-clone.sh         | 10 ++++++++++
 t/t5702-clone-options.sh |  7 +++++--
 3 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index a4d8d25..b198456 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -770,6 +770,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	git_config_set(key.buf, repo);
 	strbuf_reset(&key);
 
+	git_config_set("remote.default", option_origin);
+
 	if (option_reference.nr)
 		setup_reference();
 
diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index 67869b4..046610d 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -57,6 +57,16 @@ test_expect_success 'clone checks out files' '
 
 '
 
+test_expect_success 'clone sets remote.default' '
+
+	rm -fr dst &&
+	git clone src dst &&
+	(
+		cd dst &&
+		test "$(git config --get remote.default)" = origin
+	)
+'
+
 test_expect_success 'clone respects GIT_WORK_TREE' '
 
 	GIT_WORK_TREE=worktree git clone src bare &&
diff --git a/t/t5702-clone-options.sh b/t/t5702-clone-options.sh
index 02cb024..9e573dd 100755
--- a/t/t5702-clone-options.sh
+++ b/t/t5702-clone-options.sh
@@ -15,8 +15,11 @@ test_expect_success 'setup' '
 test_expect_success 'clone -o' '
 
 	git clone -o foo parent clone-o &&
-	(cd clone-o && git rev-parse --verify refs/remotes/foo/master)
-
+	(
+		cd clone-o &&
+		git rev-parse --verify refs/remotes/foo/master &&
+		test "$(git config --get remote.default)" = foo
+	)
 '
 
 test_expect_success 'redirected clone' '
-- 
1.7.11.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 5/6] Test that plain "git fetch" uses remote.default when on a detached HEAD.
  2012-07-11 15:33 [PATCH v2 0/6] Default remote marcnarc
                   ` (3 preceding siblings ...)
  2012-07-11 15:33 ` [PATCH 4/6] Teach clone to set remote.default marcnarc
@ 2012-07-11 15:34 ` marcnarc
  2012-07-11 15:34 ` [PATCH 6/6] Teach get_default_remote to respect remote.default marcnarc
  2012-07-11 18:19 ` [PATCH v2 0/6] Default remote Junio C Hamano
  6 siblings, 0 replies; 22+ messages in thread
From: marcnarc @ 2012-07-11 15:34 UTC (permalink / raw)
  To: git; +Cc: gitster, Jens.Lehmann, peff, phil.hord, Marc Branchaud

From: Marc Branchaud <marcnarc@xiplink.com>

Signed-off-by: Marc Branchaud <marcnarc@xiplink.com>
---
 t/t5510-fetch.sh | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index d7a19a1..8ecd996 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -69,6 +69,23 @@ test_expect_success "fetch test" '
 	test "z$mine" = "z$his"
 '
 
+test_expect_success "fetch test detached HEAD uses default remote" '
+	cd "$D" &&
+	git clone -o foo . default-remote &&
+	git checkout -b detached &&
+	test_commit update1 &&
+	(
+		cd default-remote &&
+		git checkout HEAD@{0} &&
+		git fetch &&
+		test -f .git/refs/remotes/foo/detached &&
+		mine=`git rev-parse refs/remotes/foo/detached` &&
+		his=`cd .. && git rev-parse refs/heads/detached` &&
+		test "z$mine" = "z$his"
+	) &&
+	git checkout master
+'
+
 test_expect_success "fetch test for-merge" '
 	cd "$D" &&
 	cd three &&
-- 
1.7.11.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 6/6] Teach get_default_remote to respect remote.default.
  2012-07-11 15:33 [PATCH v2 0/6] Default remote marcnarc
                   ` (4 preceding siblings ...)
  2012-07-11 15:34 ` [PATCH 5/6] Test that plain "git fetch" uses remote.default when on a detached HEAD marcnarc
@ 2012-07-11 15:34 ` marcnarc
  2012-07-11 18:19 ` [PATCH v2 0/6] Default remote Junio C Hamano
  6 siblings, 0 replies; 22+ messages in thread
From: marcnarc @ 2012-07-11 15:34 UTC (permalink / raw)
  To: git; +Cc: gitster, Jens.Lehmann, peff, phil.hord, Marc Branchaud

From: Marc Branchaud <marcnarc@xiplink.com>

Use "git remote default" instead of replicating its logic.

The unit test checks a relative-path submodule because the submodule code
is (almost) the only thing that uses get_default_remote.

Signed-off-by: Marc Branchaud <marcnarc@xiplink.com>
---
 git-parse-remote.sh        |  5 +----
 t/t7400-submodule-basic.sh | 21 +++++++++++++++++++++
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/git-parse-remote.sh b/git-parse-remote.sh
index 484b2e6..49257f0 100644
--- a/git-parse-remote.sh
+++ b/git-parse-remote.sh
@@ -5,10 +5,7 @@
 GIT_DIR=$(git rev-parse -q --git-dir) || :;
 
 get_default_remote () {
-	curr_branch=$(git symbolic-ref -q HEAD)
-	curr_branch="${curr_branch#refs/heads/}"
-	origin=$(git config --get "branch.$curr_branch.remote")
-	echo ${origin:-origin}
+	echo $(git remote default)
 }
 
 get_remote_merge_branch () {
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index 81827e6..2ac2ffc 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -507,6 +507,27 @@ test_expect_success 'relative path works with user@host:path' '
 	)
 '
 
+test_expect_success 'realtive path works when superproject on detached HEAD' '
+	(
+		test_create_repo detach &&
+		cd detach &&
+		test_create_repo sub &&
+		(
+			cd sub &&
+			test_commit foo
+		) &&
+		git add sub &&
+		git commit -m "added sub" &&
+		rm -rf sub &&
+		git checkout HEAD@{0} &&
+		git config -f .gitmodules submodule.sub.path sub &&
+		git config -f .gitmodules submodule.sub.url ../subrepo &&
+		git remote add awkward /path/to/awkward
+		git submodule init sub &&
+		test "$(git config submodule.sub.url)" = /path/to/subrepo
+	)
+'
+
 test_expect_success 'moving the superproject does not break submodules' '
 	(
 		cd addtest &&
-- 
1.7.11.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH v2 0/6] Default remote
  2012-07-11 15:33 [PATCH v2 0/6] Default remote marcnarc
                   ` (5 preceding siblings ...)
  2012-07-11 15:34 ` [PATCH 6/6] Teach get_default_remote to respect remote.default marcnarc
@ 2012-07-11 18:19 ` Junio C Hamano
  6 siblings, 0 replies; 22+ messages in thread
From: Junio C Hamano @ 2012-07-11 18:19 UTC (permalink / raw)
  To: marcnarc; +Cc: git, Jens.Lehmann, peff, phil.hord

marcnarc@xiplink.com writes:

> Incorporated feedback on the first version of this series[1], and also added
> documentation updates.
>
> Note that the documentation changes include 4 minor grammatical fixes (verb
> tenses, added a "the" in a couple fo places).  
> ...
> Patches 5 & 6 are unchanged.

Very nicely written summary that describes incremental changes.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 2/6] Teach remote.c about the remote.default configuration setting.
  2012-07-11 15:33 ` [PATCH 2/6] Teach remote.c about the remote.default configuration setting marcnarc
@ 2012-07-11 18:21   ` Junio C Hamano
  2012-07-11 20:41     ` Marc Branchaud
  0 siblings, 1 reply; 22+ messages in thread
From: Junio C Hamano @ 2012-07-11 18:21 UTC (permalink / raw)
  To: marcnarc; +Cc: git, Jens.Lehmann, peff, phil.hord

marcnarc@xiplink.com writes:

> From: Marc Branchaud <marcnarc@xiplink.com>
>
> The code now has a default_remote_name and an effective_remote_name:
>
>  - default_remote_name is set by remote.default in the config, or is "origin"
>    if remote.default doesn't exist ("origin" was the fallback value before
>    this change).
>
>  - effective_remote_name is the name of the remote tracked by the current
>    branch, or is default_remote_name if the current branch doesn't have a
>    remote.
>
> This has a minor side effect on the default behavior of "git push".  Consider
> the following sequence of commands:
>
>       git config remote.default foo                 # Set default remote
>       git checkout somelocalbranch                  # Does not track a remote
>       git remote add origin ssh://example.com/repo  # Add a new "origin"
>       git push
>
> Prior to this change, the above "git push" would attempt to push to the new
> "origin" repository at ssh://example.com/repo.  Now instead that "git push"
> will attempt to push to the repository named "foo".

Hrm, is this a _minor_ side effect?

Isn't that a natural and direct consequence of "now you can set
remote.default configuration to name the remote you want to use in
place of traditional 'origin'" feature?  I think changing the
behaviour of "git push" in such a way is the point (may not be the
only but one of the important points) of this series.

> diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
> index cb97cc1..fc17d39 100644
> --- a/Documentation/git-push.txt
> +++ b/Documentation/git-push.txt
> @@ -27,10 +27,16 @@ documentation for linkgit:git-receive-pack[1].
>  OPTIONS[[OPTIONS]]
>  ------------------
>  <repository>::
> -	The "remote" repository that is destination of a push
> +	The "remote" repository that is the destination of the push
>  	operation.  This parameter can be either a URL
>  	(see the section <<URLS,GIT URLS>> below) or the name
>  	of a remote (see the section <<REMOTES,REMOTES>> below).
> +	If this parameter is omitted, git tries to use the remote
> +	associated with the currently checked-out branch.  If there
> +	is no remote associated with the current branch, git uses
> +	the remote named by the "remote.default" configuration variable.
> +	If "remote.default" is not set, git uses the name "origin" even
> +	if there is no actual remote named "origin".

This comment applies to other changes to the documentation in this
patch I didn't quote, but I think the phrasing 'even if there is no
acutual remote named "origin"' needs to be rethought, because "we
use it even if there is no such remote determined with this logic"
applies equally to branch.$name.remote, remote.default or built-in
default value of remote.default which happens to be "origin".

> diff --git a/remote.c b/remote.c
> index 6f371e0..2ebdbbd 100644
> --- a/remote.c
> +++ b/remote.c
> @@ -47,6 +47,7 @@ static int branches_alloc;
>  static int branches_nr;
>  
>  static struct branch *current_branch;
> +static const char *default_remote_name;
>  static const char *effective_remote_name;

Coming from UNIX background, "effective" gives me an impression that
it is contrasted with "real" (i.e. there is "real remote" for the
branch, but during this particular invocation it is overridden and
"effective remote" is used instead).  Perhaps it is just me.

Something along the line of remote-name-to-use, use-remote, might
sound more natural.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 3/6] Teach "git remote" about remote.default.
  2012-07-11 15:33 ` [PATCH 3/6] Teach "git remote" about remote.default marcnarc
@ 2012-07-11 18:27   ` Junio C Hamano
  2012-07-11 20:41     ` Marc Branchaud
  0 siblings, 1 reply; 22+ messages in thread
From: Junio C Hamano @ 2012-07-11 18:27 UTC (permalink / raw)
  To: marcnarc; +Cc: git, Jens.Lehmann, peff, phil.hord

marcnarc@xiplink.com writes:

> From: Marc Branchaud <marcnarc@xiplink.com>
>
> The "rename" and "rm" commands now handle the case where the remote being
> changed is the default remote.

"handle the case" is way underspecified.

Until I peeked the patch, I couldn't tell if you were now allowing
"git remote rm" that does not say which remote to remove the remote
named via remote.default by default, and had to wonder if you made
"git remote rename frotz" without any other argument mean "git
remote rename <remote.default> frotz" or the other way around.

        The "rename" and "rm" commands adjusts the value of the
        remote.default variable when they make the current default
        remote disappear.

> If the "add" command is used to add the repo's first remote, that remote
> becomes the default remote.

Probably sensible, but I could easily imagine existing users to be
surprised, harmed and complain, especially now those who want this
behaviour already have a separate "remote default" command to set it
themselves.

> Also introduce a "default" sub-command to get or set the default remote:
>
>  - "git remote default" (with no parameter) displays the current default remote.
>
>  - "git remote default <remo>" checks if <remo> is a configured remote and if
>    so changes remote.default to <remo>.

Avoid cute and not-widely-used abbreviation; in other words s/<remo>/<remote>/.

> These changes needed a couple of new helper functions in remote.c:
>  - remote_get_default_name() returns default_remote_name.
>  - remote_count() returns the number of remotes.
>
> (The test in t5528 had to be changed because now with push.default=matching
> a plain "git push" succeeds with "Everything up-to-date".  It used to
> fail with "No configured push destination".)

I would like to see people think, when their "new feature" breaks
existing tests and needs adjustments, like this:

    Even test scripts gets upset with this unexpected behaviour
    change---real users may also be hurt the same way.  Should we
    really need to do this change?  What can we do to help them?

Even though I said "Probably sensible", I would prefer the "first
remote automatically replaces 'origin'" feature not to be part of
this patch.  It is something we can queue separately on top as a
separate feature.

I personally think in the long run it is probably the right thing to
do, but at the same time, I do not think it is something we want to
throw at the users as a flag-day event without transition planning.

> +'default'::
> +
> +Displays or sets the name of the repository's default remote.  When git needs
> +to automatically choose a remote to use, it first tries to use the remote
> +associated with the currently checked-out branch.  If the currently
> +checked-out branch has no remote, git uses the repository's default remote.
> +If the repository has no default remote, git tries to use a remote named
> +"origin" even if there is no actual remote named "origin".  (In other words,
> +the default value for the default remote name is "origin".)

After saying something long-winded and convoluted that you think it
needs "In other words," appended, try to re-read the sentence
without the long-winded part (and "In other words,").  I often find
that the long description is unnecessary after doing so myself.

I wonder if it makes the result easier to read if you consolidated
all the duplicated explanations of what the "default remote" is/does
in this patch and previous patches to a single place (perhaps
glossary) and refer to it from these places, e.g.

	default::

        	Display or sets the name of the default remote for
	        the repository.  See "default remote" in
	        linkgit:gitglossary[7].

>  'rename'::
>  
> -Rename the remote named <old> to <new>. All remote-tracking branches and
> +Renames the remote named <old> to <new>. All remote-tracking branches and

Why change the mood from imperative (which I thought was the norm
for these command descriptions) to third-person-present?

>  configuration settings for the remote are updated.
>  +
>  In case <old> and <new> are the same, and <old> is a file under
>  `$GIT_DIR/remotes` or `$GIT_DIR/branches`, the remote is converted to
>  the configuration file format.
> ++
> +If <old> was the repository's default remote name, the default remote name
> +changes to <new>.

This is unrelated to your patch, but I wonder what should happen to
this repository:

	git config branch.foo.remote origin
        git remote rename origin upstream

Should branch.foo.remote be updated, and if so how (either set to
upstream or configuration removed)?

>  'rm'::
>  
> -Remove the remote named <name>. All remote-tracking branches and
> -configuration settings for the remote are removed.
> +Removes the remote named <name>. All remote-tracking branches and

Why change the mood from imperative (which I thought was the norm
for these command descriptions) to third-person-present?

> +configuration settings for the remote are removed.  If the remote was
> +the repository's default remote, then the repository's default remote
> +name is changed to "origin".  Use 'git remote default <name>' to set
> +the repository's default remote name.

I think your patch actually removes remote.default (which I think is
good), and describing it as "changes default remot to 'origin'" like
you did above is perfectly good.

> diff --git a/builtin/remote.c b/builtin/remote.c
> index 920262d..1fb272c 100644
> --- a/builtin/remote.c
> +++ b/builtin/remote.c
> @@ -12,6 +12,7 @@ static const char * const builtin_remote_usage[] = {
>  	"git remote add [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--mirror=<fetch|push>] <name> <url>",
>  	"git remote rename <old> <new>",
>  	"git remote rm <name>",
> +	"git remote default [<name>]",
>  	"git remote set-head <name> (-a | -d | <branch>)",
>  	"git remote [-v | --verbose] show [-n] <name>",
>  	"git remote prune [-n | --dry-run] <name>",
> @@ -198,6 +199,9 @@ static int add(int argc, const char **argv)
>  	if (!valid_fetch_refspec(buf2.buf))
>  		die(_("'%s' is not a valid remote name"), name);
>  
> +	if (remote_count() == 1) /* remote_get() adds a remote if it's new */
> +		git_config_set("remote.default", name);
> +
>  	strbuf_addf(&buf, "remote.%s.url", name);
>  	if (git_config_set(buf.buf, url))
>  		return 1;
> @@ -656,6 +660,10 @@ static int mv(int argc, const char **argv)
>  		return error(_("Could not rename config section '%s' to '%s'"),
>  				buf.buf, buf2.buf);
>  
> +	if (!strcmp(oldremote->name, remote_get_default_name())) {
> +		git_config_set("remote.default", newremote->name);
> +	}
> +
>  	strbuf_reset(&buf);
>  	strbuf_addf(&buf, "remote.%s.fetch", rename.new);
>  	if (git_config_set_multivar(buf.buf, NULL, NULL, 1))
> @@ -798,6 +806,10 @@ static int rm(int argc, const char **argv)
>  	if (git_config_rename_section(buf.buf, NULL) < 1)
>  		return error(_("Could not remove config section '%s'"), buf.buf);
>  
> +	if (!strcmp(remote->name, remote_get_default_name())) {
> +		git_config_set("remote.default", NULL);
> +	}
> +
>  	read_branches();
>  	for (i = 0; i < branch_list.nr; i++) {
>  		struct string_list_item *item = branch_list.items + i;
> @@ -845,6 +857,21 @@ static int rm(int argc, const char **argv)
>  	return result;
>  }
>  
> +static int deflt(int argc, const char **argv)

Perhaps it is a good time to update the naming convention of
functions that implement subcommands (e.g. cmd_default())?

> +{
> +	if (argc < 2)
> +		printf_ln("%s", remote_get_default_name());

Good.  If somebody anal cares about the vanilla hardcoded default
'origin' and 'remote.default' having 'origin' as a configured value,
he should be using "git config" to ask the difference.  Users of
"remote default" interface should not have to care.

> +	else {
> +		const char *name = argv[1];
> +		if (remote_is_configured(name)) {
> +			git_config_set("remote.default", name);
> +			printf_ln(_("Default remote set to '%s'."), name);
> +		} else
> +			return error(_("No remote named '%s'."), name);
> +	}

I am not sure if this is a good idea.  Shouldn't "git remote default
frotz" followed by "git remote add frotz" work?  I'd prefer to see
this demoted to a warning, perhaps like this:

	if (!remote_is_configured(name))
		warning(_("No remote named '%s' defined yet."),
		name);
	git_confg_set("remote.default", name);

without the noisy report of "I did what you told me to do".

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 2/6] Teach remote.c about the remote.default configuration setting.
  2012-07-11 18:21   ` Junio C Hamano
@ 2012-07-11 20:41     ` Marc Branchaud
  2012-07-11 22:04       ` Junio C Hamano
  0 siblings, 1 reply; 22+ messages in thread
From: Marc Branchaud @ 2012-07-11 20:41 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Jens.Lehmann, peff, phil.hord

On 12-07-11 02:21 PM, Junio C Hamano wrote:
> marcnarc@xiplink.com writes:
> 
>> From: Marc Branchaud <marcnarc@xiplink.com>
>>
>> The code now has a default_remote_name and an effective_remote_name:
>>
>>  - default_remote_name is set by remote.default in the config, or is "origin"
>>    if remote.default doesn't exist ("origin" was the fallback value before
>>    this change).
>>
>>  - effective_remote_name is the name of the remote tracked by the current
>>    branch, or is default_remote_name if the current branch doesn't have a
>>    remote.
>>
>> This has a minor side effect on the default behavior of "git push".  Consider
>> the following sequence of commands:
>>
>>       git config remote.default foo                 # Set default remote
>>       git checkout somelocalbranch                  # Does not track a remote
>>       git remote add origin ssh://example.com/repo  # Add a new "origin"
>>       git push
>>
>> Prior to this change, the above "git push" would attempt to push to the new
>> "origin" repository at ssh://example.com/repo.  Now instead that "git push"
>> will attempt to push to the repository named "foo".
> 
> Hrm, is this a _minor_ side effect?

Well, I thought so...  :)

It's minor because of what you say:

> Isn't that a natural and direct consequence of "now you can set
> remote.default configuration to name the remote you want to use in
> place of traditional 'origin'" feature?  I think changing the
> behaviour of "git push" in such a way is the point (may not be the
> only but one of the important points) of this series.

I agree.  Phil Hord pointed out the change in behaviour and felt the commit
message should explain it.

Should I just remove "minor"?

>> diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
>> index cb97cc1..fc17d39 100644
>> --- a/Documentation/git-push.txt
>> +++ b/Documentation/git-push.txt
>> @@ -27,10 +27,16 @@ documentation for linkgit:git-receive-pack[1].
>>  OPTIONS[[OPTIONS]]
>>  ------------------
>>  <repository>::
>> -	The "remote" repository that is destination of a push
>> +	The "remote" repository that is the destination of the push
>>  	operation.  This parameter can be either a URL
>>  	(see the section <<URLS,GIT URLS>> below) or the name
>>  	of a remote (see the section <<REMOTES,REMOTES>> below).
>> +	If this parameter is omitted, git tries to use the remote
>> +	associated with the currently checked-out branch.  If there
>> +	is no remote associated with the current branch, git uses
>> +	the remote named by the "remote.default" configuration variable.
>> +	If "remote.default" is not set, git uses the name "origin" even
>> +	if there is no actual remote named "origin".
> 
> This comment applies to other changes to the documentation in this
> patch I didn't quote, but I think the phrasing 'even if there is no
> acutual remote named "origin"' needs to be rethought, because "we
> use it even if there is no such remote determined with this logic"
> applies equally to branch.$name.remote, remote.default or built-in
> default value of remote.default which happens to be "origin".

I'm sorry, but I'm having trouble understanding what you mean.  I don't see
how the "because ..." part of your sentence suggests what aspect needs
rephrasing.

(BTW, I'm under the impression that when git sets branch.$name.remote it
doesn't ever have to fall back to the default remote name.  That is, commands
that set the value always have the user explicitly, though perhaps
indirectly, specifying the remote.  Did I miss something?)

>> diff --git a/remote.c b/remote.c
>> index 6f371e0..2ebdbbd 100644
>> --- a/remote.c
>> +++ b/remote.c
>> @@ -47,6 +47,7 @@ static int branches_alloc;
>>  static int branches_nr;
>>  
>>  static struct branch *current_branch;
>> +static const char *default_remote_name;
>>  static const char *effective_remote_name;
> 
> Coming from UNIX background, "effective" gives me an impression that
> it is contrasted with "real" (i.e. there is "real remote" for the
> branch, but during this particular invocation it is overridden and
> "effective remote" is used instead).  Perhaps it is just me.

I did have something like that in mind when I chose "effective":  There's a
default remote name that's normally used, but in the certain circumstances
it's overridden.  Perhaps "effective_default_remote_name" would be better,
though that's getting to be a mouthful (plus it would mean having an
"explicit_effective_default_remote_name", which IMHO is a bit much).

> Something along the line of remote-name-to-use, use-remote, might
> sound more natural.

current_remote_name?

		M.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 3/6] Teach "git remote" about remote.default.
  2012-07-11 18:27   ` Junio C Hamano
@ 2012-07-11 20:41     ` Marc Branchaud
  2012-07-11 21:55       ` Junio C Hamano
  0 siblings, 1 reply; 22+ messages in thread
From: Marc Branchaud @ 2012-07-11 20:41 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Jens.Lehmann, peff, phil.hord

On 12-07-11 02:27 PM, Junio C Hamano wrote:
> marcnarc@xiplink.com writes:
> 
>> From: Marc Branchaud <marcnarc@xiplink.com>
>>
>> The "rename" and "rm" commands now handle the case where the remote being
>> changed is the default remote.
> 
> "handle the case" is way underspecified.
> 
> Until I peeked the patch, I couldn't tell if you were now allowing
> "git remote rm" that does not say which remote to remove the remote
> named via remote.default by default, and had to wonder if you made
> "git remote rename frotz" without any other argument mean "git
> remote rename <remote.default> frotz" or the other way around.
> 
>         The "rename" and "rm" commands adjusts the value of the
>         remote.default variable when they make the current default
>         remote disappear.

I'll use that.

>> If the "add" command is used to add the repo's first remote, that remote
>> becomes the default remote.
> 
> Probably sensible, but I could easily imagine existing users to be
> surprised, harmed and complain, especially now those who want this
> behaviour already have a separate "remote default" command to set it
> themselves.

As you suggest below, it makes more sense to put the
first-remote-is-the-default change in a separate patch.  I'll combine it with
the git-clone change in patch #4.

>> Also introduce a "default" sub-command to get or set the default remote:
>>
>>  - "git remote default" (with no parameter) displays the current default remote.
>>
>>  - "git remote default <remo>" checks if <remo> is a configured remote and if
>>    so changes remote.default to <remo>.
> 
> Avoid cute and not-widely-used abbreviation; in other words s/<remo>/<remote>/.

OK.

>> These changes needed a couple of new helper functions in remote.c:
>>  - remote_get_default_name() returns default_remote_name.
>>  - remote_count() returns the number of remotes.
>>
>> (The test in t5528 had to be changed because now with push.default=matching
>> a plain "git push" succeeds with "Everything up-to-date".  It used to
>> fail with "No configured push destination".)
> 
> I would like to see people think, when their "new feature" breaks
> existing tests and needs adjustments, like this:
> 
>     Even test scripts gets upset with this unexpected behaviour
>     change---real users may also be hurt the same way.  Should we
>     really need to do this change?  What can we do to help them?

I did not think the change was that important, because the fact that the
command failed looked like a bug to me (ie. just because I used "-o foo" when
I cloned shouldn't make "git push" with push.default=matching fail).  So it
feels to me like the patch is just making things work the way they should
have in the first place.

> Even though I said "Probably sensible", I would prefer the "first
> remote automatically replaces 'origin'" feature not to be part of
> this patch.  It is something we can queue separately on top as a
> separate feature.

Agreed.

However, this push.default=matching change isn't caused by the "first remote
automatically replaces 'origin'" stuff.  It's a direct result of having
remote.default set.

> I personally think in the long run it is probably the right thing to
> do, but at the same time, I do not think it is something we want to
> throw at the users as a flag-day event without transition planning.

Fair enough.

What about a warning displayed if "remote.default" is not set?  Something like:

	This repository does not have an explicitly configured default
	remote.  Selecting "origin" as the default remote repository.
	To suppress this warning, or if you wish to have a different
	default remote repository, run "git remote default <name>".
	In git X.Y, the default remote will be automatically configured
	as the first remote added to the repository.

>> +'default'::
>> +
>> +Displays or sets the name of the repository's default remote.  When git needs
>> +to automatically choose a remote to use, it first tries to use the remote
>> +associated with the currently checked-out branch.  If the currently
>> +checked-out branch has no remote, git uses the repository's default remote.
>> +If the repository has no default remote, git tries to use a remote named
>> +"origin" even if there is no actual remote named "origin".  (In other words,
>> +the default value for the default remote name is "origin".)
> 
> After saying something long-winded and convoluted that you think it
> needs "In other words," appended, try to re-read the sentence
> without the long-winded part (and "In other words,").  I often find
> that the long description is unnecessary after doing so myself.

I'll take another crack at it.

> I wonder if it makes the result easier to read if you consolidated
> all the duplicated explanations of what the "default remote" is/does
> in this patch and previous patches to a single place (perhaps
> glossary) and refer to it from these places, e.g.
> 
> 	default::
> 
>         	Display or sets the name of the default remote for
> 	        the repository.  See "default remote" in
> 	        linkgit:gitglossary[7].

Good idea!

>>  'rename'::
>>  
>> -Rename the remote named <old> to <new>. All remote-tracking branches and
>> +Renames the remote named <old> to <new>. All remote-tracking branches and
> 
> Why change the mood from imperative (which I thought was the norm
> for these command descriptions) to third-person-present?

This was to make the file consistent -- some parts were already in
third-person-present.  I simply chose the wrong tense -- will change it to
all-imperative.

>>  configuration settings for the remote are updated.
>>  +
>>  In case <old> and <new> are the same, and <old> is a file under
>>  `$GIT_DIR/remotes` or `$GIT_DIR/branches`, the remote is converted to
>>  the configuration file format.
>> ++
>> +If <old> was the repository's default remote name, the default remote name
>> +changes to <new>.
> 
> This is unrelated to your patch, but I wonder what should happen to
> this repository:
> 
> 	git config branch.foo.remote origin
>         git remote rename origin upstream
> 
> Should branch.foo.remote be updated, and if so how (either set to
> upstream or configuration removed)?

I believe it should be updated, and that it should be set to "upstream".

An lo!  This is exactly what git already does...  :)

>>  'rm'::
>>  
>> -Remove the remote named <name>. All remote-tracking branches and
>> -configuration settings for the remote are removed.
>> +Removes the remote named <name>. All remote-tracking branches and
> 
> Why change the mood from imperative (which I thought was the norm
> for these command descriptions) to third-person-present?
> 
>> +configuration settings for the remote are removed.  If the remote was
>> +the repository's default remote, then the repository's default remote
>> +name is changed to "origin".  Use 'git remote default <name>' to set
>> +the repository's default remote name.
> 
> I think your patch actually removes remote.default (which I think is
> good), and describing it as "changes default remot to 'origin'" like
> you did above is perfectly good.
> 
>> diff --git a/builtin/remote.c b/builtin/remote.c
>> index 920262d..1fb272c 100644
>> --- a/builtin/remote.c
>> +++ b/builtin/remote.c
>> @@ -12,6 +12,7 @@ static const char * const builtin_remote_usage[] = {
>>  	"git remote add [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--mirror=<fetch|push>] <name> <url>",
>>  	"git remote rename <old> <new>",
>>  	"git remote rm <name>",
>> +	"git remote default [<name>]",
>>  	"git remote set-head <name> (-a | -d | <branch>)",
>>  	"git remote [-v | --verbose] show [-n] <name>",
>>  	"git remote prune [-n | --dry-run] <name>",
>> @@ -198,6 +199,9 @@ static int add(int argc, const char **argv)
>>  	if (!valid_fetch_refspec(buf2.buf))
>>  		die(_("'%s' is not a valid remote name"), name);
>>  
>> +	if (remote_count() == 1) /* remote_get() adds a remote if it's new */
>> +		git_config_set("remote.default", name);
>> +
>>  	strbuf_addf(&buf, "remote.%s.url", name);
>>  	if (git_config_set(buf.buf, url))
>>  		return 1;
>> @@ -656,6 +660,10 @@ static int mv(int argc, const char **argv)
>>  		return error(_("Could not rename config section '%s' to '%s'"),
>>  				buf.buf, buf2.buf);
>>  
>> +	if (!strcmp(oldremote->name, remote_get_default_name())) {
>> +		git_config_set("remote.default", newremote->name);
>> +	}
>> +
>>  	strbuf_reset(&buf);
>>  	strbuf_addf(&buf, "remote.%s.fetch", rename.new);
>>  	if (git_config_set_multivar(buf.buf, NULL, NULL, 1))
>> @@ -798,6 +806,10 @@ static int rm(int argc, const char **argv)
>>  	if (git_config_rename_section(buf.buf, NULL) < 1)
>>  		return error(_("Could not remove config section '%s'"), buf.buf);
>>  
>> +	if (!strcmp(remote->name, remote_get_default_name())) {
>> +		git_config_set("remote.default", NULL);
>> +	}
>> +
>>  	read_branches();
>>  	for (i = 0; i < branch_list.nr; i++) {
>>  		struct string_list_item *item = branch_list.items + i;
>> @@ -845,6 +857,21 @@ static int rm(int argc, const char **argv)
>>  	return result;
>>  }
>>  
>> +static int deflt(int argc, const char **argv)
> 
> Perhaps it is a good time to update the naming convention of
> functions that implement subcommands (e.g. cmd_default())?

I struggled with the naming here, so I agree.  I thought of using _default().

Since the "cmd_" prefix is already used for the main commands, perhaps
another prefix for subcommands?  Maybe "sub_"?  Some of the shell-based
commands use the main command itself as a prefix (e.g. bisect_start()).
Doing that here would mean "remote_default()" etc.  Any preference?

>> +{
>> +	if (argc < 2)
>> +		printf_ln("%s", remote_get_default_name());
> 
> Good.  If somebody anal cares about the vanilla hardcoded default
> 'origin' and 'remote.default' having 'origin' as a configured value,
> he should be using "git config" to ask the difference.  Users of
> "remote default" interface should not have to care.
> 
>> +	else {
>> +		const char *name = argv[1];
>> +		if (remote_is_configured(name)) {
>> +			git_config_set("remote.default", name);
>> +			printf_ln(_("Default remote set to '%s'."), name);
>> +		} else
>> +			return error(_("No remote named '%s'."), name);
>> +	}
> 
> I am not sure if this is a good idea.  Shouldn't "git remote default
> frotz" followed by "git remote add frotz" work?

To me it feels wrong to allow the user to set the default remote to something
that doesn't actually exist.  It's like trying to add a non-existent file.
And what if the user forgets the second step?

It seems saner for a command to fail if it knows a change it's about to make
will cause problems.

> I'd prefer to see
> this demoted to a warning, perhaps like this:
> 
> 	if (!remote_is_configured(name))
> 		warning(_("No remote named '%s' defined yet."),
> 		name);
> 	git_confg_set("remote.default", name);

The warning helps, but it still feels wrong.

Plus the wording doesn't make it clear that the configuration was changed
anyway.  (Yes, it says "warning" and all, but as a user I can't be sure.)  If
we were to use a warning, it should be "Set the default remote to '%s' even
though no remote with that name exists."

> without the noisy report of "I did what you told me to do".

I'll drop the noise.

		M.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 3/6] Teach "git remote" about remote.default.
  2012-07-11 20:41     ` Marc Branchaud
@ 2012-07-11 21:55       ` Junio C Hamano
  2012-07-13 19:54         ` Marc Branchaud
  0 siblings, 1 reply; 22+ messages in thread
From: Junio C Hamano @ 2012-07-11 21:55 UTC (permalink / raw)
  To: Marc Branchaud; +Cc: git, Jens.Lehmann, peff, phil.hord

Marc Branchaud <marcnarc@xiplink.com> writes:

> What about a warning displayed if "remote.default" is not set?  Something like:
>
> 	This repository does not have an explicitly configured default
> 	remote.  Selecting "origin" as the default remote repository.
> 	To suppress this warning, or if you wish to have a different
> 	default remote repository, run "git remote default <name>".
> 	In git X.Y, the default remote will be automatically configured
> 	as the first remote added to the repository.

When do you plan to issue the above message?  Any time we default to
'origin' without remote.default?  

I do not see a value to it---if the user has been happily using
'origin' as the default remote, there is no reason to give such a
noise.  We will keep defaulting to 'origin' even in the version of
Git with this series in it.

A warning is necessary if we plan to _later_ add the "first remote
created either by 'git clone' or 'git remote add' is automatically
set as the value for remote.default configuration" feature, and the
place to do so is "git clone" and "git remote add" that creates the
first remote for the repository.  If the name of the remote created
by them is 'origin', then there is no need for warning, but if the
user called that first remote with a name that is _not_ 'origin',
later versions of Git will change the behaviour.

I can see a transition plan that goes like this:

Step 0.  With this series but without the "first one becomes default"

    $ git init
    $ git remote add upstream git://over.there.xz/git.git/
    hint: You may want to run "git remote default upstream" now so that
    hint: a lazy 'git push' and 'git fetch' defaults to this 'upstream'
    hint: repository, instead of 'origin' (which you do not yet have).

    $ git config --global advice.settingDefaultRemote false
    $ git remote rm upstream
    $ git remote add upstream git://over.there.xz/git.git/
    ... nothing, as the user declined the advice ...

Step 1.  "First one becomes default" as an opt-in feature

    $ git config --global --unset advice.settingDefaultRemote
    $ git init
    $ git remote add upstream git://over.there.xz/git.git/
    hint: You may want to run "git remote default upstream" now so that
    hint: a lazy 'git push' and 'git fetch' defaults to this 'upstream'
    hint: repository, instead of 'origin' (which you do not yet have).
    hint: "git config --global remote.firstRemoteBecomesDefault true" can be
    hint: used to make the first remote added to the repository the default
    hint: remote automatically.
    $ git remote default
    origin

    $ git config --global remote.firstRemoteBecomesDefault true
    $ git remote rm upstream
    $ git remote add upstream git://over.there.xz/git.git/
    ... nothing; user already knows about remote.firstRemoteBecomesDefault
    $ git remote default
    upstream

Step 2.  Start warning the default change for "First one becomes default"

    $ git config --global --unset advice.settingDefaultRemote
    $ git config --global --unset remote.firstRemoteBecomesDefault
    $ git init
    $ git remote add upstream git://over.there.xz/git.git/
    hint: You may want to run "git remote default upstream" now so that
    hint: a lazy 'git push' and 'git fetch' defaults to this 'upstream'
    hint: repository, instead of 'origin' (which you do not yet have).
    hint: "git config --global remote.firstRemoteBecomesDefault true" can be
    hint: used to make the first remote added to the repository the default
    hint: remote automatically.
    hint:
    hint: In future versions of Git, this will happen automatically.
    hint: If you do not want the first remote to become default, run
    hint: "git config --global remote.firstRemoteBecomesDefault false" now.

Step 3. "First one becomes default" is now default

    $ git config --global --unset advice.settingDefaultRemote
    $ git config --global --unset remote.firstRemoteBecomesDefault
    $ git init
    $ git remote add upstream git://over.there.xz/git.git/
    warning: Made 'upstream' the default remote for this repository.
    $ git remote default
    upstream

    $ git remote rm upstream
    $ git config --global remote.firstRemoteBecomesDefault true
    $ git init
    $ git remote add upstream git://over.there.xz/git.git/
    ... nothing; the user explicitly told us what to do
    $ git remote default
    upstream

    $ git remote rm upstream
    $ git config --global remote.firstRemoteBecomesDefault false
    $ git init
    $ git remote add upstream git://over.there.xz/git.git/
    ... nothing; the user explicitly told us what to do
    $ git remote default
    origin

> Since the "cmd_" prefix is already used for the main commands, perhaps
> another prefix for subcommands?  Maybe "sub_"?  Some of the shell-based
> commands use the main command itself as a prefix (e.g. bisect_start()).
> Doing that here would mean "remote_default()" etc.  Any preference?

No strong preference for file-scope-statics.

>>> +{
>>> +	if (argc < 2)
>>> +		printf_ln("%s", remote_get_default_name());
>> 
>> Good.  If somebody anal cares about the vanilla hardcoded default
>> 'origin' and 'remote.default' having 'origin' as a configured value,
>> he should be using "git config" to ask the difference.  Users of
>> "remote default" interface should not have to care.
>> 
>>> +	else {
>>> +		const char *name = argv[1];
>>> +		if (remote_is_configured(name)) {
>>> +			git_config_set("remote.default", name);
>>> +			printf_ln(_("Default remote set to '%s'."), name);
>>> +		} else
>>> +			return error(_("No remote named '%s'."), name);
>>> +	}
>> 
>> I am not sure if this is a good idea.  Shouldn't "git remote default
>> frotz" followed by "git remote add frotz" work?
>
> To me it feels wrong to allow the user to set the default remote to something
> that doesn't actually exist.  It's like trying to add a non-existent file.

Every few weeks, I do this:

	ln -f -s Documentation/RelNotes/$new_version.txt RelNotes
        edit Documentation/RelNotes/$new_version.txt

> And what if the user forgets the second step?

That is why we warn on an unusual order.  A lazy "git push" will
fail and that would be sufficient clue.

And another reason for the warning (with "you do not yet have") is
to prevent this:

	git remote add frotz git://over.there.xz/git.git
        git remote default frozt

> It seems saner for a command to fail if it knows a change it's about to make
> will cause problems.

The point is that you do *NOT* know it will cause problems.  People
who want to do things in an unusual order *know* what they are doing
a lot better than you do.  Don't get in their way.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 2/6] Teach remote.c about the remote.default configuration setting.
  2012-07-11 20:41     ` Marc Branchaud
@ 2012-07-11 22:04       ` Junio C Hamano
  2012-07-13 19:37         ` Marc Branchaud
  0 siblings, 1 reply; 22+ messages in thread
From: Junio C Hamano @ 2012-07-11 22:04 UTC (permalink / raw)
  To: Marc Branchaud; +Cc: git, Jens.Lehmann, peff, phil.hord

Marc Branchaud <marcnarc@xiplink.com> writes:

> On 12-07-11 02:21 PM, Junio C Hamano wrote:
>> marcnarc@xiplink.com writes:
>> 
>>> From: Marc Branchaud <marcnarc@xiplink.com>
>>>
>>> The code now has a default_remote_name and an effective_remote_name:
>>>
>>>  - default_remote_name is set by remote.default in the config, or is "origin"
>>>    if remote.default doesn't exist ("origin" was the fallback value before
>>>    this change).
>>>
>>>  - effective_remote_name is the name of the remote tracked by the current
>>>    branch, or is default_remote_name if the current branch doesn't have a
>>>    remote.
>>>
>>> This has a minor side effect on the default behavior of "git push"....
>> 
>> Hrm, is this a _minor_ side effect?
>
> Well, I thought so...  :)
>
> It's minor because of what you say:
>
>> Isn't that a natural and direct consequence of "now you can set
>> remote.default configuration to name the remote you want to use in
>> place of traditional 'origin'" feature?  I think changing the
>> behaviour of "git push" in such a way is the point (may not be the
>> only but one of the important points) of this series.
>
> I agree.  Phil Hord pointed out the change in behaviour and felt the commit
> message should explain it.
>
> Should I just remove "minor"?

Is it even a _side effect_?  Isn't this one of the primary points of
the series?  I do not think this patch makes sense if we did not
want that change to happen.

Or am I missing something?

>>> diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
>>> index cb97cc1..fc17d39 100644
>>> --- a/Documentation/git-push.txt
>>> +++ b/Documentation/git-push.txt
>>> @@ -27,10 +27,16 @@ documentation for linkgit:git-receive-pack[1].
>>>  OPTIONS[[OPTIONS]]
>>>  ------------------
>>>  <repository>::
>>> -	The "remote" repository that is destination of a push
>>> +	The "remote" repository that is the destination of the push
>>>  	operation.  This parameter can be either a URL
>>>  	(see the section <<URLS,GIT URLS>> below) or the name
>>>  	of a remote (see the section <<REMOTES,REMOTES>> below).
>>> +	If this parameter is omitted, git tries to use the remote
>>> +	associated with the currently checked-out branch.  If there
>>> +	is no remote associated with the current branch, git uses
>>> +	the remote named by the "remote.default" configuration variable.
>>> +	If "remote.default" is not set, git uses the name "origin" even
>>> +	if there is no actual remote named "origin".
>> 
>> This comment applies to other changes to the documentation in this
>> patch I didn't quote, but I think the phrasing 'even if there is no
>> acutual remote named "origin"' needs to be rethought, because "we
>> use it even if there is no such remote determined with this logic"
>> applies equally to branch.$name.remote, remote.default or built-in
>> default value of remote.default which happens to be "origin".
>
> I'm sorry, but I'm having trouble understanding what you mean.  I don't see
> how the "because ..." part of your sentence suggests what aspect needs
> rephrasing.

You say the remote is taken from three places (branch.$name.remote,
remote.default, or 'origin').

Imagine there is remote.origin.url at all.  If remote.default is set
to 'origin', or branch.$name.remote for the current branch is set to
'origin', the repository you will try to use is 'origin'.  And you
will fail the same way if you try to push there.  It does not matter
if the hardcoded default gave you 'origin' or configuration variable
gave it to you.  The name is used regardless, even if there is no
actual remote under such name.

So "If 'remote.default' is not set, git uses the name "origin" even
if there is no actual remote", while is not untrue, is misleading.
Even if there is no actual remote 'origin', if 'remote.default' is
set to 'origin', git will use that name, and will fail the same way.

Just saying "If 'remote.default' is not set, git uses 'origin'" or
even "'remote.default', if unset, defaults to 'origin'" would be
sufficient.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 2/6] Teach remote.c about the remote.default configuration setting.
  2012-07-11 22:04       ` Junio C Hamano
@ 2012-07-13 19:37         ` Marc Branchaud
  2012-07-13 20:29           ` Junio C Hamano
  0 siblings, 1 reply; 22+ messages in thread
From: Marc Branchaud @ 2012-07-13 19:37 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Jens.Lehmann, peff, phil.hord

On 12-07-11 06:04 PM, Junio C Hamano wrote:
> Marc Branchaud <marcnarc@xiplink.com> writes:
> 
>> On 12-07-11 02:21 PM, Junio C Hamano wrote:
>>> marcnarc@xiplink.com writes:
>>>
>>>> From: Marc Branchaud <marcnarc@xiplink.com>
>>>>
>>>> The code now has a default_remote_name and an effective_remote_name:
>>>>
>>>>  - default_remote_name is set by remote.default in the config, or is "origin"
>>>>    if remote.default doesn't exist ("origin" was the fallback value before
>>>>    this change).
>>>>
>>>>  - effective_remote_name is the name of the remote tracked by the current
>>>>    branch, or is default_remote_name if the current branch doesn't have a
>>>>    remote.
>>>>
>>>> This has a minor side effect on the default behavior of "git push"....
>>>
>>> Hrm, is this a _minor_ side effect?
>>
>> Well, I thought so...  :)
>>
>> It's minor because of what you say:
>>
>>> Isn't that a natural and direct consequence of "now you can set
>>> remote.default configuration to name the remote you want to use in
>>> place of traditional 'origin'" feature?  I think changing the
>>> behaviour of "git push" in such a way is the point (may not be the
>>> only but one of the important points) of this series.
>>
>> I agree.  Phil Hord pointed out the change in behaviour and felt the commit
>> message should explain it.
>>
>> Should I just remove "minor"?
> 
> Is it even a _side effect_?  Isn't this one of the primary points of
> the series?  I do not think this patch makes sense if we did not
> want that change to happen.
> 
> Or am I missing something?

No, you're not -- I agree that this change in behaviour makes sense.  I
simply hadn't anticipated this effect when I first did the work.

So should the commit message simply say "This changes the default behavior of
'git push' ..."?  Or are you suggesting the message needn't mention it at all?

>>>> diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
>>>> index cb97cc1..fc17d39 100644
>>>> --- a/Documentation/git-push.txt
>>>> +++ b/Documentation/git-push.txt
>>>> @@ -27,10 +27,16 @@ documentation for linkgit:git-receive-pack[1].
>>>>  OPTIONS[[OPTIONS]]
>>>>  ------------------
>>>>  <repository>::
>>>> -	The "remote" repository that is destination of a push
>>>> +	The "remote" repository that is the destination of the push
>>>>  	operation.  This parameter can be either a URL
>>>>  	(see the section <<URLS,GIT URLS>> below) or the name
>>>>  	of a remote (see the section <<REMOTES,REMOTES>> below).
>>>> +	If this parameter is omitted, git tries to use the remote
>>>> +	associated with the currently checked-out branch.  If there
>>>> +	is no remote associated with the current branch, git uses
>>>> +	the remote named by the "remote.default" configuration variable.
>>>> +	If "remote.default" is not set, git uses the name "origin" even
>>>> +	if there is no actual remote named "origin".
>>>
>>> This comment applies to other changes to the documentation in this
>>> patch I didn't quote, but I think the phrasing 'even if there is no
>>> acutual remote named "origin"' needs to be rethought, because "we
>>> use it even if there is no such remote determined with this logic"
>>> applies equally to branch.$name.remote, remote.default or built-in
>>> default value of remote.default which happens to be "origin".
>>
>> I'm sorry, but I'm having trouble understanding what you mean.  I don't see
>> how the "because ..." part of your sentence suggests what aspect needs
>> rephrasing.
> 
> You say the remote is taken from three places (branch.$name.remote,
> remote.default, or 'origin').
> 
> Imagine there is remote.origin.url at all.  If remote.default is set
> to 'origin', or branch.$name.remote for the current branch is set to
> 'origin', the repository you will try to use is 'origin'.  And you
> will fail the same way if you try to push there.  It does not matter
> if the hardcoded default gave you 'origin' or configuration variable
> gave it to you.  The name is used regardless, even if there is no
> actual remote under such name.
> 
> So "If 'remote.default' is not set, git uses the name "origin" even
> if there is no actual remote", while is not untrue, is misleading.
> Even if there is no actual remote 'origin', if 'remote.default' is
> set to 'origin', git will use that name, and will fail the same way.
> 
> Just saying "If 'remote.default' is not set, git uses 'origin'" or
> even "'remote.default', if unset, defaults to 'origin'" would be
> sufficient.

Thanks, I understand you now.

I feel it's rather surprising that git defaults to "origin".  I think the
docs should explain that git in fact ignores whatever remotes are actually
configured in the repository, that git only looks in specific places for a
remote name.  That's what I was trying to convey with the "even if" clause.

I'll try to rephrase.

		M.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 3/6] Teach "git remote" about remote.default.
  2012-07-11 21:55       ` Junio C Hamano
@ 2012-07-13 19:54         ` Marc Branchaud
  0 siblings, 0 replies; 22+ messages in thread
From: Marc Branchaud @ 2012-07-13 19:54 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Jens.Lehmann, peff, phil.hord

On 12-07-11 05:55 PM, Junio C Hamano wrote:
> Marc Branchaud <marcnarc@xiplink.com> writes:
> 
>> What about a warning displayed if "remote.default" is not set?  Something like:
>>
>> 	This repository does not have an explicitly configured default
>> 	remote.  Selecting "origin" as the default remote repository.
>> 	To suppress this warning, or if you wish to have a different
>> 	default remote repository, run "git remote default <name>".
>> 	In git X.Y, the default remote will be automatically configured
>> 	as the first remote added to the repository.
> 
> When do you plan to issue the above message?  Any time we default to
> 'origin' without remote.default?  
> 
> I do not see a value to it---if the user has been happily using
> 'origin' as the default remote, there is no reason to give such a
> noise.  We will keep defaulting to 'origin' even in the version of
> Git with this series in it.
> 
> A warning is necessary if we plan to _later_ add the "first remote
> created either by 'git clone' or 'git remote add' is automatically
> set as the value for remote.default configuration" feature, and the
> place to do so is "git clone" and "git remote add" that creates the
> first remote for the repository.  If the name of the remote created
> by them is 'origin', then there is no need for warning, but if the
> user called that first remote with a name that is _not_ 'origin',
> later versions of Git will change the behaviour.
> 
> I can see a transition plan that goes like this:

I like your plan -- thanks for working it out in such detail!

I'll re-roll the series to work like your plan's Step 0, and I'll post a
separate RFC patch on top of it that initiates the transition, so folks can
discuss it specifically.

> Step 0.  With this series but without the "first one becomes default"
> 
>     $ git init
>     $ git remote add upstream git://over.there.xz/git.git/
>     hint: You may want to run "git remote default upstream" now so that
>     hint: a lazy 'git push' and 'git fetch' defaults to this 'upstream'
>     hint: repository, instead of 'origin' (which you do not yet have).
> 
>     $ git config --global advice.settingDefaultRemote false
>     $ git remote rm upstream
>     $ git remote add upstream git://over.there.xz/git.git/
>     ... nothing, as the user declined the advice ...
> 
> Step 1.  "First one becomes default" as an opt-in feature
> 
>     $ git config --global --unset advice.settingDefaultRemote
>     $ git init
>     $ git remote add upstream git://over.there.xz/git.git/
>     hint: You may want to run "git remote default upstream" now so that
>     hint: a lazy 'git push' and 'git fetch' defaults to this 'upstream'
>     hint: repository, instead of 'origin' (which you do not yet have).
>     hint: "git config --global remote.firstRemoteBecomesDefault true" can be
>     hint: used to make the first remote added to the repository the default
>     hint: remote automatically.
>     $ git remote default
>     origin
> 
>     $ git config --global remote.firstRemoteBecomesDefault true
>     $ git remote rm upstream
>     $ git remote add upstream git://over.there.xz/git.git/
>     ... nothing; user already knows about remote.firstRemoteBecomesDefault
>     $ git remote default
>     upstream
> 
> Step 2.  Start warning the default change for "First one becomes default"
> 
>     $ git config --global --unset advice.settingDefaultRemote
>     $ git config --global --unset remote.firstRemoteBecomesDefault
>     $ git init
>     $ git remote add upstream git://over.there.xz/git.git/
>     hint: You may want to run "git remote default upstream" now so that
>     hint: a lazy 'git push' and 'git fetch' defaults to this 'upstream'
>     hint: repository, instead of 'origin' (which you do not yet have).
>     hint: "git config --global remote.firstRemoteBecomesDefault true" can be
>     hint: used to make the first remote added to the repository the default
>     hint: remote automatically.
>     hint:
>     hint: In future versions of Git, this will happen automatically.
>     hint: If you do not want the first remote to become default, run
>     hint: "git config --global remote.firstRemoteBecomesDefault false" now.
> 
> Step 3. "First one becomes default" is now default
> 
>     $ git config --global --unset advice.settingDefaultRemote
>     $ git config --global --unset remote.firstRemoteBecomesDefault
>     $ git init
>     $ git remote add upstream git://over.there.xz/git.git/
>     warning: Made 'upstream' the default remote for this repository.
>     $ git remote default
>     upstream
> 
>     $ git remote rm upstream
>     $ git config --global remote.firstRemoteBecomesDefault true
>     $ git init
>     $ git remote add upstream git://over.there.xz/git.git/
>     ... nothing; the user explicitly told us what to do
>     $ git remote default
>     upstream
> 
>     $ git remote rm upstream
>     $ git config --global remote.firstRemoteBecomesDefault false
>     $ git init
>     $ git remote add upstream git://over.there.xz/git.git/
>     ... nothing; the user explicitly told us what to do
>     $ git remote default
>     origin
> 
>> Since the "cmd_" prefix is already used for the main commands, perhaps
>> another prefix for subcommands?  Maybe "sub_"?  Some of the shell-based
>> commands use the main command itself as a prefix (e.g. bisect_start()).
>> Doing that here would mean "remote_default()" etc.  Any preference?
> 
> No strong preference for file-scope-statics.
> 
>>>> +{
>>>> +	if (argc < 2)
>>>> +		printf_ln("%s", remote_get_default_name());
>>>
>>> Good.  If somebody anal cares about the vanilla hardcoded default
>>> 'origin' and 'remote.default' having 'origin' as a configured value,
>>> he should be using "git config" to ask the difference.  Users of
>>> "remote default" interface should not have to care.
>>>
>>>> +	else {
>>>> +		const char *name = argv[1];
>>>> +		if (remote_is_configured(name)) {
>>>> +			git_config_set("remote.default", name);
>>>> +			printf_ln(_("Default remote set to '%s'."), name);
>>>> +		} else
>>>> +			return error(_("No remote named '%s'."), name);
>>>> +	}
>>>
>>> I am not sure if this is a good idea.  Shouldn't "git remote default
>>> frotz" followed by "git remote add frotz" work?
>>
>> To me it feels wrong to allow the user to set the default remote to something
>> that doesn't actually exist.  It's like trying to add a non-existent file.
> 
> Every few weeks, I do this:
> 
> 	ln -f -s Documentation/RelNotes/$new_version.txt RelNotes
>         edit Documentation/RelNotes/$new_version.txt
> 
>> And what if the user forgets the second step?
> 
> That is why we warn on an unusual order.  A lazy "git push" will
> fail and that would be sufficient clue.
> 
> And another reason for the warning (with "you do not yet have") is
> to prevent this:
> 
>         git remote add frotz git://over.there.xz/git.git
>         git remote default frozt

See, to me an error in this case makes more sense.  But I feel I'm splitting
hairs now, and I'm happy to go with the warning instead.

>> It seems saner for a command to fail if it knows a change it's about to make
>> will cause problems.
> 
> The point is that you do *NOT* know it will cause problems.  People
> who want to do things in an unusual order *know* what they are doing
> a lot better than you do.  Don't get in their way.

I'll aim to post a revised series next week.

		M.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 2/6] Teach remote.c about the remote.default configuration setting.
  2012-07-13 19:37         ` Marc Branchaud
@ 2012-07-13 20:29           ` Junio C Hamano
  0 siblings, 0 replies; 22+ messages in thread
From: Junio C Hamano @ 2012-07-13 20:29 UTC (permalink / raw)
  To: Marc Branchaud; +Cc: git, Jens.Lehmann, peff, phil.hord

Marc Branchaud <marcnarc@xiplink.com> writes:

>> Is it even a _side effect_?  Isn't this one of the primary points of
>> the series?  I do not think this patch makes sense if we did not
>> want that change to happen.
>> 
>> Or am I missing something?
>
> No, you're not -- I agree that this change in behaviour makes sense.  I
> simply hadn't anticipated this effect when I first did the work.
>
> So should the commit message simply say "This changes the default behavior of
> 'git push' ..."?  Or are you suggesting the message needn't mention it at all?

It is one of the more important behaviour changes we are making on
purpose with this series; it deserves to be described in the log, I
would think.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 2/6] Teach remote.c about the remote.default configuration setting.
  2012-07-06 19:31       ` Junio C Hamano
@ 2012-07-06 19:57         ` Marc Branchaud
  0 siblings, 0 replies; 22+ messages in thread
From: Marc Branchaud @ 2012-07-06 19:57 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Jens.Lehmann, peff, phil.hord

On 12-07-06 03:31 PM, Junio C Hamano wrote:
> Marc Branchaud <marcnarc@xiplink.com> writes:
> 
>> On 12-07-05 06:50 PM, Junio C Hamano wrote:
>>>
>>>>  - effective_remote_name is the name of the remote tracked by the current
>>>>    branch, or is default_remote_name if the current branch doesn't have a
>>>>    remote.
>>>
>>> The explanation of the latter belongs to the previous step, I think.
>>> I am not sure if "effective" is the best name for the concept the
>>> above explains, though.
>>
>> Well, the previous commit removes default_remote_name, so the explanation
>> wouldn't be valid verbatim.
> 
> The previous one introduces "effective" (which I still think is not
> the best word for the semantics you are trying to give to the
> variable)

I'm open to suggestions.

		M.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 2/6] Teach remote.c about the remote.default configuration setting.
  2012-07-06 14:36     ` Marc Branchaud
@ 2012-07-06 19:31       ` Junio C Hamano
  2012-07-06 19:57         ` Marc Branchaud
  0 siblings, 1 reply; 22+ messages in thread
From: Junio C Hamano @ 2012-07-06 19:31 UTC (permalink / raw)
  To: Marc Branchaud; +Cc: git, Jens.Lehmann, peff, phil.hord

Marc Branchaud <marcnarc@xiplink.com> writes:

> On 12-07-05 06:50 PM, Junio C Hamano wrote:
>> 
>>>  - effective_remote_name is the name of the remote tracked by the current
>>>    branch, or is default_remote_name if the current branch doesn't have a
>>>    remote.
>> 
>> The explanation of the latter belongs to the previous step, I think.
>> I am not sure if "effective" is the best name for the concept the
>> above explains, though.
>
> Well, the previous commit removes default_remote_name, so the explanation
> wouldn't be valid verbatim.

The previous one introduces "effective" (which I still think is not
the best word for the semantics you are trying to give to the
variable) without explaining what the variable is for and justifying
why "effective" is the right word (or at least a better than
"default") for it.  Something like the "- effective_remote_name is the ..."
above is necessary in its commit log message.

> How about keeping the above here, and I could add the following to the
> previous commit's message:
>
> 	effective_remote_name is the remote name that is currently "in
> 	effect".  This is the currently checked-out branch's remote, or
> 	"origin" if the branch has no remote (or the working tree is a
> 	detached HEAD).

Yeah, along that line.

> The read_config() function already has logic to avoid re-parsing the entire
> config over and over again.  There are many places in remote.c that call
> read_config(), and I thought I was just following that pattern.

OK.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 2/6] Teach remote.c about the remote.default configuration setting.
  2012-07-05 22:50   ` Junio C Hamano
@ 2012-07-06 14:36     ` Marc Branchaud
  2012-07-06 19:31       ` Junio C Hamano
  0 siblings, 1 reply; 22+ messages in thread
From: Marc Branchaud @ 2012-07-06 14:36 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Jens.Lehmann, peff, phil.hord

On 12-07-05 06:50 PM, Junio C Hamano wrote:
> marcnarc@xiplink.com writes:
> 
>> From: Marc Branchaud <marcnarc@xiplink.com>
>>
>> The code now has a default_remote_name and an effective_remote_name:
>>  - default_remote_name is set by remote.default in the config, or is "origin"
>>    if remote.default doesn't exist ("origin" was the fallback value before
>>    this change).
> 
> 
>>  - effective_remote_name is the name of the remote tracked by the current
>>    branch, or is default_remote_name if the current branch doesn't have a
>>    remote.
> 
> The explanation of the latter belongs to the previous step, I think.
> I am not sure if "effective" is the best name for the concept the
> above explains, though.

Well, the previous commit removes default_remote_name, so the explanation
wouldn't be valid verbatim.

How about keeping the above here, and I could add the following to the
previous commit's message:

	effective_remote_name is the remote name that is currently "in
	effect".  This is the currently checked-out branch's remote, or
	"origin" if the branch has no remote (or the working tree is a
	detached HEAD).

>> @@ -390,6 +391,7 @@ static int handle_config(const char *key, const char *value, void *cb)
>>  	}
>>  	if (prefixcmp(key,  "remote."))
>>  		return 0;
>> +
> 
> Why?

Oops, just a newline I neglected to clean up from some earlier hacking.  Sorry.

>>  	name = key + 7;
>> @@ -671,6 +680,18 @@ static int valid_remote_nick(const char *name)
>>  	return !strchr(name, '/'); /* no slash */
>>  }
>>  
>> +const char *remote_get_default_name()
> 
> const char *remote_get_default_name(void)

OK.

>> +{
>> +	read_config();
>> +	return default_remote_name;
>> +}
> 
> Hrmph.  I am too lazy to read outside the context of your patch to
> make sure, but isn't the root cause of the problem that when we try
> to find which remote the current branch is configured to interact
> with, we grab branch->remote_name (and this is done by calling
> git_config() to open and read the configuration file once already)
> and if it is empty we default to "origin"?  Wouldn't the callback
> function that is used for that invocation of git_config() a much
> better place to set "default_remote_name" variable, instead of
> having us to read the entire configuration file one more time only
> to get the value of this variable?

The read_config() function already has logic to avoid re-parsing the entire
config over and over again.  There are many places in remote.c that call
read_config(), and I thought I was just following that pattern.

Also, making the code be

	if (!default_remote_name)
		read_config();
	return default_remote_name;

would just replicate the check that read_config() already does.

>> +int remote_count()
> 
> int remote_count(void)

OK.

>> +{
>> +	read_config();
>> +	return remotes_nr;
>> +}
> 
> Likewise.

Doing something like

	if (!remotes_nr)
		read_config():
	return remotes_nr;

would be wrong, since having 0 remotes is perfectly fine.  And making the
check here be
	if (!default_remote_name)
seems confusing, and again it duplicates the check read_config() already does.

> Especially it is unclear who benefits from the function
> until a new caller is introduced.  I would prefer not to see the
> addition of this function in this patch.

OK, I can move it to the "git remote" patch.  The same could be said of
remote_get_default_name() though.

>>  struct remote *remote_get(const char *name)
>>  {
>>  	struct remote *ret;
>> diff --git a/remote.h b/remote.h
>> index 251d8fd..f9aac87 100644
>> --- a/remote.h
>> +++ b/remote.h
>> @@ -52,6 +52,8 @@ struct remote {
>>  
>>  struct remote *remote_get(const char *name);
>>  int remote_is_configured(const char *name);
>> +const char *remote_get_default_name();
>> +int remote_count();
> 
> const char *remote_get_default_name(void);
> int remote_count(void);

Got it.

I'll make these changes in a few days, after folks have had a chance to
review.  If things settle down I'll re-roll with the documentation updates too.

		M.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 2/6] Teach remote.c about the remote.default configuration setting.
  2012-07-05 22:11 ` [PATCH 2/6] Teach remote.c about the remote.default configuration setting marcnarc
@ 2012-07-05 22:50   ` Junio C Hamano
  2012-07-06 14:36     ` Marc Branchaud
  0 siblings, 1 reply; 22+ messages in thread
From: Junio C Hamano @ 2012-07-05 22:50 UTC (permalink / raw)
  To: marcnarc; +Cc: git, Jens.Lehmann, peff, phil.hord

marcnarc@xiplink.com writes:

> From: Marc Branchaud <marcnarc@xiplink.com>
>
> The code now has a default_remote_name and an effective_remote_name:
>  - default_remote_name is set by remote.default in the config, or is "origin"
>    if remote.default doesn't exist ("origin" was the fallback value before
>    this change).


>  - effective_remote_name is the name of the remote tracked by the current
>    branch, or is default_remote_name if the current branch doesn't have a
>    remote.

The explanation of the latter belongs to the previous step, I think.
I am not sure if "effective" is the best name for the concept the
above explains, though.

> @@ -390,6 +391,7 @@ static int handle_config(const char *key, const char *value, void *cb)
>  	}
>  	if (prefixcmp(key,  "remote."))
>  		return 0;
> +

Why?

>  	name = key + 7;
> @@ -671,6 +680,18 @@ static int valid_remote_nick(const char *name)
>  	return !strchr(name, '/'); /* no slash */
>  }
>  
> +const char *remote_get_default_name()

const char *remote_get_default_name(void)

> +{
> +	read_config();
> +	return default_remote_name;
> +}

Hrmph.  I am too lazy to read outside the context of your patch to
make sure, but isn't the root cause of the problem that when we try
to find which remote the current branch is configured to interact
with, we grab branch->remote_name (and this is done by calling
git_config() to open and read the configuration file once already)
and if it is empty we default to "origin"?  Wouldn't the callback
function that is used for that invocation of git_config() a much
better place to set "default_remote_name" variable, instead of
having us to read the entire configuration file one more time only
to get the value of this variable?

> +int remote_count()

int remote_count(void)

> +{
> +	read_config();
> +	return remotes_nr;
> +}

Likewise.  Especially it is unclear who benefits from the function
until a new caller is introduced.  I would prefer not to see the
addition of this function in this patch.

>  struct remote *remote_get(const char *name)
>  {
>  	struct remote *ret;
> diff --git a/remote.h b/remote.h
> index 251d8fd..f9aac87 100644
> --- a/remote.h
> +++ b/remote.h
> @@ -52,6 +52,8 @@ struct remote {
>  
>  struct remote *remote_get(const char *name);
>  int remote_is_configured(const char *name);
> +const char *remote_get_default_name();
> +int remote_count();

const char *remote_get_default_name(void);
int remote_count(void);

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 2/6] Teach remote.c about the remote.default configuration setting.
  2012-07-05 22:11 [PATCH " marcnarc
@ 2012-07-05 22:11 ` marcnarc
  2012-07-05 22:50   ` Junio C Hamano
  0 siblings, 1 reply; 22+ messages in thread
From: marcnarc @ 2012-07-05 22:11 UTC (permalink / raw)
  To: git; +Cc: gitster, Jens.Lehmann, peff, phil.hord, Marc Branchaud

From: Marc Branchaud <marcnarc@xiplink.com>

The code now has a default_remote_name and an effective_remote_name:
 - default_remote_name is set by remote.default in the config, or is "origin"
   if remote.default doesn't exist ("origin" was the fallback value before
   this change).
 - effective_remote_name is the name of the remote tracked by the current
   branch, or is default_remote_name if the current branch doesn't have a
   remote.

Also add two new helper functions for other code modules to use:
 - remote_get_default_name() returns default_remote_name.
 - remote_count() returns the number of remotes.

Signed-off-by: Marc Branchaud <marcnarc@xiplink.com>
---
 remote.c | 27 ++++++++++++++++++++++++---
 remote.h |  2 ++
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/remote.c b/remote.c
index 6f371e0..ccada0d 100644
--- a/remote.c
+++ b/remote.c
@@ -47,6 +47,7 @@ static int branches_alloc;
 static int branches_nr;
 
 static struct branch *current_branch;
+static const char *default_remote_name;
 static const char *effective_remote_name;
 static int explicit_effective_remote_name;
 
@@ -390,6 +391,7 @@ static int handle_config(const char *key, const char *value, void *cb)
 	}
 	if (prefixcmp(key,  "remote."))
 		return 0;
+
 	name = key + 7;
 	if (*name == '/') {
 		warning("Config remote shorthand cannot begin with '/': %s",
@@ -397,8 +399,12 @@ static int handle_config(const char *key, const char *value, void *cb)
 		return 0;
 	}
 	subkey = strrchr(name, '.');
-	if (!subkey)
+	if (!subkey) {
+		/* Look for remote.default */
+		if (!strcmp(name, "default"))
+			default_remote_name = xstrdup(value);
 		return 0;
+	}
 	remote = make_remote(name, subkey - name);
 	remote->origin = REMOTE_CONFIG;
 	if (!strcmp(subkey, ".mirror"))
@@ -481,9 +487,8 @@ static void read_config(void)
 	unsigned char sha1[20];
 	const char *head_ref;
 	int flag;
-	if (effective_remote_name) /* did this already */
+	if (default_remote_name) /* did this already */
 		return;
-	effective_remote_name = xstrdup("origin");
 	current_branch = NULL;
 	head_ref = resolve_ref_unsafe("HEAD", sha1, 0, &flag);
 	if (head_ref && (flag & REF_ISSYMREF) &&
@@ -492,6 +497,10 @@ static void read_config(void)
 			make_branch(head_ref + strlen("refs/heads/"), 0);
 	}
 	git_config(handle_config, NULL);
+	if (!default_remote_name)
+		default_remote_name = "origin";
+	if (!effective_remote_name)
+		effective_remote_name = default_remote_name;
 	alias_all_urls();
 }
 
@@ -671,6 +680,18 @@ static int valid_remote_nick(const char *name)
 	return !strchr(name, '/'); /* no slash */
 }
 
+const char *remote_get_default_name()
+{
+	read_config();
+	return default_remote_name;
+}
+
+int remote_count()
+{
+	read_config();
+	return remotes_nr;
+}
+
 struct remote *remote_get(const char *name)
 {
 	struct remote *ret;
diff --git a/remote.h b/remote.h
index 251d8fd..f9aac87 100644
--- a/remote.h
+++ b/remote.h
@@ -52,6 +52,8 @@ struct remote {
 
 struct remote *remote_get(const char *name);
 int remote_is_configured(const char *name);
+const char *remote_get_default_name();
+int remote_count();
 
 typedef int each_remote_fn(struct remote *remote, void *priv);
 int for_each_remote(each_remote_fn fn, void *priv);
-- 
1.7.11.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2012-07-13 20:29 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-11 15:33 [PATCH v2 0/6] Default remote marcnarc
2012-07-11 15:33 ` [PATCH 1/6] Rename remote.c's default_remote_name static variables marcnarc
2012-07-11 15:33 ` [PATCH 2/6] Teach remote.c about the remote.default configuration setting marcnarc
2012-07-11 18:21   ` Junio C Hamano
2012-07-11 20:41     ` Marc Branchaud
2012-07-11 22:04       ` Junio C Hamano
2012-07-13 19:37         ` Marc Branchaud
2012-07-13 20:29           ` Junio C Hamano
2012-07-11 15:33 ` [PATCH 3/6] Teach "git remote" about remote.default marcnarc
2012-07-11 18:27   ` Junio C Hamano
2012-07-11 20:41     ` Marc Branchaud
2012-07-11 21:55       ` Junio C Hamano
2012-07-13 19:54         ` Marc Branchaud
2012-07-11 15:33 ` [PATCH 4/6] Teach clone to set remote.default marcnarc
2012-07-11 15:34 ` [PATCH 5/6] Test that plain "git fetch" uses remote.default when on a detached HEAD marcnarc
2012-07-11 15:34 ` [PATCH 6/6] Teach get_default_remote to respect remote.default marcnarc
2012-07-11 18:19 ` [PATCH v2 0/6] Default remote Junio C Hamano
  -- strict thread matches above, loose matches on Subject: below --
2012-07-05 22:11 [PATCH " marcnarc
2012-07-05 22:11 ` [PATCH 2/6] Teach remote.c about the remote.default configuration setting marcnarc
2012-07-05 22:50   ` Junio C Hamano
2012-07-06 14:36     ` Marc Branchaud
2012-07-06 19:31       ` Junio C Hamano
2012-07-06 19:57         ` Marc Branchaud

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.