File Coverage

blib/lib/HiD/App/Command/publish.pm
Criterion Covered Total %
statement 40 81 49.3
branch 5 46 10.8
condition n/a
subroutine 12 16 75.0
pod 1 1 100.0
total 58 144 40.2


line stmt bran cond sub pod time code
1             # ABSTRACT: publish site
2              
3              
4             package HiD::App::Command::publish;
5             our $AUTHORITY = 'cpan:GENEHACK';
6             $HiD::App::Command::publish::VERSION = '1.99';
7 4     4   3155 use Moose;
  4         11  
  4         32  
8             extends 'HiD::App::Command';
9             with 'HiD::Role::PublishesDrafts';
10             with 'HiD::Role::DoesLogging';
11 4     4   31214 use namespace::autoclean;
  4         13  
  4         46  
12              
13 4     4   412 use 5.014; # strict, unicode_strings
  4         480  
14 4     4   28 use utf8;
  4         9  
  4         36  
15 4     4   108 use autodie;
  4         8  
  4         32  
16 4     4   20063 use warnings qw/ FATAL utf8 /;
  4         10  
  4         226  
17 4     4   23 use open qw/ :std :utf8 /;
  4         8  
  4         34  
18 4     4   1100 use charnames qw/ :full /;
  4         14  
  4         35  
19              
20 4     4   953 use Class::Load qw/ try_load_class /;
  4         8  
  4         250  
21 4     4   1892 use File::Copy qw/ move /;
  4         7911  
  4         218  
22 4     4   28 use Path::Tiny;
  4         9  
  4         3848  
