1package Git::SVN::Utils; 2 3use strict; 4use warnings; 5 6use SVN::Core; 7 8use base qw(Exporter); 9 10our @EXPORT_OK = qw( 11 fatal 12 can_compress 13 canonicalize_path 14 canonicalize_url 15); 16 17 18=head1 NAME 19 20Git::SVN::Utils - utility functions used across Git::SVN 21 22=head1 SYNOPSIS 23 24 use Git::SVN::Utils qw(functions to import); 25 26=head1 DESCRIPTION 27 28This module contains functions which are useful across many different 29parts of Git::SVN. Mostly it's a place to put utility functions 30rather than duplicate the code or have classes grabbing at other 31classes. 32 33=head1 FUNCTIONS 34 35All functions can be imported only on request. 36 37=head3 fatal 38 39 fatal(@message); 40 41Display a message and exit with a fatal error code. 42 43=cut 44 45# Note: not certain why this is in use instead of die. Probably because 46# the exit code of die is 255? Doesn't appear to be used consistently. 47sub fatal (@) { print STDERR "@_\n"; exit 1 } 48 49 50=head3 can_compress 51 52 my $can_compress = can_compress; 53 54Returns true if Compress::Zlib is available, false otherwise. 55 56=cut 57 58my $can_compress; 59sub can_compress { 60 return $can_compress if defined $can_compress; 61 62 return $can_compress = eval { require Compress::Zlib; }; 63} 64 65 66=head3 canonicalize_path 67 68 my $canoncalized_path = canonicalize_path($path); 69 70Converts $path into a canonical form which is safe to pass to the SVN 71API as a file path. 72 73=cut 74 75# Turn foo/../bar into bar 76sub _collapse_dotdot { 77 my $path = shift; 78 79 1 while $path =~ s{/[^/]+/+\.\.}{}; 80 1 while $path =~ s{[^/]+/+\.\./}{}; 81 1 while $path =~ s{[^/]+/+\.\.}{}; 82 83 return $path; 84} 85 86 87sub canonicalize_path { 88 my ($path) = @_; 89 my $dot_slash_added = 0; 90 if (substr($path, 0, 1) ne "/") { 91 $path = "./" . $path; 92 $dot_slash_added = 1; 93 } 94 # File::Spec->canonpath doesn't collapse x/../y into y (for a 95 # good reason), so let's do this manually. 96 $path =~ s#/+#/#g; 97 $path =~ s#/\.(?:/|$)#/#g; 98 $path = _collapse_dotdot($path); 99 $path =~ s#/$##g; 100 $path =~ s#^\./## if $dot_slash_added; 101 $path =~ s#^/##; 102 $path =~ s#^\.$##; 103 return $path; 104} 105 106 107=head3 canonicalize_url 108 109 my $canonicalized_url = canonicalize_url($url); 110 111Converts $url into a canonical form which is safe to pass to the SVN 112API as a URL. 113 114=cut 115 116sub canonicalize_url { 117 my $url = shift; 118 119 # The 1.7 way to do it 120 if ( defined &SVN::_Core::svn_uri_canonicalize ) { 121 return SVN::_Core::svn_uri_canonicalize($url); 122 } 123 # There wasn't a 1.6 way to do it, so we do it ourself. 124 else { 125 return _canonicalize_url_ourselves($url); 126 } 127} 128 129 130sub _canonicalize_url_ourselves { 131 my ($url) = @_; 132 $url =~ s#^([^:]+://[^/]*/)(.*)$#$1 . canonicalize_path($2)#e; 133 return $url; 134} 135 136 1371;