Chapter 18. Version Control

This is about using Aap with a Version Control System (VCS)

The generic form of version control commands is:

        :command file ...

Or:

        :command {attr = val} ... file ...

The commands use the "commit" attribute of a file to obtain the kind of version control system and its location. For example:

        :attr foo.c {commit = cvs://:ext:$CVSUSER_AAP@cvs.a-a-p.sf.net:/cvsroot/a-a-p}

For CVS it is also possible to only specify the method. CVS will then use the same specification for the repository as used when checking the files out.

        :attr foo.c {commit = cvs://}

These commands can be used:

:commitUpdate each file in the repository. Add it when needed.
:checkoutLike fetch and additionally lock for editing when possible.
:checkinLike commit, but unlock file.
:unlockRemove lock on file, don't change file in repository or locally.
:addAdd file to repository. File must exist locally. Implies a "commit" of the file.
:removeRemove file from repository. File may exist locally. Implies a "commit" of the file.
:tagAdd a tag to the current version. Uses the "tag" attribute.

Additionally, there is the generic command:

        :verscont action {attr = val} ... file ...

This calls the Version control module as specified in the "commit" attribute for "action" with the supplied arguments. What happens is specific for the VCS.

Operating On All Files

These commands work on all the files mentioned in the recipe and child recipes that have the "commit" attribute:

:checkoutallCheckout the files and locks them.
:commitall Commit the files . Files missing in the VCS will be added. No files will be removed.
:checkinallJust like :commitall and also remove any locks.
:unlockallUnlock the files.
:addallInspect directories and add items that do not exist in the VCS but are mentioned in the recipe(s) with a "commit" attribute. Uses the current directory or specified directories. May enter directories recursively.
:removeallInspect directories and remove items that do exist in the VCS but are not mentioned or do not have a "commit" attribute. Careful: Only use this command when it is certain that all files that should be in the VCS are explicitly mentioned and do have a "commit" attribute!
:reviseallJust like using both :checkinall and :removeall.
:tagallAdd a tag to all items with a "commit" and "tag" attribute.

Related to these commands are targets that are handled automatically when not defined explicitly. When defining a target for these, it would be highly unexpected if it works differently.

aap commit Normally uses the files you currently have to update the version control system. This can be used after you are done making a change. Default is using :commitall.
aap checkout Update all files from the VCS that have a "commit" attribute. When the VCS supports locking all files will be locked. Without locking this does the same as "aap fetch".
aap checkin Do :checkin for all files that have been checked out of the VCS. For a VCS that doesn't do file locking this is the same as "aap commit".
aap unlock Unlock all files that are locked in the VCS. Doesn't change any files in the VCS or locally.
aap add Do :add for all files that appear in the recipe with a "commit" attribute that do not appear in the VCS.
aap remove Do :removeall: remove all files that appear in the VCS but do not exist in the recipe with a "commit" attribute or do not exist in the local directory. This works in the current directory and recursively enters all subdirectories. Careful: files with a search path may be accidentally removed!
aap tag Do :tagall: tag all files with a "commit" and "tag" attribute. The tag name should be defined properly in the recipe, although "aap tag TAG=name" can be used if the recipe contains something like: :attr {tag = $TAG} $FILES
aap revise Same as "aap checkin" followed by "aap remove": checkin all changed files, unlock all files and remove files that don't have the "commit" attribute.

For the above the "-l" or "--local" command line option can be used to restrict the operation to the directory of the recipe and not recurse into subdirectories.

A variable can be used to set the default change log entries:

    LOGENTRY=message

This variable is used for new, changed and deleted files that don't have a {logentry} attribute.

When it's desired to commit one directory at a time the following construct can be used:

        source_files = *.c
        include_files = include/*.h
        commit-src {virtual}:
            :commit $source_files
            :removeall .
        commit-include {virtual}:
            :commit $include_files
            :removeall include

Note that this is not possible when the sources and include files are in one directory, :removeall only works per directory.

Using Subversion

Subversion is a new version control system that is going to replace CVS. It has many advantages, such as atomic commits. But version 1.0 is not ready yet (although the current versions appear to be very stable and usable).

Subversion support is not implemented yet. For the time being you can retrieve files from a Subversion repository by using a URL. That works, because subversion is using an Apache server. You can obtain a copy of single files by specifying the URL in the fetch attribute. Obviously you can't commit changed files this way.

Using Another Version Control System

To add support for a new version control system, define a Python function with the name "method_command", where "method" is the word at the start of the commit attribute. The function will be called with five arguments:

recdicta dictionary with references to all variable scopes (for expert users only)
namethe name of the repository defined with the "commit" attribute with the "scheme://" part removed.
commit_dictthe dictionary holding attributes for the specified repository; e.g., for "{commit = foo:// {arg = blah}}" it is (in Python syntax): { "name" : "foo://", "arg" : "blah" }
nodelista list of the nodes on which the action is to be performed
actionthe name of the action to be executed; can be "fetch", "commit", etc.

The function should a list of nodes that failed. When the action worked without errors an empty list should be returned.

For an example look at cvs_command() in the VersContCvs.py file of the Aap sources.

A second function that is to be defined is "method_list". It should return a list of the files that are currently in a specified directory in the repository. Return an empty list if there are no files. The function will be called with these arguments:

recdicta dictionary with references to all variable scopes (for expert users only)
namethe name of the repository defined with the "commit" attribute with the "scheme://" part removed.
commit_dictthe dictionary holding attributes for the specified repository; e.g., for "{commit = foo:// {arg = blah}}" it is (in Python syntax): { "name" : "foo://", "arg" : "blah" }
dirnamename of the directory to be listed
recursiveboolean indicating whether recursive listing is to be done

For an example look at cvs_list() in the VersContCvs.py file of the Aap sources.