9front - general discussion about 9front
 help / color / mirror / Atom feed
From: ori@eigenstate.org
To: 9front@9front.org
Subject: [9front] git/merge: preserve exec bit correctly
Date: Sat, 16 Apr 2022 17:13:04 -0400	[thread overview]
Message-ID: <25433F41CD401BB8B6FA55036C80E4F1@eigenstate.org> (raw)

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,18 @@
 	' $*
 }
 
-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 {
+		if(test -x $2 && {! test -x $1 || ! test -x $3})
+			mergedperms='-x'
+		if not
+			mergedperms='+x'
 		status=()
+	}
 }
 
 fn whoami{
@@ -76,9 +81,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,


             reply	other threads:[~2022-04-16 21:14 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-16 21:13 ori [this message]
2022-04-16 21:46 ` ori
2022-04-19  8:46   ` igor
2022-04-19 14:18     ` ori
2022-04-26  6:10       ` igor

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=25433F41CD401BB8B6FA55036C80E4F1@eigenstate.org \
    --to=ori@eigenstate.org \
    --cc=9front@9front.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).