File Coverage

blib/lib/VCI.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             package VCI;
2 5     5   236159 use 5.008;
  5         18  
  5         412  
3 5     5   9825 use Moose;
  0            
  0            
4             our $VERSION = '0.7.1';
5              
6             use Class::MOP;
7             use VCI::Util;
8              
9             use constant CLASS_BASE => 'VCI::VCS::';
10              
11             use constant revisions_are_universal => 1;
12             use constant revisions_are_global => 1;
13              
14             # Will also need a write_repo in the future, if we add commit support,
15             # for things like Hg that read from hgweb but have to write through the
16             # actual hg client.
17              
18             has 'repo' => (is => 'ro', isa => 'Str', required => 1);
19             has 'type' => (is => 'ro', isa => 'Str', required => 1);
20             has 'debug' => (is => 'ro', isa => 'VCI::Type::IntBool', coerce => 1,
21             default => sub { 0 });
22              
23             has 'repository' => (is => 'ro', isa => 'VCI::Abstract::Repository',
24             lazy_build => 1);
25              
26             has 'vci_class' => (is => 'ro', isa => 'ClassName', lazy_build => 1);
27             has 'commit_class' => (is => 'ro', isa => 'ClassName', lazy_build => 1);
28             has 'diff_class' => (is => 'ro', isa => 'ClassName', lazy_build => 1);
29             has 'directory_class' => (is => 'ro', isa => 'ClassName', lazy_build => 1);
30             has 'file_class' => (is => 'ro', isa => 'ClassName', lazy_build => 1);
31             has 'history_class' => (is => 'ro', isa => 'ClassName', lazy_build => 1);
32             has 'project_class' => (is => 'ro', isa => 'ClassName', lazy_build => 1);
33             has 'repository_class' => (is => 'ro', isa => 'ClassName', lazy_build => 1);
34              
35             sub connect {
36             my $class = shift;
37             my %params = @_;
38             my $type = $params{type};
39             my $vci_class = $params{vci_class} || CLASS_BASE . $type;
40             eval { Class::MOP::load_class($vci_class) }
41             || confess("$type is not a valid VCI driver: $@");
42             my $vci = $vci_class->new(@_);
43             $vci->_check_api();
44             my $repo = $vci->repository;
45             return $repo;
46             }
47              
48             sub missing_requirements { () }
49              
50             sub api_version {
51             my $invocant = shift;
52             my $version = $invocant->VERSION;
53             $version =~ /^(\d+)\.(\d+)/;
54             return { major => int($1), api => int($2) };
55             }
56              
57             # Note that this default build_repository doesn't do anything about
58             # authentication.
59             sub _build_repository {
60             my $self = shift;
61             return $self->repository_class->new(root => $self->repo, vci => $self);
62             }
63              
64             sub _check_api {
65             my $self = shift;
66             my $package = blessed $self;
67             my $driver = $self->api_version;
68             my $vci = __PACKAGE__->api_version;
69             my $driver_ver = "$driver->{major}.$driver->{api}";
70             my $vci_ver = "$vci->{major}.$vci->{api}";
71             if ($driver->{major} > $vci->{major}
72             || ($driver->{major} == $vci->{major} && $driver->{api} > $vci->{api}))
73             {
74             confess("This driver implements VCI $driver_ver but you only have"
75             . " VCI $vci_ver installed. You probably need to update VCI.");
76             }
77            
78             if ($driver->{major} < $vci->{major}) {
79             confess("VCI has a major version of $vci->{major} but your $package"
80             . " only implements VCI $driver->{major}. You probably need"
81             . " to upgrade $package.");
82             }
83            
84             if ($driver->{major} == $vci->{major} && $driver->{api} < $vci->{api}) {
85             warn "$package only implements VCI $driver_ver but you have VCI"
86             . " $vci_ver installed. You probably need to upgrade $package."
87             if $self->debug;
88             }
89             }
90              
91             sub _build_vci_class { CLASS_BASE . shift->type }
92             sub _build_commit_class { return shift->_class('Commit') }
93             sub _build_diff_class { return shift->_class('Diff') }
94             sub _build_directory_class { return shift->_class('Directory') }
95             sub _build_file_class { return shift->_class('File') }
96             sub _build_history_class { return shift->_class('History') }
97             sub _build_project_class { return shift->_class('Project') }
98             sub _build_repository_class { return shift->_class('Repository') }
99              
100             sub _class {
101             my ($self, $class) = @_;
102             my $module = $self->vci_class . '::' . $class;
103             Class::MOP::load_class($module);
104             return $module;
105             }
106              
107             __PACKAGE__->meta->make_immutable;
108              
109             1;
110              
111             __END__
112              
113             =head1 NAME
114              
115             VCI - A library for interacting with version-control systems.
116              
117             =head1 SYNOPSIS
118              
119             my $repository = VCI->connect(type => $type, repo => $repo);
120              
121             =head1 DESCRIPTION
122              
123             This is VCI, the generic Version Control Interface. The goal of VCI is to
124             create a common API that can interface with all version control systems
125             (which are sometimes also called Software Configuration Management or "SCM"
126             systems).
127              
128             The VCI home page is at L<http://vci.everythingsolved.com/>.
129              
130             =head2 New to VCI?
131              
132             If you aren't sure where to start, you want to first look at L</connect>
133             and then at L<VCI::Abstract::Repository>.
134              
135             Basically, when using VCI, you L<connect|/connect> to
136             a L<Repository|VCI::Abstract::Repository>,
137             L<get|VCI::Abstract::Repository/get_project> a
138             L<Project|VCI::Abstract::Project> from that Repository,
139             and then L<call methods on that Project|VCI::Abstract::Project/METHODS>.
140              
141             The general interface of VCI is described in the various VCI::Abstract
142             modules, and those contain the documentation you should read in order to
143             find out how VCI works.
144              
145             "Drivers" for different VCSes are in modules whose names start with
146             C<VCI::VCS>. For example, L<VCI::VCS::Cvs> is the "CVS support" for
147             VCI. You only have to read L<VCI::VCS::Cvs> or the manual of any other
148             driver if you want to know:
149              
150             =over
151              
152             =item *
153              
154             The L</connect> syntax for that driver.
155              
156             =item *
157              
158             The limitations of the driver. That is, any way that it differs
159             from how VCI is supposed to work.
160              
161             =item *
162              
163             Explanations of things that might be surprising or unexpected when
164             dealing with that particular version-control system.
165              
166             =item *
167              
168             Any extensions that that driver has implemented.
169              
170             =back
171              
172             =head2 Repositories and Projects
173              
174             A server that contains your version-controlled files is considered a
175             "repository", and is represented by L<VCI::Abstract::Repository>.
176              
177             An actual set of code that you could check out of the repository is
178             considered a "project", and is represented by L<VCI::Abstract::Project>.
179              
180             Almost all information that VCI gives is in relation to the I<project>.
181             For example, file paths are relative to the base directory of the project,
182             not the base directory of the entire repository.
183              
184             For information on how to get a Project object from a Repository, see
185             L<VCI::Abstract::Repository>.
186              
187             =head2 The Structure of VCI (VCI::Abstract vs. VCI::VCS)
188              
189             The general interface of VCI classes is described in the VCI::Abstract
190             modules, but the specific implementations for particular VCSes are in the
191             C<VCI::VCS> namespace.
192              
193             For example, the methods that you use on a File in your version-control
194             system are described in L<VCI::Abstract::File>, but the actual specific
195             implementation for CVS is in C<VCI::Cvs::File>. C<VCI::Cvs::File>
196             B<must> implement all of the methods described in L<VCI::Abstract::File>,
197             but it also may implement extension methods whose names start with C<x_>.
198              
199             If you are going to use C<isa> on objects to check their type, you should
200             check that they are the abstract type, not the specific type. For example,
201             to find out if an object is a File, you would do:
202              
203             $obj->isa('VCI::Abstract::File')
204              
205             =head1 VERSION NUMBERING SCHEME
206              
207             VCI has three-number version numbers, like this:
208              
209             C<MAJOR.API.MINOR>_C<DEVEL>
210              
211             Here's what each number means:
212              
213             =over
214              
215             =item B<MAJOR>
216              
217             As long as this number is C<0>, major breaking changes may
218             occur to the API all the time. When this becomes C<1>, the API is
219             stable. For numbers greater than C<1>, it means we made a major breaking
220             change to the API.
221              
222             For example, VCI 2.0.1 would have breaking changes for the user or for the
223             drivers, compared to VCI 1.0.1. But VCI 0.1.1 and 0.2.1 could contain
224             breaking changes between them, also, because the first number is still C<0>.
225              
226             =item B<API>
227              
228             VCI has various features, but the drivers may not implement all of these
229             features. So, when we add new features that drivers must implement, the
230             C<API> number gets incremented.
231              
232             For example, VCI 0.0.1 doesn't have support for authenticating to repositories,
233             but VCI 0.2.1 might support it.
234              
235             Drivers will say which VCI API they support. Using a driver that doesn't
236             support the current VCI API will throw a warning if L</debug> mode is on.
237             Using a driver that supports an API I<later> than the current VCI will
238             throw an error.
239              
240             =item B<MINOR>
241              
242             This indicates a bug-fix release, with the API staying the same.
243              
244             This will always be C<1> or higher unless this is a development release,
245             in which case it will be C<0>.
246              
247             =item B<DEVEL>
248              
249             If this is an unstable development release, this number will be included.
250             In this case, the C<MINOR> number should almost always be C<0>.
251              
252             =back
253              
254             =head1 CLASS METHODS
255              
256             =head2 Constructors
257              
258             =over
259              
260             =item C<connect>
261              
262             =over
263              
264             =item B<Description>
265              
266             Returns a L<VCI::Abstract::Repository> object based on your parameters. This is
267             how you "start" using VCI.
268              
269             Note that you cannot currently connect to repositories that require
270             authentication, as VCI has no way of dealing with usernames or
271             passwords. So you must connect to repositories that don't require
272             authentication, or to which you have already authenticated. Future versions
273             of VCI will support authentication.
274              
275             =item B<Parameters>
276              
277             =over
278              
279             =item C<repo> B<(Required)>
280              
281             This is a string representing the repository you want to connect to, in
282             the exact same format that you'd pass to the command-line interface to your
283             VCS. For example, for CVS this would be the contents of C<CVSROOT>.
284              
285             The documentation of individual drivers will explain what the format
286             required for this field is.
287              
288             B<Taint Mode>: VCI will throw an error if this is tainted, because drivers use
289             this string to do various operations (such as filesystem operations) that
290             could be unsafe with untrusted data. If VCI didn't throw the error, you'd
291             instead get some weird error from some internal part of VCI or one of the
292             modules it uses, so it's better to just throw it right here.
293              
294             =item C<type> B<(Required)>
295              
296             What VCI driver you want to use. For example, to use CVS (L<VCI::VCS::Cvs>)
297             you'd say C<Cvs> for this parameter. It is case-sensitive, and must be the
298             name of an installed module in the C<VCI::VCS> namespace.
299              
300             =item C<debug>
301              
302             If you'd like VCI to print out a lot of information about what it's doing
303             to C<STDERR>, set this to C<1>. Different drivers will print out different
304             information.
305              
306             Some drivers will print out more information if you set C<debug> to higher
307             values than C<1>.
308              
309             (Note: This is an L<IntBool|VCI::Util/VCI::Type::IntBool>.)
310              
311             =back
312              
313             =back
314              
315             =item C<missing_requirements>
316              
317             Some drivers have requirements beyond just Perl modules, in order to work.
318             Calling this method will tell you if those requirements are installed.
319             You would call this method like:
320              
321             use VCI::VCS::Cvs;
322             my @need = VCI::VCS::Cvs->missing_requirements;
323              
324             Returns an array (not an arrayref) of strings representing items that still
325             need to be installed in order for this driver to function. If the array is
326             empty, then all non-Perl requirements for this driver are already installed
327             and available.
328              
329             =item C<new>
330              
331             This has the same parameters as L</connect>, but actually returns a
332             C<VCI> object, not a L<VCI::Abstract::Repository>.
333              
334             You'll generally want use L</connect> instead of this.
335              
336             =back
337              
338             =head2 VCS Information
339              
340             These represent information about a particular version-control system.
341             You can call these on a class, like
342             C<< VCI::VCS::Cvs->revisions_are_universal >>, or if you have a
343             L<VCI::Abstract::Repository> object, you can call these methods using the
344             C<vci> accessor, like: C<< $repository->vci->revisions_are_universal >>.
345              
346             =over
347              
348             =item C<revisions_are_global>
349              
350             A boolean. If true, then the "revision" accessor on a L<VCI::Abstract::Commit>
351             for this VCS is globally unique within an entire Repository, not just
352             for this Project. (For example, Subversion's commit ids are globally unique
353             within a repository.)
354              
355             If false, then different Projects could have overlapping revision identifiers.
356              
357             =item C<revisions_are_universal>
358              
359             A boolean. If true, then the "revision" accessor on a L<VCI::Abstract::Commit>
360             returns a value that will be universally unique across all repositories in
361             the world. For example, Git, Mercurial, and Bazaar have universally unique
362             revision identifiers--no two revisions in existence are likely to have
363             duplicate revision ids unless they are actually the same revision.
364              
365             =back
366              
367             =head2 Other
368              
369             =over
370              
371             =item C<api_version>
372              
373             This is for drivers, to indicate what API version they implement.
374              
375             Returns a hashref with two items:
376              
377             C<major> - The L<major|/MAJOR> version number of the VCI API that this driver
378             implements.
379              
380             C<api> - The L<api|/API> version number of the VCI API that this driver
381             implements.
382              
383             For more information about what these numbers mean, see
384             L</VERSION NUMBERING SCHEME>.
385              
386             =back
387              
388             =head1 METHODS
389              
390             =head2 Accessors
391              
392             All of the fields that L</connect> takes can also be accessed with methods
393             named after them. In addition to the fields that you pass in to new, there
394             are other accessors:
395              
396             =over
397              
398             =item C<repository>
399              
400             Returns the L<VCI::Abstract::Repository> that this VCI is connected to.
401             Generally you don't want to use this, and you just want to use L</connect>.
402              
403             =back
404              
405             =head1 HOW TO GET VCI
406              
407             VCI is available on CPAN, which is the recommended way to get it:
408             L<http://search.cpan.org/dist/VCI/>
409              
410             VCI is also available from its source repository. You can get the latest
411             development version by doing:
412              
413             bzr co http://bzr.everythingsolved.com/vci/trunk
414              
415             Note that if you check out code from the trunk repository, it may be unstable
416             or completely broken.
417              
418             You can get the latest stable version by doing:
419              
420             bzr co http://bzr.everythingsolved.com/vci/stable
421              
422             You have to do C<perl Makefile.PL> and C<make manifest> on any checked-out
423             code before you can install it.
424              
425             =head1 PERFORMANCE
426              
427             VCI strives to perform well. It will never perform faster than the VCS being
428             used, however. Also, on very large projects (tens of thousands of
429             files or tens of thousands of commits) some operations may be slow
430             (such as asking for the History of an entire Project). However, for most
431             uses and for the majority of projects, VCI should be fast enough.
432              
433             Using local repositories is always faster than using remote repositories,
434             usually by orders of magnitude.
435              
436             VCI uses L<Moose> extensively, so installing the latest version of
437             L<Moose> often helps improve the performance of VCI.
438              
439             If the performance of VCI is too slow for your project, please let the
440             author know using one of the mechanisms described in L</SUPPORT>. Without
441             knowing exactly what sort of things are slow in real-world use, it's
442             impossible to know what to optimize.
443              
444             =head1 SUPPORT
445              
446             The author of VCI is available via IRC, on irc.mozilla.org, in
447             L<#mozwebtools|http://landfill.bugzilla.org/irc/>. His IRC name is
448             C<mkanat>.
449              
450             Otherwise, the best way to get support for VCI is just to email
451             the author at C<mkanat@cpan.org>.
452              
453             VCI also has a home page at:
454              
455             L<http://vci.everythingsolved.com/>
456              
457             And there is a blog with updates about VCI at:
458              
459             L<http://avatraxiom.livejournal.com/tag/vci>
460              
461             =head1 USING VCI IN TAINT MODE
462              
463             VCI strives to work properly and safely under taint mode. Unless specified
464             otherwise in their POD, all VCS drivers work correctly under taint mode.
465              
466             Various methods check their arguments for being tainted and throw an
467             error if they are. Methods that do this have a note about B<Taint Mode>
468             in their documentation.
469              
470             =head1 GENERAL NOTES FOR VCI::VCS IMPLEMENTORS
471              
472             This is information for people who want to hack on the internals of VCI
473             or implement a driver for their VCS.
474              
475             =head2 Constructors
476              
477             VCI uses L<Moose>, so all constructors for all objects are called
478             C<new> (although for L<VCI> itself you'll want to use L</connect>),
479             and they all take named parameters as a hash (not a hashref). Generally
480             users don't call constructors--we only call constructors internally.
481              
482             =head2 The POD is an API
483              
484             If the POD of the C<VCI::Abstract> modules says something,
485             B<that is an API for VCI>. Unless the POD specifically I<says> you can
486             change the behavior of a method, you B<must> not deviate from how the
487             POD says the methods and accessors work.
488              
489             You may add new C<required> attributes to the constructors of various
490             modules, but you must not add C<required> attributes to methods other
491             than what is already specified in the POD for that method.
492              
493             =head2 Extending VCI
494              
495             VCI provides a base set of functions that are common to all Version-Control
496             Systems, but if your VCS can do special things, feel free to add extension
497             methods.
498              
499             So that your methods don't conflict with VCI methods, their names should start
500             with C<x_> (or C<_x_> for private methods). VCI won't I<enforce> that, but
501             if you don't do it, your module could seriously break in the future if VCI
502             implements a method with the same name as yours.
503              
504             VCI promises not to have any abstract methods or accesors that start
505             with C<x_> or C<_x_>.
506              
507             =head2 The Design Goals of VCI
508              
509             In order of priority, the goals of VCI are:
510              
511             =over
512              
513             =item 1
514              
515             Correctness
516              
517             =item 2
518              
519             Ease of Driver Implementation
520              
521             =item 3
522              
523             To implement as many VCS features as possible, not to only implement the
524             common denominator of all VCSes.
525              
526             =item 4
527              
528             Speed Efficiency
529              
530             =back
531              
532             Memory Efficiency is a fourth consideration to be taken into account when
533             writing drivers, but isn't considered as important as the above items.
534              
535              
536             =head3 Correctness
537              
538             This means that drivers (and VCI) should do exactly what the user asks,
539             without any surprises or side-effects, and should conform fully to all
540             required elements of the API.
541              
542             If you have doubts about what is "correct", ask yourself the question,
543             "What would be most logical for a web application that views and interacts
544             with a repository?" That is the function that VCI was originally designed
545             for.
546              
547             =head3 Ease of Driver Implementation
548              
549             VCI is designed to make life easy for implementors. The only things
550             that you B<must> implement are:
551              
552             =over
553              
554             =item C<_build_projects> in L<VCI::Abstract::Repository>
555              
556             =item C<_build_history> in L<VCI::Abstract::Project>
557              
558             =item C<_build_contents> in L<VCI::Abstract::Directory>
559              
560             =item C<_build_revision> for L<VCI::Abstract::Committable> objects
561             (File and Directory), for objects that have no revision specified (meaning
562             this is the "HEAD" revision).
563              
564             =item C<_build_time> for L<VCI::Abstract::Committable> objects that have
565             a revision but no time specified.
566              
567             =item C<_build_as_diff> in L<VCI::Abstract::Commit>
568              
569             =item C<_build_content> in L<VCI::Abstract::File>
570              
571             =back
572              
573             That's basically the I<minimum> you have to implement. The more you implement,
574             the I<faster> your VCI driver will be. But it will still be fully I<correct>
575             (if sometimes slow) with only the above implemented.
576              
577             =head3 Many Features, Not the Common Denominator of Features
578              
579             Many abstractions limit you to the common denominator of all the things
580             they abstract. That is, we could say, "You can only do X with VCI if
581             I<all VCSes> can do X." But that's not the goal of VCI.
582              
583             Instead, we say, "VCI allows you to do X. If the VCS can't do X, VCI will
584             provide some reasonable default instead."
585              
586             For example, not all VCSes track if a file is executable. But we provide
587             L<VCI::VCS::File/is_executable>, and it behaves sensibly when the VCS
588             doesn't track that information.
589              
590             =head3 Efficiency
591              
592             In general, VCI strives to be efficient in terms of I<speed>. Working with
593             a version-control system can often be a slow experience, and we don't
594             want to make that any worse than it already is.
595              
596             This means that individual methods should do the least work possible to
597             return the information that the user needs, and store it internally for later
598             use.
599              
600             For example, a L<file|VCI::Abstract::File> in a version control system
601             has a L<first revision|VCI::Abstract::Committable/first_revision> . If
602             there's a fast way to just get the first revision, you should do that.
603              
604             But if we've already read the whole
605             L<history|VCI::Abstract::Committable/history> of a file, that has information
606             about the first revision in it, so we should just be able to reference the
607             history we already retrieved, instead of asking the version-control system
608             for the first revision all over again.
609              
610             =head2 Order of Implementation
611              
612             This is just some tips to make your life easier if you're going to implement
613             a driver for your version-control system.
614              
615             First, you want to implement a method of connecting to your VCS, which
616             means implementing L<VCI>. Then L<VCI::Abstract::Repository>, and
617             then L<VCI::Abstract::Project>.
618              
619             After that you're probably going to want to implement L<VCI::Abstract::File>
620             and L<VCI::Abstract::Directory>.
621              
622             Then you can implement L<VCI::Abstract::History>, and now that you
623             have everything, you can implement L<VCI::Abstract::Commit>.
624              
625             =head1 NOTES FOR IMPLEMENTORS OF VCI.pm
626              
627             In general, you shouldn't override L</connect>. Also, using C<before>
628             on L</connect> probably also isn't a good idea. You could use C<after>,
629             but it mostly just makes sense to implement L</_build_repository> and leave
630             it at that.
631              
632             If you I<do> override connect, you B<must> call I<this> C<connect> at some
633             point in your C<connect>.
634              
635             You B<must> not add new C<required> attributes to C<connect>.
636              
637             =head2 Optional Methods To Implement
638              
639             =over
640              
641             =item C<_build_repository>
642              
643             Returns the L<VCI::Abstract::Repository> object. (This is basically
644             what L</connect> returns, so this does the "heavy_lifting" for
645             L</connect>.)
646              
647             =back
648              
649             =head1 SEE ALSO
650              
651             L<VCI::Abstract::Repository>
652              
653             B<Drivers>: L<VCI::VCS::Svn>, L<VCI::VCS::Bzr>, L<VCI::VCS::Hg>,
654             L<VCI::VCS::Git>, and L<VCI::VCS::Cvs>
655              
656             =head1 TODO
657              
658             Eventually the drivers may be split into their own packages.
659              
660             Need C<user> and C<pass> support for L</connect>.
661              
662             Come up with a meaningful "branch" abstraction.
663              
664             Commits need to understand C<parent> and C<children>, for VCSes like
665             Hg and Git that don't necessarily have a linear series of commits.
666              
667             Commits need to have a C<subcommits> accessor that gives minor
668             commits that are part of this larger commit. (For example, "merge commits"
669             in bzr or git.)
670              
671             L<VCI::Abstract::Commit/moved> should be a hashref that points to objects,
672             not to strings.
673              
674             =head1 BUGS
675              
676             All complex software has bugs, and VCI is probably no exception.
677             However, VCI's test suite has nearly 100% code coverage, and VCI currently
678             passes all tests.
679              
680             Some drivers do have limitations, see their documentation for details.
681              
682             =head1 AUTHOR
683              
684             Max Kanat-Alexander <mkanat@cpan.org>
685              
686             =head1 COPYRIGHT AND LICENSE
687              
688             Copyright 2007-2010 by Everything Solved, Inc.
689              
690             L<http://www.everythingsolved.com>
691              
692             This library is free software; you can redistribute it and/or modify it under
693             the same terms as Perl itself.