git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC][PATCH] Rewriting revs in place in push target repository
@ 2005-08-13 21:47 Petr Baudis
  2005-08-13 22:20 ` Linus Torvalds
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Petr Baudis @ 2005-08-13 21:47 UTC (permalink / raw)
  To: git

Rewrite refs in place in receive-pack & friends

When updating a ref, it would write a new file with the new ref and
then rename it, overwriting the original file. The problem is that
this destroys permissions and ownership of the original file, which is
troublesome especially in multiuser environment, like the one I live in.

This might be controversial, but it's a showbreaker for me wrt. pushing
now. Some alternative solution barely solving my particular situation
might be surely worked out, but this is more general. The question is:

* Does this break atomicity?

	I think it does not in real setups, since thanks to O_RDWR the
	file should be overwritten only when the write() happens.
	Can a 41-byte write() be non-atomic in any real conditions?

* Does this break with full disk/quota?

	I'm not sure - we are substituting 41 bytes by another 41
	bytes; will the system ever be evil enough to truncate the
	file, then decide the user is over his quota and not write
	the new contents?

Signed-off-by: Petr Baudis <pasky@suse.cz>

diff --git a/receive-pack.c b/receive-pack.c
--- a/receive-pack.c
+++ b/receive-pack.c
@@ -92,13 +92,7 @@ static int run_update_hook(const char *r
 static int update(const char *name,
 		  unsigned char *old_sha1, unsigned char *new_sha1)
 {
-	char new_hex[60], *old_hex, *lock_name;
-	int newfd, namelen, written;
-
-	namelen = strlen(name);
-	lock_name = xmalloc(namelen + 10);
-	memcpy(lock_name, name, namelen);
-	memcpy(lock_name + namelen, ".lock", 6);
+	char new_hex[60], *old_hex;
 
 	strcpy(new_hex, sha1_to_hex(new_sha1));
 	old_hex = sha1_to_hex(old_sha1);
@@ -106,38 +100,38 @@ static int update(const char *name,
 		return error("unpack should have generated %s, "
 			     "but I can't find it!", new_hex);
 
-	safe_create_leading_directories(lock_name);
-
-	newfd = open(lock_name, O_CREAT | O_EXCL | O_WRONLY, 0666);
-	if (newfd < 0)
-		return error("unable to create %s (%s)",
-			     lock_name, strerror(errno));
-
-	/* Write the ref with an ending '\n' */
-	new_hex[40] = '\n';
-	new_hex[41] = 0;
-	written = write(newfd, new_hex, 41);
-	/* Remove the '\n' again */
-	new_hex[40] = 0;
-
-	close(newfd);
-	if (written != 41) {
-		unlink(lock_name);
-		return error("unable to write %s", lock_name);
-	}
 	if (verify_old_ref(name, old_hex) < 0) {
-		unlink(lock_name);
 		return error("%s changed during push", name);
 	}
 	if (run_update_hook(name, old_hex, new_hex)) {
-		unlink(lock_name);
 		return error("hook declined to update %s\n", name);
 	}
-	else if (rename(lock_name, name) < 0) {
-		unlink(lock_name);
-		return error("unable to replace %s", name);
-	}
 	else {
+		char *name2;
+		int newfd, written;
+
+		name2 = strdup(name);
+		safe_create_leading_directories(name2);
+		free(name2);
+
+		newfd = open(name, O_CREAT | O_RDWR, 0666);
+		if (newfd < 0)
+			return error("unable to create %s (%s)",
+				     name, strerror(errno));
+
+		/* Write the ref with an ending '\n' */
+		new_hex[40] = '\n';
+		new_hex[41] = 0;
+		written = write(newfd, new_hex, 41);
+		/* Remove the '\n' again */
+		new_hex[40] = 0;
+
+		close(newfd);
+		if (written != 41) {
+			unlink(name);
+			return error("unable to write %s", name);
+		}
+
 		fprintf(stderr, "%s: %s -> %s\n", name, old_hex, new_hex);
 		return 0;
 	}

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2005-09-15 17:16 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-08-13 21:47 [RFC][PATCH] Rewriting revs in place in push target repository Petr Baudis
2005-08-13 22:20 ` Linus Torvalds
2005-08-14  0:55 ` Junio C Hamano
2005-08-14  2:10   ` Linus Torvalds
2005-09-15 17:16   ` Petr Baudis
2005-08-14  2:20 ` Chris Wedgwood
2005-08-14 10:02   ` Matthias Urlichs

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).