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++;
--
⑨