File Coverage

blib/lib/App/Critique/Session.pm
Criterion Covered Total %
statement 30 111 27.0
branch 0 38 0.0
condition 0 15 0.0
subroutine 10 37 27.0
pod 0 23 0.0
total 40 224 17.8


line stmt bran cond sub pod time code
1             package App::Critique::Session;
2              
3 2     2   2824 use strict;
  2         3  
  2         64  
4 2     2   14 use warnings;
  2         5  
  2         103  
5              
6             our $VERSION = '0.04';
7             our $AUTHORITY = 'cpan:STEVAN';
8              
9 2     2   9 use Scalar::Util ();
  2         1  
  2         23  
10 2     2   9 use Carp ();
  2         0  
  2         25  
11              
12 2     2   25 use Path::Tiny ();
  2         3  
  2         22  
13              
14 2     2   467 use Git::Wrapper ();
  2         27635  
  2         30  
15 2     2   1166 use Perl::Critic ();
  2         1289748  
  2         47  
16 2     2   15 use Perl::Critic::Utils ();
  2         3  
  2         28  
17              
18 2     2   29 use App::Critique;
  2         3  
  2         29  
19 2     2   1183 use App::Critique::Session::File;
  2         3  
  2         898  
20              
21             sub new {
22 0     0 0   my ($class, %args) = @_;
23              
24             Carp::confess('You must specify a git_work_tree')
25 0 0 0       unless $args{git_work_tree} && -d $args{git_work_tree};
26              
27             # setup the perl critic instance
28 0           my $critic = $class->_initialize_perl_critic( %args );
29              
30             # auto-discover the current git repo and branch
31 0           my ($git, $git_branch) = $class->_initialize_git_repo( %args );
32              
33             # now that we have worked out all the details,
34             # we need to determine the path to the actual
35             # critique file.
36 0           my $path = $class->_generate_critique_file_path( $git->dir, $git_branch );
37              
38             my $self = bless {
39             # user supplied ...
40             perl_critic_profile => $args{perl_critic_profile},
41             perl_critic_theme => $args{perl_critic_theme},
42             perl_critic_policy => $args{perl_critic_policy},
43              
44             # auto-discovered
45 0           git_work_tree => Path::Tiny::path( $git->dir ),
46             git_branch => $git_branch,
47              
48             # local storage
49             current_file_idx => 0,
50             tracked_files => [],
51             file_criteria => {},
52              
53             # Do Not Serialize
54             _path => $path,
55             _critic => $critic,
56             _git => $git,
57             } => $class;
58              
59             # handle adding tracked files
60 0           $self->set_tracked_files( @{ $args{tracked_files} } )
61 0 0         if exists $args{tracked_files};
62              
63             $self->set_file_criteria( $args{file_criteria} )
64 0 0         if exists $args{file_criteria};
65              
66             $self->{current_file_idx} = $args{current_file_idx}
67 0 0         if exists $args{current_file_idx};
68              
69 0           return $self;
70             }
71              
72             sub locate_session_file {
73 0     0 0   my ($class, $git_work_tree) = @_;
74              
75 0 0         Carp::confess('Cannot call locate_session_file with an instance')
76             if Scalar::Util::blessed( $class );
77              
78 0 0 0       Carp::confess('You must specify a git-work-tree')
79             unless $git_work_tree && -d $git_work_tree;
80              
81 0           my ($git, $git_branch) = $class->_initialize_git_repo( git_work_tree => $git_work_tree );
82              
83 0           my $session_file = $class->_generate_critique_file_path(
84             Path::Tiny::path( $git->dir ),
85             $git_branch
86             );
87              
88 0           return $session_file;
89             }
90              
91             # accessors
92              
93 0     0 0   sub git_work_tree { $_[0]->{git_work_tree} }
94 0     0 0   sub git_branch { $_[0]->{git_branch} }
95 0     0 0   sub perl_critic_profile { $_[0]->{perl_critic_profile} }
96 0     0 0   sub perl_critic_theme { $_[0]->{perl_critic_theme} }
97 0     0 0   sub perl_critic_policy { $_[0]->{perl_critic_policy} }
98              
99 0     0 0   sub tracked_files { @{ $_[0]->{tracked_files} } }
  0            
