A brief introduction to Arch

Using arch on a single-developer project.

(Japanese translation) (Brazilian Portuguese translation)

This mini-guide presents a gentle overview of some of Arch's basic features. It is intended as a complement to the Arch tutorial - it may be helpful to read this first, and then move on to other mini-guides, and then the tutorial to learn more.

Creating an archive

Before we can get started with arch, we need to set up an archive. This is just a directory on your filesystem in which the revisions of a project are stored. It doesn't have to be on your local file system - you can make an archive on another machine, and access it via HTTP, FTP, SFTP, etc. We'll use a local archive to keep things simple.

If you've used something like CVS before, you can think of the archive as being akin to CVSROOT.

Setting up an archive is fairly straight-forward:

john@shell% tla make-archive john@doe.com--myarchive ~/myarchive
john@shell% tla my-default-archive john@doe.com--myarchive

What this does is associated the archive name john@doe.com--myarchive with ~/myarchive, and then sets that archive as the default. It also creates ~/myarchive and puts some control files in there.

We can verify that this step worked by asking Arch to list the available archives:

john@shell% tla archives
lord@emf.net--2003b
    http://arch.quackerhead.com/~lord/archives/lord@emf.net--2003b
john@doe.com--myarchive
    /home/john/myarchive

Notice how john@doe--myarchive is not the only archive? The other listed archive is one of the places you can grab the latest version of Arch. We won't be using it in this tutorial.

The archive name is in the form:

email@address--archive-name

The email address doesn't have to be real - it's just a way of making the archive unique. Archive names must conform to this convention.

Setting your identity

One final step before you can import your first project - you need to set your identity. You do this with the command my-id:

john@shell% tla my-id "John Doe <john@doe.com>"

Arch will remember this (as it will remember your default archive). The identity is used in things like changelog messages.

Importing your first project

Now that you've set up an archive, you're ready to import your first project. To do this, you start with a directory that your sources are in - called a working directory, or project tree. We'll use a really simple "hello world" project as an example:

john@shell% cd $wd/hello
john@shell% ls
hello.py  world.py

Naming your project

The first step to importing a project is to give it a name. We might choose to call this project:

hello--dev--1.0

This is actually three bits of information, joined together by a double hyphen.

Arch enforces this naming format, which can seem a bit foreign at first. It'll ends up being a convenient way to reference a particular revision of the software - it will grow on you.

To name the project, we initialise our directory as an arch working directory, with the command init-tree:

john@shell% tla init-tree hello--dev--1.0
john@shell% ls
hello.py  world.py  {arch}

Notice how an {arch} directory has been added. This contains information about the name of the project, what archive it's associated with, etc.

Tagging files to add

By default, Arch uses an explicit tagging method. What this means is that you need to explicitly tell Arch which files you want to be included in the archive. You do this by tagging the files. Here, we want all the files to be included.

john@shell% tla add *.py

We can verify that the operation was successful by looking at an inventory of our files:

john@shell% tla inventory
S ./hello.py
S ./world.py

Had we not tagged the files, they would be marked as unrecognised (U), rather than source files (S):

john@shell% tla inventory
U ./hello.py
U ./world.py

Importing the initial revision

We are now ready to import our working directory into the archive. There are actually two steps required to do this - one to create the relevant categories, branches and revisions in the archive, and one to do the import. We'll take advantage of a new feature in tla 1.1 to do both at once:

john@shell% tla import --setup
* creating category john@doe.com--myarchive/hello
* creating branch john@doe.com--myarchive/hello--dev
* creating version john@doe.com--myarchive/hello--dev--1.0
* imported john@doe.com--myarchive/hello--dev--1.0

Congratulations! If you've been following along, the hard part is out of the way. The rest of the tutorial will start to show you how Arch can make your life easier.

Common tasks

What changed?

Having imported our project, we can now start to modify it. Imagine that John Doe has modified hello.py to add a brand new feature - printing the string hello 5 times, instead of once. Before commiting his change to the archive, he wants to look over it to make sure it is correct, and he hasn't left any testing code in.

To do this, Arch provides a command called what-changed:

john@shell% tla what-changed
M  ./hello.py

This tells John that hello.py has been modified (M). In order to properly look over the change, John wants to see the difference between the version in the archive and his changes. To do this, he can provide an argument to what-changed:

john@shell% tla what-changed --diffs
M  ./hello.py

* modified files

--- orig/hello.py
+++ mod/hello.py
@@ -1,3 +1,4 @@
 #!/usr/bin/env python

-print "hello"
+for i in range(5):
+    print "hello"

This indicates that one line has been removed, and two added.

Note that these commands used a cached copy of the latest archive version, called a pristine tree (pristine, because it is an unmodified version of the latest revision). This is especially useful for disconnected operation - you don't have access to the archive to be able to see what you've changed.

Quick commits

John, happy that his change was as he expected, now wishes to commit his changes back to the archive. To do this, Arch provides a command commit:

