| 1 | About |
|---|
| 2 | ===== |
|---|
| 3 | |
|---|
| 4 | Tailor is a tool to migrate changesets between ArX_, `Bazaar-NG`_ |
|---|
| 5 | CVS_, Codeville_, Darcs_, Mercurial_, Monotone_, Tla_ and Subversion_ |
|---|
| 6 | [#]_ repositories. |
|---|
| 7 | |
|---|
| 8 | This script makes it easier to keep the upstream changes merged in |
|---|
| 9 | a branch of a product, storing needed information such as the upstream |
|---|
| 10 | URI and revision in special properties on the branched directory. |
|---|
| 11 | |
|---|
| 12 | The following ascii-art illustrates the usual scenario:: |
|---|
| 13 | |
|---|
| 14 | +------------+ +------------+ |
|---|
| 15 | +--------------+ | Immutable | | Working | |
|---|
| 16 | | Upstream CVS |-------->| darcs |----------->| darcs | |
|---|
| 17 | | repository | tailor | repository | darcs pull | repository | |
|---|
| 18 | +--------------+ +------------+ +------------+ |
|---|
| 19 | |^ |
|---|
| 20 | || |
|---|
| 21 | || |
|---|
| 22 | v| |
|---|
| 23 | User |
|---|
| 24 | |
|---|
| 25 | Ideally you should be able to swap and replace "CVS server" and "darcs |
|---|
| 26 | repository" with any combination of the supported systems. |
|---|
| 27 | |
|---|
| 28 | A more convoluted setup shows how brave people are using it to get a |
|---|
| 29 | two way sync:: |
|---|
| 30 | |
|---|
| 31 | +----------+ +--------+ +--------+ +---------+ |
|---|
| 32 | | | -----> | hybrid | darcs | | ----> | my | |
|---|
| 33 | | upstream | tailor | CVS | -----> | master | darcs | working | |
|---|
| 34 | | CVS | <----- | darcs | <----- | darcs | <---- | darcs | |
|---|
| 35 | | | | sync | tailor | | | | |
|---|
| 36 | +----------+ +--------+ +--------+ +---------+ |
|---|
| 37 | (cron) (cron) |
|---|
| 38 | |
|---|
| 39 | |
|---|
| 40 | .. [#] ArX, Monotone, Codeville, Mercurial and Baazar-NG systems may be |
|---|
| 41 | used only as the `target` backend, since the `source` support |
|---|
| 42 | isn't coded yet. Contributions on these backends will be very |
|---|
| 43 | appreciated, since I do not use them enough to figure out the |
|---|
| 44 | best way to get pending changes and build tailor ChangeSets out |
|---|
| 45 | of them. |
|---|
| 46 | |
|---|
| 47 | To the opposite, Tla is supported only as a source system. |
|---|
| 48 | |
|---|
| 49 | .. _arx: http://www.nongnu.org/arx/ |
|---|
| 50 | .. _bazaar-ng: http://www.bazaar-ng.org/ |
|---|
| 51 | .. _codeville: http://www.codeville.org/ |
|---|
| 52 | .. _cvs: http://www.nongnu.org/cvs/ |
|---|
| 53 | .. _darcs: http://www.darcs.net/ |
|---|
| 54 | .. _mercurial: http://www.selenic.com/mercurial/ |
|---|
| 55 | .. _monotone: http://www.venge.net/monotone/ |
|---|
| 56 | .. _subversion: http://subversion.tigris.org/ |
|---|
| 57 | .. _tla: http://www.gnuarch.org/arch/index.html |
|---|
| 58 | |
|---|
| 59 | |
|---|
| 60 | Installation |
|---|
| 61 | ============ |
|---|
| 62 | |
|---|
| 63 | tailor is written in Python, and thus Python must be installed on |
|---|
| 64 | your system to use it. It has been successfully used with Python 2.3 |
|---|
| 65 | and 2.4. |
|---|
| 66 | |
|---|
| 67 | Since it relies on external tools to do the real work such as `cvs`, |
|---|
| 68 | `darcs` [#]_ and `svn`, they need to be installed as well, although only |
|---|
| 69 | those you will actually use. |
|---|
| 70 | |
|---|
| 71 | Make tailor executable:: |
|---|
| 72 | |
|---|
| 73 | $ chmod +x tailor |
|---|
| 74 | |
|---|
| 75 | You can either run tailor where it is currently located, or move it |
|---|
| 76 | along with the vcpx directory to a location in your PATH. |
|---|
| 77 | |
|---|
| 78 | There's even a standard setup.py that you may use to install the |
|---|
| 79 | script using Python conventional distutils. |
|---|
| 80 | |
|---|
| 81 | .. [#] Darcs 1.0.2 is too old, 1.0.3 is good, 1.0.4 (the fourth |
|---|
| 82 | release candidate is under final testing) is recommended since |
|---|
| 83 | it's faster in most operations! |
|---|
| 84 | |
|---|
| 85 | |
|---|
| 86 | Testing |
|---|
| 87 | ======= |
|---|
| 88 | |
|---|
| 89 | You can run the test suite with the following command line:: |
|---|
| 90 | |
|---|
| 91 | $ tailor test -v |
|---|
| 92 | |
|---|
| 93 | that runs all the tests in sequence, or:: |
|---|
| 94 | |
|---|
| 95 | $ tailor test -v TailorTest |
|---|
| 96 | |
|---|
| 97 | to trigger just a subset of them. |
|---|
| 98 | |
|---|
| 99 | |
|---|
| 100 | Operation |
|---|
| 101 | ========= |
|---|
| 102 | |
|---|
| 103 | tailor needs now a configuration file that collects the various bits |
|---|
| 104 | of information it needs to do it's job. |
|---|
| 105 | |
|---|
| 106 | The simplest way of starting out a new configuration is by omitting |
|---|
| 107 | the --configfile command line option, and specifying the other as |
|---|
| 108 | needed plus --verbose: in this situation, tailor will print out an |
|---|
| 109 | equivalent configuration that you can redirect to a file, that you |
|---|
| 110 | later will pass as --configfile. |
|---|
| 111 | |
|---|
| 112 | |
|---|
| 113 | Examples |
|---|
| 114 | -------- |
|---|
| 115 | |
|---|
| 116 | 1. Bootstrap a new tailored project, starting at upstream revision 10 |
|---|
| 117 | |
|---|
| 118 | a. First create a config file:: |
|---|
| 119 | |
|---|
| 120 | $ tailor --verbose -s svn -R http://svn.server/path/to/svnrepo \ |
|---|
| 121 | --module /Product/trunk -r 10 --subdir Product \ |
|---|
| 122 | ~/darcs/MyProduct > myproject.tailor |
|---|
| 123 | |
|---|
| 124 | b. Modify it as you like (mostly adjusting root-directories and the |
|---|
| 125 | like):: |
|---|
| 126 | |
|---|
| 127 | $ emacs myproject.tailor |
|---|
| 128 | |
|---|
| 129 | c. Run tailor on it:: |
|---|
| 130 | |
|---|
| 131 | $ tailor --configfile myproject.tailor |
|---|
| 132 | |
|---|
| 133 | 2. Bootstrap a new product, fetching its whole CVS repository and |
|---|
| 134 | storing under SVN |
|---|
| 135 | |
|---|
| 136 | a. First create a config file:: |
|---|
| 137 | |
|---|
| 138 | $ tailor --verbose --source-kind cvs --target-kind svn \ |
|---|
| 139 | --repository :pserver:cvs.zope.org:/cvs-repository \ |
|---|
| 140 | --module CMF/CMFCore --revision INITIAL \ |
|---|
| 141 | --target-repository file:///some/where/svnrepo \ |
|---|
| 142 | --target-module / cmfcore > cmfcore.tailor |
|---|
| 143 | |
|---|
| 144 | b. Modify it as you like (mostly adjusting root-directories and the |
|---|
| 145 | like):: |
|---|
| 146 | |
|---|
| 147 | $ emacs myproject.tailor |
|---|
| 148 | |
|---|
| 149 | c. Run tailor on it once, to bootstrap the project:: |
|---|
| 150 | |
|---|
| 151 | $ tailor -D -v --configfile myproject.tailor |
|---|
| 152 | |
|---|
| 153 | If the target repository is on the local filesystem (ie, it |
|---|
| 154 | starts with ``file:///``) and it does not exist, tailor |
|---|
| 155 | creates a new empty Subversion repository at the specified |
|---|
| 156 | location. |
|---|
| 157 | |
|---|
| 158 | .. note:: Before step d) below, you may want to install an |
|---|
| 159 | appropriate hook in the repository to enable the |
|---|
| 160 | propset command to operate on unversioned properties, |
|---|
| 161 | as described in the `svn manual`__. Then you can |
|---|
| 162 | specify '--use-svn-propset' option, and tailor will |
|---|
| 163 | put the original author and timestamp in the proper |
|---|
| 164 | svn metadata instead of appending them to the changelog. |
|---|
| 165 | |
|---|
| 166 | Other than the annoying repository manual intervention, |
|---|
| 167 | this thread__ and this other__ explain why using |
|---|
| 168 | ``-r{DATE}`` may produce strange results with this setup. |
|---|
| 169 | |
|---|
| 170 | d. Run tailor again and again, to sync up with latest changes:: |
|---|
| 171 | |
|---|
| 172 | $ tailor -D -v --configfile myproject.tailor |
|---|
| 173 | |
|---|
| 174 | __ http://svnbook.red-bean.com/en/1.0/ch05s02.html#svn-ch-5-sect-2.1 |
|---|
| 175 | __ http://svn.haxx.se/users/archive-2005-07/0605.shtml |
|---|
| 176 | __ http://svn.haxx.se/users/archive-2005-03/0596.shtml |
|---|
| 177 | |
|---|
| 178 | |
|---|
| 179 | 3. Given the configuration file shown below in `Config file format`_, |
|---|
| 180 | the following command:: |
|---|
| 181 | |
|---|
| 182 | $ tailor --configfile example.tailor |
|---|
| 183 | |
|---|
| 184 | is equivalent to this one:: |
|---|
| 185 | |
|---|
| 186 | $ tailor --configfile example.tailor tailor |
|---|
| 187 | |
|---|
| 188 | in that they operate respectively on the default project(s) or |
|---|
| 189 | the ones specified on the command line (and in this case there |
|---|
| 190 | is just a single default project, tailor). |
|---|
| 191 | |
|---|
| 192 | This one instead:: |
|---|
| 193 | |
|---|
| 194 | $ tailor --configfile example.tailor tailor tailor-reverse |
|---|
| 195 | |
|---|
| 196 | operates on both projects. |
|---|
| 197 | |
|---|
| 198 | |
|---|
| 199 | CVS start-revision |
|---|
| 200 | ------------------ |
|---|
| 201 | |
|---|
| 202 | With CVS, you can specify a particular *point in time* specifying |
|---|
| 203 | a `start-revision` with a timestamp like ``2001-12-25 23:26:48 UTC``. |
|---|
| 204 | |
|---|
| 205 | To specify also a particular `branch`, prepend it before the |
|---|
| 206 | timestamp, as in ``unstable-branch 2001-12-25 23:26:48 UTC``. |
|---|
| 207 | |
|---|
| 208 | |
|---|
| 209 | Resolving conflicts |
|---|
| 210 | =================== |
|---|
| 211 | |
|---|
| 212 | Should one of the replayed changes generate any conflict, tailor |
|---|
| 213 | will prompt the user to correct them. This is done after the upstream |
|---|
| 214 | patch has been applied and before the final commit on the target |
|---|
| 215 | system, so that manually tweaking the conflict can produce a clean |
|---|
| 216 | patch. |
|---|
| 217 | |
|---|
| 218 | |
|---|
| 219 | Shortcomings |
|---|
| 220 | ============ |
|---|
| 221 | |
|---|
| 222 | Tailor currently suffers of the following reported problems: |
|---|
| 223 | |
|---|
| 224 | a) It does not handle "empty" CVS checkouts, in other words you cannot |
|---|
| 225 | bootstrap a project that has nothing in its CVS upstream |
|---|
| 226 | repository, or from a point in time where this condition was true. |
|---|
| 227 | |
|---|
| 228 | b) It's completely unsupported under Windows, evenif it now uses |
|---|
| 229 | 2.4's subprocess_ that seems able to hide Windows crazyness... |
|---|
| 230 | |
|---|
| 231 | c) ArX, Monotone, Codeville and Baazar-NG are (currently) only |
|---|
| 232 | supported as *target*; Tla only as *source*. |
|---|
| 233 | |
|---|
| 234 | d) Specifying ``--subdir .`` may not work, in particular when dealing |
|---|
| 235 | with remote CVS repositories (it does when the CVS repository is |
|---|
| 236 | on local machine). |
|---|
| 237 | |
|---|
| 238 | This list will always be incomplete, but I'll do my best to keep it |
|---|
| 239 | short :-) |
|---|
| 240 | |
|---|
| 241 | .. _subprocess: http://www.lysator.liu.se/~astrand/popen5/ |
|---|
| 242 | |
|---|
| 243 | |
|---|
| 244 | Config file format |
|---|
| 245 | ================== |
|---|
| 246 | |
|---|
| 247 | When your project is composed by multiple upstream modules, it is |
|---|
| 248 | easier to collect such information in a single file. This is done by |
|---|
| 249 | specifying the `--configfile` option with a file name as argument. In |
|---|
| 250 | this case, tailor will read the above information from a standard |
|---|
| 251 | Python ConfigParser file. |
|---|
| 252 | |
|---|
| 253 | For example:: |
|---|
| 254 | |
|---|
| 255 | [DEFAULT] |
|---|
| 256 | verbose = True |
|---|
| 257 | projects = tailor |
|---|
| 258 | |
|---|
| 259 | [tailor] |
|---|
| 260 | root = /tmp/n9 |
|---|
| 261 | source = darcs:tailor |
|---|
| 262 | target = svn:tailor |
|---|
| 263 | dont-refill-changelogs = True |
|---|
| 264 | state-file = tailor.state |
|---|
| 265 | |
|---|
| 266 | [tailor-reverse] |
|---|
| 267 | root = /tmp/n9 |
|---|
| 268 | source = svn:tailor |
|---|
| 269 | target = darcs:tailor |
|---|
| 270 | state-file = reverse.state |
|---|
| 271 | |
|---|
| 272 | [svn:tailor] |
|---|
| 273 | repository = file:///tmp/testtai |
|---|
| 274 | module = /project1 |
|---|
| 275 | |
|---|
| 276 | [darcs:tailor] |
|---|
| 277 | repository = ~/WiP/cvsync |
|---|
| 278 | |
|---|
| 279 | .. hint:: If you execute the examples above with ``--verbose --debug`` |
|---|
| 280 | **and without** ``--configfile``, tailor will write a |
|---|
| 281 | template config filled with the values specified by the |
|---|
| 282 | other options. You can redirect |
|---|
| 283 | |
|---|
| 284 | |
|---|
| 285 | Using a Python script as configuration file |
|---|
| 286 | ------------------------------------------- |
|---|
| 287 | |
|---|
| 288 | Instead of executing ``tailor --configfile project.tailor.conf`` |
|---|
| 289 | you can prepend the following signature to the config itself:: |
|---|
| 290 | |
|---|
| 291 | #!/usr/bin/env /path/to/tailor |
|---|
| 292 | |
|---|
| 293 | Giving execute mode to it will permit the launch of the tailor |
|---|
| 294 | process by running the config script directly:: |
|---|
| 295 | |
|---|
| 296 | $ ./project.tailor.conf |
|---|
| 297 | |
|---|
| 298 | When a config file is signed in this way [#]_, either you pass it as |
|---|
| 299 | argument to ``--configfile`` or executed as above, tailor will |
|---|
| 300 | actually execute it as a full fledged Python script, that may define |
|---|
| 301 | functions that alter the behaviour of tailor itself. |
|---|
| 302 | |
|---|
| 303 | A common usage of this functionality is to define so called `hooks`, |
|---|
| 304 | sequences of functions that are executed at particular points in |
|---|
| 305 | the tailorization process. |
|---|
| 306 | |
|---|
| 307 | For example:: |
|---|
| 308 | |
|---|
| 309 | #!/usr/bin/env /home/lele/WiP/tailor/tailor |
|---|
| 310 | """ |
|---|
| 311 | [project] |
|---|
| 312 | source = svn:repository |
|---|
| 313 | target = darcs:repository |
|---|
| 314 | before-commit = transform_crlf_to_lf |
|---|
| 315 | ... |
|---|
| 316 | """ |
|---|
| 317 | |
|---|
| 318 | def transform_crlf_to_lf(context, changeset): |
|---|
| 319 | for e in changeset.entries: |
|---|
| 320 | .... |
|---|
| 321 | |
|---|
| 322 | .. [#] Tailor does actually read just the first two bytes from the |
|---|
| 323 | file, and compare them with "#!", so you are free to choose |
|---|
| 324 | whatever syntax works in your environment. |
|---|
| 325 | |
|---|
| 326 | |
|---|
| 327 | State file |
|---|
| 328 | ---------- |
|---|
| 329 | |
|---|
| 330 | The state file stores two things: the last upstream revision that |
|---|
| 331 | has been applied to the tree, and a sequence of pending (not yet |
|---|
| 332 | applied) changesets, that may be empty. In the latter case, tailor |
|---|
| 333 | will fetch latest changes from the upstream repository. |
|---|
| 334 | |
|---|
| 335 | Interactive sessions |
|---|
| 336 | -------------------- |
|---|
| 337 | |
|---|
| 338 | Tailor offers an alternative way of driving its activity by using an |
|---|
| 339 | interactive session, bringing the configuration more similar to a |
|---|
| 340 | script. |
|---|
| 341 | |
|---|
| 342 | Although this is still a work-in-progress, it's quickly becoming my |
|---|
| 343 | preferred usage, as its functionality cover the underlying tailor |
|---|
| 344 | features. |
|---|
| 345 | |
|---|
| 346 | For example, this is the script I'm using to test it:: |
|---|
| 347 | |
|---|
| 348 | cd /tmp |
|---|
| 349 | state_file tailor.state |
|---|
| 350 | source_kind darcs |
|---|
| 351 | target_kind svn |
|---|
| 352 | source_repository /home/lele/WiP/cvsync |
|---|
| 353 | sub_directory cvsync |
|---|
| 354 | refill_changelogs no |
|---|
| 355 | patch_name_format [%(module)s] Changeset %(revision)s by %(author)s |
|---|
| 356 | |
|---|
| 357 | that, as you can see, specifies the context needed by tailor to do its |
|---|
| 358 | work. With the following command line:: |
|---|
| 359 | |
|---|
| 360 | $ tailor --verbose --interactive tailor.cmds |
|---|
| 361 | Welcome to the Tailor interactive session: you can issue several commands |
|---|
| 362 | with the usual `readline` facilities. With "help" you'll get a list of |
|---|
| 363 | available commands. |
|---|
| 364 | |
|---|
| 365 | Current directory: /tmp |
|---|
| 366 | Current state file: /tmp/tailor.state |
|---|
| 367 | Current source kind: darcs |
|---|
| 368 | Current target kind: svn |
|---|
| 369 | Current source repository: /home/lele/WiP/cvsync |
|---|
| 370 | Sub directory: cvsync |
|---|
| 371 | Refill changelogs: False |
|---|
| 372 | Patch name format: [%(module)s] Changeset %(revision)s by %(author)s |
|---|
| 373 | tailor $ help |
|---|
| 374 | |
|---|
| 375 | Documented commands (type help <topic>): |
|---|
| 376 | ======================================== |
|---|
| 377 | EOF print_executed_commands state_file |
|---|
| 378 | bootstrap refill_changelogs sub_directory |
|---|
| 379 | cd remove_first_log_line target_kind |
|---|
| 380 | current_directory save target_module |
|---|
| 381 | exit source_kind target_repository |
|---|
| 382 | logfile source_module |
|---|
| 383 | patch_name_format source_repository |
|---|
| 384 | |
|---|
| 385 | Undocumented commands: |
|---|
| 386 | ====================== |
|---|
| 387 | help |
|---|
| 388 | |
|---|
| 389 | tailor $ help bootstrap |
|---|
| 390 | |
|---|
| 391 | Usage: bootstrap [revision] |
|---|
| 392 | |
|---|
| 393 | Checkout the initial upstream revision, by default HEAD (or |
|---|
| 394 | specified by argument), then import the subtree into the |
|---|
| 395 | target repository. |
|---|
| 396 | |
|---|
| 397 | As another example, consider the following commands:: |
|---|
| 398 | |
|---|
| 399 | cd /tmp/wc |
|---|
| 400 | state_file tailor.state |
|---|
| 401 | source_kind cvs |
|---|
| 402 | target_kind darcs |
|---|
| 403 | source_repository :pserver:anonymous@cvs.sourceforge.net:/cvsroot/buildbot |
|---|
| 404 | source_module buildbot |
|---|
| 405 | refill_changelogs false |
|---|
| 406 | patch_name_format %(firstlogline)s |
|---|
| 407 | print_executed_commands true |
|---|
| 408 | bootstrap 2004/01/01 20:05:24 |
|---|
| 409 | update ask |
|---|
| 410 | |
|---|
| 411 | Assuming ``/tmp/wc`` exists, executing them will first bootstrap a new |
|---|
| 412 | darcs repository with a snapshot at the given date of the upstream |
|---|
| 413 | sources, then will proceed with the update, asking confirmation about |
|---|
| 414 | any single changeset:: |
|---|
| 415 | |
|---|
| 416 | ... |
|---|
| 417 | Collected 586 upstream changesets |
|---|
| 418 | Changeset 2004-01-07 00:42:07 by warner: |
|---|
| 419 | * buildbot/changes/mail.py (parseFreshCVSMail): .... |
|---|
| 420 | * test/test_mailparse.py (Test1.testMsg9): test for same |
|---|
| 421 | |
|---|
| 422 | Apply [Y/n/v/h/q]? h |
|---|
| 423 | y: yes, apply it and keep going |
|---|
| 424 | n: no, skip the current changeset |
|---|
| 425 | v: view more detailed information |
|---|
| 426 | q: do not apply the current changeset and stop iterating |
|---|
| 427 | |
|---|
| 428 | Apply [Y/n/v/h/q]? v |
|---|
| 429 | Revision: 2004-01-07 00:42:07 by warner |
|---|
| 430 | Date: 2004-01-07 00:42:07 |
|---|
| 431 | Author: warner |
|---|
| 432 | Modified: ChangeLog,buildbot/changes/mail.py,test/test_mailparse.py |
|---|
| 433 | Added: test/mail/msg9 |
|---|
| 434 | Log: * buildbot/changes/mail.py (parseFreshCVSMail): ... |
|---|
| 435 | * test/test_mailparse.py (Test1.testMsg9): test for same |
|---|
| 436 | |
|---|
| 437 | Apply [Y/n/v/h/q]? |
|---|
| 438 | |
|---|
| 439 | |
|---|
| 440 | Further help |
|---|
| 441 | ============ |
|---|
| 442 | |
|---|
| 443 | See the output of ``tailor -h`` for some further tips. There's |
|---|
| 444 | also a `wiki page`_ that may give you some other hints. The |
|---|
| 445 | development of Tailor is mainly driven by user requests at this point, |
|---|
| 446 | and the preferred comunication media is the dedicated `mailing list`_ |
|---|
| 447 | [#]_. |
|---|
| 448 | |
|---|
| 449 | .. _wiki page: |
|---|
| 450 | http://www.darcs.net/DarcsWiki/Tailor |
|---|
| 451 | |
|---|
| 452 | .. _mailing list: |
|---|
| 453 | http://lists.zooko.com/mailman/listinfo/tailor |
|---|
| 454 | |
|---|
| 455 | I will be more than happy to answer any doubt, question or suggestion |
|---|
| 456 | you may have on it. I'm usually hanging as "lelit" on the IRC channel |
|---|
| 457 | devoted to darcs on the `freenode.net` network. Do not hesitate to |
|---|
| 458 | contact me either by email or chatting there. |
|---|
| 459 | |
|---|
| 460 | .. [#] I wish to say a big `Thank you` to `Zooko <zooko@zooko.com>`_, |
|---|
| 461 | for hosting the ML and for supporting Tailor in several ways, |
|---|
| 462 | from suggestions to bug reporting and fixing. |
|---|
| 463 | |
|---|
| 464 | |
|---|
| 465 | Authors |
|---|
| 466 | ======= |
|---|
| 467 | |
|---|
| 468 | Lele Gaifax <lele@nautilus.homeip.net> |
|---|
| 469 | |
|---|
| 470 | Since I'm not currently using all the supported systems (so little |
|---|
| 471 | time, so many VCSs...) I'm not in position to test them out properly, |
|---|
| 472 | but I'll do my best to keep them in sync, maybe with your support :-) |
|---|
| 473 | |
|---|
| 474 | ArX support |
|---|
| 475 | ----------- |
|---|
| 476 | |
|---|
| 477 | ArX_ support was contributed by `Walter Landry <wlandry@ucsd.edu>`_. |
|---|
| 478 | |
|---|
| 479 | Bazaar-NG support |
|---|
| 480 | ----------------- |
|---|
| 481 | |
|---|
| 482 | `Bazaar-NG`_ support was contributed by `Johan Rydberg |
|---|
| 483 | <jrydberg@gnu.org>`_. |
|---|
| 484 | |
|---|
| 485 | Monotone support |
|---|
| 486 | ---------------- |
|---|
| 487 | |
|---|
| 488 | Monotone_ support was kindly contributed by `Markus Schiltknecht |
|---|
| 489 | <markus@bluegap.ch>`_ and further developed by `rghetta |
|---|
| 490 | <birrachiara@tin.it>`_. |
|---|
| 491 | |
|---|
| 492 | Tla support |
|---|
| 493 | ----------- |
|---|
| 494 | |
|---|
| 495 | Tla_ support was contributed by `Robin Farine |
|---|
| 496 | <robin.farine@terminus.org>`_. |
|---|
| 497 | |
|---|
| 498 | |
|---|
| 499 | License |
|---|
| 500 | ======= |
|---|
| 501 | |
|---|
| 502 | Tailor is distribuited under the `GNU General Public License`__. |
|---|
| 503 | |
|---|
| 504 | __ http://www.fsf.org/licensing/licenses/gpl.html |
|---|
| 505 | |
|---|
| 506 | |
|---|
| 507 | About this document |
|---|
| 508 | =================== |
|---|
| 509 | |
|---|
| 510 | This document and most of the internal documention use the |
|---|
| 511 | reStructuredText format so that it can be easily converted into other |
|---|
| 512 | formats, such as HTML. For more information about this, please see: |
|---|
| 513 | |
|---|
| 514 | http://docutils.sourceforge.net/rst.html |
|---|
| 515 | |
|---|
| 516 | |
|---|
| 517 | .. vim:ft=rest |
|---|
| 518 | .. Local Variables: |
|---|
| 519 | .. mode: rst |
|---|
| 520 | .. End: |
|---|