git: plan9front

Download patch

ref: 5eb5831b056f59d389801e0f5358b2be85a4b82c
parent: c220d0acc67b3f5e0e8af2bbe41fa8e367e6aa60
author: Ori Bernstein <ori@eigenstate.org>
date: Thu Jul 25 22:44:21 EDT 2024

git/query: use git entry sorting when computing dir diff

directories need to sort as though they end with a '/',
when running through them for comparison, otherwise we
flag files as added and removed spuriously, leading to
them incorrectly getting deleted when merging commits.

--- a/sys/src/cmd/git/git.h
+++ b/sys/src/cmd/git/git.h
@@ -282,6 +282,7 @@
 void	unref(Object *);
 void	cache(Object *);
 Object	*emptydir(void);
+int	entcmp(void*, void*);
 
 /* object sets */
 void	osinit(Objset *);
--- a/sys/src/cmd/git/query.c
+++ b/sys/src/cmd/git/query.c
@@ -78,7 +78,7 @@
 		be = bp + b->tree->nent;
 	}
 	while(ap != ae && bp != be){
-		c = strcmp(ap->name, bp->name);
+		c = entcmp(ap, bp);
 		if(c == 0){
 			if(ap->mode == bp->mode && hasheq(&ap->h, &bp->h))
 				goto next;
--- a/sys/src/cmd/git/save.c
+++ b/sys/src/cmd/git/save.c
@@ -54,33 +54,6 @@
 	return a-> order < b->order ? -1 : 1;
 }
 
-int
-entcmp(void *pa, void *pb)
-{
-	char abuf[256], bbuf[256], *ae, *be;
-	Dirent *a, *b;
-
-	a = pa;
-	b = pb;
-	/*
-	 * If the files have the same name, they're equal.
-	 * Otherwise, If they're trees, they sort as thoug
-	 * there was a trailing slash.
-	 *
-	 * Wat.
-	 */
-	if(strcmp(a->name, b->name) == 0)
-		return 0;
-
-	ae = seprint(abuf, abuf + sizeof(abuf) - 1, a->name);
-	be = seprint(bbuf, bbuf + sizeof(bbuf) - 1, b->name);
-	if(a->mode & DMDIR)
-		*ae = '/';
-	if(b->mode & DMDIR)
-		*be = '/';
-	return strcmp(abuf, bbuf);
-}
-
 static int
 bwrite(void *p, void *buf, int nbuf)
 {
--- a/sys/src/cmd/git/util.c
+++ b/sys/src/cmd/git/util.c
@@ -35,6 +35,34 @@
 }
 
 int
+entcmp(void *pa, void *pb)
+{
+	char abuf[256], bbuf[256], *ae, *be;
+	Dirent *a, *b;
+	int r;
+
+	a = pa;
+	b = pb;
+	/*
+	 * If the files have the same name, they're equal.
+	 * Otherwise, If they're trees, they sort as thoug
+	 * there was a trailing slash.
+	 *
+	 * Wat.
+	 */
+	r = strcmp(a->name, b->name);
+	if(r == 0 || (a->mode&DMDIR) == 0 && (b->mode&DMDIR) == 0)
+		return r;
+	ae = seprint(abuf, abuf + sizeof(abuf) - 1, a->name);
+	be = seprint(bbuf, bbuf + sizeof(bbuf) - 1, b->name);
+	if(a->mode & DMDIR)
+		*ae = '/';
+	if(b->mode & DMDIR)
+		*be = '/';
+	return strcmp(abuf, bbuf);
+}
+
+int
 hasheq(Hash *a, Hash *b)
 {
 	return memcmp(a->h, b->h, sizeof(a->h)) == 0;
--