vcs-repo-mgr: Version control repository manager

https://travis-ci.org/xolox/python-vcs-repo-mgr.svg?branch=master https://coveralls.io/repos/xolox/python-vcs-repo-mgr/badge.png?branch=master

The Python package vcs-repo-mgr provides a command line program and Python API to perform common operations (in the context of packaging/deployment) on version control repositories. It’s currently tested on Python 2.6, 2.7, 3.4, 3.5 and 3.6. Bazaar, Mercurial and Git repositories are supported.

Installation

The vcs-repo-mgr package is available on PyPI which means installation should be as simple as:

$ pip install vcs-repo-mgr

There’s actually a multitude of ways to install Python packages (e.g. the per user site-packages directory, virtual environments or just installing system wide) and I have no intention of getting into that discussion here, so if this intimidates you then read up on your options before returning to these instructions ;-).

You will also need Bazaar, Mercurial and/or Git installed (depending on the type of repositories you want to work with). Here’s how you install them on Debian and Ubuntu based systems:

$ sudo apt-get install bzr mercurial git-core

Usage

There are two ways to use the vcs-repo-mgr package: As the command line program vcs-tool and as a Python API. For details about the Python API please refer to the API documentation available on Read the Docs. The command line interface is described below.

Usage: vcs-tool [OPTIONS] [ARGS]

Command line program to perform common operations (in the context of packaging/deployment) on version control repositories. Supports Bazaar, Mercurial and Git repositories.

Supported options:

Option Description
-r, --repository=REPOSITORY

Select a repository to operate on by providing the name of a repository defined in one of the configuration files ~/.vcs-repo-mgr.ini and /etc/vcs-repo-mgr.ini.

Alternatively the location of a remote repository can be given. The location should be prefixed by the type of the repository (with a “+” in between) unless the location ends in ”.git” in which case the prefix is optional.

--rev, --revision=REVISION

Select a revision to operate on. Accepts any string that’s supported by the VCS system that manages the repository, which means you can provide branch names, tag names, exact revision ids, etc. This option is used in combination with the --find-revision-number, --find-revision-id and --export options.

If this option is not provided a default revision is selected: “last:1” for Bazaar repositories, “master” for git repositories and “default” (not “tip”!) for Mercurial repositories.

--release=RELEASE_ID

Select a release to operate on. This option works in the same way as the --revision option. Please refer to the vcs-repo-mgr documentation for details on “releases”.

Although release identifiers are based on branch or tag names they may not correspond literally, this is why the release identifier you specify here is translated to a global revision id before being passed to the VCS system.

-n, --find-revision-number Print the local revision number (an integer) of the revision given with the --revision option. Revision numbers are useful as a build number or when a simple, incrementing version number is required. Revision numbers should not be used to unambiguously refer to a revision (use revision ids for that instead). This option is used in combination with the --repository and --revision options.
-i, --find-revision-id Print the global revision id (a string) of the revision given with the --revision option. Global revision ids are useful to unambiguously refer to a revision. This option is used in combination with the --repository and --revision options.
--list-releases Print the identifiers of the releases in the repository given with the --repository option. The release identifiers are printed on standard output (one per line), ordered using natural order comparison.
--select-release=RELEASE_ID Print the identifier of the newest release that is not newer than RELEASE_ID in the repository given with the --repository option. The release identifier is printed on standard output.
-s, --sum-revisions

Print the summed revision numbers of multiple repository/revision pairs. The repository/revision pairs are taken from the positional arguments to vcs-repo-mgr.

This is useful when you’re building a package based on revisions from multiple VCS repositories. By taking changes in all repositories into account when generating version numbers you can make sure that your version number is bumped with every single change.

--vcs-control-field Print a line containing a Debian control file field and value. The field name will be one of “Vcs-Bzr”, “Vcs-Hg” or “Vcs-Git”. The value will be the repository’s remote location and the selected revision (separated by a “#” character).
-u, --update Create/update the local clone of a remote repository by pulling the latest changes from the remote repository. This option is used in combination with the --repository option.
-m, --merge-up

Merge a change into one or more release branches and the default branch.

By default merging starts from the current branch. You can explicitly select the branch where merging should start using the --rev, --revision and --release options.

You can also start by merging a feature branch into the selected release branch before merging the change up through later release branches and the default branch. To do so you pass the name of the feature branch as a positional argument.

If the feature branch is located in a different repository you can prefix the location of the repository to the name of the feature branch with a “#” token in between, to delimit the location from the branch name.

-e, --export=DIRECTORY Export the contents of a specific revision of a repository to a local directory. This option is used in combination with the --repository and --revision options.
-d, --find-directory Print the absolute pathname of a local repository. This option is used in combination with the --repository option.
-v, --verbose Increase logging verbosity (can be repeated).
-q, --quiet Decrease logging verbosity (can be repeated).
-h, --help Show this message and exit.

The primary way to use the vcs-tool command requires you to create a configuration file:

$ cat > ~/.vcs-repo-mgr.ini << EOF
[coloredlogs]
type = git
local = /tmp/coloredlogs
remote = git@github.com:xolox/python-coloredlogs.git
EOF

Because the -r, --repository option accepts remote repository locations in addition to names it’s not actually required to create a configuration file. Of course this depends on your use case(s).

Below are some examples of the command line interface. If you’re interested in using the Python API please refer to the online documentation.

Updating repositories

If the configuration file defines a local and remote repository and the local repository doesn’t exist yet it will be created the first time you update it:

$ vcs-tool --repository coloredlogs --update
2014-05-04 18:55:54 INFO Creating Git clone of git@github.com:xolox/python-coloredlogs.git at /tmp/coloredlogs ..
Cloning into bare repository '/tmp/coloredlogs'...
remote: Reusing existing pack: 96, done.
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 101 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (101/101), 28.11 KiB, done.
Resolving deltas: 100% (44/44), done.

Later runs will pull the latest changes instead of performing a full clone:

$ vcs-tool --repository coloredlogs --update
2014-05-04 18:55:56 INFO Updating Git clone of git@github.com:xolox/python-coloredlogs.git at /tmp/coloredlogs ..
From github.com:xolox/python-coloredlogs
 * branch HEAD -> FETCH_HEAD

Finding revision numbers/ids

Revision numbers are integer numbers that increment with every added revision. They’re very useful during packaging/deployment:

$ vcs-tool --repository coloredlogs --revision master --find-revision-number
24

Revision ids (hashes) are hexadecimal strings that uniquely identify revisions. They are useful to unambiguously refer to a revision and its history (e.g while building a package you can embed the revision id as a hint about the origins of the package):

$ vcs-tool --repository coloredlogs --revision master --find-revision-id
bce75c1eea88ebd40135cd45de716fe9591e348c

Exporting revisions

By default the repositories created by vcs-repo-mgr do not contain a working tree, just the version control files (in Git terminology this is called a “bare repository”). This has two reasons:

  1. Bare repositories help conserve disk space. This is insignificant for small repositories, but on large repositories it can make a noticeable difference. Especially if you’re using a lot of them :-)
  2. Bare repositories enforce the principle that the working tree shouldn’t be used during packaging (instead you should export the tree at a specific revision to a temporary directory and use that). This insistence on not using the working tree during packaging has two reasons:
    1. The working tree can contain files which are not under version control. Such files should certainly not be included in a package unintentionally.
    2. If the working tree of a repository is used, this makes it impossible to safely perform parallel builds from the same repository (the builds can corrupt each other’s working tree).

