ref: 7a9a9e674e8d963444abc8b5474cfa98ae4cf810
parent: 744de082b50aaffea83f16ca74997879a5d72b9e
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Mar 21 23:08:18 EDT 2026
git: correctly inherit permissions from the .git dir for directories git defaults to storing permission bits as 0o40000 for dirs by default, so when reconstruct permissons we need to put back the perms for the dir correctly, taking it from /.git.
--- a/sys/src/cmd/git/fs.c
+++ b/sys/src/cmd/git/fs.c
@@ -284,7 +284,7 @@
switch(i){case 0:
- d->mode = 0755 | DMDIR;
+ d->mode = DMDIR | gitdirmode;
d->name = estrdup9p("tree");d->qid.type = QTDIR;
d->qid.path = qpath(c, i, o->id, Qtree);
@@ -495,7 +495,7 @@
q->type = (w->type == GTree) ? QTDIR : 0;
q->path = qpath(p, i, w->id, qdir);
c->mode = m;
- c->mode |= (w->type == GTree) ? DMDIR|0755 : 0644;
+ c->mode |= (w->type == GTree) ? (DMDIR|0755) : 0644;
c->obj = w;
break;
}
@@ -521,7 +521,7 @@
q->type = QTDIR;
q->path = qpath(p, 4, o->id, Qtree);
unref(c->obj);
- c->mode = DMDIR | 0755;
+ c->mode = DMDIR | gitdirmode;
c->obj = readobject(o->commit->tree);
if(c->obj == nil)
sysfatal("could not read object %H: %r", o->commit->tree);--- a/sys/src/cmd/git/git.h
+++ b/sys/src/cmd/git/git.h
@@ -261,6 +261,7 @@
extern Hash Zhash;
extern int chattygit;
extern int interactive;
+extern int gitdirmode;
#pragma varargck type "H" Hash
#pragma varargck type "T" int
--- a/sys/src/cmd/git/pack.c
+++ b/sys/src/cmd/git/pack.c
@@ -70,7 +70,6 @@
Packf *packf;
int npackf;
int openpacks;
-int gitdirmode = -1;
static void
clear(Object *o)
@@ -958,18 +957,21 @@
* useful permissions, replicate the mode
* of the git repo dir.
*/
- a = (m & 0777)>>6;
- t->mode = ((a<<6)|(a<<3)|a) & gitdirmode;
+ t->mode = gitdirmode;
t->ismod = 0;
t->islink = 0;
- if(m == 0160000){+ if(m & 0777){+ a = (m & 0777)>>6;
+ t->mode &= ((a<<6)|(a<<3)|a);
+ }
+ if(m == 0160000){ /* module */t->mode |= DMDIR;
t->ismod = 1;
- }else if(m == 0120000){+ }else if(m == 0120000){ /* symlink */t->mode = 0;
t->islink = 1;
}
- if(m & 0040000)
+ if(m & 0040000) /* dir */
t->mode |= DMDIR;
t->name = p;
p = memchr(p, 0, ep - p);
@@ -1130,14 +1132,7 @@
readobject(Hash h)
{Object *o;
- Dir *d;
- if(gitdirmode == -1){- if((d = dirstat(".git")) == nil)- sysfatal("stat .git: %r");- gitdirmode = d->mode & 0777;
- free(d);
- }
if((o = readidxobject(nil, h, 0)) == nil)
return nil;
parseobject(o);
--- a/sys/src/cmd/git/util.c
+++ b/sys/src/cmd/git/util.c
@@ -4,12 +4,12 @@
#include "git.h"
-Reprog *authorpat;
-Hash Zhash;
+Reprog *authorpat;
+Hash Zhash;
+int chattygit;
+int interactive = 1;
+int gitdirmode = -1;
-int chattygit;
-int interactive = 1;
-
enum {Seed = 2928213749ULL
};
@@ -246,6 +246,8 @@
void
gitinit(void)
{+ Dir *d;
+
fmtinstall('H', Hfmt); fmtinstall('T', Tfmt); fmtinstall('O', Ofmt);@@ -254,6 +256,12 @@
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);
+ }
}
int
--
⑨