File Coverage

blib/lib/File/Truncate/Undoable.pm
Criterion Covered Total %
statement 40 41 97.5
branch 17 24 70.8
condition 8 11 72.7
subroutine 6 6 100.0
pod 1 1 100.0
total 72 83 86.7


line stmt bran cond sub pod time code
1             package File::Truncate::Undoable;
2              
3             our $DATE = '2015-08-17'; # DATE
4             our $VERSION = '0.03'; # VERSION
5              
6 1     1   37988 use 5.010001;
  1         4  
7 1     1   4 use strict;
  1         2  
  1         19  
8 1     1   4 use warnings;
  1         2  
  1         37  
9 1     1   1104 use Log::Any::IfLOG '$log';
  1         11  
  1         5  
10              
11 1     1   1536 use File::Trash::Undoable;
  1         12757  
  1         497  
12              
13             our %SPEC;
14              
15             $SPEC{truncate} = {
16             v => 1.1,
17             summary => 'Truncate a file, with undo support',
18             description => <<'_',
19              
20             On do, will trash file then create an empty file (with the same permission and
21             ownership as the original). On undo, will trash the new file and untrash the old
22             file.
23              
24             Note: chown will not be done if we are not running as root. Symlink is currently
25             not permitted.
26              
27             Fixed state: file exists and size is not zero.
28              
29             Fixable state: file exists and size is not zero.
30              
31             Unfixable state: file does not exist or path is not a regular file (directory
32             and symlink included).
33              
34             _
35             args => {
36             path => {
37             schema => 'str*',
38             req => 1,
39             pos => 0,
40             },
41             },
42             features => {
43             tx => {v=>2},
44             idempotent => 1,
45             },
46             };
47             sub truncate {
48 28     28 1 5240920 my %args = @_;
49              
50             # TMP, schema
51 28   50     269 my $tx_action = $args{-tx_action} // '';
52             my $taid = $args{-tx_action_id}
53 28 100       231 or return [400, "Please specify -tx_action_id"];
54 23         101 my $dry_run = $args{-dry_run};
55 23         91 my $path = $args{path};
56 23 50       134 defined($path) or return [400, "Please specify path"];
57              
58 23         453 my $is_sym = (-l $path);
59 23         368 my @st = stat($path);
60 23   100     236 my $exists = $is_sym || (-e _);
61 23         66 my $is_file = (-f _);
62 23         72 my $is_zero = !(-s _);
63              
64 23 100       132 if ($tx_action eq 'check_state') {
    50          
65 14 100       89 return [412, "File $path does not exist"] unless $exists;
66 13 100 100     165 return [412, "File $path is not a regular file"] if $is_sym||!$is_file;
67 11 50       51 return [500, "File $path can't be stat'd"] unless @st;
68 11 100       109 return [304, "File $path is already truncated"] if $is_zero;
69              
70 9 50       45 $log->info("(DRY) Truncating file $path ...") if $dry_run;
71 9         493 return [200, "File $path needs to be truncated", undef,
72             {undo_actions=>[
73             ['File::Trash::Undoable::untrash',
74             {path=>$path, suffix=>substr($taid,0,8)}], # restore orig
75             ['File::Trash::Undoable::trash',
76             {path=>$path, suffix=>substr($taid,0,8)."n"}], # trash new
77             ]}];
78             } elsif ($tx_action eq 'fix_state') {
79 9         194 $log->info("Truncating file $path ...");
80 9         143 my $res = File::Trash::Undoable::trash(
81             -tx_action=>'fix_state', path=>$path, suffix=>substr($taid,0,8));
82 9 50 33     52876 return $res unless $res->[0] == 200 || $res->[0] == 304;
83 9 50       786 open my($fh), ">", $path or return [500, "Can't create: $!"];
84 9         264 chmod $st[2] & 07777, $path; # ignore error?
85 9 50       79 unless ($>) { chown $st[4], $st[5], $path } # XXX ignore error?
  9         212  
86 9         556 return [200, "OK"];
87             }
88 0           [400, "Invalid -tx_action"];
89             }
90              
91             1;
92             # ABSTRACT: Truncate a file, with undo support
93              
94             __END__
95              
96             =pod
97              
98             =encoding UTF-8
99              
100             =head1 NAME
101              
102             File::Truncate::Undoable - Truncate a file, with undo support
103              
104             =head1 VERSION
105              
106             This document describes version 0.03 of File::Truncate::Undoable (from Perl distribution File-Truncate-Undoable), released on 2015-08-17.
107              
108             =head1 SEE ALSO
109              
110             L<Rinci::Transaction>
111              
112             =head1 FUNCTIONS
113              
114              
115             =head2 truncate(%args) -> [status, msg, result, meta]
116              
117             {en_US Truncate a file, with undo support}.
118              
119             {en_US
120             On do, will trash file then create an empty file (with the same permission and
121             ownership as the original). On undo, will trash the new file and untrash the old
122             file.
123              
124             Note: chown will not be done if we are not running as root. Symlink is currently
125             not permitted.
126              
127             Fixed state: file exists and size is not zero.
128              
129             Fixable state: file exists and size is not zero.
130              
131             Unfixable state: file does not exist or path is not a regular file (directory
132             and symlink included).
133             }
134              
135             This function is idempotent (repeated invocations with same arguments has the same effect as single invocation). This function supports transactions.
136              
137              
138             Arguments ('*' denotes required arguments):
139              
140             =over 4
141              
142             =item * B<path>* => I<str>
143              
144             =back
145              
146             Special arguments:
147              
148             =over 4
149              
150             =item * B<-tx_action> => I<str>
151              
152             For more information on transaction, see L<Rinci::Transaction>.
153              
154             =item * B<-tx_action_id> => I<str>
155              
156             For more information on transaction, see L<Rinci::Transaction>.
157              
158             =item * B<-tx_recovery> => I<str>
159              
160             For more information on transaction, see L<Rinci::Transaction>.
161              
162             =item * B<-tx_rollback> => I<str>
163              
164             For more information on transaction, see L<Rinci::Transaction>.
165              
166             =item * B<-tx_v> => I<str>
167              
168             For more information on transaction, see L<Rinci::Transaction>.
169              
170             =back
171              
172             Returns an enveloped result (an array).
173              
174             First element (status) is an integer containing HTTP status code
175             (200 means OK, 4xx caller error, 5xx function error). Second element
176             (msg) is a string containing error message, or 'OK' if status is
177             200. Third element (result) is optional, the actual result. Fourth
178             element (meta) is called result metadata and is optional, a hash
179             that contains extra information.
180              
181             Return value: (any)
182              
183             =head1 HOMEPAGE
184              
185             Please visit the project's homepage at L<https://metacpan.org/release/File-Truncate-Undoable>.
186              
187             =head1 SOURCE
188              
189             Source repository is at L<https://github.com/sharyanto/perl-File-Truncate-Undoable>.
190              
191             =head1 BUGS
192              
193             Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=File-Truncate-Undoable>
194              
195             When submitting a bug or request, please include a test-file or a
196             patch to an existing test-file that illustrates the bug or desired
197             feature.
198              
199             =head1 AUTHOR
200              
201             perlancar <perlancar@cpan.org>
202              
203             =head1 COPYRIGHT AND LICENSE
204              
205             This software is copyright (c) 2015 by perlancar@cpan.org.
206              
207             This is free software; you can redistribute it and/or modify it under
208             the same terms as the Perl 5 programming language system itself.
209              
210             =cut