# [PATCH 2/4] git-remote rename: support remotes->config migration

5 messages from 2008-11-12 to 2008-11-12. Participants: Miklos Vajna.
Thread: https://gitlist.dev/t/16291

## Miklos Vajna, 2008-11-12 17:11

Subject: [PATCH v2 0/4] git-remote rename: support branches->config migration
Message-ID: <cover.1226508805.git.vmiklos@frugalware.org>
URL: https://gitlist.dev/e/cover.1226508805.git.vmiklos%40frugalware.org
In-Reply-To: <7viqqtshdd.fsf@gitster.siamese.dyndns.org>

```
On Tue, Nov 11, 2008 at 08:22:38PM -0800, Junio C Hamano <gitster@pobox.com> wrote:
> The function migrate_file() introduced by [2/4] is called for any
> remote definition that did not come from config (by definition, it
> either came from remotes/foo or branches/foo).  The function adds the
> entries for the given remote definition to the config file, and then
> removes remotes/foo file if the remote definition came from it.  So it
> is a logically consistent change if you only called this function only
> for remote definitions that came from remotes/foo.
>
> But the function is called for a remote definition that originally
> came from branches/foo as well.  It happily adds the definition to the
> config, even though it *fails to remove* branches/foo file.
>
> Do you still think 2/4 is a logically contained good change?

OK, here is an updated series, which is supposed to fix this issue. 1/4
and 4/4 is unchanged.

Miklos Vajna (4):
  remote: add a new 'origin' variable to the struct
  git-remote rename: support remotes->config migration
  git-remote rename: support branches->config migration
  git-remote: document the migration feature of the rename subcommand

 Documentation/git-remote.txt |    4 ++++
 builtin-remote.c             |   37 +++++++++++++++++++++++++++++++++++++
 remote.c                     |    3 +++
 remote.h                     |    7 +++++++
 t/t5505-remote.sh            |   33 +++++++++++++++++++++++++++++++++
 5 files changed, 84 insertions(+), 0 deletions(-)

```

## Miklos Vajna, 2008-11-12 17:11

Subject: [PATCH 1/4] remote: add a new 'origin' variable to the struct
Message-ID: <95e56b46e30b41af31da86789625c93511f1faef.1226508805.git.vmiklos@frugalware.org>
URL: https://gitlist.dev/e/95e56b46e30b41af31da86789625c93511f1faef.1226508805.git.vmiklos%40frugalware.org
In-Reply-To: <cover.1226508805.git.vmiklos@frugalware.org>

```
This allows one to track where was the remote's original source, so that
it's possible to decide if it makes sense to migrate it to the config
format or not.

Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
---
 remote.c |    3 +++
 remote.h |    7 +++++++
 2 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/remote.c b/remote.c
index e530a21..cbb3e48 100644
--- a/remote.c
+++ b/remote.c
@@ -201,6 +201,7 @@ static void read_remotes_file(struct remote *remote)
 
 	if (!f)
 		return;
+	remote->origin = REMOTE_REMOTES;
 	while (fgets(buffer, BUF_SIZE, f)) {
 		int value_list;
 		char *s, *p;
@@ -261,6 +262,7 @@ static void read_branches_file(struct remote *remote)
 		s++;
 	if (!*s)
 		return;
+	remote->origin = REMOTE_BRANCHES;
 	p = s + strlen(s);
 	while (isspace(p[-1]))
 		*--p = 0;
@@ -350,6 +352,7 @@ static int handle_config(const char *key, const char *value, void *cb)
 	if (!subkey)
 		return error("Config with no key for remote %s", name);
 	remote = make_remote(name, subkey - name);
+	remote->origin = REMOTE_CONFIG;
 	if (!strcmp(subkey, ".mirror"))
 		remote->mirror = git_config_bool(key, value);
 	else if (!strcmp(subkey, ".skipdefaultupdate"))
diff --git a/remote.h b/remote.h
index d2e170c..a46a5be 100644
--- a/remote.h
+++ b/remote.h
@@ -1,8 +1,15 @@
 #ifndef REMOTE_H
 #define REMOTE_H
 
+enum {
+	REMOTE_CONFIG,
+	REMOTE_REMOTES,
+	REMOTE_BRANCHES
+};
+
 struct remote {
 	const char *name;
+	int origin;
 
 	const char **url;
 	int url_nr;
-- 
1.6.0.2

```

