mirror of
https://github.com/git/git
synced 2024-11-05 18:59:29 +00:00
5338ed2b26
We set "use warnings" in most of our perl code to catch problems. But as the name implies, warnings just emit a message to stderr and don't otherwise affect the program. So our tests are quite likely to miss that warnings are being spewed, as most of them do not look at stderr. We could ask perl to make all warnings fatal, but this is likely annoying for non-developers, who would rather have a running program with a warning than something that refuses to work at all. So instead, let's teach the perl code to respect an environment variable (GIT_PERL_FATAL_WARNINGS) to increase the severity of the warnings. This can be set for day-to-day running if people want to be really pedantic, but the primary use is to trigger it within the test suite. We could also trigger that for every test run, but likewise even the tests failing may be annoying to distro builders, etc (just as -Werror would be for compiling C code). So we'll tie it to a special test-mode variable (GIT_TEST_PERL_FATAL_WARNINGS) that can be set in the environment or as a Makefile knob, and we'll automatically turn the knob when DEVELOPER=1 is set. That should give developers and CI the more careful view without disrupting normal users or packagers. Note that the mapping from the GIT_TEST_* form to the GIT_* form in test-lib.sh is necessary even if they had the same name: the perl scripts need it to be normalized to a perl truth value, and we also have to make sure it's exported (we might have gotten it from the environment, but we might also have gotten it from GIT-BUILD-OPTIONS directly). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
232 lines
4.5 KiB
Perl
232 lines
4.5 KiB
Perl
package Git::SVN::Utils;
|
|
|
|
use strict;
|
|
use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
|
|
|
|
use SVN::Core;
|
|
|
|
use base qw(Exporter);
|
|
|
|
our @EXPORT_OK = qw(
|
|
fatal
|
|
can_compress
|
|
canonicalize_path
|
|
canonicalize_url
|
|
join_paths
|
|
add_path_to_url
|
|
);
|
|
|
|
|
|
=head1 NAME
|
|
|
|
Git::SVN::Utils - utility functions used across Git::SVN
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
use Git::SVN::Utils qw(functions to import);
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
This module contains functions which are useful across many different
|
|
parts of Git::SVN. Mostly it's a place to put utility functions
|
|
rather than duplicate the code or have classes grabbing at other
|
|
classes.
|
|
|
|
=head1 FUNCTIONS
|
|
|
|
All functions can be imported only on request.
|
|
|
|
=head3 fatal
|
|
|
|
fatal(@message);
|
|
|
|
Display a message and exit with a fatal error code.
|
|
|
|
=cut
|
|
|
|
# Note: not certain why this is in use instead of die. Probably because
|
|
# the exit code of die is 255? Doesn't appear to be used consistently.
|
|
sub fatal (@) { print STDERR "@_\n"; exit 1 }
|
|
|
|
|
|
=head3 can_compress
|
|
|
|
my $can_compress = can_compress;
|
|
|
|
Returns true if Compress::Zlib is available, false otherwise.
|
|
|
|
=cut
|
|
|
|
my $can_compress;
|
|
sub can_compress {
|
|
return $can_compress if defined $can_compress;
|
|
|
|
return $can_compress = eval { require Compress::Zlib; };
|
|
}
|
|
|
|
|
|
=head3 canonicalize_path
|
|
|
|
my $canoncalized_path = canonicalize_path($path);
|
|
|
|
Converts $path into a canonical form which is safe to pass to the SVN
|
|
API as a file path.
|
|
|
|
=cut
|
|
|
|
# Turn foo/../bar into bar
|
|
sub _collapse_dotdot {
|
|
my $path = shift;
|
|
|
|
1 while $path =~ s{/[^/]+/+\.\.}{};
|
|
1 while $path =~ s{[^/]+/+\.\./}{};
|
|
1 while $path =~ s{[^/]+/+\.\.}{};
|
|
|
|
return $path;
|
|
}
|
|
|
|
|
|
sub canonicalize_path {
|
|
my $path = shift;
|
|
my $rv;
|
|
|
|
# The 1.7 way to do it
|
|
if ( defined &SVN::_Core::svn_dirent_canonicalize ) {
|
|
$path = _collapse_dotdot($path);
|
|
$rv = SVN::_Core::svn_dirent_canonicalize($path);
|
|
}
|
|
# The 1.6 way to do it
|
|
# This can return undef on subversion-perl-1.4.2-2.el5 (CentOS 5.2)
|
|
elsif ( defined &SVN::_Core::svn_path_canonicalize ) {
|
|
$path = _collapse_dotdot($path);
|
|
$rv = SVN::_Core::svn_path_canonicalize($path);
|
|
}
|
|
|
|
return $rv if defined $rv;
|
|
|
|
# No SVN API canonicalization is available, or the SVN API
|
|
# didn't return a successful result, do it ourselves
|
|
return _canonicalize_path_ourselves($path);
|
|
}
|
|
|
|
|
|
sub _canonicalize_path_ourselves {
|
|
my ($path) = @_;
|
|
my $dot_slash_added = 0;
|
|
if (substr($path, 0, 1) ne "/") {
|
|
$path = "./" . $path;
|
|
$dot_slash_added = 1;
|
|
}
|
|
$path =~ s#/+#/#g;
|
|
$path =~ s#/\.(?:/|$)#/#g;
|
|
$path = _collapse_dotdot($path);
|
|
$path =~ s#/$##g;
|
|
$path =~ s#^\./## if $dot_slash_added;
|
|
$path =~ s#^\.$##;
|
|
return $path;
|
|
}
|
|
|
|
|
|
=head3 canonicalize_url
|
|
|
|
my $canonicalized_url = canonicalize_url($url);
|
|
|
|
Converts $url into a canonical form which is safe to pass to the SVN
|
|
API as a URL.
|
|
|
|
=cut
|
|
|
|
sub canonicalize_url {
|
|
my $url = shift;
|
|
|
|
# The 1.7 way to do it
|
|
if ( defined &SVN::_Core::svn_uri_canonicalize ) {
|
|
return SVN::_Core::svn_uri_canonicalize($url);
|
|
}
|
|
# There wasn't a 1.6 way to do it, so we do it ourself.
|
|
else {
|
|
return _canonicalize_url_ourselves($url);
|
|
}
|
|
}
|
|
|
|
|
|
sub _canonicalize_url_path {
|
|
my ($uri_path) = @_;
|
|
|
|
my @parts;
|
|
foreach my $part (split m{/+}, $uri_path) {
|
|
$part =~ s/([^!\$%&'()*+,.\/\w:=\@_`~-]|%(?![a-fA-F0-9]{2}))/sprintf("%%%02X",ord($1))/eg;
|
|
push @parts, $part;
|
|
}
|
|
|
|
return join('/', @parts);
|
|
}
|
|
|
|
sub _canonicalize_url_ourselves {
|
|
my ($url) = @_;
|
|
if ($url =~ m#^([^:]+)://([^/]*)(.*)$#) {
|
|
my ($scheme, $domain, $uri) = ($1, $2, _canonicalize_url_path(canonicalize_path($3)));
|
|
$url = "$scheme://$domain$uri";
|
|
}
|
|
$url;
|
|
}
|
|
|
|
|
|
=head3 join_paths
|
|
|
|
my $new_path = join_paths(@paths);
|
|
|
|
Appends @paths together into a single path. Any empty paths are ignored.
|
|
|
|
=cut
|
|
|
|
sub join_paths {
|
|
my @paths = @_;
|
|
|
|
@paths = grep { defined $_ && length $_ } @paths;
|
|
|
|
return '' unless @paths;
|
|
return $paths[0] if @paths == 1;
|
|
|
|
my $new_path = shift @paths;
|
|
$new_path =~ s{/+$}{};
|
|
|
|
my $last_path = pop @paths;
|
|
$last_path =~ s{^/+}{};
|
|
|
|
for my $path (@paths) {
|
|
$path =~ s{^/+}{};
|
|
$path =~ s{/+$}{};
|
|
$new_path .= "/$path";
|
|
}
|
|
|
|
return $new_path .= "/$last_path";
|
|
}
|
|
|
|
|
|
=head3 add_path_to_url
|
|
|
|
my $new_url = add_path_to_url($url, $path);
|
|
|
|
Appends $path onto the $url. If $path is empty, $url is returned unchanged.
|
|
|
|
=cut
|
|
|
|
sub add_path_to_url {
|
|
my($url, $path) = @_;
|
|
|
|
return $url if !defined $path or !length $path;
|
|
|
|
# Strip trailing and leading slashes so we don't
|
|
# wind up with http://x.com///path
|
|
$url =~ s{/+$}{};
|
|
$path =~ s{^/+}{};
|
|
|
|
# If a path has a % in it, URI escape it so it's not
|
|
# mistaken for a URI escape later.
|
|
$path =~ s{%}{%25}g;
|
|
|
|
return join '/', $url, $path;
|
|
}
|
|
|
|
1;
|