shithub: git9

Download patch

ref: 17e813bbac232ebb25273065f227674acbd97782
parent: 8000697e669a8c3b8ffed2df6c6c966727e8be9e
author: Ori Bernstein <[email protected]>
date: Wed Nov 25 21:42:53 EST 2020

git/push: allow mirrored upstreams (thanks kvik)

It's sometimes convenient to mirror repositories
to multiple locations. For example, you may be
maintaining a git server you don't yet fully trust,
and want to push to github as well.

After this change, duplicated remotes with the same
name will all get pushed to. For example:

	[remote "origin"]
		url=hjgit://orib.dev/git9
	[remote "origin"]
		url=git+ssh://[email protected]/oridb/git9
	[remote "origin"]
		url=git+ssh://[email protected]:~ori/git9

will push to all three locations on every 'git push'

--- a/conf.c
+++ b/conf.c
@@ -4,16 +4,22 @@
 
 #include "git.h"
 
+int	findroot;
+int	showall;
+int	nfile;
+char	*file[32];
+
 static int
 showconf(char *cfg, char *sect, char *key)
 {
 	char *ln, *p;
 	Biobuf *f;
-	int foundsect, nsect, nkey;
+	int foundsect, nsect, nkey, found;
 
 	if((f = Bopen(cfg, OREAD)) == nil)
 		return 0;
 
+	found = 0;
 	nsect = sect ? strlen(sect) : 0;
 	nkey = strlen(key);
 	foundsect = (sect == nil);
@@ -27,12 +33,16 @@
 				continue;
 			p = strip(p + 1);
 			print("%s\n", p);
-			free(ln);
-			return 1;
+			found = 1;
+			if(!showall){
+				free(ln);
+				goto done;
+			}
 		}
 		free(ln);
 	}
-	return 0;
+done:
+	return found;
 }
 
 
@@ -48,14 +58,13 @@
 void
 main(int argc, char **argv)
 {
-	char *file[32], repo[512], *p, *s;
-	int i, j, nfile, findroot;
+	char repo[512], *p, *s;
+	int i, j;
 
-	nfile = 0;
-	findroot = 0;
 	ARGBEGIN{
 	case 'f':	file[nfile++]=EARGF(usage());	break;
 	case 'r':	findroot++;			break;
+	case 'a':	showall++;			break;
 	default:	usage();			break;
 	}ARGEND;
 
--- a/push
+++ b/push
@@ -24,26 +24,28 @@
 if(~ $#upstream 0)
 	upstream=origin
 
-remote=`{git/conf 'remote "'$upstream'".url'}
+remotes=`$nl{git/conf -a 'remote "'$upstream'".url'}
 if(~ $#remote 0)
-	remote=$upstream
+	remotes=$upstream
 branch=-b^$branch
 if(! ~ $#remove 0)
 	remove=-r^$remove
-updates=`$nl{git/send $debug $force $branch $remove $remote || die $status}
-for(ln in $updates){
-	u=`{echo $ln}
-	refpath=`{echo $u(2) | subst '^refs/heads/' '.git/refs/remotes/'$upstream'/'}
-	switch($u(1)){
-	case update;
-		mkdir -p `{basename -d $refpath}
-		echo $u(4) > $refpath
-		echo $u(2)^':' $u(3) '=>' $u(4)
-	case delete;
-		echo $u(2)^': removed'
-		rm -f $refpath
-	case uptodate;
-		echo $u(2)^': up to date'
+for(remote in $remotes){
+	updates=`$nl{git/send $debug $force $branch $remove $remote || die $status}
+	for(ln in $updates){
+		u=`{echo $ln}
+		refpath=`{echo $u(2) | subst '^refs/heads/' '.git/refs/remotes/'$upstream'/'}
+		switch($u(1)){
+		case update;
+			mkdir -p `{basename -d $refpath}
+			echo $u(4) > $refpath
+			echo $u(2)^':' $u(3) '=>' $u(4)
+		case delete;
+			echo $u(2)^': removed'
+			rm -f $refpath
+		case uptodate;
+			echo $u(2)^': up to date'
+		}
 	}
 }
 exit ''