.PP
Trees are presented as directory listings, and blobs
as files.
+The repository controls the user permissions.
+The group and world permissions are derived by masking
+the user permissions with the permissions of the
+.I .git
+directory.
+The user and group presented is the same as the user and
+group of the
+.I .git
+directory.
.SH FILES
.TP
.SH BUGS
Symlinks are only partially supported.
-Symlinks are treated as regular files when reading.
-Modifying symlinks is unsupported.
+They will be followed when reading, but a commit that
+modifies a symlink is an error.
.PP
-There is no way to inspect the raw objects. This is
-a feature that would be useful for debugging.
+For efficiency, git/fs only loads repo permissions at startup
+
+.PP
+There is no way to inspect the raw objects.
+Inspecting raw objects would be useful for debugging.
char gitdir[512];
char *username;
+char *groupname;
char *mntpt = ".git/fs";
char **branches = nil;
Cache uqidcache[512];
d->mode = c->mode;
d->name = estrdup9p(name);
d->uid = estrdup9p(username);
- d->gid = estrdup9p(username);
+ d->gid = estrdup9p(groupname);
d->muid = estrdup9p(username);
if(o->type == GBlob || o->type == GTag){
d->qid.type = 0;
d->qid.type = strcmp(qroot[i], "ctl") == 0 ? 0 : QTDIR;
d->qid.path = qpath(nil, i, i, Qroot);
d->uid = estrdup9p(username);
- d->gid = estrdup9p(username);
+ d->gid = estrdup9p(groupname);
d->muid = estrdup9p(username);
d->mtime = c->mtime;
return 0;
d->qid.path = qpath(c, i, branchid(aux, aux->refpath), Qbranch | Internal);
d->mode = 0555 | DMDIR;
d->uid = estrdup9p(username);
- d->gid = estrdup9p(username);
+ d->gid = estrdup9p(groupname);
d->muid = estrdup9p(username);
d->mtime = c->mtime;
d->atime = c->mtime;
d->qid.type = o->type == GTree ? QTDIR : 0;
d->qid.path = qpath(c, i, o->id, aux->qdir);
d->mode = m;
- d->mode |= (o->type == GTree) ? 0755 : 0644;
d->atime = c->mtime;
d->mtime = c->mtime;
d->uid = estrdup9p(username);
- d->gid = estrdup9p(username);
+ d->gid = estrdup9p(groupname);
d->muid = estrdup9p(username);
d->name = estrdup9p(e->tree->ent[i].name);
d->length = o->size;
c = crumb(p, 0);
o = c->obj;
d->uid = estrdup9p(username);
- d->gid = estrdup9p(username);
+ d->gid = estrdup9p(groupname);
d->muid = estrdup9p(username);
d->mode = 0444;
d->atime = o->commit->ctime;
}else if(o->type == GCommit){
q->type = 0;
c->mtime = o->commit->mtime;
- c->mode = 0444;
+ c->mode = 0644;
assert(qdir == Qcommit || qdir == Qobject || qdir == Qcommittree || qdir == Qhead);
if(strcmp(name, "msg") == 0)
q->path = qpath(p, 0, o->id, Qcommitmsg);
aux = r->fid->aux;
c = crumb(aux, 0);
r->d.uid = estrdup9p(username);
- r->d.gid = estrdup9p(username);
+ r->d.gid = estrdup9p(groupname);
r->d.muid = estrdup9p(username);
r->d.qid = r->fid->qid;
r->d.mtime = c->mtime;
void
main(int argc, char **argv)
{
+ Dir *d;
+
gitinit();
ARGBEGIN{
case 'd':
if(argc != 0)
usage();
- username = getuser();
+ if((d = dirstat(".git")) == nil)
+ sysfatal("dirstat .git: %r");
+ username = strdup(d->uid);
+ groupname = strdup(d->gid);
+ free(d);
+
branches = emalloc(sizeof(char*));
branches[0] = nil;
postmountsrv(&gitsrv, nil, mntpt, MCREATE);
Packf *packf;
int npackf;
int openpacks;
+int gitdirmode = -1;
static void
clear(Object *o)
static void
parsetree(Object *o)
{
- int m, entsz, nent;
+ int m, a, entsz, nent;
Dirent *t, *ent;
char *p, *ep;
if(*p != ' ')
sysfatal("malformed tree %H: *p=(%d) %c\n", o->hash, *p, *p);
p++;
- t->mode = m & 0777;
+ /*
+ * only the stored permissions for the user
+ * are relevant; git fills group and world
+ * bits with whatever -- so to serve with
+ * useful permissions, replicate the mode
+ * of the git repo dir.
+ */
+ a = (m & 0777)>>6;
+ t->mode = ((a<<6)|(a<<3)|a) & gitdirmode;
t->ismod = 0;
t->islink = 0;
if(m == 0160000){
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);