#! /bin/sh /usr/share/dpatch/dpatch-run
## svn-clean-ignore by <peter@p12n.org>
##
## DP: Support a new 'svn-clean:ignore' directory property in
## DP: svn-clean, conceptually a lot like the svn:ignore property.
## DP: svn-clean will not remove files that match svn-clean:ignore.
## DP: Suggested by Jonathan Hall <flimzy@flimzy.com>.
## DP: Submitted upstream: http://svn.haxx.se/dev/archive-2008-05/0236.shtml

@DPATCH@
--- a/contrib/client-side/svn-clean
+++ b/contrib/client-side/svn-clean
@@ -52,11 +52,20 @@
 # Precompile regexes.
 $_ = qr/$_/ foreach @exclude;
 
+my %svn_clean_ignore;
 if ($use_svn_module) {
 
     # Create SVN client object. No need for connection to remote server.
     my $ctx = new SVN::Client;
 
+    my $ign = $ctx->propget('svn-clean:ignore', $path, undef, 1);
+    for my $dir (keys %$ign) {
+        for (split /\n/, $ign->{$dir}) {
+            for (glob "$dir/$_") {
+                $svn_clean_ignore{$_} = 1 if -e $_;
+            }
+        }
+    }
     # Call handler function with status info for each file.
     $ctx->status( $path, undef, \&clean, !$nonrecursive, 1, 0, 1 );
 }
@@ -64,8 +73,22 @@
     warn "Warning: Not using SVN Perl modules, this might be slow.\n"
       unless $quiet;
 
-    # Build svn client command
-    my @command = qw(svn status --no-ignore -v);
+    my @command = qw(svn propget svn-clean:ignore);
+    push @command, '-R' unless $nonrecursive;
+    open PG, '-|', @command, @ARGV;
+    my $dir;
+    while (<PG>) {
+        if (s/(.*?) - //) {
+            $dir = $1;
+        }
+        chomp;
+        for (glob "$dir/$_") {
+            $svn_clean_ignore{$_} = 1 if -e $_;
+        }
+    }
+    close PG;
+
+    @command = qw(svn status --no-ignore -v);
     if ($nonrecursive) {
         push @command, '-N';
     }
@@ -84,6 +107,7 @@
   LINE: while (<SVN>) {
         if (/^([\?ID])/) {
             my $file = (split)[-1];
+            next if $svn_clean_ignore{$file};
             foreach my $ex (@exclude) {
                 if ( $file =~ $ex ) {
                     print "excluded $file\n" unless $quiet or $print;
@@ -109,6 +133,7 @@
 # Main file-wiping function.
 sub clean {
     my ( $path, $status ) = @_;
+    return if $svn_clean_ignore{$path};
 
     # Use relative path for pretty-printing.
     if ( $path =~ s/^\Q$CWD\E\/?//o ) {
@@ -165,7 +190,9 @@
 B<svn-clean> will scan the given files and directories recursively and find
 unversioned files and directories (files and directories that are not present in
 the Subversion repository). After the scan is done, these files and directories
-will be deleted.
+will be deleted.  Files which match patterns in the I<svn-clean:ignore> dir
+property will be spared, much as the I<svn:ignore> property works for B<svn
+status>.
 
 If no file or directory is given, B<svn-clean> defaults to the current directory
 (".").
