About
=====

Tailor is a tool to migrate changesets between CVS, Subversion_,
darcs_, monotone_, Codeville_, Mercurial_ and `Baazar-NG`_ [#]_
repositories.

This script makes it easier to keep the upstream changes merged in
a branch of a product, storing needed information such as the upstream
URI and revision in special properties on the branched directory.

The following ascii-art illustrates the usual scenario::

                           +------------+            +------------+
  +--------------+         | Immutable  |            | Working    |
  | Upstream CVS |-------->| darcs      |----------->| darcs      |
  | repository   | tailor  | repository | darcs pull | repository |
  +--------------+         +------------+            +------------+
                                                           |^         
                                                           ||
                                                           ||
                                                           v|
                                                          User

Ideally you should be able to swap and replace "CVS server" and "darcs
repository" with any combination of the supported systems.

A more convoluted setup shows how brave people are using it to get a
two way sync::

  +----------+        +--------+        +--------+       +---------+
  |          | -----> | hybrid | darcs  |        | ----> |   my    |
  | upstream | tailor |  CVS   | -----> | master | darcs | working |
  |   CVS    | <----- | darcs  | <----- | darcs  | <---- |  darcs  |
  |          |        |  sync  | tailor |        |       |         |
  +----------+        +--------+        +--------+       +---------+
               (cron)            (cron)


.. [#] Monotone, Codeville, Mercurial and Baazar-NG systems may be
       used only as the `target` backend, since the `source` support
       isn't coded yet. Contributions on these backends will be very
       appreciated, since I do not use them enough to figure out the
       best way to get pending changes and build tailor ChangeSets out
       of them.

.. _subversion: http://subversion.tigris.org/
.. _darcs: http://www.darcs.net/
.. _codeville: http://www.codeville.org/
.. _baazar-ng: http://www.bazaar-ng.org/
.. _mercurial: http://www.selenic.com/mercurial/


Installation
============

tailor.py is written in Python, and thus Python must be installed on
your system to use it.  It has been successfully used with Python 2.3
and 2.4.

Since it relies on external tools to do the real work such as `cvs`,
`darcs` and `svn`, they need to be installed as well, although only
those you will actually use.

Make tailor.py executable::

 $ chmod +x tailor.py

You can either run tailor.py where it is currently located, or move it
along with the vcpx directory to a location in your PATH.

There's even a standard setup.py that you may use to install the
script using Python conventional distutils.


Examples
========

1. Bootstrap a new tailored project, starting at upstream revision 10::

    $ tailor.py -b -s svn -R http://svn.server/path/to/svnrepo \
      --module /Product/trunk -r 10 --subdir Product ~/darcs/MyProduct 

2. Bootstrap a new product, fetching from CVS and storing under SVN:
   this will create the directory "~/svnwc/cmfcore"; "~/svnwc" must be
   already under SVN::

    $ tailor.py --source-kind cvs --target-kind svn --bootstrap \
                --repository :pserver:cvs.zope.org:/cvs-repository \
                --module CMF/CMFCore ~/svnwc/cmfcore

3. Showing each command bootstrap a new DARCS repos in
   "~/darcs/cmftopic" under which the upstream module will be
   extracted as "CMFTopic" (ie, the last component of the module
   name)::

    $ tailor.py -D -b -R :pserver:anonymous@cvs.zope.org:/cvs-repository/ \
                -m CMF/CMFTopic ~/darcs/cmftopic
              
4. Merge upstream changes since last update/bootstrap::

    $ tailor.py ~/svnwc/MyProduct

5. Migrate a whole SVN repository, starting from the beginning::

    $ tailor.py -b -s svn -R svn+ssh://caia/tmp/svn/repo --module / \
      --subdir testsvn --revision 1 testdir

   .. warning:: When using --revision with a SVN source repository, be
                sure that the path your are tracking was there at that
                revision, otherwise svn will exit with an error.

6. Bootstrap from a CVS branch, starting from a given point in time::

    $ tailor.py -b -s cvs -R :pserver:anonymous@server.org:/cvsroot/ \
                --revision 'unstable-branch 2001-12-25 23:26:48 UTC' \
                --module something new-darcs-repository

7. Bootstrap from a CVS branch, starting from the beginning of time::

    $ tailor.py -b -s cvs -R :pserver:anonymous@server.org:/cvsroot/ \
                --revision 'unstable-branch INITIAL' \
                --module something new-darcs-repository


Resolving conflicts
===================

Should one of the replayed changes generate any conflict, tailor.py
will prompt the user to correct them. This is done after the upstream
patch has been applied and before the final commit on the target
system, so that manually tweaking the conflict can produce a clean
patch.


Shortcomings
============

Tailor currently suffers of the following reported problems:

a) It does not handle "empty" CVS checkouts, in other words you cannot
   bootstrap a project that has nothing in its CVS upstream
   repository, or from a point in time where this condition was true.

b) It does not work under Windows (no, that's not a feature :-). Maybe
   replacing the shwrap machinery with something built on top of
   subprocess_ that seems able to hide Windows crazyness...

c) Monotone, Codeville and Baazar-NG are (currently) only supported as
   *target*

