From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 23871 invoked from network); 16 Apr 2022 21:48:10 -0000 Received: from 9front.inri.net (168.235.81.73) by inbox.vuxu.org with ESMTPUTF8; 16 Apr 2022 21:48:10 -0000 Received: from mimir.eigenstate.org ([206.124.132.107]) by 9front; Sat Apr 16 17:46:19 -0400 2022 Received: from stockyard.myfiosgateway.com (cpe-68-174-86-38.nyc.res.rr.com [68.174.86.38]) by mimir.eigenstate.org (OpenSMTPD) with ESMTPSA id 7edca613 (TLSv1.2:ECDHE-RSA-AES256-SHA:256:NO) for <9front@9front.org>; Sat, 16 Apr 2022 14:46:11 -0700 (PDT) Message-ID: To: 9front@9front.org Date: Sat, 16 Apr 2022 17:46:08 -0400 From: ori@eigenstate.org In-Reply-To: <25433F41CD401BB8B6FA55036C80E4F1@eigenstate.org> MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit List-ID: <9front.9front.org> List-Help: X-Glyph: ➈ X-Bullshit: leveraged rich-client SOAP over SOAP CSS reduce/map framework Subject: Re: [9front] git/merge: preserve exec bit correctly Reply-To: 9front@9front.org Precedence: bulk Quoth ori@eigenstate.org: > 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'. diff 061ec57021a7c813844582f6f1973dafae6e668b uncommitted --- a//sys/lib/git/common.rc +++ b//sys/lib/git/common.rc @@ -29,13 +29,23 @@ ' $* } -fn present { +fn mergeperm { if(~ $1 /dev/null && cmp $2 $3>/dev/null) status=gone if not if (~ $3 /dev/null && cmp $1 $2>/dev/null) status=gone - if not + if not { + mergedperms='-x' + if(test -x $2){ + if(test -x $1 -a -x $3) + mergedperms='+x' + } + if not{ + if(test -x $1 -o -x $3) + mergedperms='+x' + } status=() + } } fn whoami{ @@ -76,9 +86,10 @@ if(! ape/diff3 -3 -m $ours $base $theirs > $tmp) echo merge needed: $out >[1=2] - if(present $ours $base $theirs){ + if(mergeperm $ours $base $theirs){ mv $tmp $out git/add $out + chmod $mergedperms $out } if not { rm -f $tmp $out --- a/sys/src/cmd/git/branch +++ b/sys/src/cmd/git/branch @@ -48,9 +48,12 @@ modified=`$nl{git/query -c HEAD $base | grep '^[^-]' | subst '^..'} deleted=`$nl{git/query -c HEAD $base | grep '^-' | subst '^..'} -if(! ~ $#modified 0 || {! ~ $#deleted 0 && ~ $#merge 0}){ - git/walk -fRMA $modified $deleted || - die 'uncommitted changes would be clobbered' +# if we're not merging, don't clobber existing changes. +if(~ $#merge 0){ + if(! ~ $#modified 0 || ! ~ $#deleted 0){ + git/walk -fRMA $modified $deleted || + die 'uncommitted changes would be clobbered' + } } if(~ $delete 1){ rm -f .git/$new @@ -97,10 +100,9 @@ rm -rf .git/index9/tracked/$m } if(~ $b file){ - if(cp -x -- $basedir/tree/$m $m) - walk -eq $m > .git/index9/tracked/$m - if not - echo -n > .git/index9/tracked/$m + cp -x -- $basedir/tree/$m $m + walk -eq $m > .git/index9/tracked/$m + touch $m } } --- a/sys/src/cmd/git/fs.c +++ b/sys/src/cmd/git/fs.c @@ -70,13 +70,14 @@ "ctl", }; -#define Eperm "permission denied"; -#define Eexist "does not exist"; -#define E2long "path too long"; -#define Enodir "not a directory"; -#define Erepo "unable to read repo"; -#define Egreg "wat"; -#define Ebadobj "invalid object"; +#define Eperm "permission denied" +#define Eexist "does not exist" +#define E2long "path too long" +#define Enodir "not a directory" +#define Erepo "unable to read repo" +#define Eobject "invalid object" +#define Egreg "wat" +#define Ebadobj "invalid object" char gitdir[512]; char *username; @@ -624,9 +625,9 @@ e = objwalk1(q, o->obj, o, c, name, Qobject, aux); }else{ if(hparse(&h, name) == -1) - return "invalid object name"; + return Eobject; if((c->obj = readobject(h)) == nil) - return "could not read object"; + return Eobject; if(c->obj->type == GBlob || c->obj->type == GTag){ c->mode = 0644; q->type = 0; @@ -805,6 +806,34 @@ } 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 gitstat(Req *r) { Gitaux *aux; @@ -830,6 +859,7 @@ .attach=gitattach, .walk1=gitwalk1, .clone=gitclone, + .open=gitopen, .read=gitread, .stat=gitstat, .destroyfid=gitdestroyfid,