john@shell% tla commit -L "print hello 5 times instead of 1"
M  ./hello.py
* update pristine tree (john@doe.com--myarchive/hello--dev--1.0--base-0
                        => hello--dev--1.0--patch-1)
* commited john@doe.com--myarchive/hello--dev--1.0--patch-1

Note the -L argument. This allows you to specify a log message on the command line. This is useful for quick changes, but sometimes you'll want to have a more detailed log message. To do this, you can create a log message before you commit.

Commiting with a log file

For longer changes, which require a more elaborate change description, it can be useful to create a log message before you go to commit. To do this, you can use Arch's make-log command:

john@shell% tla make-log
/home/john/wd/hello/++log.hello--dev--1.0--john@doe.com--myarchive

john@shell% cat ++log.hello--dev--1.0--john@doe.com--myarchive
Summary:
Keywords:

This creates an empty log message, and prints the name of the file. A common idiom is to edit this file as it is created, by doing something like:

john@shell% $EDITOR $(tla make-log)
Warning: not overwriting existing log file
<editor opens up>

The summary line above is used as a short change description - usually around 60 characters or less. The keywords field isn't used often. Any text below keywords is treated as the body of a log message - it can be as long as you wanted.

John might fill out the log message like so:

Summary: print hello 5 times instead of 1
Keywords:

Upon a request from a user, I have made hello print 5 times instead of 1. You
can still obtain the old functionality by running hello | tail -1. Comments
on this change are welcome.

When John is ready to commit the change, he can just omit the -L argument:

john@shell% tla commit
M  ./hello.py
* update pristine tree (john@doe.com--myarchive/hello--dev--1.0--base-0
                        => hello--dev--1.0--patch-1)
* commited john@doe.com--myarchive/hello--dev--1.0--patch-1

Getting a list of changes

To list the changes in the archive, you can use the command revisions. Arch also offers a command log-ls, which lists the changes in your working directory. You might find less changes in your working directory than the archive in the case where multiple people are working on the same branch - but we won't get into that here.

These changes descriptions are contained in patch logs. Each patch log looks like an email message, and it stores things like the change description, date, etc. The patch logs are stored both in the archive and in a working directory, so if you're working on some code on your laptop, and don't have access to the archive, you can still list all the changes which have been applied to the tree.

The revisions command looks like:

john@shell% tla revisions --summary
base-0
    initial import
patch-1
    print hello 5 times instead of 1

For a branch with a single developer, log-ls will always print the same thing. Here we demonstrate an extra argument that either command will accept:

john@shell% tla log-ls --summary --creator
base-0
    John Doe <john@doe.com>
    initial import
patch-1
    John Doe <john@doe.com>
    print hello 5 times instead of 1

Notice the creator name - this is the name we gave to my-id earlier.

Generating a changelog

The patch logs which have been previously mentioned describe more information than we can see using commands like log-ls or revisions. To access that extra information, Arch provides a changelog command:

john@shell% tla changelog
# do not edit -- automatically generated by arch changelog
# arch-tag: automatic-ChangeLog--john@doe.com--myarchive/hello--dev--1.0
#

2003-07-13 09:36:33 GMT John Doe <john@doe.com> patch-1

    Summary:
      print hello 5 times instead of 1
    Revision:
      hello--dev--1.0--patch-1

    Upon a request from a user, I  have made hello print 5 times instead of 1.
    You can  still obtain the  old functionality by  running hello |  tail -1.
    Comments on this change are welcome.

    modified files:
     ./hello.py


2003-07-13 08:58:18 GMT John Doe <john@doe.com> base-0

    Summary:
      initial import
    Revision:
      hello--dev--1.0--base-0

    
    (automatically generated log message)

    new files:
     ./hello.py ./world.py

The changelog command accesses the repository to provide the list of changes - so the full list of changes is printed even if your working directory is not up to date.

Getting revisions from the archive

Suppose that John notices that his new version of hello has broken some other program which used it. In order to test that the problem is with John's update, he wants to access a previous release.

He'd start by listing the changes (since he's forgotten):

john@shell% cd
john@shell% tla revisions --summary hello--dev--1.0
base-0
    initial import
patch-1
    print hello 5 times instead of 1

Notice how the name of the the project is provided to revisions. This is because we moved out of a working directory - so there is no associated project.

John, from looking at the list, realises he wants the base version (he might have chosen an earlier patch, had there been more patches to choose from). To get the base-0 release, he can run the following command:

john@shell% tla get hello--dev--1.0--base-0
* from import revision: john@doe.com--myarchive/hello--dev--1.0--base-0
* making pristine copy
* tree version set john@doe.com--myarchive/hello--dev--1.0

This creates a directory called hello--dev--1.0--base-0. You can specify an alternative name if you wish:

john@shell% tla get hello--dev--1.0--base-0 mydir

If you want the latest revision, there is a shortcut - you can omit the version specifier (base-0, patch-1, etc), like so:

john@shell% tla get hello--dev--1.0              

Damien Elmes - web@repose.cx