Better document and clean up the factory for collections of repos
[catagits/Gitalist.git] / lib / Gitalist / Model / CollectionOfRepos.pm
1 package Gitalist::Model::CollectionOfRepos;
2
3 use Moose;
4 use MooseX::Types::Moose qw/Maybe ArrayRef/;
5 use MooseX::Types::Common::String qw/NonEmptySimpleStr/;
6 use MooseX::Types::LoadableClass qw/ LoadableClass /;
7 use Moose::Util::TypeConstraints;
8 use Moose::Autobox;
9 use namespace::autoclean;
10
11 extends 'Catalyst::Model';
12
13 with 'Catalyst::Component::ApplicationAttribute';
14 with 'Catalyst::Component::InstancePerContext';
15
16 my $repo_dir_t = subtype NonEmptySimpleStr,
17     where { -d $_ },
18     message { 'Cannot find repository dir: "' . $_ . '", please set up gitalist.conf, or set GITALIST_REPO_DIR environment or pass the --repo_dir parameter when starting the application' };
19
20 my $arrayof_repos_dir_t = subtype ArrayRef[$repo_dir_t],
21     where { 1 },
22     message { 'Cannot find repository directories listed in config - these are invalid directories: ' . join(', ', $_->flatten) };
23
24 coerce $arrayof_repos_dir_t,
25     from NonEmptySimpleStr,
26     via { [ $_ ] };
27
28 has config_repo_dir => (
29     isa => NonEmptySimpleStr,
30     is => 'ro',
31     init_arg => 'repo_dir',
32     predicate => 'has_config_repo_dir',
33 );
34
35 has repo_dir => (
36     isa => $repo_dir_t,
37     is => 'ro',
38     lazy_build => 1
39 );
40
41 has repos => (
42     isa => $arrayof_repos_dir_t,
43     is => 'ro',
44     default => sub { [] },
45     traits => ['Array'],
46     handles => {
47         _repos_count => 'count',
48     },
49     coerce => 1,
50 );
51
52 has class => (
53     isa => LoadableClass,
54     is  => 'ro',
55     is => 'lazy',
56     builder => '_build_class',
57 );
58
59 sub _build_class {
60     my($self) = @_;
61
62     if($self->whitelist && -f $self->whitelist) {
63         return 'Gitalist::Git::CollectionOfRepositories::FromDirectory::WhiteList';
64     } elsif ($self->_repos_count && !$self->search_recursively) {
65         return 'Gitalist::Git::CollectionOfRepositories::FromListOfDirectories';
66     } elsif($self->search_recursively) {
67         return 'Gitalist::Git::CollectionOfRepositories::FromDirectoryRecursive';
68     }
69
70     return 'Gitalist::Git::CollectionOfRepositories::FromDirectory';
71 }
72
73 has args => (
74     isa     => 'HashRef',
75     is      => 'ro',
76     default => sub { {} },
77 );
78
79 has search_recursively => (
80     is      => 'ro',
81     isa     => 'Bool',
82     default => 0,
83 );
84
85 has export_ok => (
86     is  => 'ro',
87     isa => 'Str',
88 );
89
90 has whitelist => (
91     is  => 'ro',
92     isa => 'Str',
93 );
94
95 sub _build_repo_dir {
96     my $self = shift;
97     my $repo_dir = $self->_application->run_options->{repo_dir};
98
99     $repo_dir ?
100         $repo_dir
101       : $self->has_config_repo_dir
102       ? $self->config_repo_dir
103         : '';
104 }
105
106 after BUILD => sub {
107     my $self = shift;
108     # Explode loudly at app startup time if there is no list of
109     # repositories or repos dir, rather than on first hit
110     $self->_repos_count || $self->repo_dir;
111 };
112
113
114 sub build_per_context_instance {
115     my ($self, $app) = @_;
116
117     my %args = (
118         export_ok => $self->export_ok || '',
119         $self->_has_whitelist ? (whitelist => $self->whistlist) : (),
120         $self->_has_repos ? (repos => $self->repos) : ()
121         $self->_has_repo_dir ? (repo_dir => $self->repo_dir) : ()
122         %{ $self->args }
123     );
124
125     my $class = $self->class;
126
127     $app->log->debug("Using class '$class'");
128
129     return $class->new(%args);
130 }
131
132 __PACKAGE__->meta->make_immutable;
133
134 __END__
135
136 =encoding UTF-8
137
138 =head1 NAME
139
140 Gitalist::Model::CollectionOfRepos - Model::CollectionOfRepos module for Gitalist
141
142 =head1 DESCRIPTION
143
144 This Model is a factory for an object implementing the L<Gitalist::Git::CollectionOfRepositories>
145 interface.
146
147 The simple options passed on the command line (like C<--repos_dir>), a class will by picked by default 
148 L<Gitalist::Git::CollectionOfRepositories::FromDirectory>.
149
150 This can be overridden from config by explicitly passing in a class name and args for that class
151 in config:
152
153     <Model::CollectionOfRepos>
154         class MyClassName
155         <args>
156             ...
157         </args>
158     </Model::CollectionOfRepos>
159
160 =head1 AUTHORS
161
162 See L<Gitalist> for authors.
163
164 =head1 LICENSE
165
166 See L<Gitalist> for the license.
167
168 =cut