This means that if you want to do something with the files in the repository you have to export a revision to a (temporary) directory:

$ vcs-tool --repository coloredlogs --export /tmp/coloredlogs-snapshot
2014-05-04 19:17:24 INFO Exporting revision master of /tmp/coloredlogs to /tmp/coloredlogs-snapshot ..

$ ls -l /tmp/coloredlogs-snapshot
total 28K
drwxrwxr-x 2 peter peter 4.0K May  3 14:31 coloredlogs
drwxrwxr-x 3 peter peter 4.0K May  3 14:31 vim
-rw-rw-r-- 1 peter peter 1.1K May  3 14:31 LICENSE.txt
-rw-rw-r-- 1 peter peter   56 May  3 14:31 MANIFEST.in
-rw-rw-r-- 1 peter peter 5.4K May  3 14:31 README.rst
-rwxrwxr-x 1 peter peter 1.1K May  3 14:31 setup.py

Future improvements

This section is currently a “braindump” which means I haven’t committed to any of these improvements, I’m just thinking out loud ;-).

Improve interactive repository selection

Two improvements for interactive usage of the vcs-tool program:

  • Automatically load a repository’s configuration when a pathname is given that matches an entry in a configuration file (right now you need to give the repository’s name in order to load its configuration).
  • Do the obvious thing when no repository is specified on the command line but the working directory matches a configured repository.
Wildcard matching in configuration files
It might be interesting to support shell wildcard matching against local directory names to apply a default configuration to a group of repositories?
Enable more extensive customization
Right now the version control commands are hard coded and not easy to customize for those cases where the existing API gets you 90% of where you want to be but makes that last 10% impossible. Technically this is already possible through subclassing, but a more lightweight solution would certainly be nice to have :-).
Switch to executor.contexts
Switch to executor.contexts for external command execution to enable dependency injection of command execution contexts. I haven’t really investigated how complex the switch will be. It might be possible to somehow combine the above point (enable customization) and this point (dependency injection) but I’m not yet sure what that would look like.
Extend Bazaar support
Try to bring Bazaar support up to par with the features supported for Git and Mercurial repositories. To be honest I’m not sure this is worth the effort, I find myself working with Bazaar repositories less and less.
Refactor test suite

The test suite started out based on clones of external repositories, simply because I lacked the means to create new repositories and make new commits yet needed repositories with existing commits to test against.

Since then I never revisited this structure and the test suite has become a tangled mess of methods being called in the right order, dependent on each other’s side effects. I should definitely revisit this and attempt to isolate all of these tests into separate test methods that don’t depend on each other.

Known issues

This section documents known issues that users may run into.

Problematic dependencies

Bazaar and Mercurial are both written in Python and available on PyPI and as such I included them in the installation requirements of vcs-repo-mgr, because I couldn’t think of a good reason not to.

Adding support for Python 3 to vcs-repo-mgr made things more complicated because Bazaar and Mercurial didn’t support Python 3, leading to installation errors. To cope with this problem the Bazaar and Mercurial requirements were made conditional on the Python version:

  • On Python 2 the Bazaar and Mercurial packages would be installed together with vcs-repo-mgr.
  • On Python 3 the user was instead responsible for making sure that Bazaar and Mercurial were installed (for example using system packages).

This works fine because vcs-repo-mgr only invokes Bazaar and Mercurial using the command line interfaces so it doesn’t matter whether the version control system is using the same version of Python as vcs-repo-mgr.

Since then the installation of the Bazaar package has started failing on PyPy, unfortunately this time there is no reliable and backwards compatible way to make the Bazaar dependency optional in wheel distributions due to bugs in setuptools.

When I investigated support for environment markers that match Python implementations (refer to the link above) I decided that instead of writing a setup script full of nasty and fragile hacks I’d rather just drop official (tested) support for PyPy, as silly as the reason for it may be.

Contact

The latest version of vcs-repo-mgr is available on PyPI and GitHub. For bug reports please create an issue on GitHub. If you have questions, suggestions, etc. feel free to send me an e-mail at peter@peterodding.com.

License

This software is licensed under the MIT license.

© 2017 Peter Odding.

Function reference

The following documentation is based on the source code of version 0.34 of the vcs-repo-mgr package.

vcs_repo_mgr

Python API for the vcs-repo-mgr package.

Note

This module handles subprocess management using executor. This means that the ExternalCommandFailed exception can be raised at (more or less) any point.

Getting started

When using vcs-repo-mgr as a Python API the following top level entities should help you get started:

  • The Repository class implements most of the functionality exposed by the vcs-repo-mgr project. In practice you’ll use one of the subclasses which implement support for a specific VCS system (BzrRepo, GitRepo and HgRepo).
  • The find_configured_repository() function constructs instances of Repository subclasses based on configuration files. This is useful when you find yourself frequently instantiating the same Repository instances and you’d rather refer to a repository name in your code than repeating the complete local and remote locations everywhere in your code (this kind of duplication is bad after all :-).
  • You can choose to directly instantiate BzrRepo, GitRepo and/or HgRepo instances or you can use one of the helper functions that instantiate repository objects for you (coerce_repository() and repository_factory()).

Common operations

The operations supported by Bazaar, Git and Mercurial have confusingly similar names except when they don’t (don’t even get me started about subtly different semantics ;-) and so one challenge while developing vcs-repo-mgr has been to come up with good names that adequately capture the semantics of operations (just for the record: I’m not claiming that I always succeed on the first try :-).

In case you find yourself as confused as I have found myself at times, the following table lists common repository operations supported by vcs-repo-mgr and their equivalent Bazaar, Git and Mercurial commands:

Python API (vcs-repo-mgr) Bazaar Git Mercurial
Repository.create() bzr branch git clone hg clone
Repository.update() bzr pull git fetch hg pull
Repository.push() bzr push git push hg push
Repository.checkout() (not implemented) git checkout hg update
Repository.commit() (not implemented) git commit hg commit
Repository.create_branch() (not implemented) git checkout -b hg branch
Repository.merge() (not implemented) git merge –no-commit hg merge

Note

As you can see from the table above I’m slowly but surely forgetting about keeping Bazaar support up to par, if only because I don’t like the “lowest common denominator” approach where useful Git and Mercurial features aren’t exposed because there’s no clear alternative for Bazaar. Also I work a lot less with Bazaar which means I’m lacking knowledge; keeping Bazaar support up to par at all times drags down my progress significantly.

In contrast while there are of course a lot of small details that differ between Git and Mercurial, I’m still convinced that it’s useful to hide these differences, because overall the two systems are so similar that it seems worth it to me (so far :-).

vcs_repo_mgr.USER_CONFIG_FILE = '/home/docs/.vcs-repo-mgr.ini'

The absolute pathname of the user-specific configuration file (a string).

vcs_repo_mgr.SYSTEM_CONFIG_FILE = '/etc/vcs-repo-mgr.ini'

The absolute pathname of the system wide configuration file (a string).

vcs_repo_mgr.UPDATE_VARIABLE = 'VCS_REPO_MGR_UPDATE_LIMIT'

The name of the environment variable that’s used to rate limit repository updates (a string).

vcs_repo_mgr.KNOWN_RELEASE_SCHEMES = ('branches', 'tags')

