git/merge: preserve exec bit correctly
A while ago, qwx noticed that we clobbered the exec bit when merging files. This is not what we want, so we changed the operator precedence to avoid merging dirty files implicitly. But we do want to merge, because it's convenient for maintaining permissions. So, instead, we should do a 3 way merge of the exec bit. This patch does that, as well as reverting the rollback of that change. While we're here, we adjust the timestamps correctly in git/branch. This requires changes to git/fs, because without an open handler, lib9p allows opening any file with any mode, which confuses 'test -x'.
This commit is contained in:
parent
6949c4a707
commit
dba98f649c
2 changed files with 48 additions and 16 deletions
|
@ -48,10 +48,13 @@ if(~ $#newbr 0){
|
||||||
modified=`$nl{git/query -c HEAD $base | grep '^[^-]' | subst '^..'}
|
modified=`$nl{git/query -c HEAD $base | grep '^[^-]' | subst '^..'}
|
||||||
deleted=`$nl{git/query -c HEAD $base | grep '^-' | subst '^..'}
|
deleted=`$nl{git/query -c HEAD $base | grep '^-' | subst '^..'}
|
||||||
|
|
||||||
if(! ~ $#modified 0 || {! ~ $#deleted 0 && ~ $#merge 0}){
|
# if we're not merging, don't clobber existing changes.
|
||||||
|
if(~ $#merge 0){
|
||||||
|
if(! ~ $#modified 0 || ! ~ $#deleted 0){
|
||||||
git/walk -fRMA $modified $deleted ||
|
git/walk -fRMA $modified $deleted ||
|
||||||
die 'uncommitted changes would be clobbered'
|
die 'uncommitted changes would be clobbered'
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(~ $delete 1){
|
if(~ $delete 1){
|
||||||
rm -f .git/$new
|
rm -f .git/$new
|
||||||
echo 'deleted branch' $new
|
echo 'deleted branch' $new
|
||||||
|
@ -97,10 +100,9 @@ for(m in $cleanpaths){
|
||||||
rm -rf .git/index9/tracked/$m
|
rm -rf .git/index9/tracked/$m
|
||||||
}
|
}
|
||||||
if(~ $b file){
|
if(~ $b file){
|
||||||
if(cp -x -- $basedir/tree/$m $m)
|
cp -x -- $basedir/tree/$m $m
|
||||||
walk -eq $m > .git/index9/tracked/$m
|
walk -eq $m > .git/index9/tracked/$m
|
||||||
if not
|
touch $m
|
||||||
echo -n > .git/index9/tracked/$m
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,13 +70,14 @@ char *qroot[] = {
|
||||||
"ctl",
|
"ctl",
|
||||||
};
|
};
|
||||||
|
|
||||||
#define Eperm "permission denied";
|
#define Eperm "permission denied"
|
||||||
#define Eexist "does not exist";
|
#define Eexist "does not exist"
|
||||||
#define E2long "path too long";
|
#define E2long "path too long"
|
||||||
#define Enodir "not a directory";
|
#define Enodir "not a directory"
|
||||||
#define Erepo "unable to read repo";
|
#define Erepo "unable to read repo"
|
||||||
#define Egreg "wat";
|
#define Eobject "invalid object"
|
||||||
#define Ebadobj "invalid object";
|
#define Egreg "wat"
|
||||||
|
#define Ebadobj "invalid object"
|
||||||
|
|
||||||
char gitdir[512];
|
char gitdir[512];
|
||||||
char *username;
|
char *username;
|
||||||
|
@ -624,9 +625,9 @@ gitwalk1(Fid *fid, char *name, Qid *q)
|
||||||
e = objwalk1(q, o->obj, o, c, name, Qobject, aux);
|
e = objwalk1(q, o->obj, o, c, name, Qobject, aux);
|
||||||
}else{
|
}else{
|
||||||
if(hparse(&h, name) == -1)
|
if(hparse(&h, name) == -1)
|
||||||
return "invalid object name";
|
return Eobject;
|
||||||
if((c->obj = readobject(h)) == nil)
|
if((c->obj = readobject(h)) == nil)
|
||||||
return "could not read object";
|
return Eobject;
|
||||||
if(c->obj->type == GBlob || c->obj->type == GTag){
|
if(c->obj->type == GBlob || c->obj->type == GTag){
|
||||||
c->mode = 0644;
|
c->mode = 0644;
|
||||||
q->type = 0;
|
q->type = 0;
|
||||||
|
@ -804,6 +805,34 @@ gitread(Req *r)
|
||||||
respond(r, e);
|
respond(r, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gitopen(Req *r)
|
||||||
|
{
|
||||||
|
Gitaux *aux;
|
||||||
|
Crumb *c;
|
||||||
|
|
||||||
|
aux = r->fid->aux;
|
||||||
|
c = crumb(aux, 0);
|
||||||
|
switch(r->ifcall.mode&3){
|
||||||
|
default:
|
||||||
|
respond(r, "botched mode");
|
||||||
|
break;
|
||||||
|
case OWRITE:
|
||||||
|
respond(r, Eperm);
|
||||||
|
break;
|
||||||
|
case OREAD:
|
||||||
|
case ORDWR:
|
||||||
|
respond(r, nil);
|
||||||
|
break;
|
||||||
|
case OEXEC:
|
||||||
|
if((c->mode & 0111) == 0)
|
||||||
|
respond(r, Eperm);
|
||||||
|
else
|
||||||
|
respond(r, nil);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gitstat(Req *r)
|
gitstat(Req *r)
|
||||||
{
|
{
|
||||||
|
@ -830,6 +859,7 @@ Srv gitsrv = {
|
||||||
.attach=gitattach,
|
.attach=gitattach,
|
||||||
.walk1=gitwalk1,
|
.walk1=gitwalk1,
|
||||||
.clone=gitclone,
|
.clone=gitclone,
|
||||||
|
.open=gitopen,
|
||||||
.read=gitread,
|
.read=gitread,
|
||||||
.stat=gitstat,
|
.stat=gitstat,
|
||||||
.destroyfid=gitdestroyfid,
|
.destroyfid=gitdestroyfid,
|
||||||
|
|
Loading…
Reference in a new issue