'= Notes on the test machinery = 

A .fi extension means it's a git fast-import stream.  
An .svn extension means it's a Subversion repo dump.
A .chk extension means it's expected output from a test
A .tst extension means it's a test driver script

Additionally, reposurgeon will run unit tests when given the
"runtests" command. These tests are written in Python and built in to
the script itself.

== Writing new unit tests ==

New unit tests can be written by adding a new class derived from
unittest.TestCase, then listing this class as in the "available" list
in do_runtests(). Any methods on this class which begin with the
prefix "test_" will be automatically run by the unit test framework.

== The scripts ==

=== fi-to-fi ===

Builds a git repo from a fast-import stream on stdin, or streams an
existing repo to stdout.

=== hg-to-fi ===

Builds an hg repo from a fast-import stream on stdin, or streams an
existing repo to stdout.

=== svn-to-svn ===

Build a Subversion repo from a Subversion stream dump on stdin, or
dump an existing repo as a stream to stdout.  Can also be used to edit
a Subversion test load, regenerating its checksums.

== svn-to-git ==

Build a Subversion repo from a Subversion stream dump on stdin,
convert it to a local git repository, and stream the result to
standard output. Mainly a wrapper around git-svn, to be used
for comparison tests.  Can also be used to test against agito
and svn2git.

To add a new tool for comparison, do something like:

   git submodule add GIT-URL/foobar externals/foobar
   git update submodules

from the repo root.

== convert-check ==

Take a Subversion dump on stdin and convert it two different ways,
once with reposurgeon and then with git-svn.  Compare the results
using repodiffer.

== The tests ==

Keeping live Subversion repos under version control doesn't work very well; 
in particular, things like the entries file change too often.  So what we 
do is keep Subversion dump files and rebuild the repo before each test.

In general, a file named foo.chk is the expected output from a test involving
either some operation test on an input stream in foo.fi or a repo conversion
from foo.svn.

To see summary lines from all tests, 'make testlist'.  

The Subversion dumpfiles have summary comments in them that abuse a loophole
in Subversion's parser - header lines that begin with whitespace are ignored.
When you create a new one, insert a second line that begins with a space and
two pound signs.

=== Making new Subversion test loads ===

1. To create a new Subversion test repo, 'make svn-flat' or 'make svn-branchy'.

2. To clone an existing test load foo.svn into the test repo,
'svn-to-svn -n <foo.svn'

3. To copy trunk, creating a tag named 'foo'

   svn copy file://${PWD}/test-repo/trunk file://${PWD}/test-repo/tags/foo

4. To delete a branch foo

   svn delete file://${PWD}/test-repo/branches/foo

5. 'make svn-dump' will dump the new test load to stdout.

== The agito test case ==

Samuel Howard had this to say:

git-svn's handling of tags is broken.

In this demonstration repository, a trunk directory of /trunk/proj exists,
containing some code.  This is improperly tagged by doing:

	svn cp trunk tags/proj-1.0

Where as what should have been done is this:

	svn cp trunk/proj tags/proj-1.0

This is significant because this is exactly what the CVS to SVN conversion
script (cvs2svn) does, to handle the fact that a CVS repository can contain
multiple modules.  Fixing a "mistake" like this is therefore necessary when
converting to SVN, to get tags stored properly.

In the SVN repository, this is fixed by deleting the branch and recreating
it properly (ie. the second command above).  To verify that this has been
done successfully, try this:

	svn log file://$PWD/myrepo/tags/proj-1.0

outputs:

	-----------------------------------------------------------------------
	r4 | fraggle | 2009-10-02 23:37:42 +0100 (Fri, 02 Oct 2009) | 2 lines

	Recreating the tag properly.

	-----------------------------------------------------------------------
	r1 | fraggle | 2009-10-02 23:36:41 +0100 (Fri, 02 Oct 2009) | 2 lines

	Initial import.

	-----------------------------------------------------------------------

Only the history of the directory being tagged and the commit that created the
tag are shown.  The "mistake" is kept in the history of /tags, but not in
the history of the tag itself.

The repository is then converted to git, using git-svn (see the shell script).
Two tags are created (proj-1.0@1 is the older, broken tag).  However, the
newer tag retains the history of the broken tag:

	git log tags/proj-1.0

