This is a second iteration of remote-svn-alpha series [1].
The main changes are:
1) more strict errors checking - be ready for helper exit code being checked[3]
2) saving "rN" marks as a commit->svn revision mapping
3) supporting incremental imports
"2)" could be even nicer if there were a way for git-remote add or git-clone to
setup a show-notes config option. Another interesting aspect is notes_ref commits
author (vcs-svn <vcs-svn@local>) and timestamps ("now"). Timestamps make notes sha1
diverge on different repos/importers, so fetching notes from a peer git repo is not
fast-forward and a bad thing is they are stored in a private namespace - not likely
place for user to perform merges. But as the tests show, one may want to trust peer
notes and fetch --force svn updated imported by a peer.
But anyway, there are a few tests in this series and it looks like the helper is
really able to import from svn incrementally and exchange/clone imported data
between different git repositories. Same limitations as earlier: only whole svnroot,
only import, needs svnrdump (for file:// svnadmin+svnlook would suffice)
Further improvements for a just import from svn and maybe clone/fetch svn data from
another git peers are:
a) mentioned above "2)" problems
b) adding various configuration options (like svn username and password)
c) add progress indication, either true percentage of # of imported revisions or
some adaptive indicator or any other informative one
d) maybe issue a checkpoint command from time to time or somehow allow to specify
how many revisions to fetch - for huge initial imports
e) import a subdirectory (of svnroot) history
f) shallow imports
g) save all revprops/fileprops whether they have git counterparts or not, ideally
these are sufficient to convert the imported history back to svn lossless
h) get rid of bashisms in this helper or rewrite it in C.
These do not block proceeding to the next topics:
i) push commits to svn
ii) track svn branches.
The patch base is svn-fe-pu at git://repo.or.cz/git/jrn.git
also a commit 7153183171de77d084a4c24ef19d23d6313ded2a can be used
as an earlier patch base.
For the last five commits (those just after the "add a test") some
new svn-fe options[2] are required.
Whole git-remote-svn-alpha and a test script are cited at the bottom
of this letter as a quick reference for those who don't track svn-fe-pu.
[1] http://thread.gmane.org/gmane.comp.version-control.git/176617
[2] http://thread.gmane.org/gmane.comp.version-control.git/177025
[3] http://thread.gmane.org/gmane.comp.version-control.git/176002/focus=176019
Dmitry Ivankov (9):
svn-fe: use svnrdump --quiet in remote-svn-alpha
svn-fe: avoid error on no-op imports in remote-svn-alpha
svn-fe: allow svnadmin instead of svnrdump in remote-svn-alpha
svn-fe: add a test for remote-svn-alpha
svn-fe: use svn-fe --no-progress in remote-svn-alpha
svn-fe: use proper refspec in remote-svn-alpha
svn-fe: write svnrev notes in remote-svn-alpha
svn-fe: import incrementally in svn-remote-alpha
svn-fe: reuse import-marks in remote-svn-alpha
contrib/svn-fe/git-remote-svn-alpha | 140 +++++++++++-
contrib/svn-fe/t/.gitignore | 3 +
contrib/svn-fe/t/t9010-remote-svn-alpha.sh | 351 ++++++++++++++++++++++++++++
3 files changed, 485 insertions(+), 9 deletions(-)
create mode 100644 contrib/svn-fe/t/.gitignore
create mode 100755 contrib/svn-fe/t/t9010-remote-svn-alpha.sh
--
1.7.3.4
@@ -0,0 +1,351 @@+#!/bin/sh++test_description='check svn-alpha remote helper'++PATH=$(pwd)/..:$PATH+TEST_DIRECTORY=$(pwd)/../../../t+.$TEST_DIRECTORY/test-lib.sh++ifcommand-vsvnrdump>/dev/null;then+test_set_prereqSVNRDUMP+fi++deinit_git(){+rm-fr.git+}++reinit_git(){+deinit_git&&+gitinit+}++properties(){+whiletest"$#"-ne0+do+property="$1"&&+value="$2"&&+printf"%s\n""K ${#property}"&&+printf"%s\n""$property"&&+printf"%s\n""V ${#value}"&&+printf"%s\n""$value"&&+shift2||+return1+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"+}++dump_to_svnrepo(){+dump="$1"&&+path="$2"&&+svnadmincreate"$path"&&+svnadminload"$path"<"$dump"+}++svnurl(){+printf"svn-alpha::file://%s/%s""$(pwd)""$1"+}++test_nr_revs(){+n=$1&&+repo=$2&&+ref=$3&&+git--git-dir="$repo"log--format=oneline"$ref">revs&&+test_line_count="$n"revs+}++test_expect_success'svnadmin is present''+command-vsvnadmin&&+test_set_prereqSVNADMIN+'++test_expect_successSVNADMIN'create empty svnrepo''+echo"SVN-fs-dump-format-version: 2">empty.dump&&+dump_to_svnrepoempty.dumpempty.svn&&+test_set_prereqEMPTY_SVN+'++test_expect_successSVNADMIN'create tiny svnrepo''+{+properties\+svn:authorauthor@example.com\+svn:date"1999-02-01T00:01:002.000000Z"\+svn:log"add directory with some files in it"&&+echoPROPS-END+}>props&&+{+cat<<-EOF&&+SVN-fs-dump-format-version:3++Revision-number:1+EOF+echoProp-content-length:$(wc-c<props)&&+echoContent-length:$(wc-c<props)&&+echo&&+catprops&&+cat<<-\EOF&&++Node-path:directory+Node-kind:dir+Node-action:add+Prop-content-length:10+Content-length:10++PROPS-END+Node-path:directory/somefile+Node-kind:file+Node-action:add+EOF+text_no_propshi+}>tiny.dump&&+dump_to_svnrepotiny.dumptiny.svn&&+test_set_prereqTINY_SVN+'++test_expect_successSVNADMIN'create small svndump''+{+properties\+svn:authorauthor@example.com\+svn:date"1999-02-01T00:01:002.000000Z"\+svn:log"add directory with some files in it"&&+echoPROPS-END+}>props&&+{+echoProp-content-length:$(wc-c<props)&&+echoContent-length:$(wc-c<props)&&+echo&&+catprops+}>props_dump&&+cat>small.dump.r0<<-EOF&&+SVN-fs-dump-format-version:3+EOF+forxin`seq1110`;do+{+echo&&+echo"Revision-number: $x"&&+catprops_dump&&++iftest"$x"-eq"1";then+cat<<-\EOF++Node-path:directory+Node-kind:dir+Node-action:add+Prop-content-length:10+Content-length:10++PROPS-END++EOF+fi+echo"Node-path: directory/somefile$x"&&+echo"Node-kind: file"&&+echo"Node-action: add"&&+text_no_propshi+}>small.dump.r$x+done&&+test_set_prereqSMALL_SVNDUMP+'++test_expect_successSMALL_SVNDUMP'create small svnrepo''+rm-rfsmall.svn*&&+svnadmincreatesmall.svn&&+forxin`seq1110`;do+catsmall.dump.r0small.dump.r$x>part.dump&&+svnadminloadsmall.svn<part.dump&&+cp-rsmall.svnsmall.svn.r0-$x+done&&+test_set_prereqSMALL_SVN+'++test_expect_failureEMPTY_SVN'fetch empty''+reinit_git&&+url=$(svnurlempty.svn)&&+gitremoteaddsvn"$url"&&+gitfetchsvn+'++test_expect_failureTINY_SVN'clone tiny''+deinit_git&&+url=$(svnurltiny.svn)&&+gitclone"$url"tiny1.git&&+test_nr_revs1tiny1.gitrefs/remotes/origin/master+'++test_expect_successTINY_SVN'clone --mirror tiny''+deinit_git&&+url=$(svnurltiny.svn)&&+gitclone--mirror"$url"tiny2.git&&+test_nr_revs1tiny2.gitrefs/heads/master+'++test_expect_successTINY_SVN'clone --bare tiny''+deinit_git&&+url=$(svnurltiny.svn)&&+gitclone--bare"$url"tiny3.git&&+test_nr_revs1tiny3.gitrefs/heads/master+'++test_expect_successTINY_SVN'clone -b master tiny''+deinit_git&&+url=$(svnurltiny.svn)&&+gitclone-bmaster"$url"tiny4.git&&+test_nr_revs1tiny4.git/.gitrefs/heads/master+'++test_expect_successSMALL_SVN'clone -b master small''+deinit_git&&+url=$(svnurlsmall.svn)&&+gitclone-bmaster"$url"small.git&&+test_nr_revs10small.git/.gitrefs/heads/master+'++test_expect_successTINY_SVN,SVNRDUMP'no crash on clone url/path''+deinit_git&&+url=$(svnurlsmall.svn)/directory&&+gitclone-bmaster"$url"small_dir.git&&+test_nr_revs10small_dir.git/.gitrefs/heads/master+'++test_expect_successTINY_SVN,SVNRDUMP'no crash on clone url/path/file''+deinit_git&&+url=$(svnurlsmall.svn)/directory/somefile3&&+gitclone-bmaster"$url"small_dir_file.git&&+test_nr_revs10small_dir_file.git/.gitrefs/heads/master+'++test_expect_successSMALL_SVN'fetch each rev of SMALL separately''+reinit_git&&+url=$(svnurlsmall.svn)&&++forxin`seq1110`;do+gitremoteaddsvn_$x"$url.r0-$x"+done&&+gitremoteupdate&&++gitremoteaddsvn"$url"&&+gitfetchsvn&&++gitrev-parse-sremotes/svn_7/master~5>ref7_2&&+gitrev-parse-sremotes/svn/master~8>ref_2&&+test_cmpref7_2ref_2+'++test_expect_successSMALL_SVN'fetch updates from SMALL''+reinit_git&&+url=$(svnurllink.svn)&&+gitremoteaddsvn"$url"&&++ln-sfnsmall.svn.r0-5link.svn&&+gitfetchsvn&&+test_nr_revs5.gitrefs/remotes/svn/master&&++ln-sfnsmall.svn.r0-10link.svn&&+gitfetchsvn&&+test_nr_revs10.gitrefs/remotes/svn/master&&++gitfetchsvn&&+test_nr_revs10.gitrefs/remotes/svn/master+'++test_expect_successTINY_SVN'fetch TINY does not write to refs/heads/master''+reinit_git&&+url=$(svnurltiny.svn)&&+gitremoteaddsvn"$url"&&+gitfetchsvn&&+gitshow-ref--verifyrefs/remotes/svn/master&&+test_must_failgitshow-ref--verifyrefs/heads/master+'++test_expect_successSMALL_SVN'fetch SMALL writes revnum notes''+reinit_git&&+url=$(svnurlsmall.svn)&&+gitremoteaddsvn"$url"&&+gitfetchsvn&&+gitlog--show-notes=refs/svn-alpha/svn/SVNR--format=%N-1refs/remotes/svn/master^>actual.note&&+echor9>expect.note&&+echo>>expect.note&&+test_cmpexpect.noteactual.note+'++test_expect_successSMALL_SVN'marks from notes regeneration''+reinit_git&&+url=$(svnurllink.svn)&&+gitremoteaddsvn"$url"&&++ln-sfnsmall.svn.r0-5link.svn&&+gitfetchsvn&&+test_nr_revs5.gitrefs/remotes/svn/master&&++rm-rf.git/info/fast-import/svn-alpha&&++ln-sfnsmall.svn.r0-10link.svn&&+gitfetchsvn&&+test_nr_revs10.gitrefs/remotes/svn/master+'++test_expect_successSMALL_SVN'clone to bootstrap''+deinit_git&&+url=$(svnurllink.svn)&&+ln-sfnsmall.svn.r0-5link.svn&&+gitclone-bmaster"$url"master.git&&+{+cdmaster.git&&+gitbranchpub_headrefs/svn-alpha/origin/SVNHEAD&&+gitbranchpub_notesrefs/svn-alpha/origin/SVNR&&+cd..+}&&+ln-sfnsmall.svn.r0-8link.svn&&+gitclonemaster.gitslave.git&&+{+cdslave.git&&+gitremoteaddsvn"$url"&&+gitupdate-refrefs/svn-alpha/svn/SVNHEADrefs/remotes/origin/pub_head&&+gitupdate-refrefs/svn-alpha/svn/SVNRrefs/remotes/origin/pub_notes&&+gitfetchsvn&&+gitmerge-baserefs/svn-alpha/svn/SVNRrefs/remotes/origin/pub_notes&&+cd..+}&&+test_nr_revs8slave.git/.gitrefs/remotes/svn/master+'++test_expect_successSMALL_SVN'clone and exchange''+deinit_git&&+url=$(svnurllink.svn)&&+ln-sfnsmall.svn.r0-1link.svn&&+gitclone-bmaster"$url"A.git&&+gitclone-bmaster"$url"B.git&&+test_nr_revs1A.git/.gitorigin/master&&+test_nr_revs1B.git/.gitorigin/master&&++git--git-dir=A.git/.gitremoteaddBB.git&&+git--git-dir=B.git/.gitremoteaddAA.git&&+refspecs="+refs/svn-alpha/origin/SVNR:refs/svn-alpha/origin/SVNR"+refspecs="$refspecs refs/svn-alpha/origin/SVNHEAD:refs/svn-alpha/origin/SVNHEAD"++ln-sfnsmall.svn.r0-2link.svn&&+git--git-dir=A.git/.gitfetchorigin&&++git--git-dir=B.git/.gitfetch-fA$refspecs&&++ln-sfnsmall.svn.r0-3link.svn&&+git--git-dir=B.git/.gitfetchorigin&&++git--git-dir=A.git/.gitfetchB$refspecs&&++git--git-dir=A.git/.gitfetchorigin&&+git--git-dir=B.git/.gitfetchorigin&&++test_nr_revs3A.git/.gitorigin/master&&+test_nr_revs3B.git/.gitorigin/master+'++test_done
svnrdump by default shows "Dumped revision #n" lines on stderr.
svn-fe does it too on each imported revision, so pass --quiet to
svnrdump. Once process indication is really needed it will be
custom formatted in either svn-fe or remote-svn-alpha.
Signed-off-by: Dmitry Ivankov <redacted>
---
contrib/svn-fe/git-remote-svn-alpha | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
Currently helpers' exit codes are not checked by transport_helper.
But a proper helper should check for all possible internal errors
anyway. svnrdump dump --incremental considers -rX:HEAD range as bad
if X is greater than the actual HEAD revision. And there is no option
to change this behavior.
One way to address this issue is to fire one more svn command to get
the HEAD value, but it is one more connection, one more tool (ok,
we can svnrdump HEAD but it looks slow) and possibly one more
password prompt, and maybe even a race condition (if we talk to a
svn servers farm frontend for example).
Another one is to patch svnrdump to report the revision, because
internally it asks svn for it anyway before doing a dump. Longer
term it looks nice, moreover it can be used to display percentage
progress.
Add a wrapper around svnrdump that captures stderr and exit code.
If stderr matches a hardcoded "LOWER cannot be greater than UPPER."
and the exit code is non-zero, don't produce any dump and emulate
exit 0, otherwise the wrapper is transparent. The only side effect
is dup2-ing stdout to fd=6, ugly but fine as only standard
descriptors are used currently.
Signed-off-by: Dmitry Ivankov <redacted>
---
contrib/svn-fe/git-remote-svn-alpha | 19 +++++++++++++++++--
1 files changed, 17 insertions(+), 2 deletions(-)
svnrdump dump and svnadmin dump share a dump format. Their dump
streams representation may be different but they should have the
same effect on a dump consumer. One more difference is svnrdump being
able to dump via any svn remote protocol while svnadmin needs access
to the repository filesystem and also can't produce subdirectory dumps.
But svnrdump is a newer tool and may be unavailable on some systems.
Try to use svnadmin dump for file:// repository urls if there is no
svnrdump in the PATH. First of all this is to be used in tests, where
the repository is indeed local most of the time. Also require svnlook
utility as a lightweight option to get the youngest repository revision.
Signed-off-by: Dmitry Ivankov <redacted>
---
contrib/svn-fe/git-remote-svn-alpha | 31 ++++++++++++++++++++++++++++++-
1 files changed, 30 insertions(+), 1 deletions(-)
For each imported svn commit write "rN" note in a private namespace.
These can be viewed with somewhat ugly
$ git log --show-notes=refs/svn-alpha/<reponame>/SVNR
But also these notes can be used to import svn history incrementally.
Add a simple test for these notes.
Signed-off-by: Dmitry Ivankov <redacted>
---
contrib/svn-fe/git-remote-svn-alpha | 9 ++++++---
contrib/svn-fe/t/t9010-remote-svn-alpha.sh | 11 +++++++++++
2 files changed, 17 insertions(+), 3 deletions(-)
@@ -265,4 +265,15 @@ test_expect_success TINY_SVN 'fetch TINY does not write to refs/heads/master' 'test_must_failgitshow-ref--verifyrefs/heads/master'+test_expect_successSMALL_SVN'fetch SMALL writes revnum notes''+reinit_git&&+url=$(svnurlsmall.svn)&&+gitremoteaddsvn"$url"&&+gitfetchsvn&&+gitlog--show-notes=refs/svn-alpha/svn/SVNR--format=%N-1refs/remotes/svn/master^>actual.note&&+echor9>expect.note&&+echo>>expect.note&&+test_cmpexpect.noteactual.note+'+ test_done
svn-fe by default produces a progress line for each imported revision.
For large repos it stresses the terminal and a user, possibly scrolls
away error messages.
Just disable progress lines for now.
Signed-off-by: Dmitry Ivankov <redacted>
---
contrib/svn-fe/git-remote-svn-alpha | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
svn-remote-alpha already maintains commits tree imported from svn
and a mapping to the original svn revision numbers as notes content.
svn-fe --incremental requires import marks from previous revisions.
Just generate import marks from notes on each import. This is cheap
on small repositories, fine for a few tests.
Signed-off-by: Dmitry Ivankov <redacted>
---
contrib/svn-fe/git-remote-svn-alpha | 57 +++++++++++++++++++++-
contrib/svn-fe/t/t9010-remote-svn-alpha.sh | 72 ++++++++++++++++++++++++++++
2 files changed, 128 insertions(+), 1 deletions(-)
Create a per repository name private refs namespace as suggested by
the remote helpers documentation. This allows to have several svn
remotes at the same time. And also this way we don't overwrite the
local branch master.
The refpec is:
HEAD:refs/svn-alpha/$reponame/SVNHEAD
refs/heads/master:refs/svn-alpha/$reponame/SVNHEAD
Signed-off-by: Dmitry Ivankov <redacted>
---
contrib/svn-fe/git-remote-svn-alpha | 18 ++++++++++--------
contrib/svn-fe/t/t9010-remote-svn-alpha.sh | 9 +++++++++
2 files changed, 19 insertions(+), 8 deletions(-)
@@ -256,4 +256,13 @@ test_expect_success SMALL_SVN 'fetch updates from SMALL' 'test_nr_revs10.gitrefs/remotes/svn/master'+test_expect_successTINY_SVN'fetch TINY does not write to refs/heads/master''+reinit_git&&+url=$(svnurltiny.svn)&&+gitremoteaddsvn"$url"&&+gitfetchsvn&&+gitshow-ref--verifyrefs/remotes/svn/master&&+test_must_failgitshow-ref--verifyrefs/heads/master+'+ test_done
remote-svn-alpha needs to prepare import marks file when doing an
incremental import. This file can be left after previous imports.
Take the last imported commit and a note with corresponding svn
revision number. If the marks file exists and defines a :revision
mark pointing to the last imported commit, consider it valid.
It may accidentally contain newer revisions, they are silently
ignored. In practice the check for :revision last_commit should
be sufficient to rely on this file defining any lesser revision
marks needed correctly.
So if the import marks file looks valid, do not regenerate it from
the notes tree and have save some performance saved.
Signed-off-by: Dmitry Ivankov <redacted>
---
contrib/svn-fe/git-remote-svn-alpha | 26 ++++++++++++++++++++++----
1 files changed, 22 insertions(+), 4 deletions(-)
@@ -78,14 +78,31 @@ do_gen_marks () { prepare_marks () { dst=$1 notes=$2 rev=$3 test "z$git_dir" != "$z" || die "we were not told the gitdir"- mkdir -p "$git_dir/$marks_dir"- if test ! -f "$git_dir/$marks_dir/marks"; then- touch "$git_dir/$marks_dir/marks"+ path="$git_dir/$marks_dir"+ mkdir -p "$path"+ path="$path/marks"++ if test ! -f "$path"; then+ touch "$path" fi if test "$rev" = "-1"; then return 0 fi- do_gen_marks "$notes" >"$git_dir/$marks_dir/marks"+ mark_sha=""+ {+ while read -r m sha+ do+ if test "$m" = ":$rev"; then+ mark_sha="$sha"+ fi+ done+ } <"$path"+ dst_sha=$( git rev-parse "$dst" )+ if test -n "$mark_sha"; then+ test "$mark_sha" = "$dst_sha" || die "latest mark and note diverge"+ else+ do_gen_marks "$notes" >"$path"+ fi } last_imported_rev () {
The test creates a few svn repositories from fixed dumps using svnadmin.
Currently it checks for crashes on first time import mostly.
Signed-off-by: Dmitry Ivankov <redacted>
---
contrib/svn-fe/t/.gitignore | 3 +
contrib/svn-fe/t/t9010-remote-svn-alpha.sh | 259 ++++++++++++++++++++++++++++
2 files changed, 262 insertions(+), 0 deletions(-)
create mode 100644 contrib/svn-fe/t/.gitignore
create mode 100755 contrib/svn-fe/t/t9010-remote-svn-alpha.sh
@@ -0,0 +1,259 @@+#!/bin/sh++test_description='check svn-alpha remote helper'++PATH=$(pwd)/..:$PATH+TEST_DIRECTORY=$(pwd)/../../../t+.$TEST_DIRECTORY/test-lib.sh++ifcommand-vsvnrdump>/dev/null;then+test_set_prereqSVNRDUMP+fi++deinit_git(){+rm-fr.git+}++reinit_git(){+deinit_git&&+gitinit+}++properties(){+whiletest"$#"-ne0+do+property="$1"&&+value="$2"&&+printf"%s\n""K ${#property}"&&+printf"%s\n""$property"&&+printf"%s\n""V ${#value}"&&+printf"%s\n""$value"&&+shift2||+return1+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"+}++dump_to_svnrepo(){+dump="$1"&&+path="$2"&&+svnadmincreate"$path"&&+svnadminload"$path"<"$dump"+}++svnurl(){+printf"svn-alpha::file://%s/%s""$(pwd)""$1"+}++test_nr_revs(){+n=$1&&+repo=$2&&+ref=$3&&+git--git-dir="$repo"log--format=oneline"$ref">revs&&+test_line_count="$n"revs+}++test_expect_success'svnadmin is present''+command-vsvnadmin&&+test_set_prereqSVNADMIN+'++test_expect_successSVNADMIN'create empty svnrepo''+echo"SVN-fs-dump-format-version: 2">empty.dump&&+dump_to_svnrepoempty.dumpempty.svn&&+test_set_prereqEMPTY_SVN+'++test_expect_successSVNADMIN'create tiny svnrepo''+{+properties\+svn:authorauthor@example.com\+svn:date"1999-02-01T00:01:002.000000Z"\+svn:log"add directory with some files in it"&&+echoPROPS-END+}>props&&+{+cat<<-EOF&&+SVN-fs-dump-format-version:3++Revision-number:1+EOF+echoProp-content-length:$(wc-c<props)&&+echoContent-length:$(wc-c<props)&&+echo&&+catprops&&+cat<<-\EOF&&++Node-path:directory+Node-kind:dir+Node-action:add+Prop-content-length:10+Content-length:10++PROPS-END+Node-path:directory/somefile+Node-kind:file+Node-action:add+EOF+text_no_propshi+}>tiny.dump&&+dump_to_svnrepotiny.dumptiny.svn&&+test_set_prereqTINY_SVN+'++test_expect_successSVNADMIN'create small svndump''+{+properties\+svn:authorauthor@example.com\+svn:date"1999-02-01T00:01:002.000000Z"\+svn:log"add directory with some files in it"&&+echoPROPS-END+}>props&&+{+echoProp-content-length:$(wc-c<props)&&+echoContent-length:$(wc-c<props)&&+echo&&+catprops+}>props_dump&&+cat>small.dump.r0<<-EOF&&+SVN-fs-dump-format-version:3+EOF+forxin`seq1110`;do+{+echo&&+echo"Revision-number: $x"&&+catprops_dump&&++iftest"$x"-eq"1";then+cat<<-\EOF++Node-path:directory+Node-kind:dir+Node-action:add+Prop-content-length:10+Content-length:10++PROPS-END++EOF+fi+echo"Node-path: directory/somefile$x"&&+echo"Node-kind: file"&&+echo"Node-action: add"&&+text_no_propshi+}>small.dump.r$x+done&&+test_set_prereqSMALL_SVNDUMP+'++test_expect_successSMALL_SVNDUMP'create small svnrepo''+rm-rfsmall.svn*&&+svnadmincreatesmall.svn&&+forxin`seq1110`;do+catsmall.dump.r0small.dump.r$x>part.dump&&+svnadminloadsmall.svn<part.dump&&+cp-rsmall.svnsmall.svn.r0-$x+done&&+test_set_prereqSMALL_SVN+'++test_expect_failureEMPTY_SVN'fetch empty''+reinit_git&&+url=$(svnurlempty.svn)&&+gitremoteaddsvn"$url"&&+gitfetchsvn+'++test_expect_failureTINY_SVN'clone tiny''+deinit_git&&+url=$(svnurltiny.svn)&&+gitclone"$url"tiny1.git&&+test_nr_revs1tiny1.gitrefs/remotes/origin/master+'++test_expect_successTINY_SVN'clone --mirror tiny''+deinit_git&&+url=$(svnurltiny.svn)&&+gitclone--mirror"$url"tiny2.git&&+test_nr_revs1tiny2.gitrefs/heads/master+'++test_expect_successTINY_SVN'clone --bare tiny''+deinit_git&&+url=$(svnurltiny.svn)&&+gitclone--bare"$url"tiny3.git&&+test_nr_revs1tiny3.gitrefs/heads/master+'++test_expect_successTINY_SVN'clone -b master tiny''+deinit_git&&+url=$(svnurltiny.svn)&&+gitclone-bmaster"$url"tiny4.git&&+test_nr_revs1tiny4.git/.gitrefs/heads/master+'++test_expect_successSMALL_SVN'clone -b master small''+deinit_git&&+url=$(svnurlsmall.svn)&&+gitclone-bmaster"$url"small.git&&+test_nr_revs10small.git/.gitrefs/heads/master+'++test_expect_successTINY_SVN,SVNRDUMP'no crash on clone url/path''+deinit_git&&+url=$(svnurlsmall.svn)/directory&&+gitclone-bmaster"$url"small_dir.git&&+test_nr_revs10small_dir.git/.gitrefs/heads/master+'++test_expect_successTINY_SVN,SVNRDUMP'no crash on clone url/path/file''+deinit_git&&+url=$(svnurlsmall.svn)/directory/somefile3&&+gitclone-bmaster"$url"small_dir_file.git&&+test_nr_revs10small_dir_file.git/.gitrefs/heads/master+'++test_expect_successSMALL_SVN'fetch each rev of SMALL separately''+reinit_git&&+url=$(svnurlsmall.svn)&&++forxin`seq1110`;do+gitremoteaddsvn_$x"$url.r0-$x"+done&&+gitremoteupdate&&++gitremoteaddsvn"$url"&&+gitfetchsvn&&++gitrev-parse-sremotes/svn_7/master~5>ref7_2&&+gitrev-parse-sremotes/svn/master~8>ref_2&&+test_cmpref7_2ref_2+'++test_expect_successSMALL_SVN'fetch updates from SMALL''+reinit_git&&+url=$(svnurllink.svn)&&+gitremoteaddsvn"$url"&&++ln-sfnsmall.svn.r0-5link.svn&&+gitfetchsvn&&+test_nr_revs5.gitrefs/remotes/svn/master&&++ln-sfnsmall.svn.r0-10link.svn&&+gitfetchsvn&&+test_nr_revs10.gitrefs/remotes/svn/master&&++gitfetchsvn&&+test_nr_revs10.gitrefs/remotes/svn/master+'++test_done