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 = '2017-07-10'; # DATE
4             our $VERSION = '0.05'; # VERSION
5              
6 1     1   97265 use 5.010001;
  1         4  
7 1     1   4 use strict;
  1         2  
  1         18  
8 1     1   4 use warnings;
  1         2  
  1         24  
9 1     1   3309 use Log::ger;
  1         79  
  1         4  
10              
11 1     1   2164 use File::Trash::Undoable;
  1         13972  
  1         344  
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 4613176 my %args = @_;
49              
50             # TMP, schema
51 28   50     228 my $tx_action = $args{-tx_action} // '';
52             my $taid = $args{-tx_action_id}
53 28 100       298 or return [400, "Please specify -tx_action_id"];
54 23         112 my $dry_run = $args{-dry_run};
55 23         96 my $path = $args{path};
56 23 50       105 defined($path) or return [400, "Please specify path"];
57              
58 23         541 my $is_sym = (-l $path);
59 23         297 my @st = stat($path);
60 23   100     285 my $exists = $is_sym || (-e _);
61 23         82 my $is_file = (-f _);
62 23         238 my $is_zero = !(-s _);
63              
64 23 100       146 if ($tx_action eq 'check_state') {
    50          
65 14 100       103 return [412, "File $path does not exist"] unless $exists;
66 13 100 100     184 return [412, "File $path is not a regular file"] if $is_sym||!$is_file;
67 11 50       61 return [500, "File $path can't be stat'd"] unless @st;
68 11 100       120 return [304, "File $path is already truncated"] if $is_zero;
69              
70 9 50       39 log_info("(DRY) Truncating file $path ...") if $dry_run;
71 9         500 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         104 log_info("Truncating file $path ...");
80 9         304 my $res = File::Trash::Undoable::trash(
81             -tx_action=>'fix_state', path=>$path, suffix=>substr($taid,0,8));
82 9 50 33     60395 return $res unless $res->[0] == 200 || $res->[0] == 304;
83 9 50       602 open my($fh), ">", $path or return [500, "Can't create: $!"];
84 9         226 chmod $st[2] & 07777, $path; # ignore error?
85 9 50       84 unless ($>) { chown $st[4], $st[5], $path } # XXX ignore error?
  9         228  
86 9         3861 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.05 of File::Truncate::Undoable (from Perl distribution File-Truncate-Undoable), released on 2017-07-10.
107              
108             =head1 FUNCTIONS
109              
110              
111             =head2 truncate
112              
113             Usage:
114              
115             truncate(%args) -> [status, msg, result, meta]
116              
117             Truncate a file, with undo support.
118              
119             On do, will trash file then create an empty file (with the same permission and
120             ownership as the original). On undo, will trash the new file and untrash the old
121             file.
122              
123             Note: chown will not be done if we are not running as root. Symlink is currently
124             not permitted.
125              
126             Fixed state: file exists and size is not zero.
127              
128             Fixable state: file exists and size is not zero.
129              
130             Unfixable state: file does not exist or path is not a regular file (directory
131             and symlink included).
132              
133             This function is not exported.
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/perlancar/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 SEE ALSO
200              
201             L<Rinci::Transaction>
202              
203             =head1 AUTHOR
204              
205             perlancar <perlancar@cpan.org>
206              
207             =head1 COPYRIGHT AND LICENSE
208              
209             This software is copyright (c) 2017, 2015, 2014, 2012 by perlancar@cpan.org.
210              
211             This is free software; you can redistribute it and/or modify it under
212             the same terms as the Perl 5 programming language system itself.
213              
214             =cut