The stupid question is the question not asked | |
PerlMonks |
RFC: Automating subversion with perlby ELISHEVA (Prior) |
on Jan 22, 2009 at 20:57 UTC ( [id://738308]=perlmeditation: print w/replies, xml ) | Need Help?? |
Recently I wrote up an overview of the various options available for automating subversion within Perl. I'm rather new to this topic (and to posting things about Perl), so I'd very much appreciate feedback on what I've written. Specifically,
Automating SVN with PerlThere are two ways to automate SVN with Perl:
Calling system(...) is the easier solution, but it is not portable across operating systems and it limits you to the functionality already built into the svn client command. This is not the full set of functionality provided by subversion. Finally, the subversion team has promised full backward compatibility for each minor version of the subversion API. It makes no such promises for the command line interface. If none of these are issues for you, you can stop reading now: the system(...) command is your best and fastest option.
The SVN API gives you a lot of flexibility, especially if you need to work with lots of files at once. Even if all you need is the standard svn client commands, you still may want to think twice about using system(...). If portability is important to you, you will need to wrap the calls to system(...) in code that detects and customizes the call for the current operating system.
The system(...) command requires a command name as its first parameter. Operating systems vary in the way they name and find commands. You will need to include operating system specific code to insure that the command can be found. You will also need to choose the name of the command in an operating system specific manner. On MS operating systems the subversion client command is svn.exe. On *nix it is just plain svn.
Finding your way around Alien::SVN (also known as SVN::Core) for the first time can be intimidating. This article provides a basic overview that should make the Perl API for subversion a bit more approachable. Overview of Perl's Svn APIAlien::SVN is a very thin wrapper around the perl API. It is organized into classes that reflect the major subsystems inside the C/C++ version of the API. There are six such classes:
The first two of these classes, SVN::Client and SVN::Repos are API analogs to the command line binaries: svn and svnadmin. SVN::Ra can be used to provide server side support for incoming requests for remote repository access. The remaining classes define objects that are used either as parameters or return values to those two classes.
For an overview of the subsystems of the SVN API, see the subversion book. The editions for subversion 1.3 and up describes the subsystems in chapter 8, titled “Embedding Subversion”. Versions for earlier subversion releases (1.0 – 1.2) title this same chapter “Developer Information”. Classes representing API subsystemsClient side subsystemsThere are two subsystems that are used exclusively by subversion repository clients and perl modules that support them – Svn::Client and Svn::Wc. SVN::Client provides access to commands to add, view, remove, and modify the content of a subversion repository. It is the API analog to the command line SVN client, svn (*nix) or svn.exe on Microsoft based operating systems.
The functions on the SVN::Client object can be classed into three groups:
The behavior of a SVN::Client object is customized primarily through call back functions. Most of these can be set via the SVN::Client object's constructor or one of its setter methods:
SVN::Wc - defines objects and enums used to pass information to and from call back functions:
Server side subsystemsThe SVN::Repos, SVN::Ra and SVN::Fs subsystems are used exclusively by perl modules that support and customize local and remote repository access.
SVN::Repos – provides access to commands to create, open, and administer a repository. It is the API analog to the svnadmin command. Whereas SVN::Client operates on a specific revision or set of revisions, SVN::Repos commands operate on the repository as a whole. Repository manipulation commands include hook definition, access to node and commit editors, initialization and clean up of transactions, and dumping and loading of repository content and metadata.
SVN::Repos objects are only used to access a repository locally on the current machine. If you are developing tools to access the repository directly, you can create a repository object via one of two functions defined in the SVN::Repos package:
Both methods return an SVN::Repos object which can be used to manipulate and extract data from an open repository. For documentation of repository manipulation methods, see the file svn_repos.h in the C/C++ API documentation. Any method defined in that file is a method of an SVN::Repos object if it takes svn_repos_t as its first parameter.
If you are developing Perl tools to support the server side of remote access, you won't work with SVN::Repos directly. Instead you use an SVN::Ra object. This method provides access to the same commands but insures that the user and system requesting remote access has rights to do what it wants.
The code that creates an SVN::Ra object on the server side is usually part of a module that has been registered on the web-server as the handler for URI's that match a particular pattern or protocol. Inside this module, an instance of SVN::Ra is created. Its methods can be used to perform various standard and custom actions on the repository.
SVN::Ra provides an object representing the client and server sides of remote repository access. This obect combines data specific to a user requesting remote access and data specific to a repository with an implementation for a specific repository method.
SVN supports many kinds of remote access and new ones can be created by defining remote acess plug-ins. Remote access plugins provide support for specific remote access mechanisms. Recent versions of subversion, including the versions supported by Alien::SVN (1.4.6) have well developed support for remote access via the file system, Web-DAV/SSL, ssh, and a properietary svnserve protocol.
SVN::Fs provides an object representing the file system that backs a repository. SVN supports more than one kind of repository storage mechanism. Recent versions of subversion, including the versions supported by Alien::SVN support both Berkley DB or a FSFS backends.
Full access to the file system is only available using local access methods. The SVN::Repos::fs() function returns an instance of this object. No such method exists on SVN::Ra. SVN::Ra provides only indirect access to the file system. SVN::DeltaSVN::Delta defines objects and constants needed to create, view, and edit deltas.
You won't need to work with deltas unless you plan to write a customized commit command, a remote access method or some other command that studies and reports on how the repository and its files have changed over time. Deltas are used by three types of processes: processes that generate commit requests, processes that receive and apply commit requests, and processes that massage, import or export data stored in a repository.
Svn::Client generates deltas whenever a group of files is committed. It compares the most recently committed version of each file to the currently uncommitted version of each file. The delta is then sent onto the repository as the commit request. The methods used by this delta creation process are all functions defined within the SVN::Delta namespace. Full documentation can be found by looking at the source code for svn_delta.h
When an SVN::Ra object recieves a commit request, it extract a delta from it and applies the delta to the existing version, thus creating the new version. The functions used to apply the delta are also declared in svn_delta.h and documentation can be found by looking at the source code for svn_delta.h.
The subversion repository itself stores version history of each file as a set of deltas. By applying N deltas to revision X we get revision X + N. Consequently, deltas are also used when importing, viewing, or exporting the change history of a repository. They are also used to update working copies from the repository and by diff commands.
All of these commands work with deltas via a SVN::Delta::Editor object. Both SVN::Ra and SVN::Repos have methods that accept a customized instance of SVN::Delta::Editor and use it to scan the repository's set of deltas. Its behavior can be customized by overriding methods that define which deltas are interesting and what to do with them. Additional modules in Alien::SVNAlien::SVN provides three other modules in addition to the subsystem classes,:
Memory PoolsMost of the API functions accept a “pool” parameter. A pool is a large chunk of memory that can be allocated and deallocated as a single unit or broken up into small chunks. It is a convenient way to allocate tiny bits of data that need to be cleaned up as a group. As such, it is especially well suited to recursive algorithms which typically allocate lots of data for child nodes and then need to clean up all of those nodes as a group. Subversion has a lot of recursive programming and pools are especially suitable for its internal architecture. Pools are one of many data structures and resources that subversion has borrowed from the Apache Portable Runtime library – an OS independent library for performing various “system” like functions, including memory allocation and release. You can find more about how subversion uses pools by looking in the subversion book. For versions 1.3 and above, the relevant section in chapter 8 is titled “The Apache Portable Runtime Library”. For earlier subversion versions (1.0-1.2), memory pools are discussed in a section titled ”Programming with memory pools”. The subversion API perl binding provide access to pool objecgtvs via the SVN::Pool class. Exception handlingBy default, exceptions thrown by the Subversion API cause Alien::SVN to croak. To override this behavior with custom exception handling create a custom subclass of svn_error_t and assign it to the $SVN::Error::handler global variable. The SVN::Core module recommends that those interested in defining a custom error handler take a look at the implementation of SVN::Error::croak_on_error and SVN::Error::expanded_message. One should also look at the C/C++ API documentation of svn_error_t. Using the C/C++ APIThe documentation for the Perl SVN API is somewhat sketchy. For more detailed information about each of its modules, you might wish to look at the C/C++ API documentation, found here. The Perl documentation for Alien::SVN is sometimes sketchy, but it usually preserves the names of functions and constants used in the C/C++ API and notes the exceptions.
The following table summarizes the mapping betwen C/C++ API documentation and the subsystem modules:
A few especially important C/C++ APIs also have a perl oriented name: e.g. SVN::Delta::Editor is the perl name for svn_delta_editor in the C/C++ API. All of the other C/C++ API types, classes and variables use the same name in both the C/C++ API and in the perl bindings. For example, both the C/C++ API call the custom error handler class svn_error_t.
For more information, please see the documentation of the various files in the Alien::SVN distribution. Paths in SubversionSubversion functions get around portability problems by using relative and absolute URIs. Working copies of files and directories may be identified using either relative or absolute URIs. Relative URIs are always resolved relative to the current directory. Files and directories with a repository are identified using fully qualified URIs. In these URIs the protocol identifies the repository access method. The initial portion of the path identifies the repository. The remainder identifies a file or directory within the repository. These URIs are expected to use UTF8 encoded canonical form. All Uris are in canonical form using UTF8 encoding. To properly produce paths for subversion you can use the following Perl CPAN modules:
CPAN distributions using the Subversion APIOne of the best ways to comfortable with using an API is to look at applications that have already been written using that API. Looking at existing applications is also a good way to avoid reinventing the wheel. CPAN has about 40 subversion related distributions, 15 of which use Alien::SVN to work with a subversion repository:
CPAN distributions using Subversion binariesOccasionally there are times when the subversion libraries cannot be installed. For example, subversion and the web server might be using different versions of the Apache Portable Runtime Library. For this reason, some modules provide the option of using either the subversion binary or the subversion API. They include:
In addition, CPAN has several distributions using the subversion binaries exclusively:
Other CPAN subversion related toolsCPAN also provides a number of Subversion modules that neither use the API nor binaries. Most of these distributions fall into one of four categories:
Back to
Meditations
|
|