23              
24              
25             has clean => (
26             is => 'ro' ,
27             isa => 'Bool' ,
28             cmd_aliases => 'C' ,
29             traits => [ 'Getopt' ] ,
30             );
31              
32              
33             has limit_posts => (
34             is => 'ro' ,
35             isa => 'Int' ,
36             cmd_aliases => 'l' ,
37             traits => [ 'Getopt' ] ,
38             );
39              
40              
41             has to_github_pages => (
42             is => 'ro' ,
43             isa => 'Bool' ,
44             cmd_aliases => 'G' ,
45             traits => [ 'Getopt' ]
46             );
47              
48              
49             has verbose => (
50             is => 'ro' ,
51             isa => 'Bool' ,
52             cmd_aliases => 'v' ,
53             traits => [ 'Getopt' ] ,
54             default => 0 ,
55             );
56              
57             # internal attributes
58              
59             has gw => (
60             is => 'ro' ,
61             isa => 'Git::Wrapper' ,
62             lazy => 1 ,
63             builder => '_build_gw' ,
64             traits => [ 'NoGetopt' ] ,
65             handles => [ qw/
66             add
67             branch
68             checkout
69             commit
70             push
71             rev_parse
72             status
73             / ] ,
74             );
75              
76 0     0   0 sub _build_gw { Git::Wrapper->new('.') }
77              
78             has saved_branch => (
79             is => 'rw' ,
80             isa => 'Str' ,
81             writer => 'set_saved_branch' ,
82             traits => [ 'NoGetopt' ] ,
83             );
84              
85             sub _run {
86 15     15   56 my( $self , $opts , $args ) = @_;
87              
88 15         185 my $config = $self->config;
89 15 50       483 if ( $self->clean ) {
90 0         0 $config->{clean_destination} = 1;
91             }
92              
93 15 50       502 if ( $self->limit_posts ) {
94 0         0 $config->{limit_posts} = $self->limit_posts;
95             }
96              
97 15 50       478 if ( $self->publish_drafts ){
98 0         0 $config->{publish_drafts} = 1;
99             }
100              
101 15 50       509 if ( $self->to_github_pages ) {
102 0 0       0 say( "PUBLISHING TO gh-pages BRANCH" ) if $self->verbose;
103              
104 0 0       0 $self->FATAL( "Not in the root level of a Git repo" )
105             unless -e -d '.git';
106              
107 0 0       0 $self->FATAL( "Git::Wrapper is required for the '--to-github-pages' option" )
108             unless try_load_class( 'Git::Wrapper' );
109              
110             # publish into a tempdir...
111 0         0 $config->{destination} = Path::Tiny->tempdir->stringify();
112 0 0       0 say( "*** destination set to $config->{destination}" ) if $self->verbose;
113             }
114              
115 15         124 $self->publish();
116              
117 14 50       483 if ( $self->to_github_pages ) {
118              
119 0 0         say( "Storing current branch" ) if $self->verbose;
120 0           $self->set_saved_branch( $self->get_current_branch() );
121              
122 0 0         say( "Switching to gh_pages branch (creating if needed)" ) if $self->verbose;
123 0           $self->_create_gh_pages_if_needed_and_switch_branch();
124              
125             # move stuff out of destination (which is a tempdir at this point,
126             # remember) into the current dir
127 0 0         say( "Moving published files to current directory" ) if $self->verbose;
128 0           my $d = path( $self->config->{destination} );
129             ## use File::Copy::move b/c Path::Tiny::move is mud spelled backwards
130 0           move( $_ , './' ) foreach ( $d->children() );
131              
132             # add everything, commit, and push
133 0 0         if ( $self->status->is_dirty() ) {
134 0 0         say( "Committing files and pushing" ) if $self->verbose;
135              
136 0           $self->add( '.' );
137             ### FIXME include the date or something.
138             ### or have a '--message/-m' option and some sensible default
139 0           $self->commit( "-m" => "Published to GitHub pages by HiD!" );
140 0           $self->push( '-u' );
141             }
142             else {
143 0 0         say( "No changes to commit." ) if $self->verbose;
144             }
145              
146             # and go back to the starting branch
147 0 0         say( "Restoring previous branch" ) if $self->verbose;
148 0           $self->checkout( $self->saved_branch );
149             }
150             }
151              
152             sub _create_gh_pages_if_needed_and_switch_branch {
153 0     0     my $self = shift;
154              
155             # do we already have 'gh-pages' ?
156             ## 'branch' output is either '* NAME' or ' NAME', so strip that
157             ### FIXME can we require 5.20 and then switch to s///r ?
158 0 0         if ( grep { $_ eq 'gh-pages' } map { s/\*? ?// ; $_ } $self->branch() ) {
  0            
  0            
  0            
159 0 0         say( "* Checking out existing gh-pages branch" ) if $self->verbose;
160 0 0         $self->checkout( 'gh-pages' )
161             unless $self->_get_current_branch eq 'gh-pages';
162              
163 0           return 1;
164             }
165              
166             # otherwise, let's set it up
167 0 0         say( '* Creating gh-pages branch' ) if $self->verbose;
168              
169             # make the orphan branch
170 0           $self->checkout( '--orphan' => 'gh-pages' );
171              
172             # clean out all files already there
173 0 0         say( '* Cleaning out existing files' ) if $self->verbose;
174 0           foreach ( path('.')->children() ) {
175             # skip over .git*
176 0 0         next if /^.git/;
177              
178 0 0         $_->is_dir() ? $_->remove_tree() : $_->remove()
179             }
180              
181             # and we're good to go
182 0           return 1;
183             }
184              
185              
186             # this is required by DoesLogging -- but having an empty hash for it works
187             # just as well.
188 0     0 1   sub get_config { {} }
189              
190 0     0     sub _get_current_branch { shift->rev_parse( '--abbrev-ref' => 'HEAD' ) }
191              
192             __PACKAGE__->meta->make_immutable;
193             1;
194              
195             __END__
196              
197             =pod
198              
199             =encoding UTF-8
200              
201             =head1 NAME
202              
203             HiD::App::Command::publish - publish site
204              
205             =head1 SYNOPSIS
206              
207             $ hid publish
208              
209             # publish directly to GitHub Pages
210             $ hid publish --to_github_pages
211             $ hid publist -G
212              
213             =head1 DESCRIPTION
214              
215             Processes files according to the active configuration and writes output files
216             accordingly.
217              
218             =head1 ATTRIBUTES
219              
220             =head2 clean
221              
222             Remove any existing site directory prior to the publication run
223              
224             =head2 limit_posts
225              
226             Limit the number of blog posts that will be written out. If you have a large
227             number of blog posts that haven't changed, setting this can significantly
228             speed up the publication process.
229              
230             =head2 to_github_pages
231              
232             If this option is set, the publishing process will switch to a 'gh-pages'
233             branch in the current repository. If such a branch does not exist, a new
234             "orphan" branch of that name will be created. Publication will happen in the
235             normal destination directory, and then files will be moved into the root level
236             of the repo and the destination directory removed. At the end of publication,
237             all pending changes will be committed and a push (specifically, 'git push -u')
238             will be done. Finally, the repository will be set back to whatever branch had
239             been checked out before.
240              
241             If this option is given and the current working directory is not the root
242             level of a Git repository, an error will be thrown.
243              
244             =head2 verbose
245              
246             Be noisy. Primarily useful for debugging issues publishing to GitHub.
247              
248             =head1 METHODS
249              
250             =head2 get_config
251              
252             Required for logging output, can be ignored by end users.
253              
254             =head1 SEE ALSO
255              
256             See L<HiD::App::Command> for additional command line options supported by all
257             sub commands.
258              
259             =head1 VERSION
260              
261             version 1.99
262              
263             =head1 AUTHOR
264              
265             John SJ Anderson <genehack@genehack.org>
266              
267             =head1 COPYRIGHT AND LICENSE
268              
269             This software is copyright (c) 2015 by John SJ Anderson.
270              
271             This is free software; you can redistribute it and/or modify it under
272             the same terms as the Perl 5 programming language system itself.
273              
274             =cut