diff --git a/.gitignore b/.gitignore index ee509a2ad2..9673e792db 100644 --- a/.gitignore +++ b/.gitignore @@ -134,7 +134,6 @@ /git-remote-fd /git-remote-ext /git-remote-testpy -/git-remote-testsvn /git-repack /git-replace /git-request-pull diff --git a/Makefile b/Makefile index 2b821fc762..314179d918 100644 --- a/Makefile +++ b/Makefile @@ -569,7 +569,6 @@ BUILT_INS = COMPAT_CFLAGS = COMPAT_OBJS = XDIFF_OBJS = -VCSSVN_OBJS = GENERATED_H = EXTRA_CPPFLAGS = FUZZ_OBJS = @@ -674,7 +673,6 @@ PROGRAMS += $(EXTRA_PROGRAMS) PROGRAM_OBJS += daemon.o PROGRAM_OBJS += http-backend.o PROGRAM_OBJS += imap-send.o -PROGRAM_OBJS += remote-testsvn.o PROGRAM_OBJS += sh-i18n--envsubst.o PROGRAM_OBJS += shell.o @@ -746,8 +744,6 @@ TEST_BUILTINS_OBJS += test-xml-encode.o # Do not add more tests here unless they have extra dependencies. Add # them in TEST_BUILTINS_OBJS above. TEST_PROGRAMS_NEED_X += test-fake-ssh -TEST_PROGRAMS_NEED_X += test-line-buffer -TEST_PROGRAMS_NEED_X += test-svn-fe TEST_PROGRAMS_NEED_X += test-tool TEST_PROGRAMS = $(patsubst %,t/helper/%$X,$(TEST_PROGRAMS_NEED_X)) @@ -803,7 +799,6 @@ TEST_SHELL_PATH = $(SHELL_PATH) LIB_FILE = libgit.a XDIFF_LIB = xdiff/lib.a -VCSSVN_LIB = vcs-svn/lib.a GENERATED_H += config-list.h GENERATED_H += command-list.h @@ -2345,16 +2340,9 @@ XDIFF_OBJS += xdiff/xpatience.o XDIFF_OBJS += xdiff/xprepare.o XDIFF_OBJS += xdiff/xutils.o -VCSSVN_OBJS += vcs-svn/fast_export.o -VCSSVN_OBJS += vcs-svn/line_buffer.o -VCSSVN_OBJS += vcs-svn/sliding_window.o -VCSSVN_OBJS += vcs-svn/svndiff.o -VCSSVN_OBJS += vcs-svn/svndump.o - TEST_OBJS := $(patsubst %$X,%.o,$(TEST_PROGRAMS)) $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS)) OBJECTS := $(LIB_OBJS) $(BUILTIN_OBJS) $(PROGRAM_OBJS) $(TEST_OBJS) \ $(XDIFF_OBJS) \ - $(VCSSVN_OBJS) \ $(FUZZ_OBJS) \ common-main.o \ git.o @@ -2469,10 +2457,6 @@ git-http-push$X: http.o http-push.o GIT-LDFLAGS $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) $(LIBS) -git-remote-testsvn$X: remote-testsvn.o GIT-LDFLAGS $(GITLIBS) $(VCSSVN_LIB) - $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) \ - $(VCSSVN_LIB) - $(REMOTE_CURL_ALIASES): $(REMOTE_CURL_PRIMARY) $(QUIET_LNCP)$(RM) $@ && \ ln $< $@ 2>/dev/null || \ @@ -2489,9 +2473,6 @@ $(LIB_FILE): $(LIB_OBJS) $(XDIFF_LIB): $(XDIFF_OBJS) $(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^ -$(VCSSVN_LIB): $(VCSSVN_OBJS) - $(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^ - export DEFAULT_EDITOR DEFAULT_PAGER Documentation/GIT-EXCLUDED-PROGRAMS: FORCE @@ -2766,10 +2747,6 @@ perf: all .PHONY: test perf -t/helper/test-line-buffer$X: $(VCSSVN_LIB) - -t/helper/test-svn-fe$X: $(VCSSVN_LIB) - .PRECIOUS: $(TEST_OBJS) t/helper/test-tool$X: $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS)) @@ -2902,7 +2879,6 @@ ifdef MSVC $(INSTALL) git-http-push.pdb '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' $(INSTALL) git-imap-send.pdb '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' $(INSTALL) git-remote-http.pdb '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' - $(INSTALL) git-remote-testsvn.pdb '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' $(INSTALL) git-sh-i18n--envsubst.pdb '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' ifndef DEBUG $(INSTALL) $(vcpkg_rel_bin)/*.dll '$(DESTDIR_SQ)$(bindir_SQ)' @@ -3103,7 +3079,7 @@ cocciclean: clean: profile-clean coverage-clean cocciclean $(RM) *.res $(RM) $(OBJECTS) - $(RM) $(LIB_FILE) $(XDIFF_LIB) $(VCSSVN_LIB) + $(RM) $(LIB_FILE) $(XDIFF_LIB) $(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X $(RM) $(TEST_PROGRAMS) $(RM) $(FUZZ_PROGRAMS) diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index 4a6f135b16..5007f173f1 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -502,7 +502,7 @@ unset(CMAKE_REQUIRED_INCLUDES) #programs set(PROGRAMS_BUILT git git-daemon git-http-backend git-sh-i18n--envsubst - git-shell git-remote-testsvn) + git-shell) if(NOT CURL_FOUND) list(APPEND excluded_progs git-http-fetch git-http-push) @@ -568,12 +568,6 @@ parse_makefile_for_sources(libxdiff_SOURCES "XDIFF_OBJS") list(TRANSFORM libxdiff_SOURCES PREPEND "${CMAKE_SOURCE_DIR}/") add_library(xdiff STATIC ${libxdiff_SOURCES}) -#libvcs-svn -parse_makefile_for_sources(libvcs-svn_SOURCES "VCSSVN_OBJS") - -list(TRANSFORM libvcs-svn_SOURCES PREPEND "${CMAKE_SOURCE_DIR}/") -add_library(vcs-svn STATIC ${libvcs-svn_SOURCES}) - if(WIN32) if(NOT MSVC)#use windres when compiling with gcc and clang add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/git.res @@ -654,9 +648,6 @@ if(CURL_FOUND) endif() endif() -add_executable(git-remote-testsvn ${CMAKE_SOURCE_DIR}/remote-testsvn.c) -target_link_libraries(git-remote-testsvn common-main vcs-svn) - set(git_builtin_extra cherry cherry-pick format-patch fsck-objects init merge-subtree restore show @@ -832,12 +823,6 @@ if(BUILD_TESTING) add_executable(test-fake-ssh ${CMAKE_SOURCE_DIR}/t/helper/test-fake-ssh.c) target_link_libraries(test-fake-ssh common-main) -add_executable(test-line-buffer ${CMAKE_SOURCE_DIR}/t/helper/test-line-buffer.c) -target_link_libraries(test-line-buffer common-main vcs-svn) - -add_executable(test-svn-fe ${CMAKE_SOURCE_DIR}/t/helper/test-svn-fe.c) -target_link_libraries(test-svn-fe common-main vcs-svn) - #test-tool parse_makefile_for_sources(test-tool_SOURCES "TEST_BUILTINS_OBJS") @@ -845,13 +830,13 @@ list(TRANSFORM test-tool_SOURCES PREPEND "${CMAKE_SOURCE_DIR}/t/helper/") add_executable(test-tool ${CMAKE_SOURCE_DIR}/t/helper/test-tool.c ${test-tool_SOURCES}) target_link_libraries(test-tool common-main) -set_target_properties(test-fake-ssh test-line-buffer test-svn-fe test-tool +set_target_properties(test-fake-ssh test-tool PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/t/helper) if(MSVC) - set_target_properties(test-fake-ssh test-line-buffer test-svn-fe test-tool + set_target_properties(test-fake-ssh test-tool PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/t/helper) - set_target_properties(test-fake-ssh test-line-buffer test-svn-fe test-tool + set_target_properties(test-fake-ssh test-tool PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/t/helper) endif() @@ -860,7 +845,7 @@ set(wrapper_scripts git git-upload-pack git-receive-pack git-upload-archive git-shell git-remote-ext) set(wrapper_test_scripts - test-fake-ssh test-line-buffer test-svn-fe test-tool) + test-fake-ssh test-tool) foreach(script ${wrapper_scripts}) @@ -961,7 +946,6 @@ if(NOT ${CMAKE_BINARY_DIR}/CMakeCache.txt STREQUAL ${CACHE_PATH}) file(COPY ${CMAKE_SOURCE_DIR}/mergetools/tkdiff DESTINATION ${CMAKE_BINARY_DIR}/mergetools/) file(COPY ${CMAKE_SOURCE_DIR}/contrib/completion/git-prompt.sh DESTINATION ${CMAKE_BINARY_DIR}/contrib/completion/) file(COPY ${CMAKE_SOURCE_DIR}/contrib/completion/git-completion.bash DESTINATION ${CMAKE_BINARY_DIR}/contrib/completion/) - file(COPY ${CMAKE_SOURCE_DIR}/contrib/svn-fe/svnrdump_sim.py DESTINATION ${CMAKE_BINARY_DIR}/contrib/svn-fe/) endif() file(GLOB test_scipts "${CMAKE_SOURCE_DIR}/t/t[0-9]*.sh") diff --git a/contrib/svn-fe/.gitignore b/contrib/svn-fe/.gitignore deleted file mode 100644 index 02a7791585..0000000000 --- a/contrib/svn-fe/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/*.xml -/*.1 -/*.html -/svn-fe diff --git a/contrib/svn-fe/Makefile b/contrib/svn-fe/Makefile deleted file mode 100644 index e8651aaf4b..0000000000 --- a/contrib/svn-fe/Makefile +++ /dev/null @@ -1,105 +0,0 @@ -all:: svn-fe$X - -CC = cc -RM = rm -f -MV = mv - -CFLAGS = -g -O2 -Wall -LDFLAGS = -EXTLIBS = -lz - -include ../../config.mak.uname --include ../../config.mak.autogen --include ../../config.mak - -ifeq ($(uname_S),Darwin) - ifndef NO_FINK - ifeq ($(shell test -d /sw/lib && echo y),y) - CFLAGS += -I/sw/include - LDFLAGS += -L/sw/lib - endif - endif - ifndef NO_DARWIN_PORTS - ifeq ($(shell test -d /opt/local/lib && echo y),y) - CFLAGS += -I/opt/local/include - LDFLAGS += -L/opt/local/lib - endif - endif -endif - -ifndef NO_OPENSSL - EXTLIBS += -lssl - ifdef NEEDS_CRYPTO_WITH_SSL - EXTLIBS += -lcrypto - endif -endif - -ifndef NO_PTHREADS - CFLAGS += $(PTHREADS_CFLAGS) - EXTLIBS += $(PTHREAD_LIBS) -endif - -ifdef HAVE_CLOCK_GETTIME - CFLAGS += -DHAVE_CLOCK_GETTIME - EXTLIBS += -lrt -endif - -ifdef NEEDS_LIBICONV - EXTLIBS += -liconv -endif - -GIT_LIB = ../../libgit.a -VCSSVN_LIB = ../../vcs-svn/lib.a -XDIFF_LIB = ../../xdiff/lib.a - -LIBS = $(VCSSVN_LIB) $(GIT_LIB) $(XDIFF_LIB) - -QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir -QUIET_SUBDIR1 = - -ifneq ($(findstring $(MAKEFLAGS),w),w) -PRINT_DIR = --no-print-directory -else # "make -w" -NO_SUBDIR = : -endif - -ifneq ($(findstring $(MAKEFLAGS),s),s) -ifndef V - QUIET_CC = @echo ' ' CC $@; - QUIET_LINK = @echo ' ' LINK $@; - QUIET_SUBDIR0 = +@subdir= - QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \ - $(MAKE) $(PRINT_DIR) -C $$subdir -endif -endif - -svn-fe$X: svn-fe.o $(VCSSVN_LIB) $(XDIFF_LIB) $(GIT_LIB) - $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(EXTLIBS) -o $@ svn-fe.o $(LIBS) - -svn-fe.o: svn-fe.c ../../vcs-svn/svndump.h - $(QUIET_CC)$(CC) $(CFLAGS) -I../../vcs-svn -o $*.o -c $< - -svn-fe.html: svn-fe.txt - $(QUIET_SUBDIR0)../../Documentation $(QUIET_SUBDIR1) \ - MAN_TXT=../contrib/svn-fe/svn-fe.txt \ - ../contrib/svn-fe/$@ - -svn-fe.1: svn-fe.txt - $(QUIET_SUBDIR0)../../Documentation $(QUIET_SUBDIR1) \ - MAN_TXT=../contrib/svn-fe/svn-fe.txt \ - ../contrib/svn-fe/$@ - $(MV) ../../Documentation/svn-fe.1 . - -../../vcs-svn/lib.a: FORCE - $(QUIET_SUBDIR0)../.. $(QUIET_SUBDIR1) vcs-svn/lib.a - -../../xdiff/lib.a: FORCE - $(QUIET_SUBDIR0)../.. $(QUIET_SUBDIR1) xdiff/lib.a - -../../libgit.a: FORCE - $(QUIET_SUBDIR0)../.. $(QUIET_SUBDIR1) libgit.a - -clean: - $(RM) svn-fe$X svn-fe.o svn-fe.html svn-fe.xml svn-fe.1 - -.PHONY: all clean FORCE diff --git a/contrib/svn-fe/svn-fe.c b/contrib/svn-fe/svn-fe.c deleted file mode 100644 index f363505abb..0000000000 --- a/contrib/svn-fe/svn-fe.c +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file is in the public domain. - * You may freely use, modify, distribute, and relicense it. - */ - -#include -#include "svndump.h" - -int main(int argc, char **argv) -{ - if (svndump_init(NULL)) - return 1; - svndump_read((argc > 1) ? argv[1] : NULL, "refs/heads/master", - "refs/notes/svn/revs"); - svndump_deinit(); - svndump_reset(); - return 0; -} diff --git a/contrib/svn-fe/svn-fe.txt b/contrib/svn-fe/svn-fe.txt deleted file mode 100644 index 19333fc8df..0000000000 --- a/contrib/svn-fe/svn-fe.txt +++ /dev/null @@ -1,71 +0,0 @@ -svn-fe(1) -========= - -NAME ----- -svn-fe - convert an SVN "dumpfile" to a fast-import stream - -SYNOPSIS --------- -[verse] -mkfifo backchannel && -svnadmin dump --deltas REPO | - svn-fe [url] 3backchannel - -DESCRIPTION ------------ - -Converts a Subversion dumpfile into input suitable for -git-fast-import(1) and similar importers. REPO is a path to a -Subversion repository mirrored on the local disk. Remote Subversion -repositories can be mirrored on local disk using the `svnsync` -command. - -Note: this tool is very young. The details of its commandline -interface may change in backward incompatible ways. - -INPUT FORMAT ------------- -Subversion's repository dump format is documented in full in -`notes/dump-load-format.txt` from the Subversion source tree. -Files in this format can be generated using the 'svnadmin dump' or -'svk admin dump' command. - -OUTPUT FORMAT -------------- -The fast-import format is documented by the git-fast-import(1) -manual page. - -NOTES ------ -Subversion dumps do not record a separate author and committer for -each revision, nor do they record a separate display name and email -address for each author. Like git-svn(1), 'svn-fe' will use the name - ---------- -user ---------- - -as committer, where 'user' is the value of the `svn:author` property -and 'UUID' the repository's identifier. - -To support incremental imports, 'svn-fe' puts a `git-svn-id` line at -the end of each commit log message if passed a URL on the command -line. This line has the form `git-svn-id: URL@REVNO UUID`. - -The resulting repository will generally require further processing -to put each project in its own repository and to separate the history -of each branch. The 'git filter-repo --subdirectory-filter' command -may be useful for this purpose. - -BUGS ----- -Empty directories and unknown properties are silently discarded. - -The exit status does not reflect whether an error was detected. - -SEE ALSO --------- -git-svn(1), svn2git(1), svk(1), git-filter-repo(1), git-fast-import(1), -https://svn.apache.org/repos/asf/subversion/trunk/notes/dump-load-format.txt diff --git a/contrib/svn-fe/svnrdump_sim.py b/contrib/svn-fe/svnrdump_sim.py deleted file mode 100755 index 8a3cee6175..0000000000 --- a/contrib/svn-fe/svnrdump_sim.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env python -""" -Simulates svnrdump by replaying an existing dump from a file, taking care -of the specified revision range. -To simulate incremental imports the environment variable SVNRMAX can be set -to the highest revision that should be available. -""" -import sys -import os - -if sys.hexversion < 0x02040000: - # The limiter is the ValueError() calls. This may be too conservative - sys.stderr.write("svnrdump-sim.py: requires Python 2.4 or later.\n") - sys.exit(1) - - -def getrevlimit(): - var = 'SVNRMAX' - if var in os.environ: - return os.environ[var] - return None - - -def writedump(url, lower, upper): - if url.startswith('sim://'): - filename = url[6:] - if filename[-1] == '/': - filename = filename[:-1] # remove terminating slash - else: - raise ValueError('sim:// url required') - f = open(filename, 'r') - state = 'header' - wroterev = False - while(True): - l = f.readline() - if l == '': - break - if state == 'header' and l.startswith('Revision-number: '): - state = 'prefix' - if state == 'prefix' and l == 'Revision-number: %s\n' % lower: - state = 'selection' - if not upper == 'HEAD' and state == 'selection' and \ - l == 'Revision-number: %s\n' % upper: - break - - if state == 'header' or state == 'selection': - if state == 'selection': - wroterev = True - sys.stdout.write(l) - return wroterev - -if __name__ == "__main__": - if not (len(sys.argv) in (3, 4, 5)): - print("usage: %s dump URL -rLOWER:UPPER") - sys.exit(1) - if not sys.argv[1] == 'dump': - raise NotImplementedError('only "dump" is supported.') - url = sys.argv[2] - r = ('0', 'HEAD') - if len(sys.argv) == 4 and sys.argv[3][0:2] == '-r': - r = sys.argv[3][2:].lstrip().split(':') - if not getrevlimit() is None: - r[1] = getrevlimit() - if writedump(url, r[0], r[1]): - ret = 0 - else: - ret = 1 - sys.exit(ret) diff --git a/remote-testsvn.c b/remote-testsvn.c deleted file mode 100644 index 636b2b62a6..0000000000 --- a/remote-testsvn.c +++ /dev/null @@ -1,341 +0,0 @@ -#include "cache.h" -#include "refs.h" -#include "remote.h" -#include "object-store.h" -#include "strbuf.h" -#include "url.h" -#include "exec-cmd.h" -#include "run-command.h" -#include "vcs-svn/svndump.h" -#include "notes.h" -#include "strvec.h" - -static const char *url; -static int dump_from_file; -static const char *private_ref; -static char *remote_ref; -static const char *marksfilename, *notes_ref; -struct rev_note { unsigned int rev_nr; }; - -static int cmd_capabilities(const char *line); -static int cmd_import(const char *line); -static int cmd_list(const char *line); - -typedef int (*input_command_handler)(const char *); -struct input_command_entry { - const char *name; - input_command_handler fn; - unsigned char batchable; /* whether the command starts or is part of a batch */ -}; - -static const struct input_command_entry input_command_list[] = { - { "capabilities", cmd_capabilities, 0 }, - { "import", cmd_import, 1 }, - { "list", cmd_list, 0 }, - { NULL, NULL } -}; - -static int cmd_capabilities(const char *line) -{ - printf("import\n"); - printf("bidi-import\n"); - printf("refspec %s:%s\n\n", remote_ref, private_ref); - fflush(stdout); - return 0; -} - -static void terminate_batch(void) -{ - /* terminate a current batch's fast-import stream */ - printf("done\n"); - fflush(stdout); -} - -/* NOTE: 'ref' refers to a git reference, while 'rev' refers to a svn revision. */ -static char *read_ref_note(const struct object_id *oid) -{ - const struct object_id *note_oid; - char *msg = NULL; - unsigned long msglen; - enum object_type type; - - init_notes(NULL, notes_ref, NULL, 0); - if (!(note_oid = get_note(NULL, oid))) - return NULL; /* note tree not found */ - if (!(msg = read_object_file(note_oid, &type, &msglen))) - error("Empty notes tree. %s", notes_ref); - else if (!msglen || type != OBJ_BLOB) { - error("Note contains unusable content. " - "Is something else using this notes tree? %s", notes_ref); - FREE_AND_NULL(msg); - } - free_notes(NULL); - return msg; -} - -static int parse_rev_note(const char *msg, struct rev_note *res) -{ - const char *key, *value, *end; - size_t len; - - while (*msg) { - end = strchrnul(msg, '\n'); - len = end - msg; - - key = "Revision-number: "; - if (starts_with(msg, key)) { - long i; - char *end; - value = msg + strlen(key); - i = strtol(value, &end, 0); - if (end == value || i < 0 || i > UINT32_MAX) - return -1; - res->rev_nr = i; - return 0; - } - msg += len + 1; - } - /* didn't find it */ - return -1; -} - -static int note2mark_cb(const struct object_id *object_oid, - const struct object_id *note_oid, char *note_path, - void *cb_data) -{ - FILE *file = (FILE *)cb_data; - char *msg; - unsigned long msglen; - enum object_type type; - struct rev_note note; - - if (!(msg = read_object_file(note_oid, &type, &msglen)) || - !msglen || type != OBJ_BLOB) { - free(msg); - return 1; - } - if (parse_rev_note(msg, ¬e)) - return 2; - if (fprintf(file, ":%d %s\n", note.rev_nr, oid_to_hex(object_oid)) < 1) - return 3; - return 0; -} - -static void regenerate_marks(void) -{ - int ret; - FILE *marksfile = xfopen(marksfilename, "w+"); - - ret = for_each_note(NULL, 0, note2mark_cb, marksfile); - if (ret) - die("Regeneration of marks failed, returned %d.", ret); - fclose(marksfile); -} - -static void check_or_regenerate_marks(int latestrev) -{ - FILE *marksfile; - struct strbuf sb = STRBUF_INIT; - struct strbuf line = STRBUF_INIT; - int found = 0; - - if (latestrev < 1) - return; - - init_notes(NULL, notes_ref, NULL, 0); - marksfile = fopen(marksfilename, "r"); - if (!marksfile) { - regenerate_marks(); - marksfile = xfopen(marksfilename, "r"); - fclose(marksfile); - } else { - strbuf_addf(&sb, ":%d ", latestrev); - while (strbuf_getline_lf(&line, marksfile) != EOF) { - if (starts_with(line.buf, sb.buf)) { - found++; - break; - } - } - fclose(marksfile); - if (!found) - regenerate_marks(); - } - free_notes(NULL); - strbuf_release(&sb); - strbuf_release(&line); -} - -static int cmd_import(const char *line) -{ - int code; - int dumpin_fd; - char *note_msg; - struct object_id head_oid; - unsigned int startrev; - struct child_process svndump_proc = CHILD_PROCESS_INIT; - const char *command = "svnrdump"; - - if (read_ref(private_ref, &head_oid)) - startrev = 0; - else { - note_msg = read_ref_note(&head_oid); - if(note_msg == NULL) { - warning("No note found for %s.", private_ref); - startrev = 0; - } else { - struct rev_note note = { 0 }; - if (parse_rev_note(note_msg, ¬e)) - die("Revision number couldn't be parsed from note."); - startrev = note.rev_nr + 1; - free(note_msg); - } - } - check_or_regenerate_marks(startrev - 1); - - if (dump_from_file) { - dumpin_fd = open(url, O_RDONLY); - if(dumpin_fd < 0) - die_errno("Couldn't open svn dump file %s.", url); - } else { - svndump_proc.out = -1; - strvec_push(&svndump_proc.args, command); - strvec_push(&svndump_proc.args, "dump"); - strvec_push(&svndump_proc.args, url); - strvec_pushf(&svndump_proc.args, "-r%u:HEAD", startrev); - - code = start_command(&svndump_proc); - if (code) - die("Unable to start %s, code %d", command, code); - dumpin_fd = svndump_proc.out; - } - /* setup marks file import/export */ - printf("feature import-marks-if-exists=%s\n" - "feature export-marks=%s\n", marksfilename, marksfilename); - - svndump_init_fd(dumpin_fd, STDIN_FILENO); - svndump_read(url, private_ref, notes_ref); - svndump_deinit(); - svndump_reset(); - - close(dumpin_fd); - if (!dump_from_file) { - code = finish_command(&svndump_proc); - if (code) - warning("%s, returned %d", command, code); - } - - return 0; -} - -static int cmd_list(const char *line) -{ - printf("? %s\n\n", remote_ref); - fflush(stdout); - return 0; -} - -static int do_command(struct strbuf *line) -{ - const struct input_command_entry *p = input_command_list; - static struct string_list batchlines = STRING_LIST_INIT_DUP; - static const struct input_command_entry *batch_cmd; - /* - * commands can be grouped together in a batch. - * Batches are ended by \n. If no batch is active the program ends. - * During a batch all lines are buffered and passed to the handler function - * when the batch is terminated. - */ - if (line->len == 0) { - if (batch_cmd) { - struct string_list_item *item; - for_each_string_list_item(item, &batchlines) - batch_cmd->fn(item->string); - terminate_batch(); - batch_cmd = NULL; - string_list_clear(&batchlines, 0); - return 0; /* end of the batch, continue reading other commands. */ - } - return 1; /* end of command stream, quit */ - } - if (batch_cmd) { - if (!starts_with(batch_cmd->name, line->buf)) - die("Active %s batch interrupted by %s", batch_cmd->name, line->buf); - /* buffer batch lines */ - string_list_append(&batchlines, line->buf); - return 0; - } - - for (p = input_command_list; p->name; p++) { - if (starts_with(line->buf, p->name) && (strlen(p->name) == line->len || - line->buf[strlen(p->name)] == ' ')) { - if (p->batchable) { - batch_cmd = p; - string_list_append(&batchlines, line->buf); - return 0; - } - return p->fn(line->buf); - } - } - die("Unknown command '%s'\n", line->buf); - return 0; -} - -int cmd_main(int argc, const char **argv) -{ - struct strbuf buf = STRBUF_INIT, url_sb = STRBUF_INIT, - private_ref_sb = STRBUF_INIT, marksfilename_sb = STRBUF_INIT, - notes_ref_sb = STRBUF_INIT; - static struct remote *remote; - const char *url_in, *remote_ref_short; - - setup_git_directory(); - if (argc < 2 || argc > 3) { - usage("git-remote-svn []"); - return 1; - } - - remote_ref_short = git_default_branch_name(); - remote_ref = xstrfmt("refs/heads/%s", remote_ref_short); - - remote = remote_get(argv[1]); - url_in = (argc == 3) ? argv[2] : remote->url[0]; - - if (starts_with(url_in, "file://")) { - dump_from_file = 1; - url = url_decode(url_in + sizeof("file://")-1); - } else { - dump_from_file = 0; - end_url_with_slash(&url_sb, url_in); - url = url_sb.buf; - } - - strbuf_addf(&private_ref_sb, "refs/svn/%s/%s", - remote->name, remote_ref_short); - private_ref = private_ref_sb.buf; - - strbuf_addf(¬es_ref_sb, "refs/notes/%s/revs", remote->name); - notes_ref = notes_ref_sb.buf; - - strbuf_addf(&marksfilename_sb, "%s/info/fast-import/remote-svn/%s.marks", - get_git_dir(), remote->name); - marksfilename = marksfilename_sb.buf; - - while (1) { - if (strbuf_getline_lf(&buf, stdin) == EOF) { - if (ferror(stdin)) - die("Error reading command stream"); - else - die("Unexpected end of command stream"); - } - if (do_command(&buf)) - break; - strbuf_reset(&buf); - } - - strbuf_release(&buf); - strbuf_release(&url_sb); - strbuf_release(&private_ref_sb); - strbuf_release(¬es_ref_sb); - strbuf_release(&marksfilename_sb); - return 0; -} diff --git a/t/helper/.gitignore b/t/helper/.gitignore index 48c7bb0bbb..8c2ddcce95 100644 --- a/t/helper/.gitignore +++ b/t/helper/.gitignore @@ -1,4 +1,2 @@ /test-tool /test-fake-ssh -/test-line-buffer -/test-svn-fe diff --git a/t/helper/test-line-buffer.c b/t/helper/test-line-buffer.c deleted file mode 100644 index 078dd7e29d..0000000000 --- a/t/helper/test-line-buffer.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * test-line-buffer.c: code to exercise the svn importer's input helper - */ - -#include "git-compat-util.h" -#include "strbuf.h" -#include "vcs-svn/line_buffer.h" - -static uint32_t strtouint32(const char *s) -{ - char *end; - uintmax_t n = strtoumax(s, &end, 10); - if (*s == '\0' || *end != '\0') - die("invalid count: %s", s); - return (uint32_t) n; -} - -static void handle_command(const char *command, const char *arg, struct line_buffer *buf) -{ - if (starts_with(command, "binary ")) { - struct strbuf sb = STRBUF_INIT; - strbuf_addch(&sb, '>'); - buffer_read_binary(buf, &sb, strtouint32(arg)); - fwrite(sb.buf, 1, sb.len, stdout); - strbuf_release(&sb); - } else if (starts_with(command, "copy ")) { - buffer_copy_bytes(buf, strtouint32(arg)); - } else if (starts_with(command, "skip ")) { - buffer_skip_bytes(buf, strtouint32(arg)); - } else { - die("unrecognized command: %s", command); - } -} - -static void handle_line(const char *line, struct line_buffer *stdin_buf) -{ - const char *arg = strchr(line, ' '); - if (!arg) - die("no argument in line: %s", line); - handle_command(line, arg + 1, stdin_buf); -} - -int cmd_main(int argc, const char **argv) -{ - struct line_buffer stdin_buf = LINE_BUFFER_INIT; - struct line_buffer file_buf = LINE_BUFFER_INIT; - struct line_buffer *input = &stdin_buf; - const char *filename; - char *s; - - if (argc == 1) - filename = NULL; - else if (argc == 2) - filename = argv[1]; - else - usage("test-line-buffer [file | &fd] < script"); - - if (buffer_init(&stdin_buf, NULL)) - die_errno("open error"); - if (filename) { - if (*filename == '&') { - if (buffer_fdinit(&file_buf, strtouint32(filename + 1))) - die_errno("error opening fd %s", filename + 1); - } else { - if (buffer_init(&file_buf, filename)) - die_errno("error opening %s", filename); - } - input = &file_buf; - } - - while ((s = buffer_read_line(&stdin_buf))) - handle_line(s, input); - - if (filename && buffer_deinit(&file_buf)) - die("error reading from %s", filename); - if (buffer_deinit(&stdin_buf)) - die("input error"); - if (ferror(stdout)) - die("output error"); - return 0; -} diff --git a/t/helper/test-svn-fe.c b/t/helper/test-svn-fe.c deleted file mode 100644 index 7667c0803f..0000000000 --- a/t/helper/test-svn-fe.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * test-svn-fe: Code to exercise the svn import lib - */ - -#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" - -static const char test_svnfe_usage[] = - "test-svn-fe ( | [-d] )"; - -static int apply_delta(int argc, const char **argv) -{ - struct line_buffer preimage = LINE_BUFFER_INIT; - struct line_buffer delta = LINE_BUFFER_INIT; - struct sliding_view preimage_view = SLIDING_VIEW_INIT(&preimage, -1); - - if (argc != 5) - usage(test_svnfe_usage); - - 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) strtoumax(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"); - strbuf_release(&preimage_view.buf); - return 0; -} - -int cmd_main(int argc, const char **argv) -{ - if (argc == 2) { - if (svndump_init(argv[1])) - return 1; - svndump_read(NULL, "refs/heads/master", "refs/notes/svn/revs"); - svndump_deinit(); - svndump_reset(); - return 0; - } - - if (argc >= 2 && !strcmp(argv[1], "-d")) - return apply_delta(argc, argv); - usage(test_svnfe_usage); -} diff --git a/t/t0081-line-buffer.sh b/t/t0081-line-buffer.sh deleted file mode 100755 index ce92e6acad..0000000000 --- a/t/t0081-line-buffer.sh +++ /dev/null @@ -1,90 +0,0 @@ -#!/bin/sh - -test_description="Test the svn importer's input handling routines. - -These tests provide some simple checks that the line_buffer API -behaves as advertised. - -While at it, check that input of newlines and null bytes are handled -correctly. -" -. ./test-lib.sh - -test_expect_success 'hello world' ' - echo ">HELLO" >expect && - test-line-buffer <<-\EOF >actual && - binary 6 - HELLO - EOF - test_cmp expect actual -' - -test_expect_success '0-length read, send along greeting' ' - echo ">HELLO" >expect && - test-line-buffer <<-\EOF >actual && - binary 0 - copy 6 - HELLO - EOF - test_cmp expect actual -' - -test_expect_success !MINGW 'read from file descriptor' ' - rm -f input && - echo hello >expect && - echo hello >input && - echo copy 6 | - test-line-buffer "&4" 4actual && - test_cmp expect actual -' - -test_expect_success 'skip, copy null byte' ' - echo Q | q_to_nul >expect && - q_to_nul <<-\EOF | test-line-buffer >actual && - skip 2 - Q - copy 2 - Q - EOF - test_cmp expect actual -' - -test_expect_success 'read null byte' ' - echo ">QhelloQ" | q_to_nul >expect && - q_to_nul <<-\EOF | test-line-buffer >actual && - binary 8 - QhelloQ - EOF - test_cmp expect actual -' - -test_expect_success 'long reads are truncated' ' - echo ">foo" >expect && - test-line-buffer <<-\EOF >actual && - binary 5 - foo - EOF - test_cmp expect actual -' - -test_expect_success 'long copies are truncated' ' - printf "%s\n" ">" foo >expect && - test-line-buffer <<-\EOF >actual && - binary 1 - - copy 5 - foo - EOF - test_cmp expect actual -' - -test_expect_success 'long binary reads are truncated' ' - echo ">foo" >expect && - test-line-buffer <<-\EOF >actual && - binary 5 - foo - EOF - test_cmp expect actual -' - -test_done diff --git a/t/t9010-svn-fe.sh b/t/t9010-svn-fe.sh deleted file mode 100755 index 83f8f5cacb..0000000000 --- a/t/t9010-svn-fe.sh +++ /dev/null @@ -1,1105 +0,0 @@ -#!/bin/sh - -test_description='check svn dumpfile importer' - -. ./test-lib.sh - -if test_have_prereq !PIPE -then - skip_all="svn dumpfile importer testing requires the PIPE prerequisite" - test_done -fi - -reinit_git () { - rm -fr .git && - rm -f stream backflow && - git init && - mkfifo stream backflow -} - -try_dump () { - input=$1 && - maybe_fail_svnfe=${2:+test_$2} && - maybe_fail_fi=${3:+test_$3} && - - { - $maybe_fail_svnfe test-svn-fe "$input" >stream 3backflow && - wait $! -} - -properties () { - while test "$#" -ne 0 - do - property="$1" && - value="$2" && - printf "%s\n" "K ${#property}" && - printf "%s\n" "$property" && - printf "%s\n" "V ${#value}" && - printf "%s\n" "$value" && - shift 2 || - return 1 - done -} - -text_no_props () { - text="$1 -" && - printf "%s\n" "Prop-content-length: 10" && - printf "%s\n" "Text-content-length: ${#text}" && - printf "%s\n" "Content-length: $((${#text} + 10))" && - printf "%s\n" "" "PROPS-END" && - printf "%s\n" "$text" -} - -test_expect_success 'empty dump' ' - reinit_git && - echo "SVN-fs-dump-format-version: 2" >input && - try_dump input -' - -test_expect_success 'v4 dumps not supported' ' - reinit_git && - echo "SVN-fs-dump-format-version: 4" >v4.dump && - try_dump v4.dump must_fail -' - -test_expect_failure 'empty revision' ' - reinit_git && - printf "rev : %s\n" "" "" >expect && - cat >emptyrev.dump <<-\EOF && - SVN-fs-dump-format-version: 3 - - Revision-number: 1 - Prop-content-length: 0 - Content-length: 0 - - Revision-number: 2 - Prop-content-length: 0 - Content-length: 0 - - EOF - try_dump emptyrev.dump && - git log -p --format="rev <%an, %ae>: %s" HEAD >actual && - test_cmp expect actual -' - -test_expect_success 'empty properties' ' - reinit_git && - printf "rev : %s\n" "" "" >expect && - cat >emptyprop.dump <<-\EOF && - SVN-fs-dump-format-version: 3 - - Revision-number: 1 - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - - Revision-number: 2 - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - EOF - try_dump emptyprop.dump && - git log -p --format="rev <%an, %ae>: %s" HEAD >actual && - test_cmp expect actual -' - -test_expect_success 'author name and commit message' ' - reinit_git && - echo "" >expect.author && - cat >message <<-\EOF && - A concise summary of the change - - A detailed description of the change, why it is needed, what - was broken and why applying this is the best course of action. - - * file.c - Details pertaining to an individual file. - EOF - { - properties \ - svn:author author@example.com \ - svn:log "$(cat message)" && - echo PROPS-END - } >props && - { - echo "SVN-fs-dump-format-version: 3" && - echo && - echo "Revision-number: 1" && - echo Prop-content-length: $(wc -c log.dump && - try_dump log.dump && - git log -p --format="%B" HEAD >actual.log && - git log --format="<%an, %ae>" >actual.author && - test_cmp message actual.log && - test_cmp expect.author actual.author -' - -test_expect_success 'unsupported properties are ignored' ' - reinit_git && - echo author >expect && - cat >extraprop.dump <<-\EOF && - SVN-fs-dump-format-version: 3 - - Revision-number: 1 - Prop-content-length: 56 - Content-length: 56 - - K 8 - nonsense - V 1 - y - K 10 - svn:author - V 6 - author - PROPS-END - EOF - try_dump extraprop.dump && - git log -p --format=%an HEAD >actual && - test_cmp expect actual -' - -test_expect_failure 'timestamp and empty file' ' - echo author@example.com >expect.author && - echo 1999-01-01 >expect.date && - echo file >expect.files && - reinit_git && - { - properties \ - svn:author author@example.com \ - svn:date "1999-01-01T00:01:002.000000Z" \ - svn:log "add empty file" && - echo PROPS-END - } >props && - { - cat <<-EOF && - SVN-fs-dump-format-version: 3 - - Revision-number: 1 - EOF - echo Prop-content-length: $(wc -c emptyfile.dump && - try_dump emptyfile.dump && - git log --format=%an HEAD >actual.author && - git log --date=short --format=%ad HEAD >actual.date && - git ls-tree -r --name-only HEAD >actual.files && - test_cmp expect.author actual.author && - test_cmp expect.date actual.date && - test_cmp expect.files actual.files && - git checkout HEAD empty-file && - test_must_be_empty file -' - -test_expect_success 'directory with files' ' - reinit_git && - printf "%s\n" directory/file1 directory/file2 >expect.files && - echo hi >hi && - echo hello >hello && - { - properties \ - svn:author author@example.com \ - svn:date "1999-02-01T00:01:002.000000Z" \ - svn:log "add directory with some files in it" && - echo PROPS-END - } >props && - { - cat <<-EOF && - SVN-fs-dump-format-version: 3 - - Revision-number: 1 - EOF - echo Prop-content-length: $(wc -c directory.dump && - try_dump directory.dump && - - git ls-tree -r --name-only HEAD >actual.files && - git checkout HEAD directory && - test_cmp expect.files actual.files && - test_cmp hello directory/file1 && - test_cmp hi directory/file2 -' - -test_expect_success 'branch name with backslash' ' - reinit_git && - sort <<-\EOF >expect.branch-files && - trunk/file1 - trunk/file2 - "branches/UpdateFOPto094\\/file1" - "branches/UpdateFOPto094\\/file2" - EOF - - echo hi >hi && - echo hello >hello && - { - properties \ - svn:author author@example.com \ - svn:date "1999-02-02T00:01:02.000000Z" \ - svn:log "add directory with some files in it" && - echo PROPS-END - } >props.setup && - { - properties \ - svn:author brancher@example.com \ - svn:date "2007-12-06T21:38:34.000000Z" \ - svn:log "Updating fop to .94 and adjust fo-stylesheets" && - echo PROPS-END - } >props.branch && - { - cat <<-EOF && - SVN-fs-dump-format-version: 3 - - Revision-number: 1 - EOF - echo Prop-content-length: $(wc -c branch.dump && - try_dump branch.dump && - - git ls-tree -r --name-only HEAD | - sort >actual.branch-files && - test_cmp expect.branch-files actual.branch-files -' - -test_expect_success 'node without action' ' - reinit_git && - cat >inaction.dump <<-\EOF && - SVN-fs-dump-format-version: 3 - - Revision-number: 1 - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - - Node-path: directory - Node-kind: dir - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - EOF - try_dump inaction.dump must_fail -' - -test_expect_success 'action: add node without text' ' - reinit_git && - cat >textless.dump <<-\EOF && - SVN-fs-dump-format-version: 3 - - Revision-number: 1 - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - - Node-path: textless - Node-kind: file - Node-action: add - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - EOF - try_dump textless.dump must_fail -' - -test_expect_failure 'change file mode but keep old content' ' - reinit_git && - cat >expect <<-\EOF && - OBJID - :120000 100644 OBJID OBJID T greeting - OBJID - :100644 120000 OBJID OBJID T greeting - OBJID - :000000 100644 OBJID OBJID A greeting - EOF - echo "link hello" >expect.blob && - echo hello >hello && - cat >filemode.dump <<-\EOF && - SVN-fs-dump-format-version: 3 - - Revision-number: 1 - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - - Node-path: greeting - Node-kind: file - Node-action: add - Prop-content-length: 10 - Text-content-length: 11 - Content-length: 21 - - PROPS-END - link hello - - Revision-number: 2 - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - - Node-path: greeting - Node-kind: file - Node-action: change - Prop-content-length: 33 - Content-length: 33 - - K 11 - svn:special - V 1 - * - PROPS-END - - Revision-number: 3 - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - - Node-path: greeting - Node-kind: file - Node-action: change - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - EOF - try_dump filemode.dump && - { - git rev-list HEAD | - git diff-tree --root --stdin | - sed "s/$OID_REGEX/OBJID/g" - } >actual && - git show HEAD:greeting >actual.blob && - git show HEAD^:greeting >actual.target && - test_cmp expect actual && - test_cmp expect.blob actual.blob && - test_cmp hello actual.target -' - -test_expect_success 'NUL in property value' ' - reinit_git && - echo "commit message" >expect.message && - { - properties \ - unimportant "something with a NUL (Q)" \ - svn:log "commit message" && - echo PROPS-END - } | - q_to_nul >props && - { - cat <<-\EOF && - SVN-fs-dump-format-version: 3 - - Revision-number: 1 - EOF - echo Prop-content-length: $(wc -c nulprop.dump && - try_dump nulprop.dump && - git diff-tree --always -s --format=%s HEAD >actual.message && - test_cmp expect.message actual.message -' - -test_expect_success 'NUL in log message, file content, and property name' ' - # Caveat: svnadmin 1.6.16 (r1073529) truncates at \0 in the - # svn:specialQnotreally example. - reinit_git && - cat >expect <<-\EOF && - OBJID - :100644 100644 OBJID OBJID M greeting - OBJID - :000000 100644 OBJID OBJID A greeting - EOF - printf "\n%s\n" "something with an ASCII NUL (Q)" >expect.message && - printf "%s\n" "helQo" >expect.hello1 && - printf "%s\n" "link hello" >expect.hello2 && - { - properties svn:log "something with an ASCII NUL (Q)" && - echo PROPS-END - } | - q_to_nul >props && - { - q_to_nul <<-\EOF && - SVN-fs-dump-format-version: 3 - - Revision-number: 1 - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - - Node-path: greeting - Node-kind: file - Node-action: add - Prop-content-length: 10 - Text-content-length: 6 - Content-length: 16 - - PROPS-END - helQo - - Revision-number: 2 - EOF - echo Prop-content-length: $(wc -c 8bitclean.dump && - try_dump 8bitclean.dump && - { - git rev-list HEAD | - git diff-tree --root --stdin | - sed "s/$OID_REGEX/OBJID/g" - } >actual && - { - git cat-file commit HEAD | nul_to_q && - echo - } | - sed -ne "/^\$/,\$ p" >actual.message && - git cat-file blob HEAD^:greeting | nul_to_q >actual.hello1 && - git cat-file blob HEAD:greeting | nul_to_q >actual.hello2 && - test_cmp expect actual && - test_cmp expect.message actual.message && - test_cmp expect.hello1 actual.hello1 && - test_cmp expect.hello2 actual.hello2 -' - -test_expect_success 'change file mode and reiterate content' ' - reinit_git && - cat >expect <<-\EOF && - OBJID - :120000 100644 OBJID OBJID T greeting - OBJID - :100644 120000 OBJID OBJID T greeting - OBJID - :000000 100644 OBJID OBJID A greeting - EOF - echo "link hello" >expect.blob && - echo hello >hello && - cat >filemode2.dump <<-\EOF && - SVN-fs-dump-format-version: 3 - - Revision-number: 1 - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - - Node-path: greeting - Node-kind: file - Node-action: add - Prop-content-length: 10 - Text-content-length: 11 - Content-length: 21 - - PROPS-END - link hello - - Revision-number: 2 - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - - Node-path: greeting - Node-kind: file - Node-action: change - Prop-content-length: 33 - Text-content-length: 11 - Content-length: 44 - - K 11 - svn:special - V 1 - * - PROPS-END - link hello - - Revision-number: 3 - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - - Node-path: greeting - Node-kind: file - Node-action: change - Prop-content-length: 10 - Text-content-length: 11 - Content-length: 21 - - PROPS-END - link hello - EOF - try_dump filemode2.dump && - { - git rev-list HEAD | - git diff-tree --root --stdin | - sed "s/$OID_REGEX/OBJID/g" - } >actual && - git show HEAD:greeting >actual.blob && - git show HEAD^:greeting >actual.target && - test_cmp expect actual && - test_cmp expect.blob actual.blob && - test_cmp hello actual.target -' - -test_expect_success 'deltas supported' ' - reinit_git && - { - # (old) h + (inline) ello + (old) \n - printf "SVNQ%b%b%s" "Q\003\006\005\004" "\001Q\0204\001\002" "ello" | - q_to_nul - } >delta && - { - properties \ - svn:author author@example.com \ - svn:date "1999-01-05T00:01:002.000000Z" \ - svn:log "add greeting" && - echo PROPS-END - } >props && - { - properties \ - svn:author author@example.com \ - svn:date "1999-01-06T00:01:002.000000Z" \ - svn:log "change it" && - echo PROPS-END - } >props2 && - { - echo SVN-fs-dump-format-version: 3 && - echo && - echo Revision-number: 1 && - echo Prop-content-length: $(wc -c delta.dump && - try_dump delta.dump -' - -test_expect_success 'property deltas supported' ' - reinit_git && - cat >expect <<-\EOF && - OBJID - :100755 100644 OBJID OBJID M script.sh - EOF - { - properties \ - svn:author author@example.com \ - svn:date "1999-03-06T00:01:002.000000Z" \ - svn:log "make an executable, or chmod -x it" && - echo PROPS-END - } >revprops && - { - echo SVN-fs-dump-format-version: 3 && - echo && - echo Revision-number: 1 && - echo Prop-content-length: $(wc -c propdelta.dump && - try_dump propdelta.dump && - { - git rev-list HEAD | - git diff-tree --stdin | - sed "s/$OID_REGEX/OBJID/g" - } >actual && - test_cmp expect actual -' - -test_expect_success 'properties on /' ' - reinit_git && - cat <<-\EOF >expect && - OBJID - OBJID - :000000 100644 OBJID OBJID A greeting - EOF - sed -e "s/X$//" <<-\EOF >changeroot.dump && - SVN-fs-dump-format-version: 3 - - Revision-number: 1 - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - - Node-path: greeting - Node-kind: file - Node-action: add - Text-content-length: 0 - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - - Revision-number: 2 - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - - Node-path: X - Node-kind: dir - Node-action: change - Prop-delta: true - Prop-content-length: 43 - Content-length: 43 - - K 10 - svn:ignore - V 11 - build-area - - PROPS-END - EOF - try_dump changeroot.dump && - { - git rev-list HEAD | - git diff-tree --root --always --stdin | - sed "s/$OID_REGEX/OBJID/g" - } >actual && - test_cmp expect actual -' - -test_expect_success 'deltas for typechange' ' - reinit_git && - cat >expect <<-\EOF && - OBJID - :120000 100644 OBJID OBJID T test-file - OBJID - :100755 120000 OBJID OBJID T test-file - OBJID - :000000 100755 OBJID OBJID A test-file - EOF - cat >deleteprop.dump <<-\EOF && - SVN-fs-dump-format-version: 3 - - Revision-number: 1 - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - - Node-path: test-file - Node-kind: file - Node-action: add - Prop-delta: true - Prop-content-length: 35 - Text-content-length: 17 - Content-length: 52 - - K 14 - svn:executable - V 0 - - PROPS-END - link testing 123 - - Revision-number: 2 - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - - Node-path: test-file - Node-kind: file - Node-action: change - Prop-delta: true - Prop-content-length: 53 - Text-content-length: 17 - Content-length: 70 - - K 11 - svn:special - V 1 - * - D 14 - svn:executable - PROPS-END - link testing 231 - - Revision-number: 3 - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - - Node-path: test-file - Node-kind: file - Node-action: change - Prop-delta: true - Prop-content-length: 27 - Text-content-length: 17 - Content-length: 44 - - D 11 - svn:special - PROPS-END - link testing 321 - EOF - try_dump deleteprop.dump && - { - git rev-list HEAD | - git diff-tree --root --stdin | - sed "s/$OID_REGEX/OBJID/g" - } >actual && - test_cmp expect actual -' - -test_expect_success 'deltas need not consume the whole preimage' ' - reinit_git && - cat >expect <<-\EOF && - OBJID - :120000 100644 OBJID OBJID T postimage - OBJID - :100644 120000 OBJID OBJID T postimage - OBJID - :000000 100644 OBJID OBJID A postimage - EOF - echo "first preimage" >expect.1 && - printf target >expect.2 && - printf lnk >expect.3 && - { - printf "SVNQ%b%b%b" "QQ\017\001\017" "\0217" "first preimage\n" | - q_to_nul - } >delta.1 && - { - properties svn:special "*" && - echo PROPS-END - } >symlink.props && - { - printf "SVNQ%b%b%b" "Q\002\013\004\012" "\0201\001\001\0211" "lnk target" | - q_to_nul - } >delta.2 && - { - printf "SVNQ%b%b" "Q\004\003\004Q" "\001Q\002\002" | - q_to_nul - } >delta.3 && - { - cat <<-\EOF && - SVN-fs-dump-format-version: 3 - - Revision-number: 1 - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - - Node-path: postimage - Node-kind: file - Node-action: add - Text-delta: true - Prop-content-length: 10 - EOF - echo Text-content-length: $(wc -c deltapartial.dump && - try_dump deltapartial.dump && - { - git rev-list HEAD | - git diff-tree --root --stdin | - sed "s/$OID_REGEX/OBJID/g" - } >actual && - test_cmp expect actual && - git show HEAD:postimage >actual.3 && - git show HEAD^:postimage >actual.2 && - git show HEAD^^:postimage >actual.1 && - test_cmp expect.1 actual.1 && - test_cmp expect.2 actual.2 && - test_cmp expect.3 actual.3 -' - -test_expect_success 'no hang for delta trying to read past end of preimage' ' - reinit_git && - { - # COPY 1 - printf "SVNQ%b%b" "Q\001\001\002Q" "\001Q" | - q_to_nul - } >greedy.delta && - { - cat <<-\EOF && - SVN-fs-dump-format-version: 3 - - Revision-number: 1 - Prop-content-length: 10 - Content-length: 10 - - PROPS-END - - Node-path: bootstrap - Node-kind: file - Node-action: add - Text-delta: true - Prop-content-length: 10 - EOF - echo Text-content-length: $(wc -c greedydelta.dump && - try_dump greedydelta.dump must_fail might_fail -' - -test_expect_success 'set up svn repo' ' - svnconf=$PWD/svnconf && - mkdir -p "$svnconf" && - - if - svnadmin -h >/dev/null 2>&1 && - svnadmin create simple-svn && - svnadmin load simple-svn <"$TEST_DIRECTORY/t9135/svn.dump" && - svn export --config-dir "$svnconf" "file://$PWD/simple-svn" simple-svnco - then - test_set_prereq SVNREPO - fi -' - -test_expect_success SVNREPO 't9135/svn.dump' ' - mkdir -p simple-git && - ( - cd simple-git && - reinit_git && - try_dump "$TEST_DIRECTORY/t9135/svn.dump" - ) && - ( - cd simple-svnco && - git init && - git add . && - git fetch ../simple-git master && - git diff --exit-code FETCH_HEAD - ) -' - -test_done diff --git a/t/t9011-svn-da.sh b/t/t9011-svn-da.sh deleted file mode 100755 index ab1ef28fd9..0000000000 --- a/t/t9011-svn-da.sh +++ /dev/null @@ -1,248 +0,0 @@ -#!/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_must_be_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_success 'one-window empty delta' ' - printf "SVNQ%s" "QQQQQ" | q_to_nul >clear.onewindow && - test-svn-fe -d preimage clear.onewindow 9 >actual && - test_must_be_empty actual -' - -test_expect_success 'reject incomplete window header' ' - printf "SVNQ%s" "QQQQQ" | q_to_nul >clear.onewindow && - printf "SVNQ%s" "QQ" | q_to_nul >clear.partialwindow && - test_must_fail test-svn-fe -d preimage clear.onewindow 6 && - test_must_fail test-svn-fe -d preimage clear.partialwindow 6 -' - -test_expect_success 'reject declared delta longer than actual delta' ' - printf "SVNQ%s" "QQQQQ" | q_to_nul >clear.onewindow && - printf "SVNQ%s" "QQ" | q_to_nul >clear.partialwindow && - test_must_fail test-svn-fe -d preimage clear.onewindow 14 && - test_must_fail test-svn-fe -d preimage clear.partialwindow 9 -' - -test_expect_success 'two-window empty delta' ' - printf "SVNQ%s%s" "QQQQQ" "QQQQQ" | q_to_nul >clear.twowindow && - test-svn-fe -d preimage clear.twowindow 14 >actual && - test_must_fail test-svn-fe -d preimage clear.twowindow 13 && - test_must_be_empty actual -' - -test_expect_success 'noisy zeroes' ' - printf "SVNQ%s" \ - "RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRQQQQQ" | - tr R "\200" | - q_to_nul >clear.noisy && - len=$(wc -c clear.badmagic && - test_must_fail test-svn-fe -d preimage clear.badmagic 5 -' - -test_expect_success 'reject truncated integer' ' - printf "SVNQ%s%s" "QQQQQ" "QQQQRRQ" | - tr R "\200" | - q_to_nul >clear.fullint && - printf "SVNQ%s%s" "QQQQQ" "QQQQRR" | - tr RT "\201" | - q_to_nul >clear.partialint && - test_must_fail test-svn-fe -d preimage clear.fullint 15 && - test-svn-fe -d preimage clear.fullint 16 && - test_must_fail test-svn-fe -d preimage clear.partialint 15 -' - -test_expect_success 'nonempty (but unused) preimage view' ' - printf "SVNQ%b" "Q\003QQQ" | q_to_nul >clear.readpreimage && - test-svn-fe -d preimage clear.readpreimage 9 >actual && - test_must_be_empty actual -' - -test_expect_success 'preimage view: right endpoint cannot backtrack' ' - printf "SVNQ%b%b" "Q\003QQQ" "Q\002QQQ" | - q_to_nul >clear.backtrack && - test_must_fail test-svn-fe -d preimage clear.backtrack 14 -' - -test_expect_success 'preimage view: left endpoint can advance' ' - printf "SVNQ%b%b" "Q\003QQQ" "\001\002QQQ" | - q_to_nul >clear.preshrink && - printf "SVNQ%b%b" "Q\003QQQ" "\001\001QQQ" | - q_to_nul >clear.shrinkbacktrack && - test-svn-fe -d preimage clear.preshrink 14 >actual && - test_must_fail test-svn-fe -d preimage clear.shrinkbacktrack 14 && - test_must_be_empty actual -' - -test_expect_success 'preimage view: offsets compared by value' ' - printf "SVNQ%b%b" "\001\001QQQ" "\0200Q\003QQQ" | - q_to_nul >clear.noisybacktrack && - printf "SVNQ%b%b" "\001\001QQQ" "\0200\001\002QQQ" | - q_to_nul >clear.noisyadvance && - test_must_fail test-svn-fe -d preimage clear.noisybacktrack 15 && - test-svn-fe -d preimage clear.noisyadvance 15 && - test_must_be_empty actual -' - -test_expect_success 'preimage view: reject truncated preimage' ' - printf "SVNQ%b" "\010QQQQ" | q_to_nul >clear.lateemptyread && - printf "SVNQ%b" "\010\001QQQ" | q_to_nul >clear.latenonemptyread && - printf "SVNQ%b" "\001\010QQQ" | q_to_nul >clear.longread && - test_must_fail test-svn-fe -d preimage clear.lateemptyread 9 && - test_must_fail test-svn-fe -d preimage clear.latenonemptyread 9 && - test_must_fail test-svn-fe -d preimage clear.longread 9 -' - -test_expect_success 'forbid unconsumed inline data' ' - printf "SVNQ%b%s%b%s" "QQQQ\003" "bar" "QQQQ\001" "x" | - q_to_nul >inline.clear && - test_must_fail test-svn-fe -d preimage inline.clear 18 >actual -' - -test_expect_success 'reject truncated inline data' ' - printf "SVNQ%b%s" "QQQQ\003" "b" | q_to_nul >inline.trunc && - test_must_fail test-svn-fe -d preimage inline.trunc 10 -' - -test_expect_success 'reject truncated inline data (after instruction section)' ' - printf "SVNQ%b%b%s" "QQ\001\001\003" "\0201" "b" | q_to_nul >insn.trunc && - test_must_fail test-svn-fe -d preimage insn.trunc 11 -' - -test_expect_success 'copyfrom_data' ' - echo hi >expect && - printf "SVNQ%b%b%b" "QQ\003\001\003" "\0203" "hi\n" | q_to_nul >copydat && - test-svn-fe -d preimage copydat 13 >actual && - test_cmp expect actual -' - -test_expect_success 'multiple copyfrom_data' ' - echo hi >expect && - printf "SVNQ%b%b%b%b%b" "QQ\003\002\003" "\0201\0202" "hi\n" \ - "QQQ\002Q" "\0200Q" | q_to_nul >copy.multi && - len=$(wc -c actual && - test_cmp expect actual -' - -test_expect_success 'incomplete multiple insn' ' - printf "SVNQ%b%b%b" "QQ\003\002\003" "\0203\0200" "hi\n" | - q_to_nul >copy.partial && - len=$(wc -c copy.incomplete && - len=$(wc -c expect && - printf "SVNQ%b%b%s" "QQ\006\004\003" "\0203\0100\003Q" "foo" | - q_to_nul >copytarget.repeat && - len=$(wc -c actual && - test_cmp expect actual -' - -test_expect_success 'copyfrom target out of order' ' - printf foooof >expect && - printf "SVNQ%b%b%s" \ - "QQ\006\007\003" "\0203\0101\002\0101\001\0101Q" "foo" | - q_to_nul >copytarget.reverse && - len=$(wc -c actual && - test_cmp expect actual -' - -test_expect_success 'catch copyfrom future' ' - printf "SVNQ%b%b%s" "QQ\004\004\003" "\0202\0101\002\0201" "XYZ" | - q_to_nul >copytarget.infuture && - len=$(wc -c expect && - printf "SVNQ%b%b%s" "QQ\014\004\003" "\0202\0111Q\0201" "XYZ" | - q_to_nul >copytarget.sustain && - len=$(wc -c actual && - test_cmp expect actual -' - -test_expect_success 'catch copy that overflows' ' - printf "SVNQ%b%b%s" "QQ\003\003\001" "\0201\0177Q" X | - q_to_nul >copytarget.overflow && - len=$(wc -c expect && - printf "SVNQ%b%b" "Q\003\003\002Q" "\003Q" | q_to_nul >copysource.all && - test-svn-fe -d preimage copysource.all 11 >actual && - test_cmp expect actual -' - -test_expect_success 'copy backwards' ' - printf oof >expect && - printf "SVNQ%b%b" "Q\003\003\006Q" "\001\002\001\001\001Q" | - q_to_nul >copysource.rev && - test-svn-fe -d preimage copysource.rev 15 >actual && - test_cmp expect actual -' - -test_expect_success 'offsets are relative to window' ' - printf fo >expect && - printf "SVNQ%b%b%b%b" "Q\003\001\002Q" "\001Q" \ - "\002\001\001\002Q" "\001Q" | - q_to_nul >copysource.two && - test-svn-fe -d preimage copysource.two 18 >actual && - test_cmp expect actual -' - -test_expect_success 'example from notes/svndiff' ' - printf aaaaccccdddddddd >expect && - printf aaaabbbbcccc >source && - printf "SVNQ%b%b%s" "Q\014\020\007\001" \ - "\004Q\004\010\0201\0107\010" d | - q_to_nul >delta.example && - len=$(wc -c actual && - test_cmp expect actual -' - -test_done diff --git a/t/t9020-remote-svn.sh b/t/t9020-remote-svn.sh deleted file mode 100755 index 754c4a3284..0000000000 --- a/t/t9020-remote-svn.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/bin/sh - -test_description='tests remote-svn' - -. ./test-lib.sh - -MARKSPATH=.git/info/fast-import/remote-svn - -if ! test_have_prereq PYTHON -then - skip_all='skipping remote-svn tests, python not available' - test_done -fi - -# Override svnrdump with our simulator -PATH="$HOME:$PATH" -export PATH PYTHON_PATH GIT_BUILD_DIR - -write_script "$HOME/svnrdump" <<\EOF -exec "$PYTHON_PATH" "$GIT_BUILD_DIR/contrib/svn-fe/svnrdump_sim.py" "$@" -EOF - -init_git () { - rm -fr .git && - git init && - #git remote add svnsim testsvn::sim:///$TEST_DIRECTORY/t9020/example.svnrdump - # let's reuse an existing dump file!? - git remote add svnsim "testsvn::sim://$TEST_DIRECTORY/t9154/svn.dump" - git remote add svnfile "testsvn::file://$TEST_DIRECTORY/t9154/svn.dump" -} - -if test -e "$GIT_BUILD_DIR/git-remote-testsvn" -then - test_set_prereq REMOTE_SVN -fi - -test_debug ' - git --version - type git - type svnrdump -' - -test_expect_success REMOTE_SVN 'simple fetch' ' - init_git && - git fetch svnsim && - test_cmp .git/refs/svn/svnsim/master .git/refs/remotes/svnsim/master && - cp .git/refs/remotes/svnsim/master master.good -' - -test_debug ' - git show-ref -s refs/svn/svnsim/master - git show-ref -s refs/remotes/svnsim/master -' - -test_expect_success REMOTE_SVN 'repeated fetch, nothing shall change' ' - git fetch svnsim && - test_cmp master.good .git/refs/remotes/svnsim/master -' - -test_expect_success REMOTE_SVN 'fetch from a file:// url gives the same result' ' - git fetch svnfile -' - -test_expect_failure REMOTE_SVN 'the sha1 differ because the git-svn-id line in the commit msg contains the url' ' - test_cmp .git/refs/remotes/svnfile/master .git/refs/remotes/svnsim/master -' - -test_expect_success REMOTE_SVN 'mark-file regeneration' ' - # filter out any other marks, that can not be regenerated. Only up to 3 digit revisions are allowed here - grep ":[0-9]\{1,3\} " $MARKSPATH/svnsim.marks > $MARKSPATH/svnsim.marks.old && - rm $MARKSPATH/svnsim.marks && - git fetch svnsim && - test_cmp $MARKSPATH/svnsim.marks.old $MARKSPATH/svnsim.marks -' - -test_expect_success REMOTE_SVN 'incremental imports must lead to the same head' ' - SVNRMAX=3 && - export SVNRMAX && - init_git && - git fetch svnsim && - test_cmp .git/refs/svn/svnsim/master .git/refs/remotes/svnsim/master && - unset SVNRMAX && - git fetch svnsim && - test_cmp master.good .git/refs/remotes/svnsim/master -' - -test_expect_success REMOTE_SVN 'respects configured default initial branch' ' - git -c init.defaultBranch=trunk remote add -f trunk \ - "testsvn::file://$TEST_DIRECTORY/t9154/svn.dump" && - git rev-parse --verify refs/remotes/trunk/trunk -' - -test_debug 'git branch -a' - -test_done diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index 596c549cdd..6d9ea1bb67 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -820,7 +820,7 @@ test_must_fail_acceptable () { fi case "$1" in - git|__git*|test-tool|test-svn-fe|test_terminal) + git|__git*|test-tool|test_terminal) return 0 ;; *) diff --git a/vcs-svn/LICENSE b/vcs-svn/LICENSE deleted file mode 100644 index eb91858b82..0000000000 --- a/vcs-svn/LICENSE +++ /dev/null @@ -1,32 +0,0 @@ -Copyright (C) 2010 David Barr . -All rights reserved. - -Copyright (C) 2010 Jonathan Nieder . - -Copyright (C) 2005 Stefan Hegny, hydrografix Consulting GmbH, -Frankfurt/Main, Germany -and others, see http://svn2cc.sarovar.org - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice(s), this list of conditions and the following disclaimer - unmodified other than the allowable addition of one or more - copyright notices. -2. Redistributions in binary form must reproduce the above copyright - notice(s), this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vcs-svn/fast_export.c b/vcs-svn/fast_export.c deleted file mode 100644 index b5b8913cb0..0000000000 --- a/vcs-svn/fast_export.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Licensed under a two-clause BSD-style license. - * See LICENSE for details. - */ - -#include "cache.h" -#include "quote.h" -#include "fast_export.h" -#include "strbuf.h" -#include "svndiff.h" -#include "sliding_window.h" -#include "line_buffer.h" - -#define MAX_GITSVN_LINE_LEN 4096 - -static uint32_t first_commit_done; -static struct line_buffer postimage = LINE_BUFFER_INIT; -static struct line_buffer report_buffer = LINE_BUFFER_INIT; - -/* NEEDSWORK: move to fast_export_init() */ -static int init_postimage(void) -{ - static int postimage_initialized; - if (postimage_initialized) - return 0; - postimage_initialized = 1; - return buffer_tmpfile_init(&postimage); -} - -void fast_export_init(int fd) -{ - first_commit_done = 0; - if (buffer_fdinit(&report_buffer, fd)) - die_errno("cannot read from file descriptor %d", fd); -} - -void fast_export_deinit(void) -{ - if (buffer_deinit(&report_buffer)) - die_errno("error closing fast-import feedback stream"); -} - -void fast_export_delete(const char *path) -{ - putchar('D'); - putchar(' '); - quote_c_style(path, NULL, stdout, 0); - putchar('\n'); -} - -static void fast_export_truncate(const char *path, uint32_t mode) -{ - fast_export_modify(path, mode, "inline"); - printf("data 0\n\n"); -} - -void fast_export_modify(const char *path, uint32_t mode, const char *dataref) -{ - /* Mode must be 100644, 100755, 120000, or 160000. */ - if (!dataref) { - fast_export_truncate(path, mode); - return; - } - printf("M %06"PRIo32" %s ", mode, dataref); - quote_c_style(path, NULL, stdout, 0); - putchar('\n'); -} - -void fast_export_begin_note(uint32_t revision, const char *author, - const char *log, timestamp_t timestamp, const char *note_ref) -{ - static int firstnote = 1; - size_t loglen = strlen(log); - printf("commit %s\n", note_ref); - printf("committer %s <%s@%s> %"PRItime" +0000\n", author, author, "local", timestamp); - printf("data %"PRIuMAX"\n", (uintmax_t)loglen); - fwrite(log, loglen, 1, stdout); - if (firstnote) { - if (revision > 1) - printf("from %s^0", note_ref); - firstnote = 0; - } - fputc('\n', stdout); -} - -void fast_export_note(const char *committish, const char *dataref) -{ - printf("N %s %s\n", dataref, committish); -} - -static char gitsvnline[MAX_GITSVN_LINE_LEN]; -void fast_export_begin_commit(uint32_t revision, const char *author, - const struct strbuf *log, - const char *uuid, const char *url, - timestamp_t timestamp, const char *local_ref) -{ - static const struct strbuf empty = STRBUF_INIT; - if (!log) - log = ∅ - if (*uuid && *url) { - snprintf(gitsvnline, MAX_GITSVN_LINE_LEN, - "\n\ngit-svn-id: %s@%"PRIu32" %s\n", - url, revision, uuid); - } else { - *gitsvnline = '\0'; - } - printf("commit %s\n", local_ref); - printf("mark :%"PRIu32"\n", revision); - printf("committer %s <%s@%s> %"PRItime" +0000\n", - *author ? author : "nobody", - *author ? author : "nobody", - *uuid ? uuid : "local", timestamp); - printf("data %"PRIuMAX"\n", - (uintmax_t) (log->len + strlen(gitsvnline))); - fwrite(log->buf, log->len, 1, stdout); - printf("%s\n", gitsvnline); - if (!first_commit_done) { - if (revision > 1) - printf("from :%"PRIu32"\n", revision - 1); - first_commit_done = 1; - } -} - -void fast_export_end_commit(uint32_t revision) -{ - printf("progress Imported commit %"PRIu32".\n\n", revision); -} - -static void ls_from_rev(uint32_t rev, const char *path) -{ - /* ls :5 path/to/old/file */ - printf("ls :%"PRIu32" ", rev); - quote_c_style(path, NULL, stdout, 0); - putchar('\n'); - fflush(stdout); -} - -static void ls_from_active_commit(const char *path) -{ - /* ls "path/to/file" */ - printf("ls \""); - quote_c_style(path, NULL, stdout, 1); - printf("\"\n"); - fflush(stdout); -} - -static const char *get_response_line(void) -{ - const char *line = buffer_read_line(&report_buffer); - if (line) - return line; - if (buffer_ferror(&report_buffer)) - die_errno("error reading from fast-import"); - die("unexpected end of fast-import feedback"); -} - -static void die_short_read(struct line_buffer *input) -{ - if (buffer_ferror(input)) - die_errno("error reading dump file"); - die("invalid dump: unexpected end of file"); -} - -static int parse_cat_response_line(const char *header, off_t *len) -{ - uintmax_t n; - const char *type; - const char *end; - - if (ends_with(header, " missing")) - return error("cat-blob reports missing blob: %s", header); - type = strstr(header, " blob "); - if (!type) - return error("cat-blob header has wrong object type: %s", header); - n = strtoumax(type + strlen(" blob "), (char **) &end, 10); - if (end == type + strlen(" blob ")) - return error("cat-blob header does not contain length: %s", header); - if (memchr(type + strlen(" blob "), '-', end - type - strlen(" blob "))) - return error("cat-blob header contains negative length: %s", header); - if (n == UINTMAX_MAX || n > maximum_signed_value_of_type(off_t)) - return error("blob too large for current definition of off_t"); - *len = n; - if (*end) - return error("cat-blob header contains garbage after length: %s", header); - return 0; -} - -static void check_preimage_overflow(off_t a, off_t b) -{ - if (signed_add_overflows(a, b)) - die("blob too large for current definition of off_t"); -} - -static long apply_delta(off_t len, struct line_buffer *input, - const char *old_data, uint32_t old_mode) -{ - long ret; - struct sliding_view preimage = SLIDING_VIEW_INIT(&report_buffer, 0); - FILE *out; - - if (init_postimage() || !(out = buffer_tmpfile_rewind(&postimage))) - die("cannot open temporary file for blob retrieval"); - if (old_data) { - const char *response; - printf("cat-blob %s\n", old_data); - fflush(stdout); - response = get_response_line(); - if (parse_cat_response_line(response, &preimage.max_off)) - die("invalid cat-blob response: %s", response); - check_preimage_overflow(preimage.max_off, 1); - } - if (old_mode == S_IFLNK) { - strbuf_addstr(&preimage.buf, "link "); - check_preimage_overflow(preimage.max_off, strlen("link ")); - preimage.max_off += strlen("link "); - check_preimage_overflow(preimage.max_off, 1); - } - if (svndiff0_apply(input, len, &preimage, out)) - die("cannot apply delta"); - if (old_data) { - /* Read the remainder of preimage and trailing newline. */ - assert(!signed_add_overflows(preimage.max_off, 1)); - preimage.max_off++; /* room for newline */ - if (move_window(&preimage, preimage.max_off - 1, 1)) - die("cannot seek to end of input"); - if (preimage.buf.buf[0] != '\n') - die("missing newline after cat-blob response"); - } - ret = buffer_tmpfile_prepare_to_read(&postimage); - if (ret < 0) - die("cannot read temporary file for blob retrieval"); - strbuf_release(&preimage.buf); - return ret; -} - -void fast_export_buf_to_data(const struct strbuf *data) -{ - printf("data %"PRIuMAX"\n", (uintmax_t)data->len); - fwrite(data->buf, data->len, 1, stdout); - fputc('\n', stdout); -} - -void fast_export_data(uint32_t mode, off_t len, struct line_buffer *input) -{ - assert(len >= 0); - if (mode == S_IFLNK) { - /* svn symlink blobs start with "link " */ - if (len < 5) - die("invalid dump: symlink too short for \"link\" prefix"); - len -= 5; - if (buffer_skip_bytes(input, 5) != 5) - die_short_read(input); - } - printf("data %"PRIuMAX"\n", (uintmax_t) len); - if (buffer_copy_bytes(input, len) != len) - die_short_read(input); - fputc('\n', stdout); -} - -static int parse_ls_response(const char *response, uint32_t *mode, - struct strbuf *dataref) -{ - const char *tab; - const char *response_end; - - assert(response); - response_end = response + strlen(response); - - if (*response == 'm') { /* Missing. */ - errno = ENOENT; - return -1; - } - - /* Mode. */ - if (response_end - response < (signed) strlen("100644") || - response[strlen("100644")] != ' ') - die("invalid ls response: missing mode: %s", response); - *mode = 0; - for (; *response != ' '; response++) { - char ch = *response; - if (ch < '0' || ch > '7') - die("invalid ls response: mode is not octal: %s", response); - *mode *= 8; - *mode += ch - '0'; - } - - /* ' blob ' or ' tree ' */ - if (response_end - response < (signed) strlen(" blob ") || - (response[1] != 'b' && response[1] != 't')) - die("unexpected ls response: not a tree or blob: %s", response); - response += strlen(" blob "); - - /* Dataref. */ - tab = memchr(response, '\t', response_end - response); - if (!tab) - die("invalid ls response: missing tab: %s", response); - strbuf_add(dataref, response, tab - response); - return 0; -} - -int fast_export_ls_rev(uint32_t rev, const char *path, - uint32_t *mode, struct strbuf *dataref) -{ - ls_from_rev(rev, path); - return parse_ls_response(get_response_line(), mode, dataref); -} - -int fast_export_ls(const char *path, uint32_t *mode, struct strbuf *dataref) -{ - ls_from_active_commit(path); - return parse_ls_response(get_response_line(), mode, dataref); -} - -const char *fast_export_read_path(const char *path, uint32_t *mode_out) -{ - int err; - static struct strbuf buf = STRBUF_INIT; - - strbuf_reset(&buf); - err = fast_export_ls(path, mode_out, &buf); - if (err) { - if (errno != ENOENT) - BUG("unexpected fast_export_ls error: %s", - strerror(errno)); - /* Treat missing paths as directories. */ - *mode_out = S_IFDIR; - return NULL; - } - return buf.buf; -} - -void fast_export_copy(uint32_t revision, const char *src, const char *dst) -{ - int err; - uint32_t mode; - static struct strbuf data = STRBUF_INIT; - - strbuf_reset(&data); - err = fast_export_ls_rev(revision, src, &mode, &data); - if (err) { - if (errno != ENOENT) - BUG("unexpected fast_export_ls_rev error: %s", - strerror(errno)); - fast_export_delete(dst); - return; - } - fast_export_modify(dst, mode, data.buf); -} - -void fast_export_blob_delta(uint32_t mode, - uint32_t old_mode, const char *old_data, - off_t len, struct line_buffer *input) -{ - long postimage_len; - - assert(len >= 0); - postimage_len = apply_delta(len, input, old_data, old_mode); - if (mode == S_IFLNK) { - buffer_skip_bytes(&postimage, strlen("link ")); - postimage_len -= strlen("link "); - } - printf("data %ld\n", postimage_len); - buffer_copy_bytes(&postimage, postimage_len); - fputc('\n', stdout); -} diff --git a/vcs-svn/line_buffer.c b/vcs-svn/line_buffer.c deleted file mode 100644 index e416caf8a4..0000000000 --- a/vcs-svn/line_buffer.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Licensed under a two-clause BSD-style license. - * See LICENSE for details. - */ - -#include "git-compat-util.h" -#include "line_buffer.h" -#include "strbuf.h" - -#define COPY_BUFFER_LEN 4096 - -int buffer_init(struct line_buffer *buf, const char *filename) -{ - buf->infile = filename ? fopen(filename, "r") : stdin; - if (!buf->infile) - return -1; - return 0; -} - -int buffer_fdinit(struct line_buffer *buf, int fd) -{ - buf->infile = fdopen(fd, "r"); - if (!buf->infile) - return -1; - return 0; -} - -int buffer_tmpfile_init(struct line_buffer *buf) -{ - buf->infile = tmpfile(); - if (!buf->infile) - return -1; - return 0; -} - -int buffer_deinit(struct line_buffer *buf) -{ - int err; - if (buf->infile == stdin) - return ferror(buf->infile); - err = ferror(buf->infile); - err |= fclose(buf->infile); - return err; -} - -FILE *buffer_tmpfile_rewind(struct line_buffer *buf) -{ - rewind(buf->infile); - return buf->infile; -} - -long buffer_tmpfile_prepare_to_read(struct line_buffer *buf) -{ - long pos = ftell(buf->infile); - if (pos < 0) - return error_errno("ftell error"); - if (fseek(buf->infile, 0, SEEK_SET)) - return error_errno("seek error"); - return pos; -} - -int buffer_ferror(struct line_buffer *buf) -{ - return ferror(buf->infile); -} - -int buffer_read_char(struct line_buffer *buf) -{ - return fgetc(buf->infile); -} - -/* Read a line without trailing newline. */ -char *buffer_read_line(struct line_buffer *buf) -{ - char *end; - if (!fgets(buf->line_buffer, sizeof(buf->line_buffer), buf->infile)) - /* Error or data exhausted. */ - return NULL; - end = buf->line_buffer + strlen(buf->line_buffer); - if (end[-1] == '\n') - end[-1] = '\0'; - else if (feof(buf->infile)) - ; /* No newline at end of file. That's fine. */ - else - /* - * Line was too long. - * There is probably a saner way to deal with this, - * but for now let's return an error. - */ - return NULL; - return buf->line_buffer; -} - -size_t buffer_read_binary(struct line_buffer *buf, - struct strbuf *sb, size_t size) -{ - return strbuf_fread(sb, size, buf->infile); -} - -off_t buffer_copy_bytes(struct line_buffer *buf, off_t nbytes) -{ - char byte_buffer[COPY_BUFFER_LEN]; - off_t done = 0; - while (done < nbytes && !feof(buf->infile) && !ferror(buf->infile)) { - off_t len = nbytes - done; - size_t in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN; - in = fread(byte_buffer, 1, in, buf->infile); - done += in; - fwrite(byte_buffer, 1, in, stdout); - if (ferror(stdout)) - return done + buffer_skip_bytes(buf, nbytes - done); - } - return done; -} - -off_t buffer_skip_bytes(struct line_buffer *buf, off_t nbytes) -{ - char byte_buffer[COPY_BUFFER_LEN]; - off_t done = 0; - while (done < nbytes && !feof(buf->infile) && !ferror(buf->infile)) { - off_t len = nbytes - done; - size_t in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN; - done += fread(byte_buffer, 1, in, buf->infile); - } - return done; -} diff --git a/vcs-svn/line_buffer.txt b/vcs-svn/line_buffer.txt deleted file mode 100644 index 8e139eb22d..0000000000 --- a/vcs-svn/line_buffer.txt +++ /dev/null @@ -1,77 +0,0 @@ -line_buffer API -=============== - -The line_buffer library provides a convenient interface for -mostly-line-oriented input. - -Each line is not permitted to exceed 10000 bytes. The provided -functions are not thread-safe or async-signal-safe, and like -`fgets()`, they generally do not function correctly if interrupted -by a signal without SA_RESTART set. - -Calling sequence ----------------- - -The calling program: - - - initializes a `struct line_buffer` to LINE_BUFFER_INIT - - specifies a file to read with `buffer_init` - - processes input with `buffer_read_line`, `buffer_skip_bytes`, - and `buffer_copy_bytes` - - closes the file with `buffer_deinit`, perhaps to start over and - read another file. - -When finished, the caller can use `buffer_reset` to deallocate -resources. - -Using temporary files ---------------------- - -Temporary files provide a place to store data that should not outlive -the calling program. A program - - - initializes a `struct line_buffer` to LINE_BUFFER_INIT - - requests a temporary file with `buffer_tmpfile_init` - - acquires an output handle by calling `buffer_tmpfile_rewind` - - uses standard I/O functions like `fprintf` and `fwrite` to fill - the temporary file - - declares writing is over with `buffer_tmpfile_prepare_to_read` - - can re-read what was written with `buffer_read_line`, - `buffer_copy_bytes`, and so on - - can reuse the temporary file by calling `buffer_tmpfile_rewind` - again - - removes the temporary file with `buffer_deinit`, perhaps to - reuse the line_buffer for some other file. - -When finished, the calling program can use `buffer_reset` to deallocate -resources. - -Functions ---------- - -`buffer_init`, `buffer_fdinit`:: - Open the named file or file descriptor for input. - buffer_init(buf, NULL) prepares to read from stdin. - On failure, returns -1 (with errno indicating the nature - of the failure). - -`buffer_deinit`:: - Stop reading from the current file (closing it unless - it was stdin). Returns nonzero if `fclose` fails or - the error indicator was set. - -`buffer_read_line`:: - Read a line and strip off the trailing newline. - On failure or end of file, returns NULL. - -`buffer_copy_bytes`:: - Read `len` bytes of input and dump them to the standard output - stream. Returns early for error or end of file. - -`buffer_skip_bytes`:: - Discards `len` bytes from the input stream (stopping early - if necessary because of an error or eof). Return value is - the number of bytes successfully read. - -`buffer_reset`:: - Deallocates non-static buffers. diff --git a/vcs-svn/sliding_window.c b/vcs-svn/sliding_window.c deleted file mode 100644 index 06d273c9e8..0000000000 --- a/vcs-svn/sliding_window.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Licensed under a two-clause BSD-style license. - * See LICENSE for details. - */ - -#include "git-compat-util.h" -#include "sliding_window.h" -#include "line_buffer.h" -#include "strbuf.h" - -static int input_error(struct line_buffer *file) -{ - if (!buffer_ferror(file)) - return error("delta preimage ends early"); - return error_errno("cannot read delta preimage"); -} - -static int skip_or_whine(struct line_buffer *file, off_t gap) -{ - if (buffer_skip_bytes(file, gap) != gap) - return input_error(file); - return 0; -} - -static int read_to_fill_or_whine(struct line_buffer *file, - struct strbuf *buf, size_t width) -{ - buffer_read_binary(file, buf, width - buf->len); - if (buf->len != width) - return input_error(file); - return 0; -} - -static int check_offset_overflow(off_t offset, uintmax_t len) -{ - if (len > maximum_signed_value_of_type(off_t)) - return error("unrepresentable length in delta: " - "%"PRIuMAX" > OFF_MAX", len); - if (signed_add_overflows(offset, (off_t) len)) - return error("unrepresentable offset in delta: " - "%"PRIuMAX" + %"PRIuMAX" > OFF_MAX", - (uintmax_t) offset, len); - return 0; -} - -int move_window(struct sliding_view *view, off_t off, size_t width) -{ - off_t file_offset; - assert(view); - assert(view->width <= view->buf.len); - assert(!check_offset_overflow(view->off, view->buf.len)); - - if (check_offset_overflow(off, width)) - return -1; - if (off < view->off || off + width < view->off + view->width) - return error("invalid delta: window slides left"); - if (view->max_off >= 0 && view->max_off < off + (off_t) width) - return error("delta preimage ends early"); - - file_offset = view->off + view->buf.len; - if (off < file_offset) { - /* Move the overlapping region into place. */ - strbuf_remove(&view->buf, 0, off - view->off); - } else { - /* Seek ahead to skip the gap. */ - if (skip_or_whine(view->file, off - file_offset)) - return -1; - strbuf_setlen(&view->buf, 0); - } - - if (view->buf.len > width) - ; /* Already read. */ - else if (read_to_fill_or_whine(view->file, &view->buf, width)) - return -1; - - view->off = off; - view->width = width; - return 0; -} diff --git a/vcs-svn/svndiff.c b/vcs-svn/svndiff.c deleted file mode 100644 index 75c753162a..0000000000 --- a/vcs-svn/svndiff.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Licensed under a two-clause BSD-style license. - * See LICENSE for details. - */ - -#include "git-compat-util.h" -#include "sliding_window.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* - * window ::= int int int int int instructions inline_data; - * instructions ::= instruction*; - * instruction ::= view_selector int int - * | copyfrom_data int - * | packed_view_selector int - * | packed_copyfrom_data - * ; - * view_selector ::= copyfrom_source - * | copyfrom_target - * ; - * copyfrom_source ::= # binary 00 000000; - * copyfrom_target ::= # binary 01 000000; - * copyfrom_data ::= # binary 10 000000; - * packed_view_selector ::= # view_selector OR-ed with 6 bit value; - * packed_copyfrom_data ::= # copyfrom_data OR-ed with 6 bit value; - * int ::= highdigit* lowdigit; - * highdigit ::= # binary 1000 0000 OR-ed with 7 bit value; - * lowdigit ::= # 7 bit value; - */ - -#define INSN_MASK 0xc0 -#define INSN_COPYFROM_SOURCE 0x00 -#define INSN_COPYFROM_TARGET 0x40 -#define INSN_COPYFROM_DATA 0x80 -#define OPERAND_MASK 0x3f - -#define VLI_CONTINUE 0x80 -#define VLI_DIGIT_MASK 0x7f -#define VLI_BITS_PER_DIGIT 7 - -struct window { - struct sliding_view *in; - struct strbuf out; - struct strbuf instructions; - struct strbuf data; -}; - -#define WINDOW_INIT(w) { (w), STRBUF_INIT, STRBUF_INIT, STRBUF_INIT } - -static void window_release(struct window *ctx) -{ - strbuf_release(&ctx->out); - strbuf_release(&ctx->instructions); - strbuf_release(&ctx->data); -} - -static int write_strbuf(struct strbuf *sb, FILE *out) -{ - if (fwrite(sb->buf, 1, sb->len, out) == sb->len) /* Success. */ - return 0; - return error_errno("cannot write delta postimage"); -} - -static int error_short_read(struct line_buffer *input) -{ - if (buffer_ferror(input)) - return error_errno("error reading delta"); - return error("invalid delta: unexpected end of file"); -} - -static int read_chunk(struct line_buffer *delta, off_t *delta_len, - struct strbuf *buf, size_t len) -{ - assert(*delta_len >= 0); - strbuf_reset(buf); - if (len > (uintmax_t) *delta_len || - buffer_read_binary(delta, buf, len) != len) - return error_short_read(delta); - *delta_len -= buf->len; - return 0; -} - -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 (read_chunk(in, len, &sb, sizeof(magic))) { - strbuf_release(&sb); - return -1; - } - if (memcmp(sb.buf, magic, sizeof(magic))) { - strbuf_release(&sb); - return error("invalid delta: unrecognized file type"); - } - strbuf_release(&sb); - return 0; -} - -static int read_int(struct line_buffer *in, uintmax_t *result, off_t *len) -{ - uintmax_t rv = 0; - off_t sz; - for (sz = *len; sz; sz--) { - const int ch = buffer_read_char(in); - if (ch == EOF) - break; - - rv <<= VLI_BITS_PER_DIGIT; - rv += (ch & VLI_DIGIT_MASK); - if (ch & VLI_CONTINUE) - continue; - - *result = rv; - *len = sz - 1; - return 0; - } - return error_short_read(in); -} - -static int parse_int(const char **buf, size_t *result, const char *end) -{ - size_t rv = 0; - const char *pos; - for (pos = *buf; pos != end; pos++) { - unsigned char ch = *pos; - - rv <<= VLI_BITS_PER_DIGIT; - rv += (ch & VLI_DIGIT_MASK); - if (ch & VLI_CONTINUE) - continue; - - *result = rv; - *buf = pos + 1; - return 0; - } - return error("invalid delta: unexpected end of instructions section"); -} - -static int read_offset(struct line_buffer *in, off_t *result, off_t *len) -{ - uintmax_t val; - if (read_int(in, &val, len)) - return -1; - if (val > maximum_signed_value_of_type(off_t)) - return error("unrepresentable offset in delta: %"PRIuMAX"", val); - *result = val; - return 0; -} - -static int read_length(struct line_buffer *in, size_t *result, off_t *len) -{ - uintmax_t val; - if (read_int(in, &val, len)) - return -1; - if (val > SIZE_MAX) - return error("unrepresentable length in delta: %"PRIuMAX"", val); - *result = val; - return 0; -} - -static int copyfrom_source(struct window *ctx, const char **instructions, - size_t nbytes, const char *insns_end) -{ - size_t offset; - if (parse_int(instructions, &offset, insns_end)) - return -1; - if (unsigned_add_overflows(offset, nbytes) || - offset + nbytes > ctx->in->width) - return error("invalid delta: copies source data outside view"); - strbuf_add(&ctx->out, ctx->in->buf.buf + offset, nbytes); - return 0; -} - -static int copyfrom_target(struct window *ctx, const char **instructions, - size_t nbytes, const char *instructions_end) -{ - size_t offset; - if (parse_int(instructions, &offset, instructions_end)) - return -1; - if (offset >= ctx->out.len) - return error("invalid delta: copies from the future"); - for (; nbytes > 0; nbytes--) - strbuf_addch(&ctx->out, ctx->out.buf[offset++]); - return 0; -} - -static int copyfrom_data(struct window *ctx, size_t *data_pos, size_t nbytes) -{ - const size_t pos = *data_pos; - if (unsigned_add_overflows(pos, nbytes) || - pos + nbytes > ctx->data.len) - return error("invalid delta: copies unavailable inline data"); - strbuf_add(&ctx->out, ctx->data.buf + pos, nbytes); - *data_pos += nbytes; - return 0; -} - -static int parse_first_operand(const char **buf, size_t *out, const char *end) -{ - size_t result = (unsigned char) *(*buf)++ & OPERAND_MASK; - if (result) { /* immediate operand */ - *out = result; - return 0; - } - return parse_int(buf, out, end); -} - -static int execute_one_instruction(struct window *ctx, - const char **instructions, size_t *data_pos) -{ - unsigned int instruction; - const char *insns_end = ctx->instructions.buf + ctx->instructions.len; - size_t nbytes; - assert(ctx); - assert(instructions && *instructions); - assert(data_pos); - - instruction = (unsigned char) **instructions; - if (parse_first_operand(instructions, &nbytes, insns_end)) - return -1; - switch (instruction & INSN_MASK) { - case INSN_COPYFROM_SOURCE: - return copyfrom_source(ctx, instructions, nbytes, insns_end); - case INSN_COPYFROM_TARGET: - return copyfrom_target(ctx, instructions, nbytes, insns_end); - case INSN_COPYFROM_DATA: - return copyfrom_data(ctx, data_pos, nbytes); - default: - return error("invalid delta: unrecognized instruction"); - } -} - -static int apply_window_in_core(struct window *ctx) -{ - const char *instructions; - size_t data_pos = 0; - - /* - * Fill ctx->out.buf using data from the source, target, - * and inline data views. - */ - for (instructions = ctx->instructions.buf; - instructions != ctx->instructions.buf + ctx->instructions.len; - ) - if (execute_one_instruction(ctx, &instructions, &data_pos)) - return -1; - if (data_pos != ctx->data.len) - return error("invalid delta: does not copy all inline data"); - return 0; -} - -static int apply_one_window(struct line_buffer *delta, off_t *delta_len, - struct sliding_view *preimage, FILE *out) -{ - int rv = -1; - struct window ctx = WINDOW_INIT(preimage); - size_t out_len; - size_t instructions_len; - size_t data_len; - assert(delta_len); - - /* "source view" offset and length already handled; */ - if (read_length(delta, &out_len, delta_len) || - read_length(delta, &instructions_len, delta_len) || - read_length(delta, &data_len, delta_len) || - read_chunk(delta, delta_len, &ctx.instructions, instructions_len) || - read_chunk(delta, delta_len, &ctx.data, data_len)) - goto error_out; - strbuf_grow(&ctx.out, out_len); - if (apply_window_in_core(&ctx)) - goto error_out; - if (ctx.out.len != out_len) { - rv = error("invalid delta: incorrect postimage length"); - goto error_out; - } - if (write_strbuf(&ctx.out, out)) - goto error_out; - rv = 0; -error_out: - window_release(&ctx); - return rv; -} - -int svndiff0_apply(struct line_buffer *delta, off_t delta_len, - struct sliding_view *preimage, FILE *postimage) -{ - assert(delta && preimage && postimage && delta_len >= 0); - - if (read_magic(delta, &delta_len)) - return -1; - while (delta_len) { /* For each window: */ - off_t pre_off = -1; - size_t pre_len; - - if (read_offset(delta, &pre_off, &delta_len) || - read_length(delta, &pre_len, &delta_len) || - move_window(preimage, pre_off, pre_len) || - apply_one_window(delta, &delta_len, preimage, postimage)) - return -1; - } - return 0; -} diff --git a/vcs-svn/svndump.c b/vcs-svn/svndump.c deleted file mode 100644 index 08d136b8cc..0000000000 --- a/vcs-svn/svndump.c +++ /dev/null @@ -1,540 +0,0 @@ -/* - * Parse and rearrange a svnadmin dump. - * Create the dump with: - * svnadmin dump --incremental -r: >outfile - * - * Licensed under a two-clause BSD-style license. - * See LICENSE for details. - */ - -#include "cache.h" -#include "fast_export.h" -#include "line_buffer.h" -#include "strbuf.h" -#include "svndump.h" - -/* - * Compare start of string to literal of equal length; - * must be guarded by length test. - */ -#define constcmp(s, ref) memcmp(s, ref, sizeof(ref) - 1) - -#define REPORT_FILENO 3 - -#define NODEACT_REPLACE 4 -#define NODEACT_DELETE 3 -#define NODEACT_ADD 2 -#define NODEACT_CHANGE 1 -#define NODEACT_UNKNOWN 0 - -/* States: */ -#define DUMP_CTX 0 /* dump metadata */ -#define REV_CTX 1 /* revision metadata */ -#define NODE_CTX 2 /* node metadata */ -#define INTERNODE_CTX 3 /* between nodes */ - -#define DATE_RFC2822_LEN 31 - -static struct line_buffer input = LINE_BUFFER_INIT; - -static struct { - uint32_t action, srcRev, type; - off_t prop_length, text_length; - struct strbuf src, dst; - uint32_t text_delta, prop_delta; -} node_ctx; - -static struct { - uint32_t revision; - timestamp_t timestamp; - struct strbuf log, author, note; -} rev_ctx; - -static struct { - uint32_t version; - struct strbuf uuid, url; -} dump_ctx; - -static void reset_node_ctx(char *fname) -{ - node_ctx.type = 0; - node_ctx.action = NODEACT_UNKNOWN; - node_ctx.prop_length = -1; - node_ctx.text_length = -1; - strbuf_reset(&node_ctx.src); - node_ctx.srcRev = 0; - strbuf_reset(&node_ctx.dst); - if (fname) - strbuf_addstr(&node_ctx.dst, fname); - node_ctx.text_delta = 0; - node_ctx.prop_delta = 0; -} - -static void reset_rev_ctx(uint32_t revision) -{ - rev_ctx.revision = revision; - rev_ctx.timestamp = 0; - strbuf_reset(&rev_ctx.log); - strbuf_reset(&rev_ctx.author); - strbuf_reset(&rev_ctx.note); -} - -static void reset_dump_ctx(const char *url) -{ - strbuf_reset(&dump_ctx.url); - if (url) - strbuf_addstr(&dump_ctx.url, url); - dump_ctx.version = 1; - strbuf_reset(&dump_ctx.uuid); -} - -static void handle_property(const struct strbuf *key_buf, - struct strbuf *val, - uint32_t *type_set) -{ - const char *key = key_buf->buf; - size_t keylen = key_buf->len; - - switch (keylen + 1) { - case sizeof("svn:log"): - if (constcmp(key, "svn:log")) - break; - if (!val) - die("invalid dump: unsets svn:log"); - strbuf_swap(&rev_ctx.log, val); - break; - case sizeof("svn:author"): - if (constcmp(key, "svn:author")) - break; - if (!val) - strbuf_reset(&rev_ctx.author); - else - strbuf_swap(&rev_ctx.author, val); - break; - case sizeof("svn:date"): - if (constcmp(key, "svn:date")) - break; - if (!val) - die("invalid dump: unsets svn:date"); - if (parse_date_basic(val->buf, &rev_ctx.timestamp, NULL)) - warning("invalid timestamp: %s", val->buf); - break; - case sizeof("svn:executable"): - case sizeof("svn:special"): - if (keylen == strlen("svn:executable") && - constcmp(key, "svn:executable")) - break; - if (keylen == strlen("svn:special") && - constcmp(key, "svn:special")) - break; - if (*type_set) { - if (!val) - return; - die("invalid dump: sets type twice"); - } - if (!val) { - node_ctx.type = S_IFREG | 0644; - return; - } - *type_set = 1; - node_ctx.type = keylen == strlen("svn:executable") ? - (S_IFREG | 0755) : - S_IFLNK; - } -} - -static void die_short_read(void) -{ - if (buffer_ferror(&input)) - die_errno("error reading dump file"); - die("invalid dump: unexpected end of file"); -} - -static void read_props(void) -{ - static struct strbuf key = STRBUF_INIT; - static struct strbuf val = STRBUF_INIT; - const char *t; - /* - * NEEDSWORK: to support simple mode changes like - * K 11 - * svn:special - * V 1 - * * - * D 14 - * svn:executable - * we keep track of whether a mode has been set and reset to - * plain file only if not. We should be keeping track of the - * symlink and executable bits separately instead. - */ - uint32_t type_set = 0; - while ((t = buffer_read_line(&input)) && strcmp(t, "PROPS-END")) { - uint32_t len; - const char type = t[0]; - int ch; - - if (!type || t[1] != ' ') - die("invalid property line: %s", t); - len = atoi(&t[2]); - strbuf_reset(&val); - buffer_read_binary(&input, &val, len); - if (val.len < len) - die_short_read(); - - /* Discard trailing newline. */ - ch = buffer_read_char(&input); - if (ch == EOF) - die_short_read(); - if (ch != '\n') - die("invalid dump: expected newline after %s", val.buf); - - switch (type) { - case 'K': - strbuf_swap(&key, &val); - continue; - case 'D': - handle_property(&val, NULL, &type_set); - continue; - case 'V': - handle_property(&key, &val, &type_set); - strbuf_reset(&key); - continue; - default: - die("invalid property line: %s", t); - } - } -} - -static void handle_node(void) -{ - const uint32_t type = node_ctx.type; - const int have_props = node_ctx.prop_length != -1; - const int have_text = node_ctx.text_length != -1; - /* - * Old text for this node: - * NULL - directory or bug - * empty_blob - empty - * "" - data retrievable from fast-import - */ - static const char *const empty_blob = "::empty::"; - const char *old_data = NULL; - uint32_t old_mode = S_IFREG | 0644; - - if (node_ctx.action == NODEACT_DELETE) { - if (have_text || have_props || node_ctx.srcRev) - die("invalid dump: deletion node has " - "copyfrom info, text, or properties"); - fast_export_delete(node_ctx.dst.buf); - return; - } - if (node_ctx.action == NODEACT_REPLACE) { - fast_export_delete(node_ctx.dst.buf); - node_ctx.action = NODEACT_ADD; - } - if (node_ctx.srcRev) { - fast_export_copy(node_ctx.srcRev, node_ctx.src.buf, node_ctx.dst.buf); - if (node_ctx.action == NODEACT_ADD) - node_ctx.action = NODEACT_CHANGE; - } - if (have_text && type == S_IFDIR) - die("invalid dump: directories cannot have text attached"); - - /* - * Find old content (old_data) and decide on the new mode. - */ - if (node_ctx.action == NODEACT_CHANGE && !*node_ctx.dst.buf) { - if (type != S_IFDIR) - die("invalid dump: root of tree is not a regular file"); - old_data = NULL; - } else if (node_ctx.action == NODEACT_CHANGE) { - uint32_t mode; - old_data = fast_export_read_path(node_ctx.dst.buf, &mode); - if (mode == S_IFDIR && type != S_IFDIR) - die("invalid dump: cannot modify a directory into a file"); - if (mode != S_IFDIR && type == S_IFDIR) - die("invalid dump: cannot modify a file into a directory"); - node_ctx.type = mode; - old_mode = mode; - } else if (node_ctx.action == NODEACT_ADD) { - if (type == S_IFDIR) - old_data = NULL; - else if (have_text) - old_data = empty_blob; - else - die("invalid dump: adds node without text"); - } else { - die("invalid dump: Node-path block lacks Node-action"); - } - - /* - * Adjust mode to reflect properties. - */ - if (have_props) { - if (!node_ctx.prop_delta) - node_ctx.type = type; - if (node_ctx.prop_length) - read_props(); - } - - /* - * Save the result. - */ - if (type == S_IFDIR) /* directories are not tracked. */ - return; - assert(old_data); - if (old_data == empty_blob) - /* 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); - return; - } - if (!node_ctx.text_delta) { - fast_export_modify(node_ctx.dst.buf, node_ctx.type, "inline"); - fast_export_data(node_ctx.type, node_ctx.text_length, &input); - return; - } - fast_export_modify(node_ctx.dst.buf, node_ctx.type, "inline"); - fast_export_blob_delta(node_ctx.type, old_mode, old_data, - node_ctx.text_length, &input); -} - -static void begin_revision(const char *remote_ref) -{ - if (!rev_ctx.revision) /* revision 0 gets no git commit. */ - return; - fast_export_begin_commit(rev_ctx.revision, rev_ctx.author.buf, - &rev_ctx.log, dump_ctx.uuid.buf, dump_ctx.url.buf, - rev_ctx.timestamp, remote_ref); -} - -static void end_revision(const char *note_ref) -{ - struct strbuf mark = STRBUF_INIT; - if (rev_ctx.revision) { - fast_export_end_commit(rev_ctx.revision); - fast_export_begin_note(rev_ctx.revision, "remote-svn", - "Note created by remote-svn.", rev_ctx.timestamp, note_ref); - strbuf_addf(&mark, ":%"PRIu32, rev_ctx.revision); - fast_export_note(mark.buf, "inline"); - fast_export_buf_to_data(&rev_ctx.note); - strbuf_release(&mark); - } -} - -void svndump_read(const char *url, const char *local_ref, const char *notes_ref) -{ - char *val; - char *t; - uint32_t active_ctx = DUMP_CTX; - uint32_t len; - - reset_dump_ctx(url); - while ((t = buffer_read_line(&input))) { - val = strchr(t, ':'); - if (!val) - continue; - val++; - if (*val != ' ') - continue; - val++; - - /* strlen(key) + 1 */ - switch (val - t - 1) { - case sizeof("SVN-fs-dump-format-version"): - if (constcmp(t, "SVN-fs-dump-format-version")) - continue; - dump_ctx.version = atoi(val); - if (dump_ctx.version > 3) - die("expected svn dump format version <= 3, found %"PRIu32, - dump_ctx.version); - break; - case sizeof("UUID"): - if (constcmp(t, "UUID")) - continue; - strbuf_reset(&dump_ctx.uuid); - strbuf_addstr(&dump_ctx.uuid, val); - break; - case sizeof("Revision-number"): - if (constcmp(t, "Revision-number")) - continue; - if (active_ctx == NODE_CTX) - handle_node(); - if (active_ctx == REV_CTX) - begin_revision(local_ref); - if (active_ctx != DUMP_CTX) - end_revision(notes_ref); - active_ctx = REV_CTX; - reset_rev_ctx(atoi(val)); - strbuf_addf(&rev_ctx.note, "%s\n", t); - break; - case sizeof("Node-path"): - if (constcmp(t, "Node-")) - continue; - if (!constcmp(t + strlen("Node-"), "path")) { - if (active_ctx == NODE_CTX) - handle_node(); - if (active_ctx == REV_CTX) - begin_revision(local_ref); - active_ctx = NODE_CTX; - reset_node_ctx(val); - strbuf_addf(&rev_ctx.note, "%s\n", t); - break; - } - if (constcmp(t + strlen("Node-"), "kind")) - continue; - strbuf_addf(&rev_ctx.note, "%s\n", t); - if (!strcmp(val, "dir")) - node_ctx.type = S_IFDIR; - else if (!strcmp(val, "file")) - node_ctx.type = S_IFREG | 0644; - else - fprintf(stderr, "Unknown node-kind: %s\n", val); - break; - case sizeof("Node-action"): - if (constcmp(t, "Node-action")) - continue; - strbuf_addf(&rev_ctx.note, "%s\n", t); - if (!strcmp(val, "delete")) { - node_ctx.action = NODEACT_DELETE; - } else if (!strcmp(val, "add")) { - node_ctx.action = NODEACT_ADD; - } else if (!strcmp(val, "change")) { - node_ctx.action = NODEACT_CHANGE; - } else if (!strcmp(val, "replace")) { - node_ctx.action = NODEACT_REPLACE; - } else { - fprintf(stderr, "Unknown node-action: %s\n", val); - node_ctx.action = NODEACT_UNKNOWN; - } - break; - case sizeof("Node-copyfrom-path"): - if (constcmp(t, "Node-copyfrom-path")) - continue; - strbuf_reset(&node_ctx.src); - strbuf_addstr(&node_ctx.src, val); - strbuf_addf(&rev_ctx.note, "%s\n", t); - break; - case sizeof("Node-copyfrom-rev"): - if (constcmp(t, "Node-copyfrom-rev")) - continue; - node_ctx.srcRev = atoi(val); - strbuf_addf(&rev_ctx.note, "%s\n", t); - break; - case sizeof("Text-content-length"): - if (constcmp(t, "Text") && constcmp(t, "Prop")) - continue; - if (constcmp(t + 4, "-content-length")) - continue; - { - char *end; - uintmax_t len; - - len = strtoumax(val, &end, 10); - if (!isdigit(*val) || *end) - die("invalid dump: non-numeric length %s", val); - if (len > maximum_signed_value_of_type(off_t)) - die("unrepresentable length in dump: %s", val); - - if (*t == 'T') - node_ctx.text_length = (off_t) len; - else - node_ctx.prop_length = (off_t) len; - break; - } - case sizeof("Text-delta"): - if (!constcmp(t, "Text-delta")) { - node_ctx.text_delta = !strcmp(val, "true"); - break; - } - if (constcmp(t, "Prop-delta")) - continue; - node_ctx.prop_delta = !strcmp(val, "true"); - break; - case sizeof("Content-length"): - if (constcmp(t, "Content-length")) - continue; - len = atoi(val); - t = buffer_read_line(&input); - if (!t) - die_short_read(); - if (*t) - die("invalid dump: expected blank line after content length header"); - if (active_ctx == REV_CTX) { - read_props(); - } else if (active_ctx == NODE_CTX) { - handle_node(); - active_ctx = INTERNODE_CTX; - } else { - fprintf(stderr, "Unexpected content length header: %"PRIu32"\n", len); - if (buffer_skip_bytes(&input, len) != len) - die_short_read(); - } - } - } - if (buffer_ferror(&input)) - die_short_read(); - if (active_ctx == NODE_CTX) - handle_node(); - if (active_ctx == REV_CTX) - begin_revision(local_ref); - if (active_ctx != DUMP_CTX) - end_revision(notes_ref); -} - -static void init(int report_fd) -{ - fast_export_init(report_fd); - strbuf_init(&dump_ctx.uuid, 4096); - strbuf_init(&dump_ctx.url, 4096); - strbuf_init(&rev_ctx.log, 4096); - strbuf_init(&rev_ctx.author, 4096); - strbuf_init(&rev_ctx.note, 4096); - strbuf_init(&node_ctx.src, 4096); - strbuf_init(&node_ctx.dst, 4096); - reset_dump_ctx(NULL); - reset_rev_ctx(0); - reset_node_ctx(NULL); - return; -} - -int svndump_init(const char *filename) -{ - if (buffer_init(&input, filename)) - return error_errno("cannot open %s", filename ? filename : "NULL"); - init(REPORT_FILENO); - return 0; -} - -int svndump_init_fd(int in_fd, int back_fd) -{ - if(buffer_fdinit(&input, xdup(in_fd))) - return error_errno("cannot open fd %d", in_fd); - init(xdup(back_fd)); - return 0; -} - -void svndump_deinit(void) -{ - fast_export_deinit(); - reset_dump_ctx(NULL); - reset_rev_ctx(0); - reset_node_ctx(NULL); - strbuf_release(&rev_ctx.log); - strbuf_release(&rev_ctx.author); - strbuf_release(&rev_ctx.note); - strbuf_release(&node_ctx.src); - strbuf_release(&node_ctx.dst); - if (buffer_deinit(&input)) - fprintf(stderr, "Input error\n"); - if (ferror(stdout)) - fprintf(stderr, "Output error\n"); -} - -void svndump_reset(void) -{ - strbuf_release(&dump_ctx.uuid); - strbuf_release(&dump_ctx.url); - strbuf_release(&rev_ctx.log); - strbuf_release(&rev_ctx.author); -}