NAME
VCI - A library for interacting with version-control systems.
SYNOPSIS
my $repository = VCI->connect(type => $type, repo => $repo);
DESCRIPTION
This is VCI, the generic Version Control Interface. The goal of VCI is to create a common API that can interface with all version control systems (which are sometimes also called Software Configuration Management or "SCM" systems).
The VCI home page is at http://vci.everythingsolved.com/.
New to VCI?
If you aren't sure where to start, you want to first look at "connect" and then at VCI::Abstract::Repository.
Basically, when using VCI, you connect to a Repository, get a Project from that Repository, and then call methods on that Project.
The general interface of VCI is described in the various VCI::Abstract modules, and those contain the documentation you should read in order to find out how VCI works.
"Drivers" for different VCSes are in modules whose names start with VCI::VCS
. For example, VCI::VCS::Cvs is the "CVS support" for VCI. You only have to read VCI::VCS::Cvs or the manual of any other driver if you want to know:
The "connect" syntax for that driver.
The limitations of the driver. That is, any way that it differs from how VCI is supposed to work.
Explanations of things that might be surprising or unexpected when dealing with that particular version-control system.
Any extensions that that driver has implemented.
Repositories and Projects
A server that contains your version-controlled files is considered a "repository", and is represented by VCI::Abstract::Repository.
An actual set of code that you could check out of the repository is considered a "project", and is represented by VCI::Abstract::Project.
Almost all information that VCI gives is in relation to the project. For example, file paths are relative to the base directory of the project, not the base directory of the entire repository.
For information on how to get a Project object from a Repository, see VCI::Abstract::Repository.
The Structure of VCI (VCI::Abstract vs. VCI::VCS)
The general interface of VCI classes is described in the VCI::Abstract modules, but the specific implementations for particular VCSes are in the VCI::VCS
namespace.
For example, the methods that you use on a File in your version-control system are described in VCI::Abstract::File, but the actual specific implementation for CVS is in VCI::Cvs::File
. VCI::Cvs::File
must implement all of the methods described in VCI::Abstract::File, but it also may implement extension methods whose names start with x_
.
If you are going to use isa
on objects to check their type, you should check that they are the abstract type, not the specific type. For example, to find out if an object is a File, you would do:
$obj->isa('VCI::Abstract::File')
VERSION NUMBERING SCHEME
VCI has three-number version numbers, like this:
MAJOR.API.MINOR
_DEVEL
Here's what each number means:
- MAJOR
-
As long as this number is
0
, major breaking changes may occur to the API all the time. When this becomes1
, the API is stable. For numbers greater than1
, it means we made a major breaking change to the API.For example, VCI 2.0.1 would have breaking changes for the user or for the drivers, compared to VCI 1.0.1. But VCI 0.1.1 and 0.2.1 could contain breaking changes between them, also, because the first number is still
0
. - API
-
VCI has various features, but the drivers may not implement all of these features. So, when we add new features that drivers must implement, the
API
number gets incremented.For example, VCI 0.0.1 doesn't have support for authenticating to repositories, but VCI 0.2.1 might support it.
Drivers will say which VCI API they support. Using a driver that doesn't support the current VCI API will throw a warning if "debug" mode is on. Using a driver that supports an API later than the current VCI will throw an error.
- MINOR
-
This indicates a bug-fix release, with the API staying the same.
This will always be
1
or higher unless this is a development release, in which case it will be0
. - DEVEL
-
If this is an unstable development release, this number will be included. In this case, the
MINOR
number should almost always be0
.
CLASS METHODS
Constructors
connect
-
- Description
-
Returns a VCI::Abstract::Repository object based on your parameters. This is how you "start" using VCI.
Note that you cannot currently connect to repositories that require authentication, as VCI has no way of dealing with usernames or passwords. So you must connect to repositories that don't require authentication, or to which you have already authenticated. Future versions of VCI will support authentication.
- Parameters
-
repo
(Required)-
This is a string representing the repository you want to connect to, in the exact same format that you'd pass to the command-line interface to your VCS. For example, for CVS this would be the contents of
CVSROOT
.The documentation of individual drivers will explain what the format required for this field is.
Taint Mode: VCI will throw an error if this is tainted, because drivers use this string to do various operations (such as filesystem operations) that could be unsafe with untrusted data. If VCI didn't throw the error, you'd instead get some weird error from some internal part of VCI or one of the modules it uses, so it's better to just throw it right here.
type
(Required)-
What VCI driver you want to use. For example, to use CVS (VCI::VCS::Cvs) you'd say
Cvs
for this parameter. It is case-sensitive, and must be the name of an installed module in theVCI::VCS
namespace. debug
-
If you'd like VCI to print out a lot of information about what it's doing to
STDERR
, set this to1
. Different drivers will print out different information.Some drivers will print out more information if you set
debug
to higher values than1
.(Note: This is an IntBool.)
missing_requirements
-
Some drivers have requirements beyond just Perl modules, in order to work. Calling this method will tell you if those requirements are installed. You would call this method like:
use VCI::VCS::Cvs; my @need = VCI::VCS::Cvs->missing_requirements;
Returns an array (not an arrayref) of strings representing items that still need to be installed in order for this driver to function. If the array is empty, then all non-Perl requirements for this driver are already installed and available.
new
-
This has the same parameters as "connect", but actually returns a
VCI
object, not a VCI::Abstract::Repository.You'll generally want use "connect" instead of this.
Other
api_version
-
This is for drivers, to indicate what API version they implement.
Returns a hashref with two items:
major
- The major version number of the VCI API that this driver implements.api
- The api version number of the VCI API that this driver implements.For more information about what these numbers mean, see "VERSION NUMBERING SCHEME".
METHODS
Accessors
All of the fields that "connect" takes can also be accessed with methods named after them. In addition to the fields that you pass in to new, there are other accessors:
repository
-
Returns the VCI::Abstract::Repository that this VCI is connected to. Generally you don't want to use this, and you just want to use "connect".
HOW TO GET VCI
VCI is available on CPAN, which is the recommended way to get it: http://search.cpan.org/dist/VCI/
VCI is also available from its source repository. You can get the latest development version by doing:
bzr co http://bzr.everythingsolved.com/vci/trunk
Note that if you check out code from the trunk repository, it may be unstable or completely broken.
You can get the latest stable version by doing:
bzr co http://bzr.everythingsolved.com/vci/stable
You have to do perl Makefile.PL
and make manifest
on any checked-out code before you can install it.
PERFORMANCE
VCI strives to perform well. It will never perform faster than the VCS being used, however. Also, on very large projects (tens of thousands of files or tens of thousands of commits) some operations may be slow (such as asking for the History of an entire Project). However, for most uses and for the majority of projects, VCI should be fast enough.
Using local repositories is always faster than using remote repositories, usually by orders of magnitude.
VCI uses Moose extensively, so installing the latest version of Moose often helps improve the performance of VCI.
If the performance of VCI is too slow for your project, please let the author know using one of the mechanisms described in "SUPPORT". Without knowing exactly what sort of things are slow in real-world use, it's impossible to know what to optimize.
SUPPORT
The author of VCI is available via IRC, on irc.mozilla.org, in #mozwebtools. His IRC name is mkanat
.
Otherwise, the best way to get support for VCI is just to email the author at mkanat@cpan.org
.
VCI also has a home page at:
http://vci.everythingsolved.com/
And there is a blog with updates about VCI at:
http://avatraxiom.livejournal.com/tag/vci
USING VCI IN TAINT MODE
VCI strives to work properly and safely under taint mode. Unless specified otherwise in their POD, all VCS drivers work correctly under taint mode.
Various methods check their arguments for being tainted and throw an error if they are. Methods that do this have a note about Taint Mode in their documentation.
GENERAL NOTES FOR VCI::VCS IMPLEMENTORS
This is information for people who want to hack on the internals of VCI or implement a driver for their VCS.
Constructors
VCI uses Moose, so all constructors for all objects are called new
(although for VCI itself you'll want to use "connect"), and they all take named parameters as a hash (not a hashref). Generally users don't call constructors--we only call constructors internally.
The POD is an API
If the POD of the VCI::Abstract
modules says something, that is an API for VCI. Unless the POD specifically says you can change the behavior of a method, you must not deviate from how the POD says the methods and accessors work.
You may add new required
attributes to the constructors of various modules, but you must not add required
attributes to methods other than what is already specified in the POD for that method.
Extending VCI
VCI provides a base set of functions that are common to all Version-Control Systems, but if your VCS can do special things, feel free to add extension methods.
So that your methods don't conflict with VCI methods, their names should start with x_
(or _x_
for private methods). VCI won't enforce that, but if you don't do it, your module could seriously break in the future if VCI implements a method with the same name as yours.
VCI promises not to have any abstract methods or accesors that start with x_
or _x_
.
The Design Goals of VCI
In order of priority, the goals of VCI are:
Correctness
Ease of Driver Implementation
To implement as many VCS features as possible, not to only implement the common denominator of all VCSes.
Speed Efficiency
Memory Efficiency is a fourth consideration to be taken into account when writing drivers, but isn't considered as important as the above items.
Correctness
This means that drivers (and VCI) should do exactly what the user asks, without any surprises or side-effects, and should conform fully to all required elements of the API.
If you have doubts about what is "correct", ask yourself the question, "What would be most logical for a web application that views and interacts with a repository?" That is the function that VCI was originally designed for.
Ease of Driver Implementation
VCI is designed to make life easy for implementors. The only things that you must implement are:
_build_projects
in VCI::Abstract::Repository_build_history
in VCI::Abstract::Project_build_contents
in VCI::Abstract::Directory_build_revision
for VCI::Abstract::Committable objects (File and Directory), for objects that have no revision specified (meaning this is the "HEAD" revision)._build_time
for VCI::Abstract::Committable objects that have a revision but no time specified._build_as_diff
in VCI::Abstract::Commit_build_content
in VCI::Abstract::File
That's basically the minimum you have to implement. The more you implement, the faster your VCI driver will be. But it will still be fully correct (if sometimes slow) with only the above implemented.
Many Features, Not the Common Denominator of Features
Many abstractions limit you to the common denominator of all the things they abstract. That is, we could say, "You can only do X with VCI if all VCSes can do X." But that's not the goal of VCI.
Instead, we say, "VCI allows you to do X. If the VCS can't do X, VCI will provide some reasonable default instead."
For example, not all VCSes track if a file is executable. But we provide "is_executable" in VCI::VCS::File, and it behaves sensibly when the VCS doesn't track that information.
Efficiency
In general, VCI strives to be efficient in terms of speed. Working with a version-control system can often be a slow experience, and we don't want to make that any worse than it already is.
This means that individual methods should do the least work possible to return the information that the user needs, and store it internally for later use.
For example, a file in a version control system has a first revision . If there's a fast way to just get the first revision, you should do that.
But if we've already read the whole history of a file, that has information about the first revision in it, so we should just be able to reference the history we already retrieved, instead of asking the version-control system for the first revision all over again.
Order of Implementation
This is just some tips to make your life easier if you're going to implement a driver for your version-control system.
First, you want to implement a method of connecting to your VCS, which means implementing VCI. Then VCI::Abstract::Repository, and then VCI::Abstract::Project.
After that you're probably going to want to implement VCI::Abstract::File and VCI::Abstract::Directory.
Then you can implement VCI::Abstract::History, and now that you have everything, you can implement VCI::Abstract::Commit.
NOTES FOR IMPLEMENTORS OF VCI.pm
In general, you shouldn't override "connect". Also, using before
on "connect" probably also isn't a good idea. You could use after
, but it mostly just makes sense to implement "_build_repository" and leave it at that.
If you do override connect, you must call this connect
at some point in your connect
.
You must not add new required
attributes to connect
.
Optional Methods To Implement
_build_repository
-
Returns the VCI::Abstract::Repository object. (This is basically what "connect" returns, so this does the "heavy_lifting" for "connect".)
SEE ALSO
Drivers: VCI::VCS::Svn, VCI::VCS::Bzr, VCI::VCS::Hg, VCI::VCS::Git, and VCI::VCS::Cvs
TODO
Eventually the drivers may be split into their own packages.
Need user
and pass
support for "connect".
Come up with a meaningful "branch" abstraction.
Commits need to understand parent
and children
, for VCSes like Hg and Git that don't necessarily have a linear series of commits.
Commits need to have a subcommits
accessor that gives minor commits that are part of this larger commit. (For example, "merge commits" in bzr or git.)
"moved" in VCI::Abstract::Commit should be a hashref that points to objects, not to strings.
BUGS
All complex software has bugs, and VCI is probably no exception. However, VCI's test suite has nearly 100% code coverage, and VCI currently passes all tests.
Some drivers do have limitations, see their documentation for details.
AUTHOR
Max Kanat-Alexander <mkanat@cpan.org>
COPYRIGHT AND LICENSE
Copyright 2007-2010 by Everything Solved, Inc.
http://www.everythingsolved.com
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.