## Miklos Vajna, 2008-11-12 17:11

Subject: [PATCH 2/4] git-remote rename: support remotes->config migration
Message-ID: <d99804ad3579d4882e8241d9dcaee1b7dd6508af.1226508805.git.vmiklos@frugalware.org>
URL: https://gitlist.dev/e/d99804ad3579d4882e8241d9dcaee1b7dd6508af.1226508805.git.vmiklos%40frugalware.org
In-Reply-To: <95e56b46e30b41af31da86789625c93511f1faef.1226508805.git.vmiklos@frugalware.org>

```
This patch makes it possible to migrate a remote stored in a
$GIT_DIR/remotes/nick file to the configuration file format.

Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
---
 builtin-remote.c  |   33 +++++++++++++++++++++++++++++++++
 t/t5505-remote.sh |   21 +++++++++++++++++++++
 2 files changed, 54 insertions(+), 0 deletions(-)

diff --git a/builtin-remote.c b/builtin-remote.c
index 1ca6cdb..4fa64a2 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -359,6 +359,36 @@ static int read_remote_branches(const char *refname,
 	return 0;
 }
 
+static int migrate_file(struct remote *remote)
+{
+	struct strbuf buf = STRBUF_INIT;
+	int i;
+	char *path = NULL;
+
+	strbuf_addf(&buf, "remote.%s.url", remote->name);
+	for (i = 0; i < remote->url_nr; i++)
+		if (git_config_set_multivar(buf.buf, remote->url[i], "^$", 0))
+			return error("Could not append '%s' to '%s'",
+					remote->url[i], buf.buf);
+	strbuf_reset(&buf);
+	strbuf_addf(&buf, "remote.%s.push", remote->name);
+	for (i = 0; i < remote->push_refspec_nr; i++)
+		if (git_config_set_multivar(buf.buf, remote->push_refspec[i], "^$", 0))
+			return error("Could not append '%s' to '%s'",
+					remote->push_refspec[i], buf.buf);
+	strbuf_reset(&buf);
+	strbuf_addf(&buf, "remote.%s.fetch", remote->name);
+	for (i = 0; i < remote->fetch_refspec_nr; i++)
+		if (git_config_set_multivar(buf.buf, remote->fetch_refspec[i], "^$", 0))
+			return error("Could not append '%s' to '%s'",
+					remote->fetch_refspec[i], buf.buf);
+	if (remote->origin == REMOTE_REMOTES)
+		path = git_path("remotes/%s", remote->name);
+	if (path && unlink(path))
+		warning("failed to remove '%s'", path);
+	return 0;
+}
+
 static int mv(int argc, const char **argv)
 {
 	struct option options[] = {
@@ -381,6 +411,9 @@ static int mv(int argc, const char **argv)
 	if (!oldremote)
 		die("No such remote: %s", rename.old);
 
+	if (!strcmp(rename.old, rename.new) && oldremote->origin == REMOTE_REMOTES)
+		return migrate_file(oldremote);
+
 	newremote = remote_get(rename.new);
 	if (newremote && (newremote->url_nr > 1 || newremote->fetch_refspec_nr))
 		die("remote %s already exists.", rename.new);
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index 0c956ba..1567631 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -343,4 +343,25 @@ test_expect_success 'rename a remote' '
 	 test "$(git config branch.master.remote)" = "upstream")
 
 '
+
+cat > remotes_origin << EOF
+URL: $(pwd)/one
+Push: refs/heads/master:refs/heads/upstream
+Pull: refs/heads/master:refs/heads/origin
+EOF
+
+test_expect_success 'migrate a remote from named file in $GIT_DIR/remotes' '
+	git clone one five &&
+	origin_url=$(pwd)/one &&
+	(cd five &&
+	 git remote rm origin &&
+	 mkdir -p .git/remotes &&
+	 cat ../remotes_origin > .git/remotes/origin &&
+	 git remote rename origin origin &&
+	 ! test -f .git/remotes/origin &&
+	 test "$(git config remote.origin.url)" = "$origin_url" &&
+	 test "$(git config remote.origin.push)" = "refs/heads/master:refs/heads/upstream" &&
+	 test "$(git config remote.origin.fetch)" = "refs/heads/master:refs/heads/origin")
+'
+
 test_done
-- 
1.6.0.2

```