The names of valid release schemes (a tuple of strings).

vcs_repo_mgr.REPOSITORY_TYPES = set([<class 'vcs_repo_mgr.BzrRepo'>, <class 'vcs_repo_mgr.GitRepo'>, <class 'vcs_repo_mgr.HgRepo'>])

Available Repository subclasses (a set of type objects).

vcs_repo_mgr.coerce_feature_branch(value)[source]

Convert a string to a FeatureBranchSpec object.

Parameters:value – A string or FeatureBranchSpec object.
Returns:A FeatureBranchSpec object.
vcs_repo_mgr.coerce_repository(value)[source]

Convert a string (taken to be a repository name or location) to a Repository object.

Parameters:value – The name or location of a repository (a string) or a Repository object.
Returns:A Repository object.
Raises:ValueError when the given value is not a string or a Repository object or if the value is a string but doesn’t match the name of any configured repository and also can’t be parsed as the location of a repository.

The coerce_repository() function creates Repository objects:

  1. If the value is already a Repository object it is returned to the caller untouched.
  2. If the value is accepted by find_configured_repository() then the resulting Repository object is returned.
  3. If the value is a string that starts with a known VCS type prefix (e.g. hg+https://bitbucket.org/ianb/virtualenv) the prefix is removed from the string and a Repository object is returned:
    • If the resulting string points to an existing local directory it will be used to set local.
    • Otherwise the resulting string is used to set remote.
  4. If the value is a string pointing to an existing local directory, the VCS type is inferred from the directory’s contents and a Repository object is returned whose local property is set to the local directory.
  5. If the value is a string that ends with .git (a common idiom for git repositories) a Repository object is returned:
    • If the value points to an existing local directory it will be used to set local.
    • Otherwise the value is used to set remote.
vcs_repo_mgr.find_configured_repository(name)[source]

Find a version control repository defined by the user in a configuration file.

Parameters:name – The name of the repository (a string).
Returns:A Repository object.
Raises:NoSuchRepositoryError when the given repository name doesn’t match any of the configured repositories.
Raises:AmbiguousRepositoryNameError when the given repository name is ambiguous (i.e. it matches multiple repository names).
Raises:UnknownRepositoryTypeError when a repository definition with an unknown type is encountered.

The following configuration files are supported:

  1. /etc/vcs-repo-mgr.ini
  2. ~/.vcs-repo-mgr.ini

Repositories defined in the second file override repositories defined in the first. Here is an example of a repository definition:

[vcs-repo-mgr]
type = git
local = ~/projects/vcs-repo-mgr
remote = git@github.com:xolox/python-vcs-repo-mgr.git
bare = true
release-scheme = tags
release-filter = .*

Three VCS types are currently supported: hg (mercurial is also accepted), git and bzr (bazaar is also accepted).

vcs_repo_mgr.repository_factory(vcs_type, **kw)[source]

Instantiate a Repository object based on the given type and arguments.

Parameters:
  • vcs_type – One of the strings ‘bazaar’, ‘bzr’, ‘git’, ‘hg’ or ‘mercurial’ or a subclass of Repository.
  • kw – The keyword arguments to Repository.__init__().
Returns:

A Repository object.

Raises:

UnknownRepositoryTypeError when the given type is unknown.

vcs_repo_mgr.find_cache_directory(remote)[source]

Find the directory where temporary local checkouts are to be stored.

Returns:The absolute pathname of a directory (a string).
vcs_repo_mgr.normalize_name(name)[source]

Normalize a repository name.

Parameters:name – The name of a repository (a string).
Returns:The normalized repository name (a string).

This makes sure that minor variations in character case and/or punctuation don’t disrupt the name matching in find_configured_repository().

vcs_repo_mgr.sum_revision_numbers(arguments)[source]

Sum revision numbers of multiple repository/revision pairs.

Parameters:arguments – A list of strings with repository names and revision strings.
Returns:A single integer containing the summed revision numbers.

This is useful when you’re building a package based on revisions from multiple VCS repositories. By taking changes in all repositories into account when generating version numbers you can make sure that your version number is bumped with every single change.

class vcs_repo_mgr.limit_vcs_updates[source]

Avoid duplicate repository updates.

This context manager uses an environment variable to ensure that each configured repository isn’t updated more than once by the current process and/or subprocesses.

__enter__()[source]

Set UPDATE_VARIABLE to the current time when entering the context.

__exit__(exc_type=None, exc_value=None, traceback=None)[source]

Restore the previous value of UPDATE_VARIABLE when leaving the context.

class vcs_repo_mgr.Revision(repository, revision_id, revision_number=None, branch=None, tag=None)[source]

Revision objects represent a specific revision in a Repository.

The following fields are available:

repository

The Repository object of the version control repository containing the revision.

revision_id

A string containing a global revision id (a hexadecimal hash) comparable between local and remote repositories. Useful to unambiguously refer to a revision and its history. This field is always available.

revision_number[source]

A local revision number (an incrementing integer). Useful as a build number or when a simple, incrementing version number is required. Should not be used to unambiguously refer to a revision. If not available this will be None.

branch

The name of the branch in which the revision exists (a string). If not available this will be None.

tag

The name of the tag associated to the revision (a string). If not available this will be None.

__init__(repository, revision_id, revision_number=None, branch=None, tag=None)[source]

Create a Revision object.

Parameters:
  • repository – A Repository object.
  • revision_id – A string containing a hexadecimal hash.
  • revision_number – The revision number (an integer, optional).
  • branch – The name of the branch (a string, optional).
  • tag – The name of the tag (a string, optional).
revision_number[source]

The revision number of the revision (an integer).

Note

The revision_number property is a custom_property. You can change the value of this property using normal attribute assignment syntax. This property’s value is computed once (the first time it is accessed) and the result is cached.

__repr__()[source]

Generate a human readable representation of a revision object.

class vcs_repo_mgr.RepositoryMeta(name, bases, dict)[source]

Metaclass for automatic registration of Repository subclasses.

__init__(name, bases, dict)[source]

Register a Repository subclass as soon as its defined.

class vcs_repo_mgr.Repository(local=None, remote=None, bare=None, release_scheme=None, release_filter=None, **kw)[source]

Base class for version control repository interfaces.

Please don’t use this directly, use subclasses like HgRepo and/or GitRepo instead.

ALIASES = []

A list of strings with aliases/names for the repository type.

The repository_factory() function searches the ALIASES of all known subclasses of Repository in order to map repository specifications like hg+https://bitbucket.org/ianb/virtualenv to the correct Repository subclass.

static get_vcs_directory(directory)[source]

Get the pathname of the directory containing the VCS metadata files.

Parameters:directory – The pathname of a local directory (a string). The directory doesn’t have to exist.
Returns:A subdirectory of the given directory or the directory itself (a string).

This static method needs to be implemented by Repository subclasses.

classmethod contains_repository(directory)[source]

Check whether the given directory contains a local clone.

Parameters:directory – The pathname of a local directory (a string).
Returns:True if it looks like the directory contains a local clone, False otherwise.

By default contains_repository() just checks whether the result of get_vcs_directory() points to an existing local directory. Repository subclasses can override this class method to improve detection accuracy.

__init__(local=None, remote=None, bare=None, release_scheme=None, release_filter=None, **kw)[source]

Initialize a version control repository interface.

Parameters:
Raises:

ValueError for any of the following:

  • Neither the local repository directory nor the remote repository location is specified.
  • The local repository directory doesn’t exist and no remote repository location is specified.
  • The local repository directory already exists but is_bare doesn’t match the status requested with the bare keyword argument.
  • The given release scheme is not ‘tags’ or ‘branches’.
  • The release filter regular expression contains more than one capture group (if you need additional groups but without the capturing aspect use a non-capturing group).

This method supports two calling conventions:

  1. The old calling convention consists of up to five positional arguments and is supported to preserve backwards compatibility (refer to the arguments documented above).
  2. The new calling convention is to pass only the required keyword arguments, this improves extensibility. Please refer to the PropertyManager documentation for details about the handling of keyword arguments.
local[source]

The pathname of the repository’s local clone (a string).

If remote is set but local isn’t set it is assumed that the location of the local clone doesn’t matter (because vcs-repo-mgr will act as an exclusive proxy to the local clone) and local is computed (once) using find_cache_directory().

Note

The local property is a custom_property. You are required to provide a value for this property by calling the constructor of the class that defines the property with a keyword argument named local (unless a custom constructor is defined, in this case please refer to the documentation of that constructor). You can change the value of this property using normal attribute assignment syntax. This property’s value is computed once (the first time it is accessed) and the result is cached.

remote[source]

The location of the remote (upstream) repository (a string).

In most cases remote will be a URL pointing to a remote repository but it can also be a pathname of a local directory. If remote isn’t given then local must be set to the pathname of an existing local repository clone.

Note

The remote property is a writable_property. You can change the value of this property using normal attribute assignment syntax.

bare[source]

Whether the local repository clone should be bare (a boolean or None).

This property specifies whether the local repository clone should have a working tree or not:

  • True means the local clone doesn’t need and shouldn’t have a working tree (in older versions of vcs-repo-mgr this was the default and only choice).
  • False means the local clone does need a working tree (for example because you want to commit).

The value of bare defaults to is_bare for repositories with an existing local clone, if only to preserve compatibility with versions of vcs-repo-mgr that didn’t have working tree support. For repositories without a local clone, bare defaults to True so that create() defaults to creating bare clones.

If bare is explicitly set and the local clone already exists it will be checked by __init__() to make sure that the values of bare and is_bare match. If they don’t an exception will be raised.

Note

The bare property is a writable_property. You can change the value of this property using normal attribute assignment syntax.

release_scheme[source]

The repository’s release scheme (a string, defaults to ‘tags’).

The value of release_scheme determines whether Repository.releases is based on Repository.tags or Repository.branches. It should match one of the values in KNOWN_RELEASE_SCHEMES.

Note

The release_scheme property is a writable_property. You can change the value of this property using normal attribute assignment syntax.

release_filter[source]

The repository’s release filter (a string or regular expression, defaults to .*).

The value of release_filter should be a string containing a regular expression or the result of re.compile(). The regular expression is used by Repository.releases to match tags or branches that signify “releases”. If the regular expression contains a single capture group, the identifier of a Release object is set to the substring captured by the capture group (instead of the complete tag or branch name). This defaults to the regular expression .* which matches any branch or tag name.

Note

The release_filter property is a writable_property. You can change the value of this property using normal attribute assignment syntax.

compiled_filter

The result of re.compile() on release_filter.

If release_filter isn’t a string then it is assumed to be a compiled regular expression object and returned directly.

author[source]

The author for commits created using commit() (a string).

This is a string of the form name <email> where both the name and the email address are required (this is actually a slight simplification, but I digress).

The author property needs to be provided by subclasses and/or the caller (by passing it to __init__() as a keyword argument).

Note

The author property is a writable_property. You can change the value of this property using normal attribute assignment syntax.

friendly_name[source]

The human friendly name for the repository’s version control system (a string).

The friendly_name property needs to be provided by subclasses and/or the caller (by passing it to __init__() as a keyword argument).

Note

The friendly_name property is a required_property. You are required to provide a value for this property by calling the constructor of the class that defines the property with a keyword argument named friendly_name (unless a custom constructor is defined, in this case please refer to the documentation of that constructor). You can change the value of this property using normal attribute assignment syntax.

vcs_directory[source]

The pathname of the directory containing the local clone’s VCS files (a string).

Note

The vcs_directory property is a required_property. You are required to provide a value for this property by calling the constructor of the class that defines the property with a keyword argument named vcs_directory (unless a custom constructor is defined, in this case please refer to the documentation of that constructor). You can change the value of this property using normal attribute assignment syntax.

default_revision[source]

The default revision for the given version control system and repository (a string).

The default_revision property needs to be implemented by subclasses and/or passed to __init__() as a keyword argument.

Note

The default_revision property is a required_property. You are required to provide a value for this property by calling the constructor of the class that defines the property with a keyword argument named default_revision (unless a custom constructor is defined, in this case please refer to the documentation of that constructor). You can change the value of this property using normal attribute assignment syntax.

current_branch

The name of the branch that’s currently checked out in the working tree (a string or None).

The current_branch property needs to be implemented by subclasses.

merge_conflicts

The filenames of any files with merge conflicts (a list of strings).

The merge_conflicts property needs to be implemented by subclasses.

exists

True if the local clone exists, False otherwise.

last_updated_file

The pathname of the file used to mark the last successful update (a string).

Used internally by the last_updated property.

last_updated

The date/time when vcs-repo-mgr last checked for updates (an integer).

Used internally by update() when used in combination with limit_vcs_updates. The value is a UNIX time stamp (0 for remote repositories that don’t have a local clone yet).

mark_updated()[source]

Mark a successful update so that last_updated can report it.

Used internally by update().

get_author(author=None)[source]

Get the name and email address of the author for commits.

Parameters:author – Override the value of author (a string). If author is None this argument is required.
Returns:A dictionary with the keys ‘author_name’ and ‘author_email’ and string values.
Raises:ValueError when no author information is available or the author information is in the wrong format.
get_command(method_name, attribute_name, **kw)[source]

Get the command for a given VCS operation.

Parameters:
  • method_name – The name of the method that wants to execute the command (a string).
  • attribute_name – The name of the attribute that is expected to hold the VCS command (a string).
  • kw – Any keyword arguments are shell escaped and interpolated into the VCS command.
Returns:

The VCS command (a string).

Raises:

NotImplementedError when the requested attribute isn’t available (e.g. because the VCS operation isn’t supported).

create(remote=None)[source]

Create the local clone of the remote version control repository.

Parameters:remote – Overrides the value of remote for the duration of the call to create().
Returns:True if the repository was just created, False if it already existed.
Raises:ExternalCommandFailed if the command fails.

It’s not an error if the repository already exists.

update(remote=None)[source]

Update the local clone of the remote version control repository.

Parameters:remote – Overrides the value of remote for the duration of the call to update().
Raises:ExternalCommandFailed if the command fails.

If used in combination with limit_vcs_updates this won’t perform redundant updates.

Note

Automatically creates the local repository on the first run.

push(remote=None)[source]

Push changes from the local repository to a remote repository.

Parameters:remote – Overrides the value of remote for the duration of the call to push().
Raises:ExternalCommandFailed if the command fails.

Warning

Depending on the version control backend the push command may fail when there are no changes to push. No attempt has been made to make this behavior consistent between implementations (although the thought has crossed my mind and I’ll likely revisit this in the future).

checkout(revision=None, clean=False)[source]

Update the repository’s local working tree to the specified revision.

Parameters:
  • revision – The revision to check out (a string, defaults to default_revision).
  • clean – If True any changes in the working tree are discarded (defaults to False).
Raises:

ExternalCommandFailed if the command fails.

Note

Automatically creates the local repository on the first run.

create_branch(branch_name)[source]

Create a new branch based on the working tree’s revision.

Parameters:branch_name – The name of the branch to create (a string).
Raises:ExternalCommandFailed if the command fails.

This method automatically checks out the new branch, but note that the new branch may not actually exist until a commit has been made on the branch.

Note

Automatically creates the local repository on the first run.

delete_branch(branch_name, message=None)[source]

Delete (or close) a branch in the local repository clone.

Parameters:
  • branch_name – The name of the branch to delete (a string).
  • message – The message to use when closing the branch requires a commit (a string or None). Defaults to “Closing branch NAME”.
Raises:

ExternalCommandFailed if the command fails.

Note

Automatically creates the local repository on the first run.

merge(revision=None)[source]

Merge a revision into the current branch (without committing the result).

Parameters:

revision – The revision to merge in (a string, defaults to default_revision).

Raises:

The following exceptions can be raised:

  • MergeConflictError if the merge command reports an error and merge conflicts are detected that can’t be (or haven’t been) resolved interactively.
  • ExternalCommandFailed if the merge command reports an error but no merge conflicts are detected.

Refer to the documentation of merge_conflict_handler if you want to customize the handling of merge conflicts.

Note

Automatically creates the local repository on the first run.

merge_conflict_handler[source]

The merge conflict handler (a callable, defaults to interactive_merge_conflict_handler()).

Note

The merge_conflict_handler property is a writable_property. You can change the value of this property using normal attribute assignment syntax.

interactive_merge_conflict_handler(exception)[source]

Give the operator a chance to interactively resolve merge conflicts.

Parameters:exception – An ExternalCommandFailed object.
Returns:True if the operator has interactively resolved any merge conflicts (and as such the merge error doesn’t need to be propagated), False otherwise.

This method checks whether sys.stdin is connected to a terminal to decide whether interaction with an operator is possible. If it is then an interactive terminal prompt is used to ask the operator to resolve the merge conflict(s). If the operator confirms the prompt, the merge error is swallowed instead of propagated. When sys.stdin is not connected to a terminal or the operator denies the prompt the merge error is propagated.

merge_up(target_branch=None, feature_branch=None, delete=True)[source]

Merge a change into one or more release branches and the default branch.

Parameters:
  • target_branch – The name of the release branch where merging of the feature branch starts (a string or None, defaults to current_branch).
  • feature_branch – The feature branch to merge in (any value accepted by coerce_feature_branch()).
  • deleteTrue (the default) to delete or close the feature branch after it is merged, False otherwise.
Returns:

If feature_branch is given the global revision id of the feature branch is returned, otherwise the global revision id of the target branch (before any merges performed by merge_up()) is returned.

Raises:

The following exceptions can be raised:

Note

Automatically creates the local repository on the first run.

add_files(*pathnames, **kw)[source]

Stage new files in the working tree to be included in the next commit.

Parameters:
  • pathnames – Any positional arguments are expected to be pathnames relative to the root of the repository.
  • all – If the keyword argument all is True then all new files are added to the repository (in this case no pathnames should be given).
Raises:

The following exceptions can be raised:

Note

Automatically creates the local repository on the first run.

commit(message, author=None)[source]

Commit changes to tracked files in the working tree.

Parameters:
  • message – The commit message (a string).
  • author – Override the value of author (a string). If author is None this argument is required.
Raises:

ExternalCommandFailed if the command fails.

Note

Automatically creates the local repository on the first run.

export(directory, revision=None)[source]

Export the complete tree from the local version control repository.

Parameters:
  • directory – The directory where the tree should be exported (a string).
  • revision – The revision to export (a string, defaults to default_revision).
Raises:

ExternalCommandFailed if the command fails.

Note

Automatically creates the local repository on the first run.

is_bare

True if the repository is a bare checkout, False otherwise.

The is_bare property needs to be implemented by subclasses.

is_clean

True if the working tree is clean, False otherwise.

The is_clean property needs to be implemented by subclasses.

ensure_clean()[source]

Make sure the working tree is clean (contains no changes to tracked files).

Raises:WorkingTreeNotCleanError when the working tree contains changes to tracked files.
find_revision_number(revision=None)[source]

Find the local revision number of the given revision.

Parameters:revision – A reference to a revision, most likely the name of a branch (a string, defaults to default_revision).
Returns:The local revision number (an integer).

Note

Automatically creates the local repository on the first run.

The find_revision_number() method needs to be implemented by subclasses.

find_revision_id(revision=None)[source]

Find the global revision id of the given revision.

Parameters:revision – A reference to a revision, most likely the name of a branch (a string, defaults to default_revision).
Returns:The global revision id (a hexadecimal string).

Note

Automatically creates the local repository on the first run.

The find_revision_id() method needs to be implemented by subclasses.

generate_control_field(revision=None)[source]

Generate a Debian control file name/value pair for the given repository and revision.

Parameters:revision – A reference to a revision, most likely the name of a branch (a string, defaults to default_revision).
Returns:A tuple with two strings: The name of the field and the value.

This generates a Vcs-Bzr field for Bazaar repositories, a Vcs-Hg field for Mercurial repositories and a Vcs-Git field for Git repositories. Here’s an example based on the public git repository of the vcs-repo-mgr project:

>>> from vcs_repo_mgr import coerce_repository
>>> repository = coerce_repository('https://github.com/xolox/python-vcs-repo-mgr.git')
>>> repository.generate_control_field()
('Vcs-Git', 'https://github.com/xolox/python-vcs-repo-mgr.git#b617731b6c0ca746665f597d2f24b8814b137ebc')
branches

Find information about the branches in the version control repository.

Returns:A dict with branch names (strings) as keys and Revision objects as values.

Note

Automatically creates the local repository on the first run.

Here’s an example based on a mirror of the git project’s repository:

>>> from vcs_repo_mgr import GitRepo
>>> from pprint import pprint
>>> repository = GitRepo(remote='https://github.com/git/git.git')
>>> pprint(repository.branches)
{'maint':  Revision(repository=GitRepo(...), branch='maint',  revision_id='16018ae'),
 'master': Revision(repository=GitRepo(...), branch='master', revision_id='8440f74'),
 'next':   Revision(repository=GitRepo(...), branch='next',   revision_id='38e7071'),
 'pu':     Revision(repository=GitRepo(...), branch='pu',     revision_id='d61c1fa'),
 'todo':   Revision(repository=GitRepo(...), branch='todo',   revision_id='dea8a2d')}
ordered_branches

Find information about the branches in the version control repository.

Returns:An ordered list of Revision objects. The list is ordered by performing a natural order sort of branch names in ascending order (i.e. the first value is the “oldest” branch and the last value is the “newest” branch).

Note

Automatically creates the local repository on the first run.

tags

Find information about the tags in the version control repository.

Returns:A dict with tag names (strings) as keys and Revision objects as values.

Note

Automatically creates the local repository on the first run.

Here’s an example based on a mirror of the git project’s repository:

>>> from vcs_repo_mgr import GitRepo
>>> from pprint import pprint
>>> repository = GitRepo(remote='https://github.com/git/git.git')
>>> pprint(repository.tags)
{'v0.99': Revision(repository=GitRepo(...),
                   tag='v0.99',
                   revision_id='d6602ec5194c87b0fc87103ca4d67251c76f233a'),
 'v0.99.1': Revision(repository=GitRepo(...),
                     tag='v0.99.1',
                     revision_id='f25a265a342aed6041ab0cc484224d9ca54b6f41'),
 'v0.99.2': Revision(repository=GitRepo(...),
                     tag='v0.99.2',
                     revision_id='c5db5456ae3b0873fc659c19fafdde22313cc441'),
 ..., # dozens of tags omitted to keep this example short
 'v2.3.6': Revision(repository=GitRepo(...),
                    tag='v2.3.6',
                    revision_id='8e7304597727126cdc52771a9091d7075a70cc31'),
 'v2.3.7': Revision(repository=GitRepo(...),
                    tag='v2.3.7',
                    revision_id='b17db4d9c966de30f5445632411c932150e2ad2f'),
 'v2.4.0': Revision(repository=GitRepo(...),
                    tag='v2.4.0',
                    revision_id='67308bd628c6235dbc1bad60c9ad1f2d27d576cc')}
ordered_tags

Find information about the tags in the version control repository.

Returns:An ordered list of Revision objects. The list is ordered by performing a natural order sort of tag names in ascending order (i.e. the first value is the “oldest” tag and the last value is the “newest” tag).

Note

Automatically creates the local repository on the first run.

releases

Find information about the releases in the version control repository.

Returns:A dict with release identifiers (strings) as keys and Release objects as values.

Note

Automatically creates the local repository on the first run.

Here’s an example based on a mirror of the git project’s repository which shows the last ten releases based on tags, where each release identifier captures a tag without its ‘v’ prefix:

>>> from vcs_repo_mgr import GitRepo
>>> from pprint import pprint
>>> repository = GitRepo(remote='https://github.com/git/git.git',
...                      release_scheme='tags',
...                      release_filter=r'^v(\d+(?:\.\d+)*)$')
>>> pprint(repository.ordered_releases[-10:])
[Release(revision=Revision(..., tag='v2.2.2', ...), identifier='2.2.2'),
 Release(revision=Revision(..., tag='v2.3.0', ...), identifier='2.3.0'),
 Release(revision=Revision(..., tag='v2.3.1', ...), identifier='2.3.1'),
 Release(revision=Revision(..., tag='v2.3.2', ...), identifier='2.3.2'),
 Release(revision=Revision(..., tag='v2.3.3', ...), identifier='2.3.3'),
 Release(revision=Revision(..., tag='v2.3.4', ...), identifier='2.3.4'),
 Release(revision=Revision(..., tag='v2.3.5', ...), identifier='2.3.5'),
 Release(revision=Revision(..., tag='v2.3.6', ...), identifier='2.3.6'),
 Release(revision=Revision(..., tag='v2.3.7', ...), identifier='2.3.7'),
 Release(revision=Revision(..., tag='v2.4.0', ...), identifier='2.4.0')]
ordered_releases

Find information about the releases in the version control repository.

Returns:An ordered list of Release objects. The list is ordered by performing a natural order sort of release identifiers in ascending order (i.e. the first value is the “oldest” release and the last value is the newest “release”).

Note

Automatically creates the local repository on the first run.

select_release(highest_allowed_release)[source]

Select the newest release that is not newer than the given release.

Parameters:highest_allowed_release – The identifier of the release that sets the upper bound for the selection (a string).
Returns:The identifier of the selected release (a string).
Raises:NoMatchingReleasesError when no matching releases are found.
release_to_branch(release_id)[source]

Shortcut to translate a release identifier to a branch name.

Parameters:release_id – A Release.identifier value (a string).
Returns:A branch name (a string).
Raises:TypeError when the repository is not using branches as its release scheme.
release_to_tag(release_id)[source]

Shortcut to translate a release identifier to a tag name.

Parameters:release_id – A Release.identifier value (a string).
Returns:A tag name (a string).
Raises:TypeError when the repository is not using tags as its release scheme.
find_branches()[source]

Find information about the branches in the version control repository.

This is an internal method that is expected to be implemented by subclasses of Repository and is used by Repository.branches.

Returns:A generator of Revision objects.
find_tags()[source]

Find information about the tags in the version control repository.

This is an internal method that is expected to be implemented by subclasses of Repository and is used by Repository.tags.

Returns:A generator of Revision objects.
__repr__()[source]

Generate a human readable representation of a repository object.

class vcs_repo_mgr.Release(revision, identifier)[source]

Release objects are revisions that specify a software “release”.

Most version control repositories are used to store software projects and most software projects have the concept of “releases”: Specific versions of a software project that have been given a human and machine readable version number (in one form or another). Release objects exist to capture this concept in a form that is concrete enough to be generally useful while being abstract enough to be used in various ways (because every software project has its own scheme for releases).

By default the Release objects created by Repository.releases are based on Repository.tags, but using the release_scheme argument to the Repository constructor you can specify that releases should be based on Repository.branches instead. Additionally you can use the release_filter argument to specify a regular expression that will be used to distinguish valid releases from other tags/branches.

revision

The Revision that the release relates to.

identifier

The name of the tag or branch (a string). If a release_filter containing a single capture group is used this identifier is set to the captured substring instead of the complete tag or branch name.

__init__(revision, identifier)[source]

Initialize a release.

Parameters:
  • revision – The Revision that the release relates to.
  • identifier – The (substring of the) tag or branch name that the release is based on (a string).
__repr__()[source]

Generate a human readable representation of a release object.

class vcs_repo_mgr.FeatureBranchSpec(expression)[source]

Simple and human friendly feature branch specifications.

__init__(expression)[source]

Initialize a FeatureBranchSpec object.

Parameters:expression – A feature branch specification (a string).

The expression string is parsed as follows:

  • If expression contains two nonempty substrings separated by the character # it is split into two parts where the first part is used to set location and the second part is used to set revision.
  • Otherwise expression is interpreted as a revision without a location (in this case location will be None).

Some examples to make things more concrete:

>>> from vcs_repo_mgr import FeatureBranchSpec
>>> FeatureBranchSpec('https://github.com/xolox/python-vcs-repo-mgr.git#remote-feature-branch')
FeatureBranchSpec(expression='https://github.com/xolox/python-vcs-repo-mgr.git#remote-feature-branch',
                  location='https://github.com/xolox/python-vcs-repo-mgr.git',
                  revision='remote-feature-branch')
>>> FeatureBranchSpec('local-feature-branch')
FeatureBranchSpec(expression='local-feature-branch',
                  location=None,
                  revision='local-feature-branch')
expression[source]

The feature branch specification provided by the user (a string).

Note

The expression property is a required_property. You are required to provide a value for this property by calling the constructor of the class that defines the property with a keyword argument named expression (unless a custom constructor is defined, in this case please refer to the documentation of that constructor). You can change the value of this property using normal attribute assignment syntax.

location[source]

The location of the repository that contains revision (a string or None).

The computed default value of location is based on the value of expression as described in the documentation of __init__().

Note

The location property is a writable_property. You can change the value of this property using normal attribute assignment syntax.

revision[source]

The name of the feature branch (a string).

The computed default value of revision is based on the value of expression as described in the documentation of __init__().

Note

The revision property is a required_property. You are required to provide a value for this property by calling the constructor of the class that defines the property with a keyword argument named revision (unless a custom constructor is defined, in this case please refer to the documentation of that constructor). You can change the value of this property using normal attribute assignment syntax.

class vcs_repo_mgr.HgRepo(local=None, remote=None, bare=None, release_scheme=None, release_filter=None, **kw)[source]

Version control repository interface for Mercurial repositories.

ALIASES = ['hg', 'mercurial']

A list of strings with aliases/names for Mercurial.

static get_vcs_directory(directory)[source]

Get the pathname of the directory containing Mercurial’s metadata files.

Parameters:directory – The pathname of a local directory (a string). The directory doesn’t have to exist.
Returns:The .hg subdirectory of the given directory (a string).
author[source]

The author for commits created using commit() (a string).

The HgRepo class overrides this property to discover the configured username and email address using the command hg config ui.username. This means that by default your Mercurial configuration will be respected, but you are still free to explicitly specify a value for author.

Note

The author property is a custom_property. You can change the value of this property using normal attribute assignment syntax. This property’s value is computed once (the first time it is accessed) and the result is cached.

default_revision[source]

The default revision for Mercurial repositories (a string, defaults to default).

Note

The default_revision property is a required_property. You are required to provide a value for this property by calling the constructor of the class that defines the property with a keyword argument named default_revision (unless a custom constructor is defined, in this case please refer to the documentation of that constructor). You can change the value of this property using normal attribute assignment syntax.

current_branch

The name of the branch that’s currently checked out in the working tree (a string or None).

merge_conflicts

The filenames of any files with merge conflicts (a list of strings).

is_bare

True if the repository is a bare checkout, False otherwise.

Runs the hg id command to check whether the (special) global revision id 000000000000 is reported.

is_clean

True if the working tree is clean, False otherwise.

find_revision_number(revision=None)[source]

Find the revision number of the given revision expression.

Parameters:revision – A Mercurial specific revision expression (a string).
Returns:The revision number (an integer).
find_revision_id(revision=None)[source]

Find the revision id of the given revision expression.

Parameters:revision – A Mercurial specific revision expression (a string).
Returns:The revision id (a hexadecimal string).
find_branches()[source]

Find the branches in the Mercurial repository.

Returns:A generator of Revision objects.

Note

Closed branches are not included.

find_tags()[source]

Find the tags in the Mercurial repository.

Returns:A generator of Revision objects.
class vcs_repo_mgr.GitRepo(local=None, remote=None, bare=None, release_scheme=None, release_filter=None, **kw)[source]

Version control repository interface for Git repositories.

ALIASES = ['git']

A list of strings with aliases/names for Git.

static get_vcs_directory(directory)[source]

Get the pathname of the directory containing Git’s metadata files.

Parameters:directory – The pathname of a local directory (a string). The directory doesn’t have to exist.
Returns:The .git subdirectory of the given directory (for repositories with a working tree) or the given directory itself (for repositories without a working tree).
classmethod contains_repository(directory)[source]

Check whether the given directory contains a local Git clone.

Parameters:directory – The pathname of a local directory (a string).
Returns:True if it looks like the directory contains a local Git clone, False otherwise.

This static method checks whether the directory returned by get_vcs_directory() contains a file called config.

author[source]

The author for commits created using commit() (a string).

The GitRepo class overrides this property to discover the configured username using the command git config user.name and email address using git config user.email. This means that by default your Git configuration will be respected, but you are still free to explicitly specify a value for author.

Note

The author property is a custom_property. You can change the value of this property using normal attribute assignment syntax. This property’s value is computed once (the first time it is accessed) and the result is cached.

default_revision[source]

The default revision for Git repositories (a string, defaults to master).

Note

The default_revision property is a required_property. You are required to provide a value for this property by calling the constructor of the class that defines the property with a keyword argument named default_revision (unless a custom constructor is defined, in this case please refer to the documentation of that constructor). You can change the value of this property using normal attribute assignment syntax.

current_branch

The name of the branch that’s currently checked out in the working tree (a string or None).

merge_conflicts

The filenames of any files with merge conflicts (a list of strings).

is_bare

True if the repository is a bare checkout, False otherwise.

Runs the git config --get core.bare command to check whether we’re dealing with a bare checkout.

is_clean

True if the working tree (and index) is clean, False otherwise.

The implementation of GitRepo.is_clean checks whether git diff reports any differences. This command has several variants:

  1. git diff shows the difference between the index and working tree.
  2. git diff --cached shows the difference between the last commit and index.
  3. git diff HEAD shows the difference between the last commit and working tree.

The implementation of GitRepo.is_clean uses the third command (git diff HEAD) in an attempt to hide the existence of git’s index from callers that are trying to write code that works with Git and Mercurial using the same Python API.

find_revision_number(revision=None)[source]

Find the revision number of the given revision expression.

Parameters:revision – A git specific revision expression (a string).
Returns:The revision number (an integer).
find_revision_id(revision=None)[source]

Find the revision id of the given revision expression.

Parameters:revision – A git specific revision expression (a string).
Returns:The revision id (a hexadecimal string).
find_branches()[source]

Find the branches in the git repository.

Returns:A generator of Revision objects.
find_tags()[source]

Find the tags in the git repository.

Returns:A generator of Revision objects.
class vcs_repo_mgr.BzrRepo(local=None, remote=None, bare=None, release_scheme=None, release_filter=None, **kw)[source]

Version control repository interface for Bazaar repositories.

ALIASES = ['bzr', 'bazaar']

A list of strings with aliases/names for Bazaar.

static get_vcs_directory(directory)[source]

Get the pathname of the directory containing Bazaar’s metadata files.

Parameters:directory – The pathname of a local directory (a string). The directory doesn’t have to exist.
Returns:The .bzr subdirectory of the given directory (a string).
classmethod contains_repository(directory)[source]

Check whether the given directory contains a local Bazaar clone.

Parameters:directory – The pathname of a local directory (a string).
Returns:True if it looks like the directory contains a local Bazaar clone, False otherwise.

This method checks whether the directory returned by get_vcs_directory() contains a file called branch-format.

default_revision[source]

The default revision for Bazaar repositories (a string, defaults to last:1).

Note

The default_revision property is a required_property. You are required to provide a value for this property by calling the constructor of the class that defines the property with a keyword argument named default_revision (unless a custom constructor is defined, in this case please refer to the documentation of that constructor). You can change the value of this property using normal attribute assignment syntax.

is_bare

True if the repository is a bare checkout, False otherwise.

Checks whether the .bzr/checkout directory exists (it doesn’t exist in Bazaar repositories created using bzr branch --no-tree ...).

is_clean

True if the working tree is clean, False otherwise.

find_revision_number(revision=None)[source]

Find the revision number of the given revision expression.

Parameters:revision – A Bazaar specific revision expression (a string).
Returns:The revision number (an integer).

Note

Bazaar has the concept of dotted revision numbers:

For revisions which have been merged into a branch, a dotted notation is used (e.g., 3112.1.5). Dotted revision numbers have three numbers. The first number indicates what mainline revision change is derived from. The second number is the branch counter. There can be many branches derived from the same revision, so they all get a unique number. The third number is the number of revisions since the branch started. For example, 3112.1.5 is the first branch from revision 3112, the fifth revision on that branch.

(From http://doc.bazaar.canonical.com/bzr.2.6/en/user-guide/zen.html#understanding-revision-numbers)

However we really just want to give a bare integer to our callers. It doesn’t have to be globally accurate, but it should increase as new commits are made. Below is the equivalent of the git implementation for Bazaar.

find_revision_id(revision=None)[source]

Find the revision id of the given revision expression.

Parameters:revision – A Bazaar specific revision expression (a string).
Returns:The revision id (a hexadecimal string).
find_branches()[source]

Bazaar repository support doesn’t support branches.

This method logs a warning message and returns an empty list. Consider using tags instead.

find_tags()[source]

Find the tags in the Bazaar repository.

Returns:A generator of Revision objects.

Note

The bzr tags command reports tags pointing to non-existing revisions as ? but doesn’t provide revision ids. We can get the revision ids using the bzr tags --show-ids command but this command doesn’t mark tags pointing to non-existing revisions. We combine the output of both because we want all the information.

vcs_repo_mgr.cli

Usage: vcs-tool [OPTIONS] [ARGS]

Command line program to perform common operations (in the context of packaging/deployment) on version control repositories. Supports Bazaar, Mercurial and Git repositories.

Supported options:

Option Description
-r, --repository=REPOSITORY

Select a repository to operate on by providing the name of a repository defined in one of the configuration files ~/.vcs-repo-mgr.ini and /etc/vcs-repo-mgr.ini.

Alternatively the location of a remote repository can be given. The location should be prefixed by the type of the repository (with a “+” in between) unless the location ends in ”.git” in which case the prefix is optional.

--rev, --revision=REVISION

Select a revision to operate on. Accepts any string that’s supported by the VCS system that manages the repository, which means you can provide branch names, tag names, exact revision ids, etc. This option is used in combination with the --find-revision-number, --find-revision-id and --export options.

If this option is not provided a default revision is selected: “last:1” for Bazaar repositories, “master” for git repositories and “default” (not “tip”!) for Mercurial repositories.

--release=RELEASE_ID

Select a release to operate on. This option works in the same way as the --revision option. Please refer to the vcs-repo-mgr documentation for details on “releases”.

Although release identifiers are based on branch or tag names they may not correspond literally, this is why the release identifier you specify here is translated to a global revision id before being passed to the VCS system.

-n, --find-revision-number Print the local revision number (an integer) of the revision given with the --revision option. Revision numbers are useful as a build number or when a simple, incrementing version number is required. Revision numbers should not be used to unambiguously refer to a revision (use revision ids for that instead). This option is used in combination with the --repository and --revision options.
-i, --find-revision-id Print the global revision id (a string) of the revision given with the --revision option. Global revision ids are useful to unambiguously refer to a revision. This option is used in combination with the --repository and --revision options.
--list-releases Print the identifiers of the releases in the repository given with the --repository option. The release identifiers are printed on standard output (one per line), ordered using natural order comparison.
--select-release=RELEASE_ID Print the identifier of the newest release that is not newer than RELEASE_ID in the repository given with the --repository option. The release identifier is printed on standard output.
-s, --sum-revisions

Print the summed revision numbers of multiple repository/revision pairs. The repository/revision pairs are taken from the positional arguments to vcs-repo-mgr.

This is useful when you’re building a package based on revisions from multiple VCS repositories. By taking changes in all repositories into account when generating version numbers you can make sure that your version number is bumped with every single change.

--vcs-control-field Print a line containing a Debian control file field and value. The field name will be one of “Vcs-Bzr”, “Vcs-Hg” or “Vcs-Git”. The value will be the repository’s remote location and the selected revision (separated by a “#” character).
-u, --update Create/update the local clone of a remote repository by pulling the latest changes from the remote repository. This option is used in combination with the --repository option.
-m, --merge-up

Merge a change into one or more release branches and the default branch.

By default merging starts from the current branch. You can explicitly select the branch where merging should start using the --rev, --revision and --release options.

You can also start by merging a feature branch into the selected release branch before merging the change up through later release branches and the default branch. To do so you pass the name of the feature branch as a positional argument.

If the feature branch is located in a different repository you can prefix the location of the repository to the name of the feature branch with a “#” token in between, to delimit the location from the branch name.

-e, --export=DIRECTORY Export the contents of a specific revision of a repository to a local directory. This option is used in combination with the --repository and --revision options.
-d, --find-directory Print the absolute pathname of a local repository. This option is used in combination with the --repository option.
-v, --verbose Increase logging verbosity (can be repeated).
-q, --quiet Decrease logging verbosity (can be repeated).
-h, --help Show this message and exit.
vcs_repo_mgr.cli.main()[source]

The command line interface of the vcs-tool program.

vcs_repo_mgr.cli.print_directory(repository)[source]

Report the local directory of a repository to standard output.

vcs_repo_mgr.cli.print_revision_number(repository, revision)[source]

Report the revision number of the given revision to standard output.

vcs_repo_mgr.cli.print_revision_id(repository, revision)[source]

Report the revision id of the given revision to standard output.

vcs_repo_mgr.cli.print_selected_release(repository, release_id)[source]

Report the identifier of the given release to standard output.

vcs_repo_mgr.cli.print_releases(repository)[source]

Report the identifiers of all known releases of the given repository to standard output.

vcs_repo_mgr.cli.print_summed_revisions(arguments)[source]

Report the summed revision numbers for the given arguments to standard output.

vcs_repo_mgr.cli.print_vcs_control_field(repository, revision)[source]

Report the VCS control field for the given repository and revision to standard output.

vcs_repo_mgr.exceptions

Custom exception types raised by the vcs-repo-mgr package.

When vcs-repo-mgr encounters known errors it will raise an exception. Most of these exceptions have special types that capture the type of error so that the Python except statement can be used to handle different types of errors in different ways.

exception vcs_repo_mgr.exceptions.VcsRepoMgrError[source]

Base class for exceptions directly raised by vcs_repo_mgr.

exception vcs_repo_mgr.exceptions.AmbiguousRepositoryNameError[source]

Exception raised when an ambiguous repository name is encountered.

Raised by find_configured_repository() when the given repository name is ambiguous (i.e. it matches multiple repository names).

exception vcs_repo_mgr.exceptions.NoMatchingReleasesError[source]

Exception raised when no matching releases are found.

Raised by select_release() when no matching releases are found in the repository.

exception vcs_repo_mgr.exceptions.NoSuchRepositoryError[source]

Exception raised when a repository by the given name doesn’t exist.

Raised by find_configured_repository() when the given repository name doesn’t match any of the configured repositories.

exception vcs_repo_mgr.exceptions.UnknownRepositoryTypeError[source]

Exception raised when a repository has an unknown type configured.

Raised by find_configured_repository() when it encounters a repository definition with an unknown type.

exception vcs_repo_mgr.exceptions.WorkingTreeNotCleanError[source]

Exception raised when a working tree contains changes to tracked files.

Raised by ensure_clean() when it encounters a repository whose local working tree contains changes to tracked files.

exception vcs_repo_mgr.exceptions.MergeConflictError[source]

Exception raised when a merge results in merge conflicts.

Raised by merge() when it performs a merge that results in merge conflicts.