git: 9front

Download patch

ref: e7ff6450ac77f81a4b15f1b93577224a5e92565a
parent: 65dca5e4ff03dd124b3c6d8a12132bf6dd931771
author: Ori Bernstein <ori@eigenstate.org>
date: Fri Mar 27 03:33:56 EDT 2026

git: fix and improve subdirectory handling

fold findrepo() into gitinit(), use it consistently,
and chdir into the root correctly whenever it makes
sense; git/fs, git/conf, and git/walk are now made
subdir aware.

--- a/sys/src/cmd/git/conf.c
+++ b/sys/src/cmd/git/conf.c
@@ -68,16 +68,17 @@
 	default:	usage();			break;
 	}ARGEND;
 
+	gitinit(repo, sizeof(repo), &nrel);
 	if(findroot){
-		if(findrepo(repo, sizeof(repo), &nrel) == -1)
-			sysfatal("%r");
 		print("%s\n", repo);
 		exits(nil);
 	}
 	if(nfile == 0){
-		file[nfile++] = ".git/config";
+		if((file[nfile++] = smprint("%s/.git/config", repo)) == nil)
+			sysfatal("smprint: %r");
 		if((p = getenv("home")) != nil)
-			file[nfile++] = smprint("%s/lib/git/config", p);
+			if((file[nfile++] = smprint("%s/lib/git/config", p)) == nil)
+				sysfatal("smprint: %r");
 		file[nfile++] = "/sys/lib/git/config";
 	}
 
--- a/sys/src/cmd/git/fs.c
+++ b/sys/src/cmd/git/fs.c
@@ -892,9 +892,14 @@
 void
 main(int argc, char **argv)
 {
+	char repo[512];
+	int nelt;
 	Dir *d;
 
-	gitinit();
+	gitinit(repo, sizeof(repo), &nelt);
+	if(chdir(repo) == -1)
+		sysfatal("chdir: %r");
+
 	ARGBEGIN{
 	case 'd':
 		chatty9p++;
--- a/sys/src/cmd/git/get.c
+++ b/sys/src/cmd/git/get.c
@@ -500,7 +500,7 @@
 		break;
 	}ARGEND;
 
-	gitinit();
+	gitinit(nil, 0, nil);
 	if(argc != 1)
 		usage();
 
--- a/sys/src/cmd/git/git.h
+++ b/sys/src/cmd/git/git.h
@@ -272,7 +272,7 @@
 int Ofmt(Fmt*);
 int Qfmt(Fmt*);
 
-void gitinit(void);
+void gitinit(char*, int, int*);
 
 /* object io */
 int	resolverefs(Hash **, char *);
@@ -319,7 +319,6 @@
 int	hassuffix(char *, char *);
 int	swapsuffix(char *, int, char *, char *, char *);
 char	*strip(char *);
-int	findrepo(char *, int, int*);
 int	showprogress(int, int);
 u64int	murmurhash2(void*, usize);
 Qid	parseqid(char*);
--- a/sys/src/cmd/git/log.c
+++ b/sys/src/cmd/git/log.c
@@ -261,8 +261,7 @@
 		break;
 	}ARGEND;
 
-	if(findrepo(repo, sizeof(repo), &nrel) == -1)
-		sysfatal("find root: %r");
+	gitinit(repo, sizeof(repo), &nrel);
 	nrepo = strlen(repo);
 	if(argc != 0){
 		if(getwd(path, sizeof(path)) == nil)
@@ -286,7 +285,6 @@
 	if(chdir(repo) == -1)
 		sysfatal("chdir: %r");
 
-	gitinit();
 	tmfmtinstall();
 	out = Bfdopen(1, OWRITE);
 	if(queryexpr != nil)
--- a/sys/src/cmd/git/query.c
+++ b/sys/src/cmd/git/query.c
@@ -165,13 +165,10 @@
 	default:	usage();	break;
 	}ARGEND;
 
-	gitinit();
 	fmtinstall('P', Pfmt);
-
 	if(argc == 0)
 		usage();
-	if(findrepo(repo, sizeof(repo), &nrel) == -1)
-		sysfatal("find root: %r");
+	gitinit(repo, sizeof(repo), &nrel);
 	if(chdir(repo) == -1)
 		sysfatal("chdir: %r");
 	if((objpfx = smprint("%s/.git/fs/object/", repo)) == nil)
--- a/sys/src/cmd/git/repack.c
+++ b/sys/src/cmd/git/repack.c
@@ -59,7 +59,7 @@
 		usage();
 	}ARGEND;
 
-	gitinit();
+	gitinit(nil, 0, nil);
 	refs = nil;
 	if((nrefs = listrefs(&refs, &names)) == -1)
 		sysfatal("load refs: %r");