d) Specifying ``--subdir .`` may not work, in particular when dealing
   with remote CVS repositories (it does when the CVS repository is
   on local machine).
   
This list will always be incomplete, but I'll do my best to keep it
short :-)

.. _subprocess: http://www.lysator.liu.se/~astrand/popen5/


Tailor's metadata
=================

To do its work, tailor needs some information about your source tree,
such as the upstream repository URL and the current revision of the
sources on your harddisk.

In the simpler case, tailor keeps this information in a file called
`tailor.info`, one for each tailored project, that is a very simple
text document, with the following information, one per line:

1. Upstream repository kind (either "cvs", "darcs" or "svn)
2. Target repository kind (the same as above)
3. The name of the "module" that's been tailored
4. The URL of the upstream repository (that may not be an URL, for cvs...)
5. The current revision, from the upstream point of view, of the sources
6. The subdirectory that contains the checked out upstream tree,
   either that given with with the `--subdir` option or computed
   taking the last part of the module name. 

This is everything tailor needs, to be able to keep going from where it
left last time.


Config file format
------------------

When your project is composed by multiple upstream modules, it is
easier to collect such information in a single file. This is done by
specifying the `--configfile` option with a file name as argument. In
this case, tailor will read/write the above information from a
standard Python dictionary stored in the given file. 

The dictionary is keyed on the relative position of each project, and
each entry carries the same information described above.

Here's an example config file entry::

 {'plone/atcontenttypes': {'module': 'ATContentTypes',
                           'source_kind': 'cvs',
                           'subdir': 'ATContentTypes',
                           'target_kind': 'darcs',
                           'upstream_repos': ':ext:cvs.sourceforge.net:/cvsroot/collective',
                           'upstream_revision': '2004-11-24 19:42:06 by ctheune'}}

By convention, config files are named with the extension ".tailor",
but this is not enforced.

In the example above, 'plone/atcontenttypes' is a directory where the
target source will be stored. The keys such 'module', 'source_kind',
etc correspond to options of the same name.

When using a config file, tailor will perform its job on each project
contained in the dictionary.


Interactive sessions
--------------------

Tailor offers an alternative way of driving its activity by using an
interactive session, bringing the configuration more similar to a
script.

Although this is still a work-in-progress, it's quickly becoming my
preferred usage, as its functionality cover the underlying tailor
features.

For example, this is the script I'm using to test it::

    cd /tmp
    state_file tailor.state
    source_kind darcs
    target_kind svn
    source_repository /home/lele/WiP/cvsync
    sub_directory cvsync
    refill_changelogs no
    patch_name_format [%(module)s] Changeset %(revision)s by %(author)s

that, as you can see, specifies the context needed by tailor to do its
work. With the following command line::

    $ tailor.py --verbose --interactive tailor.cmds
    Welcome to the Tailor interactive session: you can issue several commands
    with the usual `readline` facilities. With "help" you'll get a list of
    available commands.

    Current directory: /tmp
    Current state file: /tmp/tailor.state
    Current source kind: darcs
    Current target kind: svn
    Current source repository: /home/lele/WiP/cvsync
    Sub directory: cvsync
    Refill changelogs: False
    Patch name format: [%(module)s] Changeset %(revision)s by %(author)s
    tailor $ help
    
    Documented commands (type help <topic>):
    ========================================
    EOF                print_executed_commands  state_file
    bootstrap          refill_changelogs        sub_directory
    cd                 remove_first_log_line    target_kind
    current_directory  save                     target_module
    exit               source_kind              target_repository
    logfile            source_module
    patch_name_format  source_repository

    Undocumented commands:
    ======================
    help

    tailor $ help bootstrap
    
        Usage: bootstrap [revision]

        Checkout the initial upstream revision, by default HEAD (or
        specified by argument), then import the subtree into the
        target repository.

As another example, consider the following commands::

    cd /tmp/wc
    state_file tailor.state
    source_kind cvs
    target_kind darcs
    source_repository :pserver:anonymous@cvs.sourceforge.net:/cvsroot/buildbot
    source_module buildbot
    refill_changelogs false
    patch_name_format %(firstlogline)s
    print_executed_commands true
    bootstrap 2004/01/01 20:05:24
    update ask

Assuming ``/tmp/wc`` exists, executing them will first bootstrap a new
darcs repository with a snapshot at the given date of the upstream
sources, then will proceed with the update, asking confirmation about
any single changeset::

    ...
    Collected 586 upstream changesets
    Changeset 2004-01-07 00:42:07 by warner:
    * buildbot/changes/mail.py (parseFreshCVSMail): ....
    * test/test_mailparse.py (Test1.testMsg9): test for same

    Apply [Y/n/v/h/q]? h
    y: yes, apply it and keep going
    n: no, skip the current changeset
    v: view more detailed information
    q: do not apply the current changeset and stop iterating

    Apply [Y/n/v/h/q]? v
    Revision: 2004-01-07 00:42:07 by warner
    Date: 2004-01-07 00:42:07
    Author: warner
    Modified: ChangeLog,buildbot/changes/mail.py,test/test_mailparse.py
    Added: test/mail/msg9
    Log: * buildbot/changes/mail.py (parseFreshCVSMail): ...
    * test/test_mailparse.py (Test1.testMsg9): test for same
    
    Apply [Y/n/v/h/q]?

        
Further help
============

See the output of ``tailor.py -h`` for some further tips.  There's
also a `wiki page`_ that may give you some other hints.  The
development of Tailor is mainly driven by user requests at this point,
and the preferred comunication media is the dedicated `mailing list`_
[#]_.

.. _wiki page:
   http://www.darcs.net/DarcsWiki/Tailor

.. _mailing list:
   http://lists.zooko.com/mailman/listinfo/tailor
   
I will be more than happy to answer any doubt, question or suggestion
you may have on it. I'm usually hanging as "lelit" on the IRC channel
devoted to darcs on the `freenode.net` network. Do not hesitate to
contact me either by email or chatting there.

.. [#] I wish to say a big `Thank you` to `Zooko <zooko@zooko.com>`_,
       for hosting the ML and for supporting Tailor in several ways,
       from suggestions to bug reporting and fixing.


Author
======

Lele Gaifax <lele@nautilus.homeip.net>


Monotone support
----------------

Monotone_ support was kindly contributed by `Markus Schiltknecht
<markus@bluegap.ch>`_ and further developed by `rghetta
<birrachiara@tin.it>`_.  Since I'm not currently using monotone (so
little time, so many VCSs...) I'm not in position to test it out
properly, but I'll do my best to keep it in sync, maybe with your
support :-)

.. _monotone: http://www.venge.net/monotone/


License
=======

Tailor is distribuited under the `GNU General Public License`__.

__ http://www.fsf.org/licensing/licenses/gpl.html


About this document
===================

This document and most of the internal documention use the
reStructuredText format so that it can be easily converted into other
formats, such as HTML.  For more information about this, please see:

  http://docutils.sourceforge.net/rst.html


.. vim:ft=rest
.. Local Variables:
.. mode: rst
.. End:
