"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Stefan Sperling <stsp@stsp.name>
Subject:
tweak git config created by 'got clone'
To:
gameoftrees@openbsd.org
Date:
Tue, 12 Jan 2021 23:15:57 +0100

Download raw body.

Thread
Could someone with Git experience please take a look at this?

My goal is to have 'got clone' generate Git config files that make
'git fetch' behave more or less, if not perfectly, like 'got fetch'
will behave in the presence of a got.conf created by 'got clone'.

Instead of using wildcards like refs/heads/*, list the branches and refs
which were passed on the command line and/or fetched by default.
This matches what the generated got.conf file contains.

Add a refspec that fetches all of refs/tags/* into refs/tags/*
This matches Got's hard-coded behaviour. My assumption is that tag names are
a global resource across all clones of the repository, and fireworks should
occur if this assumption is violated. This makes sense to me because Got is
focussing on the centralized-repo workflow. Truly distributed workflows are
rare and require a lot of Git's crazy flexibility.

I noticed that we currently enable 'git fetch --force', which I expect could
probably lead to surprises. I've dropped the + prefix from all refspecs.
Git users will probably know when using --force is safe.

I'm not sure what 'mirror = true' will accomplish without the corresponding
fetch refspec "+refs/*:refs/*". I have dropped 'mirror = true' for now.

Do these changes make sense?

diff 99495ddb79841fe89b0746d35a49bb81e9220096 /home/stsp/src/got
blob - 588f144e15210cef646e4d3b143f8cb74e7e5abe
file + got/got.c
--- got/got.c
+++ got/got.c
@@ -1277,7 +1277,7 @@ create_gitconfig(const char *git_url, const char *defa
 	char *gitconfig = NULL;
 	FILE *gitconfig_file = NULL;
 	char *branches = NULL, *refs = NULL;
-	const char *branchname, *mirror = NULL;
+	const char *branchname;
 	ssize_t n;
 
 	/* Create a config file Git can understand. */
@@ -1291,16 +1291,15 @@ create_gitconfig(const char *git_url, const char *defa
 		err = got_error_from_errno2("fopen", gitconfig_path);
 		goto done;
 	}
-	if (mirror_references) {
-		mirror = "\tmirror = true\n";
-		branches = strdup("\tfetch = +refs/*:refs/*\n");
-		if (branches == NULL) {
-			err = got_error_from_errno("strdup");
-			goto done;
-		}
-	} else if (fetch_all_branches) {
-		if (asprintf(&branches,
-		    "\tfetch = +refs/heads/*:refs/remotes/%s/*\n",
+	if (fetch_all_branches) {
+		if (mirror_references) {
+			if (asprintf(&branches,
+			    "\tfetch = refs/heads/*:refs/heads/*\n") == -1) {
+				err = got_error_from_errno("asprintf");
+				goto done;
+			}
+		} else if (asprintf(&branches,
+		    "\tfetch = refs/heads/*:refs/remotes/%s/*\n",
 		    GOT_FETCH_DEFAULT_REMOTE_NAME) == -1) {
 			err = got_error_from_errno("asprintf");
 			goto done;
@@ -1312,8 +1311,16 @@ create_gitconfig(const char *git_url, const char *defa
 			branchname = pe->path;
 			if (strncmp(branchname, "refs/heads/", 11) == 0)
 				branchname += 11;
-			if (asprintf(&s,
-			    "%s\tfetch = +refs/heads/%s:refs/remotes/%s/%s\n",
+			if (mirror_references) {
+				if (asprintf(&s,
+				    "%s\tfetch = refs/heads/%s:refs/heads/%s\n",
+				    branches ? branches : "",
+				    branchname, branchname) == -1) {
+					err = got_error_from_errno("asprintf");
+					goto done;
+				}
+			} else if (asprintf(&s,
+			    "%s\tfetch = refs/heads/%s:refs/remotes/%s/%s\n",
 			    branches ? branches : "",
 			    branchname, GOT_FETCH_DEFAULT_REMOTE_NAME,
 			    branchname) == -1) {
@@ -1334,23 +1341,37 @@ create_gitconfig(const char *git_url, const char *defa
 				branchname += 11;
 		} else
 			branchname = "*"; /* fall back to all branches */
-		if (asprintf(&branches,
-		    "\tfetch = +refs/heads/%s:refs/remotes/%s/%s\n",
+		if (mirror_references) {
+			if (asprintf(&branches,
+			    "\tfetch = refs/heads/%s:refs/heads/%s\n",
+			    branchname, branchname) == -1) {
+				err = got_error_from_errno("asprintf");
+				goto done;
+			}
+		} else if (asprintf(&branches,
+		    "\tfetch = refs/heads/%s:refs/remotes/%s/%s\n",
 		    branchname, GOT_FETCH_DEFAULT_REMOTE_NAME,
 		    branchname) == -1) {
 			err = got_error_from_errno("asprintf");
 			goto done;
 		}
 	}
-	if (!mirror_references && !TAILQ_EMPTY(wanted_refs)) {
+	if (!TAILQ_EMPTY(wanted_refs)) {
 		struct got_pathlist_entry *pe;
 		TAILQ_FOREACH(pe, wanted_refs, entry) {
 			char *s;
 			const char *refname = pe->path;
 			if (strncmp(refname, "refs/", 5) == 0)
 				refname += 5;
-			if (asprintf(&s,
-			    "%s\tfetch = +refs/%s:refs/remotes/%s/%s\n",
+			if (mirror_references) {
+				if (asprintf(&s,
+				    "%s\tfetch = refs/%s:refs/%s\n",
+				    refs ? refs : "", refname, refname) == -1) {
+					err = got_error_from_errno("asprintf");
+					goto done;
+				}
+			} else if (asprintf(&s,
+			    "%s\tfetch = refs/%s:refs/remotes/%s/%s\n",
 			    refs ? refs : "",
 			    refname, GOT_FETCH_DEFAULT_REMOTE_NAME,
 			    refname) == -1) {
@@ -1367,9 +1388,9 @@ create_gitconfig(const char *git_url, const char *defa
 	    "\turl = %s\n"
 	    "%s"
 	    "%s"
-	    "%s",
+	    "\tfetch = refs/tags/*:refs/tags/*\n",
 	    GOT_FETCH_DEFAULT_REMOTE_NAME, git_url, branches ? branches : "",
-	    refs ? refs : "", mirror ? mirror : "") == -1) {
+	    refs ? refs : "") == -1) {
 		err = got_error_from_errno("asprintf");
 		goto done;
 	}
blob - 44c5e030d3c0d68974cecd35b85f6edabc096ee3
file + regress/cmdline/clone.sh
--- regress/cmdline/clone.sh
+++ regress/cmdline/clone.sh
@@ -114,7 +114,8 @@ EOF
 
 [remote "origin"]
 	url = ssh://127.0.0.1$testroot/repo
-	fetch = +refs/heads/master:refs/remotes/origin/master
+	fetch = refs/heads/master:refs/remotes/origin/master
+	fetch = refs/tags/*:refs/tags/*
 EOF
 	cmp -s $testroot/repo-clone/config $testroot/config.expected
 	ret="$?"
@@ -214,7 +215,8 @@ EOF
 
 [remote "origin"]
 	url = ssh://127.0.0.1$testroot/repo
-	fetch = +refs/heads/foo:refs/remotes/origin/foo
+	fetch = refs/heads/foo:refs/remotes/origin/foo
+	fetch = refs/tags/*:refs/tags/*
 EOF
 	cmp -s $testroot/repo-clone/config $testroot/config.expected
 	ret="$?"
@@ -290,7 +292,8 @@ EOF
 
 [remote "origin"]
 	url = ssh://127.0.0.1$testroot/repo
-	fetch = +refs/heads/*:refs/remotes/origin/*
+	fetch = refs/heads/*:refs/remotes/origin/*
+	fetch = refs/tags/*:refs/tags/*
 EOF
 	cmp -s $testroot/repo-clone/config $testroot/config.expected
 	ret="$?"
@@ -362,8 +365,8 @@ EOF
 
 [remote "origin"]
 	url = ssh://127.0.0.1$testroot/repo
-	fetch = +refs/*:refs/*
-	mirror = true
+	fetch = refs/heads/master:refs/heads/master
+	fetch = refs/tags/*:refs/tags/*
 EOF
 	cmp -s $testroot/repo-clone/config $testroot/config.expected
 	ret="$?"
@@ -435,8 +438,8 @@ EOF
 
 [remote "origin"]
 	url = ssh://127.0.0.1$testroot/repo
-	fetch = +refs/*:refs/*
-	mirror = true
+	fetch = refs/heads/*:refs/heads/*
+	fetch = refs/tags/*:refs/tags/*
 EOF
 	cmp -s $testroot/repo-clone/config $testroot/config.expected
 	ret="$?"
@@ -512,8 +515,9 @@ EOF
 
 [remote "origin"]
 	url = ssh://127.0.0.1$testroot/repo
-	fetch = +refs/heads/master:refs/remotes/origin/master
-	fetch = +refs/hoo:refs/remotes/origin/hoo
+	fetch = refs/heads/master:refs/remotes/origin/master
+	fetch = refs/hoo:refs/remotes/origin/hoo
+	fetch = refs/tags/*:refs/tags/*
 EOF
 	cmp -s $testroot/repo-clone/config $testroot/config.expected
 	ret="$?"
@@ -587,8 +591,9 @@ EOF
 
 [remote "origin"]
 	url = ssh://127.0.0.1$testroot/repo
-	fetch = +refs/heads/foo:refs/remotes/origin/foo
-	fetch = +refs/hoo/boo/zoo:refs/remotes/origin/hoo/boo/zoo
+	fetch = refs/heads/foo:refs/remotes/origin/foo
+	fetch = refs/hoo/boo/zoo:refs/remotes/origin/hoo/boo/zoo
+	fetch = refs/tags/*:refs/tags/*
 EOF
 	cmp -s $testroot/repo-clone/config $testroot/config.expected
 	ret="$?"
@@ -660,8 +665,9 @@ EOF
 
 [remote "origin"]
 	url = ssh://127.0.0.1$testroot/repo
-	fetch = +refs/*:refs/*
-	mirror = true
+	fetch = refs/heads/master:refs/heads/master
+	fetch = refs/hoo:refs/hoo
+	fetch = refs/tags/*:refs/tags/*
 EOF
 	cmp -s $testroot/repo-clone/config $testroot/config.expected
 	ret="$?"
@@ -731,8 +737,9 @@ EOF
 
 [remote "origin"]
 	url = ssh://127.0.0.1$testroot/repo
-	fetch = +refs/heads/foo:refs/remotes/origin/foo
-	fetch = +refs/heads/bar:refs/remotes/origin/bar
+	fetch = refs/heads/foo:refs/remotes/origin/foo
+	fetch = refs/heads/bar:refs/remotes/origin/bar
+	fetch = refs/tags/*:refs/tags/*
 EOF
 	cmp -s $testroot/repo-clone/config $testroot/config.expected
 	ret="$?"