100 0     0 0   sub file_criteria { $_[0]->{file_criteria} }
101              
102 0     0 0   sub current_file_idx { $_[0]->{current_file_idx} }
103 0     0 0   sub inc_file_idx { $_[0]->{current_file_idx}++ }
104 0     0 0   sub dec_file_idx { $_[0]->{current_file_idx}-- }
105 0     0 0   sub reset_file_idx { $_[0]->{current_file_idx}=0 }
106              
107 0     0 0   sub session_file_path { $_[0]->{_path} }
108 0     0 0   sub git_wrapper { $_[0]->{_git} }
109 0     0 0   sub perl_critic { $_[0]->{_critic} }
110              
111             # Instance Methods
112              
113             sub session_file_exists {
114 0     0 0   my ($self) = @_;
115 0           return !! -e $self->{_path};
116             }
117              
118             sub set_tracked_files {
119 0     0 0   my ($self, @files) = @_;
120 0           @{ $self->{tracked_files} } = map {
121 0 0 0       (Scalar::Util::blessed($_) && $_->isa('App::Critique::Session::File')
  0 0          
122             ? $_
123             : ((ref $_ eq 'HASH')
124             ? App::Critique::Session::File->new( %$_ )
125             : App::Critique::Session::File->new( path => $_ )))
126             } @files;
127             }
128              
129             sub set_file_criteria {
130 0     0 0   my ($self, $filters_used) = @_;
131             $self->{file_criteria}->{ $_ } = $filters_used->{ $_ }
132 0           foreach keys %$filters_used;
133             }
134              
135             # ...
136              
137             sub pack {
138 0     0 0   my ($self) = @_;
139             return +{
140             perl_critic_profile => ($self->{perl_critic_profile} ? $self->{perl_critic_profile}->stringify : undef),
141             perl_critic_theme => $self->{perl_critic_theme},
142             perl_critic_policy => $self->{perl_critic_policy},
143              
144             git_work_tree => ($self->{git_work_tree} ? $self->{git_work_tree}->stringify : undef),
145             git_branch => $self->{git_branch},
146              
147             current_file_idx => $self->{current_file_idx},
148 0           tracked_files => [ map $_->pack, @{ $self->{tracked_files} } ],
149             file_criteria => $self->{file_criteria}
150 0 0         };
    0          
151             }
152              
153             sub unpack {
154 0     0 0   my ($class, $data) = @_;
155 0           return $class->new( %$data );
156             }
157              
158             # ...
159              
160             sub load {
161 0     0 0   my ($class, $path) = @_;
162              
163 0 0 0       Carp::confess('Invalid path: ' . $path)
164             unless $path->exists && $path->is_file;
165              
166 0           my $file = Path::Tiny::path( $path );
167 0           my $json = $file->slurp;
168 0           my $data = $App::Critique::JSON->decode( $json );
169              
170 0           return $class->unpack( $data );
171             }
172              
173             sub store {
174 0     0 0   my ($self) = @_;
175              
176 0           my $file = $self->{_path};
177 0           my $data = $self->pack;
178              
179             eval {
180             # JSON might die here ...
181 0           my $json = $App::Critique::JSON->encode( $data );
182              
183             # if the file does not exist
184             # then we should try and make
185             # the path, just in case ...
186 0 0         $file->parent->mkpath unless -e $file;
187              
188             # now try and write out the JSON
189 0           my $fh = $file->openw;
190 0           $fh->print( $json );
191 0           $fh->close;
192              
193 0           1;
194 0 0         } or do {
195 0           Carp::confess('Unable to store critique session file because: ' . $@);
196             };
197             }
198              
199             # ...
200              
201             sub _generate_critique_dir_path {
202 0     0     my ($class, $git_work_tree, $git_branch) = @_;
203              
204 0           my $root = Path::Tiny::path( $App::Critique::CONFIG{'HOME'} );
205 0           my $git = Path::Tiny::path( $git_work_tree );
206              
207             # ~/.critique/<git-repo-name>/<git-branch-name>/session.json
208              
209 0           $root->child( '.critique' )
210             ->child( $git->basename )
211             ->child( $git_branch );
212             }
213              
214             sub _generate_critique_file_path {
215 0     0     my ($class, $git_work_tree, $git_branch) = @_;
216 0           $class->_generate_critique_dir_path(
217             $git_work_tree,
218             $git_branch
219             )->child(
220             'session.json'
221             );
222             }
223              
224             sub _initialize_git_repo {
225 0     0     my ($class, %args) = @_;
226              
227 0           my $git = Git::Wrapper->new( $args{git_work_tree} );
228              
229             # auto-discover the current git branch
230 0           my ($git_branch) = map /^\*\s(.*)$/, grep /^\*/, $git->branch;
231              
232 0 0         Carp::confess('Unable to determine git branch, looks like your repository is bare')
233             unless $git_branch;
234              
235             # make sure the branch we are on is the
236             # same one we are being asked to load,
237             # this is very much unlikely to happen
238             # but something we should die about none
239             # the less.
240             Carp::confess('Attempting to inflate session for branch ('.$args{git_branch}.') but branch ('.$git_branch.') is currently active')
241 0 0 0       if exists $args{git_branch} && $args{git_branch} ne $git_branch;
242              
243             # if all is well, return ...
244 0           return ($git, $git_branch);
245             }
246              
247             sub _initialize_perl_critic {
248 0     0     my ($class, %args) = @_;
249              
250 0           my $critic;
251 0 0         if ( $args{perl_critic_policy} ) {
252 0           $critic = Perl::Critic->new( '-single-policy' => $args{perl_critic_policy} );
253             }
254             else {
255             $critic = Perl::Critic->new(
256             ($args{perl_critic_profile} ? ('-profile' => $args{perl_critic_profile}) : ()),
257 0 0         ($args{perl_critic_theme} ? ('-theme' => $args{perl_critic_theme}) : ()),
    0          
258             );
259              
260             # inflate this as needed
261             $args{perl_critic_profile} = Path::Tiny::path( $args{perl_critic_profile} )
262 0 0         if $args{perl_critic_profile};
263             }
264              
265 0           return $critic;
266             }
267              
268             1;
269              
270             =pod
271              
272             =head1 NAME
273              
274             App::Critique::Session - Session interface for App::Critique
275              
276             =head1 VERSION
277              
278             version 0.04
279              
280             =head1 DESCRIPTION
281              
282             This is the main interace to the L<App::Critique> session file
283             and contains no real user serviceable parts.
284              
285             =head1 AUTHOR
286              
287             Stevan Little <stevan@cpan.org>
288              
289             =head1 COPYRIGHT AND LICENSE
290              
291             This software is copyright (c) 2016 by Stevan Little.
292              
293             This is free software; you can redistribute it and/or modify it under
294             the same terms as the Perl 5 programming language system itself.
295              
296             =cut
297              
298             __END__
299              
300             # ABSTRACT: Session interface for App::Critique
301