outputs:

	Author: fraggle <fraggle@f01c4a58-e860-4891-ae86-76464917f484>
	Date:   Fri Oct 2 22:37:42 2009 +0000

	    Recreating the tag properly.

	commit 4aeb0a415e5be12d28a8af1128315e44d44a10d7
	Author: fraggle <fraggle@f01c4a58-e860-4891-ae86-76464917f484>
	Date:   Fri Oct 2 22:37:07 2009 +0000

	    Creating a tag in a BROKEN way, like how cvs2svn does it.

	commit 866f94c91de7628d7251098efcc133e6b5900f88
	Author: fraggle <fraggle@f01c4a58-e860-4891-ae86-76464917f484>
	Date:   Fri Oct 2 22:36:41 2009 +0000

	    Initial import.

	commit e8a2ee18774e319d33cb5bd418e03a5281b75268
	Author: fraggle <fraggle@f01c4a58-e860-4891-ae86-76464917f484>
	Date:   Fri Oct 2 22:36:41 2009 +0000

	    Initial import.

== The tagretract test case ==

According to Mike Fleetwood, fleetwood.svn was created with the following
sequence of operations:

------------------------------------------------------
svn commit -m 'commit one'
svn copy $REPO/trunk $REPO/tags/1.0 -m 'Release 1.0'
svn mv $REPO/tags/1.0 $REPO/tags/1.0rc1 -m 'No release ready yet'
svn commit -m 'commit two'
svn copy $REPO/trunk $REPO/tags/1.0 -m 'Fixed release 1.0'
------------------------------------------------------

He then converted it with these commands:

------------------------------------------------------
branchify_map :tags/(.*)/:tags/\1:
read </tmp/repo.svndump
prefer git
write >/tmp/repo.fi
------------------------------------------------------

This sequence is captured in tagretract.tst.

After conversion the, tag named '1.0' refers to the first commit with
the first tagging message 'Release 1.0', rather than the second commit
with the second tagging message 'Fixed release 1.0'.

The behavior does not change if the initial branchify is omitted, except
for a mid-branch-delete warning.

This is arguably a bug.

== A note about branchreplace.svn ==

This was produced from the NUT Subversion repo as follows:

svncutter -q -r 0:4,6,8,56,58,61,65,350,355,356,543:546 select <nut.svn \
    | svncutter -q expunge 'tags/' \
        'branches/regex_branch' \
        'branches/Tripp_Lite_Omni' \
        'branches/r2.0.1' \
        'branches/v2.1.0' \
        'branches/Stable' \
        '.*/ChangeLog' \
        '.*/CHANGES' \
        '.*/README' \
        '.*/INSTALL' \
        '.*/UPGRADING' \
        '.*/NEWS' \
        '.*/CREDITS' \
        '.*/COPYING' \
        '.*/man/' \
        '.*/docs/' \
        '.*/.*txt' \
        '.*/.cvsignore' \
        '.*/MAINTAINERS' \
        '.*/configure' \
        '.*/config.sub' \
        '.*/config.guess' \
        '.*\.conf' \
        '.*mge.*' \
        '.*hid.*' \
        '.*libupsclient.*' \
        '.*missing.*' \
        '.*aclocal.*' \
        '.*/ltmain.sh' \
        '.*/Makefile.in' \
        '.*/Makefile.am' \
        '.*/stamp.h.in' \
        '.*/depcomp' \
        '.*\.h' \
        'trunk/drivers/megatec.c' \
        'trunk/drivers/optiups.c' \
        'trunk/drivers/tripplite-hid.c' \
        'branches/reportbuf/server/conf.c' \
        'branches/Development/drivers/apc-hid.c' \
        'branches/reportbuf/Makefile' \
        'branches/Testing/drivers/apc-hid.c' \
        'branches/Testing/drivers/tripplite_usb.c' \
        'trunk/drivers/al175.c' \
        'trunk/drivers/apc-hid.c' \
        'trunk/drivers/belkin-hid.c' \
        'branches/reportbuf/packaging/debian' \
        'branches/automake/packaging/debian' \
        'branches/JD-NewConf/common/data_types.c' \
        'branches/JD-NewConf/lib/libupsconfig.c' \
        'branches/JD-NewConf/utils/Makefile.in' \
        'branches/JD-NewConf/utils/migratetool.c' \
        'branches/JD-NewConf/utils/upsconfig.c' \
        'branches/JD-NewConf/clients/upsmon.c' \
        'branches/JD-NewConf/common/nutparser.c' \
        'branches/JD-NewConf/common/tree.c' \
        'branches/JD-NewConf/drivers/main.c' \
        'branches/JD-NewConf/drivers/upsdrvctl.c' \
        'branches/JD-NewConf/server/conf.c' \
        'branches/JD-NewConf/server/user.c' \
        'branches/JD-NewConf/utils/migrateconfig.c' \
        'branches/HAL/Makefile.in' \
        'branches/HAL/drivers' \
        'branches/HAL/utils' \
        'branches/JD-NewConf/conf' \
        'branches/JD-NewConf/drivers' \
        'branches/JD-NewConf/Makefile.in' \
        'branches/reportbuf/drivers' \
        'trunk/drivers/rhino.c' \
        'branches/Testing/drivers/rhino.c' \
        'branches/automake/AUTHORS' \
        'branches/reportbuf/scripts' \
        'trunk/scripts' \
        'trunk/clients' \
        'trunk/server' \
        'branches/Testing/scripts' \
        'branches/Testing/clients' \
        'branches/Testing/server' \
        'branches/Development/scripts' \
        'branches/Development/clients' \
        'branches/Development/server' \
        'branches/Development/drivers/tripplite_usb.c' \
        'branches/Development/drivers/dummy-ups.c' \
        'branches/automake/m4' \
        'branches/automake/clients' \
        'branches/automake/server' \
        'branches/automake/scripts' \
        'branches/Development/data' \
        'branches/automake/data' \
        'trunk/common' \
        'branches/automake/common' \
        'branches/Development/debian' \
        'trunk/packaging' \
        'branches/Development/packaging' \
        'branches/Testing/packaging' \
        'branches/automake/packaging' \
        'branches/automake/.*\.[ch]' \
        'trunk/drivers/belkin.c' \
        'trunk/drivers/belkinunv.c' \
        'trunk/drivers/bestfcom.c' \
        'trunk/drivers/bestuferrups.c' \
        'trunk/drivers/bestups.c' \
        'trunk/drivers/blazer.c' \
        'trunk/drivers/dstate.c' \
        'trunk/drivers/dummycons.c' \
        'trunk/drivers/esupssmart.c' \
        'trunk/drivers/everups.c' \
        'trunk/drivers/genericups.c' \
        'trunk/drivers/liebert.c' \
        'trunk/drivers/masterguard.c' \
        'trunk/drivers/metasys.c' \
        'trunk/drivers/mustek.c' \
        'trunk/drivers/oneac.c' \
        'trunk/drivers/powercom.c' \
        'trunk/drivers/safenet.c' \
        'trunk/drivers/skel.c' \
        'trunk/drivers/sms.c' \
        'trunk/drivers/tripplitesu.c' \
        'trunk/drivers/victronups.c' \
        '.*/apcsmart.c' \
        '.*/ippon.c' \
        '.*/isbmex.c' \
        '.*/powermust.c' \
        '.*/cyberpower.c' \
        '.*/solis.c' \
        '.*/fentonups.c' \
        '.*/tripplite.c' \
        'trunk/Makefile' \
        '.*/energizerups.c' \
        '.*/etapro.c' \
        '.*/upsdrvctl.c' \
        '.*/snmp-ups.c' \
        '.*/cpsups.c' \
        '.*/main.c' \
        '.*/upscode2.c' \
        '.*/bcmxcp.c' \
        'branches/automake/Makefile.dist' \
        '.*/gendb' \
        '.*/version' \
        '.*/install-sh' \
        '.*/upsd.users' \
    | svncutter -q renumber \
>reduced.svn

It captures the most serious pathologies in the NUT repo.

== The repodiffer test loads ==

sample1.fi::
   A small sample repository with branches and tags.  Started out identical
   to svnfodder.fi

sample2.fi::
   Identical to sample1.fi, except for the change comment in the third commit.

sample3.fi::
   Identical to sample1.fi, except for one changed blob in the third commit.

sample4.fi::
   Identical to sample1.fi, except :29 (the second commit on the alternate 
   branch) has been removed.

// end

