[PATCH] vcs-svn: fix broken test 'keep content, but change mode'

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



svn symlinks are files with "link destination" content and a
"svn:special=*" property set. These are imported as blobs with
"destination" content and S_IFLNK mode. When svn copy a file without
altering it's content(but maybe altering it's mode), we reuse the blob
object thus loosing or not adding the "link " prefix.

But we take possible prefix into account when applying svn deltas. And
this is the only place we ask fast-import for original blob. So pretend
that we want to apply a zero delta to resolve the issue.

There is some overhead due to using a temporary file to store such a small
blob. But hopefully such node change is too rare to care.

Signed-off-by: Dmitry Ivankov <divanorama@xxxxxxxxx>
---
This could be done better if we just read the cat-blob to memory, added or
removed the "link " prefix and wrote it to the stream, because the link
destination should be a tiny string. But on the other hand it'd blow up
if for some reason it's huge.

And taking into account that changing file mode from/to link without a
content change should be extremely rare anyway, I think it's ok.

Maybe it is redundant to add svndiff0_identity function to just cat blob
to a temporary file. The excuse is that svndiff.c is the only user of this
temporary file and the cat-blob response, so keep it there.

The patch base is svn-fe branch at git://repo.or.cz/git/jrn.git
Not backporting it to git master because vcs-svn stuff differs quite much
around this change.

 t/t9010-svn-fe.sh     |    2 +-
 vcs-svn/fast_export.c |    6 +++++-
 vcs-svn/svndiff.c     |   17 +++++++++++++++++
 vcs-svn/svndiff.h     |    1 +
 vcs-svn/svndump.c     |   16 +++++++++++++++-
 5 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/t/t9010-svn-fe.sh b/t/t9010-svn-fe.sh
index b7eed24..b6bdfeb 100755
--- a/t/t9010-svn-fe.sh
+++ b/t/t9010-svn-fe.sh
@@ -413,7 +413,7 @@ test_expect_success PIPE 'action: add node without text' '
 	try_dump textless.dump must_fail
 '
 
-test_expect_failure PIPE 'change file mode but keep old content' '
+test_expect_success PIPE 'change file mode but keep old content' '
 	reinit_git &&
 	cat >expect <<-\EOF &&
 	OBJID
diff --git a/vcs-svn/fast_export.c b/vcs-svn/fast_export.c
index 19d7c34..8c7295f 100644
--- a/vcs-svn/fast_export.c
+++ b/vcs-svn/fast_export.c
@@ -209,7 +209,11 @@ static long apply_delta(off_t len, struct line_buffer *input,
 		preimage.max_off += strlen("link ");
 		check_preimage_overflow(preimage.max_off, 1);
 	}
-	if (svndiff0_apply(input, len, &preimage, out))
+
+	if (!input) {
+		if (svndiff0_identity(&preimage, out))
+			die("cannot cat blob");
+	} else if (svndiff0_apply(input, len, &preimage, out))
 		die("cannot apply delta");
 	if (old_data) {
 		/* Read the remainder of preimage and trailing newline. */
diff --git a/vcs-svn/svndiff.c b/vcs-svn/svndiff.c
index 9ee41bb..bf104db 100644
--- a/vcs-svn/svndiff.c
+++ b/vcs-svn/svndiff.c
@@ -306,3 +306,20 @@ int svndiff0_apply(struct line_buffer *delta, off_t delta_len,
 	}
 	return 0;
 }
+int svndiff0_identity(struct sliding_view *preimage, FILE *postimage)
+{
+	assert(preimage && postimage);
+	off_t pre_off = 0;
+
+	while (pre_off != preimage->max_off) {
+		size_t pre_len = 8192;
+		if (pre_off + pre_len > preimage->max_off)
+			pre_len = preimage->max_off - pre_off;
+		if (move_window(preimage, pre_off, pre_len) ||
+			write_strbuf(&preimage->buf, postimage))
+			return -1;
+		pre_off += pre_len;
+	}
+
+	return 0;
+}
diff --git a/vcs-svn/svndiff.h b/vcs-svn/svndiff.h
index 74eb464..5afa3f2 100644
--- a/vcs-svn/svndiff.h
+++ b/vcs-svn/svndiff.h
@@ -6,5 +6,6 @@ struct sliding_view;
 
 extern int svndiff0_apply(struct line_buffer *delta, off_t delta_len,
 		struct sliding_view *preimage, FILE *postimage);
+extern int svndiff0_identity(struct sliding_view *preimage, FILE *postimage);
 
 #endif
diff --git a/vcs-svn/svndump.c b/vcs-svn/svndump.c
index b1f4161..1e7ed48 100644
--- a/vcs-svn/svndump.c
+++ b/vcs-svn/svndump.c
@@ -285,7 +285,21 @@ static void handle_node(void)
 		/* For the fast_export_* functions, NULL means empty. */
 		old_data = NULL;
 	if (!have_text) {
-		fast_export_modify(node_ctx.dst.buf, node_ctx.type, old_data);
+		/*
+		 * This is clean content copy in svn, but we alter the content
+		 * of symlinks (add/remove "link " prefix used by svn). So when
+		 * mode changes from/to symlink specify (recreate) data inline.
+		 */
+		if (node_ctx.type != old_mode && (old_mode == REPO_MODE_LNK
+					|| node_ctx.type == REPO_MODE_LNK)) {
+
+			fast_export_modify(node_ctx.dst.buf,
+						node_ctx.type, "inline");
+			fast_export_blob_delta(node_ctx.type, old_mode,
+						old_data, 0, NULL);
+		} else
+			fast_export_modify(node_ctx.dst.buf,
+						node_ctx.type, old_data);
 		return;
 	}
 	if (!node_ctx.text_delta) {
-- 
1.7.3.4

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]