summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rwxr-xr-xt/t9011-svn-da.sh35
-rw-r--r--test-svn-fe.c42
-rw-r--r--vcs-svn/svndiff.c52
-rw-r--r--vcs-svn/svndiff.h10
5 files changed, 133 insertions, 8 deletions
diff --git a/Makefile b/Makefile
index 5cd141d..cd7dd97 100644
--- a/Makefile
+++ b/Makefile
@@ -1854,6 +1854,7 @@ VCSSVN_OBJS += vcs-svn/line_buffer.o
VCSSVN_OBJS += vcs-svn/sliding_window.o
VCSSVN_OBJS += vcs-svn/repo_tree.o
VCSSVN_OBJS += vcs-svn/fast_export.o
+VCSSVN_OBJS += vcs-svn/svndiff.o
VCSSVN_OBJS += vcs-svn/svndump.o
VCSSVN_TEST_OBJS += test-obj-pool.o
@@ -1997,6 +1998,7 @@ VCSSVN_H += vcs-svn/line_buffer.h
VCSSVN_H += vcs-svn/sliding_window.h
VCSSVN_H += vcs-svn/repo_tree.h
VCSSVN_H += vcs-svn/fast_export.h
+VCSSVN_H += vcs-svn/svndiff.h
VCSSVN_H += vcs-svn/svndump.h
$(VCSSVN_OBJS) $(VCSSVN_TEST_OBJS): $(LIB_H) $(VCSSVN_H)
diff --git a/t/t9011-svn-da.sh b/t/t9011-svn-da.sh
new file mode 100755
index 0000000..ee0c1e2
--- /dev/null
+++ b/t/t9011-svn-da.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+test_description='test parsing of svndiff0 files
+
+Using the "test-svn-fe -d" helper, check that svn-fe correctly
+interprets deltas using various facilities (some from the spec,
+some only learned from practice).
+'
+. ./test-lib.sh
+
+>empty
+printf foo >preimage
+
+test_expect_success 'reject empty delta' '
+ test_must_fail test-svn-fe -d preimage empty 0
+'
+
+test_expect_success 'delta can empty file' '
+ printf "SVNQ" | q_to_nul >clear.delta &&
+ test-svn-fe -d preimage clear.delta 4 >actual &&
+ test_cmp empty actual
+'
+
+test_expect_success 'reject svndiff2' '
+ printf "SVN\002" >bad.filetype &&
+ test_must_fail test-svn-fe -d preimage bad.filetype 4
+'
+
+test_expect_failure 'one-window empty delta' '
+ printf "SVNQ%s" "QQQQQ" | q_to_nul >clear.onewindow &&
+ test-svn-fe -d preimage clear.onewindow 9 >actual &&
+ test_cmp empty actual
+'
+
+test_done
diff --git a/test-svn-fe.c b/test-svn-fe.c
index b42ba78..66bd040 100644
--- a/test-svn-fe.c
+++ b/test-svn-fe.c
@@ -4,15 +4,41 @@
#include "git-compat-util.h"
#include "vcs-svn/svndump.h"
+#include "vcs-svn/svndiff.h"
+#include "vcs-svn/sliding_window.h"
+#include "vcs-svn/line_buffer.h"
int main(int argc, char *argv[])
{
- if (argc != 2)
- usage("test-svn-fe <file>");
- if (svndump_init(argv[1]))
- return 1;
- svndump_read(NULL);
- svndump_deinit();
- svndump_reset();
- return 0;
+ static const char test_svnfe_usage[] =
+ "test-svn-fe (<dumpfile> | [-d] <preimage> <delta> <len>)";
+ if (argc == 2) {
+ if (svndump_init(argv[1]))
+ return 1;
+ svndump_read(NULL);
+ svndump_deinit();
+ svndump_reset();
+ return 0;
+ }
+ if (argc == 5 && !strcmp(argv[1], "-d")) {
+ struct line_buffer preimage = LINE_BUFFER_INIT;
+ struct line_buffer delta = LINE_BUFFER_INIT;
+ struct sliding_view preimage_view = SLIDING_VIEW_INIT(&preimage);
+ if (buffer_init(&preimage, argv[2]))
+ die_errno("cannot open preimage");
+ if (buffer_init(&delta, argv[3]))
+ die_errno("cannot open delta");
+ if (svndiff0_apply(&delta, (off_t) strtoull(argv[4], NULL, 0),
+ &preimage_view, stdout))
+ return 1;
+ if (buffer_deinit(&preimage))
+ die_errno("cannot close preimage");
+ if (buffer_deinit(&delta))
+ die_errno("cannot close delta");
+ buffer_reset(&preimage);
+ strbuf_release(&preimage_view.buf);
+ buffer_reset(&delta);
+ return 0;
+ }
+ usage(test_svnfe_usage);
}
diff --git a/vcs-svn/svndiff.c b/vcs-svn/svndiff.c
new file mode 100644
index 0000000..5916036
--- /dev/null
+++ b/vcs-svn/svndiff.c
@@ -0,0 +1,52 @@
+/*
+ * Licensed under a two-clause BSD-style license.
+ * See LICENSE for details.
+ */
+
+#include "git-compat-util.h"
+#include "line_buffer.h"
+#include "svndiff.h"
+
+/*
+ * svndiff0 applier
+ *
+ * See http://svn.apache.org/repos/asf/subversion/trunk/notes/svndiff.
+ *
+ * svndiff0 ::= 'SVN\0' window*
+ */
+
+static int error_short_read(struct line_buffer *input)
+{
+ if (buffer_ferror(input))
+ return error("error reading delta: %s", strerror(errno));
+ return error("invalid delta: unexpected end of file");
+}
+
+static int read_magic(struct line_buffer *in, off_t *len)
+{
+ static const char magic[] = {'S', 'V', 'N', '\0'};
+ struct strbuf sb = STRBUF_INIT;
+
+ if (*len < sizeof(magic) ||
+ buffer_read_binary(in, &sb, sizeof(magic)) != sizeof(magic))
+ return error_short_read(in);
+
+ if (memcmp(sb.buf, magic, sizeof(magic)))
+ return error("invalid delta: unrecognized file type");
+
+ *len -= sizeof(magic);
+ strbuf_release(&sb);
+ return 0;
+}
+
+int svndiff0_apply(struct line_buffer *delta, off_t delta_len,
+ struct sliding_view *preimage, FILE *postimage)
+{
+ assert(delta && preimage && postimage);
+
+ if (read_magic(delta, &delta_len))
+ return -1;
+ if (delta_len)
+ return error("What do you think I am? A delta applier?");
+ return 0;
+}
diff --git a/vcs-svn/svndiff.h b/vcs-svn/svndiff.h
new file mode 100644
index 0000000..74eb464
--- /dev/null
+++ b/vcs-svn/svndiff.h
@@ -0,0 +1,10 @@
+#ifndef SVNDIFF_H_
+#define SVNDIFF_H_
+
+struct line_buffer;
+struct sliding_view;
+
+extern int svndiff0_apply(struct line_buffer *delta, off_t delta_len,
+ struct sliding_view *preimage, FILE *postimage);
+
+#endif