## Miklos Vajna, 2008-11-12 17:11

Subject: [PATCH 3/4] git-remote rename: support branches->config migration
Message-ID: <c3744d00a3d612a637cf520d2719492265e4f061.1226508805.git.vmiklos@frugalware.org>
URL: https://gitlist.dev/e/c3744d00a3d612a637cf520d2719492265e4f061.1226508805.git.vmiklos%40frugalware.org
In-Reply-To: <d99804ad3579d4882e8241d9dcaee1b7dd6508af.1226508805.git.vmiklos@frugalware.org>

```
This is similar to the remotes->config one, but it makes the
branches->config conversion possible.

Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
---
 builtin-remote.c  |    6 +++++-
 t/t5505-remote.sh |   12 ++++++++++++
 2 files changed, 17 insertions(+), 1 deletions(-)

diff --git a/builtin-remote.c b/builtin-remote.c
index 4fa64a2..5b525c7 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -384,6 +384,8 @@ static int migrate_file(struct remote *remote)
 					remote->fetch_refspec[i], buf.buf);
 	if (remote->origin == REMOTE_REMOTES)
 		path = git_path("remotes/%s", remote->name);
+	else if (remote->origin == REMOTE_BRANCHES)
+		path = git_path("branches/%s", remote->name);
 	if (path && unlink(path))
 		warning("failed to remove '%s'", path);
 	return 0;
@@ -411,7 +413,9 @@ static int mv(int argc, const char **argv)
 	if (!oldremote)
 		die("No such remote: %s", rename.old);
 
-	if (!strcmp(rename.old, rename.new) && oldremote->origin == REMOTE_REMOTES)
+	if (!strcmp(rename.old, rename.new) &&
+			(oldremote->origin == REMOTE_REMOTES ||
+			 oldremote->origin == REMOTE_BRANCHES))
 		return migrate_file(oldremote);
 
 	newremote = remote_get(rename.new);
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index 1567631..1f59960 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -364,4 +364,16 @@ test_expect_success 'migrate a remote from named file in $GIT_DIR/remotes' '
 	 test "$(git config remote.origin.fetch)" = "refs/heads/master:refs/heads/origin")
 '
 
+test_expect_success 'migrate a remote from named file in $GIT_DIR/branches' '
+	git clone one six &&
+	origin_url=$(pwd)/one &&
+	(cd six &&
+	 git remote rm origin &&
+	 echo "$origin_url" > .git/branches/origin &&
+	 git remote rename origin origin &&
+	 ! test -f .git/branches/origin &&
+	 test "$(git config remote.origin.url)" = "$origin_url" &&
+	 test "$(git config remote.origin.fetch)" = "refs/heads/master:refs/heads/origin")
+'
+
 test_done
-- 
1.6.0.2

```

## Miklos Vajna, 2008-11-12 17:11

Subject: [PATCH 4/4] git-remote: document the migration feature of the rename subcommand
Message-ID: <a8b13b05417ca3ecc360472c7c44e824402aa6e6.1226508805.git.vmiklos@frugalware.org>
URL: https://gitlist.dev/e/a8b13b05417ca3ecc360472c7c44e824402aa6e6.1226508805.git.vmiklos%40frugalware.org
In-Reply-To: <c3744d00a3d612a637cf520d2719492265e4f061.1226508805.git.vmiklos@frugalware.org>

```
Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
---
 Documentation/git-remote.txt |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt
index 7b227b3..fad983e 100644
--- a/Documentation/git-remote.txt
+++ b/Documentation/git-remote.txt
@@ -66,6 +66,10 @@ was passed.
 
 Rename 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.
 
 'rm'::
 
-- 
1.6.0.2

```