--- a/sys/src/cmd/git/save.c
+++ b/sys/src/cmd/git/save.c
@@ -383,7 +383,7 @@
 	Biobuf *f;
 	Object *t;
 
-	gitinit();
+	gitinit(nil, 0, nil);
 	if(access(".git", AEXIST) != 0)
 		sysfatal("could not find git repo: %r");
 	if(getwd(cwd, sizeof(cwd)) == nil)
--- a/sys/src/cmd/git/send.c
+++ b/sys/src/cmd/git/send.c
@@ -268,7 +268,7 @@
 		break;
 	}ARGEND;
 
-	gitinit();
+	gitinit(nil, 0, nil);
 	if(argc != 1)
 		usage();
 	if(gitconnect(&c, argv[0], "receive") == -1)
--- a/sys/src/cmd/git/serve.c
+++ b/sys/src/cmd/git/serve.c
@@ -578,7 +578,7 @@
 		break;
 	}ARGEND;
 
-	gitinit();
+	gitinit(nil, 0, nil);
 	interactive = 0;
 	if(rfork(RFNAMEG) == -1)
 		sysfatal("rfork: %r");
--- a/sys/src/cmd/git/util.c
+++ b/sys/src/cmd/git/util.c
@@ -243,9 +243,33 @@
 		return fmtprint(fmt, "%llux.%lud.%hhx", q.path, q.vers, q.type);
 }
 
+/* Finds the directory containing the git repo. */
+static void
+findrepo(char *buf, int nbuf, int *nrel)
+{
+	char *p, *suff;
+
+	suff = "/.git/HEAD";
+	if(getwd(buf, nbuf - strlen(suff) - 1) == nil)
+		sysfatal("getwd: %r");
+
+	*nrel = 0;
+	for(p = buf + strlen(buf); p != nil; p = strrchr(buf, '/')){
+		strcpy(p, suff);
+		if(access(buf, AEXIST) == 0){
+			p[p == buf] = '\0';
+			return;
+		}
+		*nrel += 1;
+		*p = '\0';
+	}
+	sysfatal("not a git repository");
+}
+
 void
-gitinit(void)
+gitinit(char *root, int nroot, int *nrel)
 {
+	char repo[512] = ".git";
 	Dir *d;
 
 	fmtinstall('H', Hfmt);
@@ -256,12 +280,14 @@
 	deflateinit();
 	authorpat = regcomp("[\t ]*(.*)[\t ]+([0-9]+)[\t ]*([\\-+]?[0-9]+)?");
 	osinit(&objcache);
-	if(gitdirmode == -1){
-		if((d = dirstat(".git")) == nil)
-			sysfatal("stat .git: %r");
-		gitdirmode = d->mode & 0777;
-		free(d);
+	if(root != nil){
+		findrepo(root, nroot, nrel);
+		snprint(repo, sizeof(repo), "%s/.git", root);
 	}
+	if((d = dirstat(repo)) == nil)
+		sysfatal("stat %s: %r", repo);
+	gitdirmode = d->mode & 0777;
+	free(d);
 }
 
 int
@@ -341,30 +367,6 @@
 	va_start(ap, fmt);
 	vfprint(2, fmt, ap);
 	va_end(ap);
-}
-
-/* Finds the directory containing the git repo. */
-int
-findrepo(char *buf, int nbuf, int *nrel)
-{
-	char *p, *suff;
-
-	suff = "/.git/HEAD";
-	if(getwd(buf, nbuf - strlen(suff) - 1) == nil)
-		return -1;
-
-	*nrel = 0;
-	for(p = buf + strlen(buf); p != nil; p = strrchr(buf, '/')){
-		strcpy(p, suff);
-		if(access(buf, AEXIST) == 0){
-			p[p == buf] = '\0';
-			return 0;
-		}
-		*nrel += 1;
-		*p = '\0';
-	}
-	werrstr("not a git repository");
-	return -1;
 }
 
 int
--- a/sys/src/cmd/git/walk.c
+++ b/sys/src/cmd/git/walk.c
@@ -392,16 +392,13 @@
 	Hash h;
 	Dir rn;
 
-	gitinit();
-	if(access(".git/fs/ctl", AEXIST) != 0)
-		sysfatal("no running git/fs");
+	gitinit(repopath, sizeof(repopath), &nrel);
 	if(getwd(wdirpath, sizeof(wdirpath)) == nil)
 		sysfatal("getwd: %r");
-	if(findrepo(repopath, sizeof(repopath), &nrel) == -1)
-		sysfatal("find root: %r");
 	if(chdir(repopath) == -1)
 		sysfatal("chdir: %r");
-
+	if(access(".git/fs/ctl", AEXIST) != 0)
+		sysfatal("no running git/fs");
 	ARGBEGIN{
 	case 'q':
 		quiet++;
--