perl / Git / SVN / GlobSpec.pmon commit Merge git://ozlabs.org/~paulus/gitk (0e94f7a)
   1package Git::SVN::GlobSpec;
   2use strict;
   3use warnings;
   4
   5sub new {
   6        my ($class, $glob, $pattern_ok) = @_;
   7        my $re = $glob;
   8        $re =~ s!/+$!!g; # no need for trailing slashes
   9        my (@left, @right, @patterns);
  10        my $state = "left";
  11        my $die_msg = "Only one set of wildcards " .
  12                                "(e.g. '*' or '*/*/*') is supported: $glob\n";
  13        for my $part (split(m|/|, $glob)) {
  14                if ($pattern_ok && $part =~ /[{}]/ &&
  15                         $part !~ /^\{[^{}]+\}/) {
  16                        die "Invalid pattern in '$glob': $part\n";
  17                }
  18                my $nstars = $part =~ tr/*//;
  19                if ($nstars > 1) {
  20                        die "Only one '*' is allowed in a pattern: '$part'\n";
  21                }
  22                if ($part =~ /(.*)\*(.*)/) {
  23                        die $die_msg if $state eq "right";
  24                        my ($l, $r) = ($1, $2);
  25                        $state = "pattern";
  26                        my $pat = quotemeta($l) . '[^/]*' . quotemeta($r);
  27                        push(@patterns, $pat);
  28                } elsif ($pattern_ok && $part =~ /^\{(.*)\}$/) {
  29                        die $die_msg if $state eq "right";
  30                        $state = "pattern";
  31                        my $p = quotemeta($1);
  32                        $p =~ s/\\,/|/g;
  33                        push(@patterns, "(?:$p)");
  34                } else {
  35                        if ($state eq "left") {
  36                                push(@left, $part);
  37                        } else {
  38                                push(@right, $part);
  39                                $state = "right";
  40                        }
  41                }
  42        }
  43        my $depth = @patterns;
  44        if ($depth == 0) {
  45                die "One '*' is needed in glob: '$glob'\n";
  46        }
  47        my $left = join('/', @left);
  48        my $right = join('/', @right);
  49        $re = join('/', @patterns);
  50        $re = join('\/',
  51                   grep(length, quotemeta($left),
  52                                "($re)(?=/|\$)",
  53                                quotemeta($right)));
  54        my $left_re = qr/^\/\Q$left\E(\/|$)/;
  55        bless { left => $left, right => $right, left_regex => $left_re,
  56                regex => qr/$re/, glob => $glob, depth => $depth }, $class;
  57}
  58
  59sub full_path {
  60        my ($self, $path) = @_;
  61        return (length $self->{left} ? "$self->{left}/" : '') .
  62               $path . (length $self->{right} ? "/$self->{right}" : '');
  63}
  64
  651;