3
# svn-clean - Wipes out unversioned files from SVN working copy.
4
# Copyright (C) 2004, 2005, 2006 Simon Perreault
6
# This program is free software; you can redistribute it and/or
7
# modify it under the terms of the GNU General Public License
8
# as published by the Free Software Foundation; either version 2
9
# of the License, or (at your option) any later version.
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
# GNU General Public License for more details.
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
# Try to use SVN module if available.
27
my $use_svn_module = eval { require SVN::Client };
40
"exclude=s" => \@exclude,
42
"non-recursive|N" => \$nonrecursive,
48
pod2usage(1) if $help;
49
pod2usage( -exitstatus => 0, -verbose => 2 ) if $man;
50
@paths = map { Cwd::abs_path($_) } @ARGV if @ARGV;
53
$_ = qr/$_/ foreach @exclude;
56
if ($use_svn_module) {
58
# Create SVN client object. No need for connection to remote server.
59
my $ctx = new SVN::Client;
61
for my $path (@paths) {
62
my $ign = $ctx->propget('svn-clean:ignore', $path, undef, 1);
63
for my $dir (keys %$ign) {
64
for (split /\n/, $ign->{$dir}) {
65
for (glob "$dir/$_") {
66
$svn_clean_ignore{$_} = 1 if -e $_;
70
# Call handler function with status info for each file.
71
$ctx->status( $path, undef, \&clean, !$nonrecursive, 1, 0, 1 );
76
warn "Warning: Not using SVN Perl modules, this might be slow.\n"
79
my @command = qw(svn propget svn-clean:ignore);
80
push @command, '-R' unless $nonrecursive;
81
open PG, '-|', @command, @paths;
88
for (glob "$dir/$_") {
89
$svn_clean_ignore{$_} = 1 if -e $_;
94
@command = qw(svn status --no-ignore -v);
99
# Main file-wiping loop.
100
if ( $^O eq 'MSWin32' ) {
102
# Perl on Windows currently doesn't have list pipe opens.
103
open SVN, join( ' ', @command, @paths ) . '|'
104
or die "Can't call program \"svn\": $!\n";
107
open SVN, "-|", @command, @paths
108
or die "Can't call program \"svn\": $!\n";
110
LINE: while (<SVN>) {
112
my $file = (split)[-1];
113
next if $svn_clean_ignore{$file};
114
foreach my $ex (@exclude) {
115
if ( $file =~ $ex ) {
116
print "excluded $file\n" unless $quiet or $print;
121
next unless -f $file;
124
next unless -e $file;
130
rmtree( $file, !$quiet, !$force );
136
# Main file-wiping function.
138
my ( $path, $status ) = @_;
139
return if $svn_clean_ignore{$path};
141
# Use relative path for pretty-printing.
142
if ( $path =~ s/^\Q$CWD\E\/?//o ) {
144
# If the substitution succeeded, we should have a relative path. Make
145
# sure we don't delete critical stuff.
146
return if $path =~ /^\//;
149
# Find files needing to be removed.
150
if ( $status->text_status == $SVN::Wc::Status::unversioned
151
or $status->text_status == $SVN::Wc::Status::ignored
152
or $status->text_status == $SVN::Wc::Status::deleted )
154
foreach my $ex (@exclude) {
155
if ( $path =~ $ex ) {
156
print "excluded $path\n" unless $quiet or $print;
161
# Make sure the file exists before removing it. Do not remove deleted
162
# directories as they are needed to remove the files they contain when
164
lstat $path or stat $path;
168
or $status->text_status != $SVN::Wc::Status::deleted )
175
rmtree( $path, !$quiet, !$force );
185
svn-clean - Wipes out unversioned files from Subversion working copy
189
svn-clean [options] [directory or file ...]
193
B<svn-clean> will scan the given files and directories recursively and find
194
unversioned files and directories (files and directories that are not present in
195
the Subversion repository). After the scan is done, these files and directories
196
will be deleted. Files which match patterns in the I<svn-clean:ignore> dir
197
property will be spared, much as the I<svn:ignore> property works for B<svn
200
If no file or directory is given, B<svn-clean> defaults to the current directory
203
B<svn-clean> uses the SVN Perl modules if they are available. This is much
204
faster than parsing the output of the B<svn> command-line client.
210
=item B<-e>, B<--exclude>
212
A regular expression for filenames to be exluded. For example, the following
213
command will skip files ending in ".zip":
217
svn-clean --exclude '\.zip$'
221
Multiple exclude patterns can be specified. If at least one matches, then the
222
file is skipped. For example, the following command will skip files ending in
227
svn-clean --exclude '\.jpg$' --exclude '\.png$'
231
The following command will skip the entire "build" subdirectory:
235
svn-clean --exclude '^build(/|$)'
239
=item B<-f>, B<--force>
241
Files to which you do not have delete access (if running under VMS) or write
242
access (if running under another OS) will not be deleted unless you use this
245
=item B<-N>, B<--non-recursive>
247
Do not search recursively for unversioned files and directories. Unversioned
248
directories will still be deleted along with all their contents.
250
=item B<-q>, B<--quiet>
252
Do not print progress info. In particular, do not print a message each time a
253
file is examined, giving the name of the file, and indicating whether "rmdir" or
254
"unlink" is used to remove it, or that it's skipped.
256
=item B<-p>, B<--print>
258
Do not delete anything. Instead, print the name of every file and directory that
259
would have been deleted.
261
=item B<-?>, B<-h>, B<--help>
263
Prints a brief help message and exits.
267
Prints the manual page and exits.
273
Simon Perreault <nomis80@nomis80.org>