diff --git a/svn-find.pl b/svn-find.pl new file mode 100755 index 0000000..b1b35cd --- /dev/null +++ b/svn-find.pl @@ -0,0 +1,68 @@ +#!/usr/bin/env perl + +use strict; +use warnings FATAL => 'all'; + +use Getopt::Long; + +GetOptions( + 'type=s' => \my $type, + 'max-depth=i' => \my $max_depth, + 'min-depth=i' => \my $min_depth, + 'name=s' => \my $name, +) and @ARGV or die "Usage: $0 [--type=f|--type=d] [--max-depth=N] [--min-depth=N] [--name=NAME] REPOS_URL ...\n"; + +for ( @ARGV ) { + $_ .= '/' unless $_ =~ m{/$}; + svn_find( $_, 0 ); +} + +sub is_match { + my $path = shift; + + my ( $basename, $is_dir ) = $path =~ m{([^/]+)(/?)$}; + + if ( defined $type ) { + if ( $type eq 'f' ) { + return if $is_dir; + } + elsif ( $type eq 'd' ) { + return unless $is_dir; + } + } + + if ( defined $name and $name ne $basename ) { + return; + } + + return 1; +} + +sub svn_find { + my ( $repos_url, $depth ) = @_; + + if ( defined $max_depth and $depth > $max_depth ) { + return; + } + + my @dirents = svn_ls( $repos_url ); + + if ( ( not defined $min_depth ) or $depth >= $min_depth ) { + print $repos_url . $_ . "\n" for grep { is_match($_) } @dirents; + } + + for my $dir ( grep m{/$}, @dirents ) { + svn_find( $repos_url . $dir, $depth++ ); + } +} + +sub svn_ls { + my $svn_url = shift; + + open( my $ls, '-|', 'svn', 'ls', $svn_url ) + or die "svn ls $svn_url failed"; + map { chomp; $_ } <$ls>; +} + + +