From a6ed7fc6ac9d45733c03e935d1a6e5ec08871944 Mon Sep 17 00:00:00 2001 From: Modestas Vainius Date: Mon, 29 Jun 2009 22:00:26 +0300 Subject: [PATCH] Support absolute paths for builddir. If build directory is absolute or ../ path, _rel2rel falls back to absolute paths. Try even harder to convert supplied builddir to relative in _set_builddir(). Signed-off-by: Modestas Vainius --- Debian/Debhelper/Buildsystem.pm | 75 ++++++++++++++++++++------------ t/buildsystems/buildsystem_tests | 23 ++++++---- 2 files changed, 60 insertions(+), 38 deletions(-) diff --git a/Debian/Debhelper/Buildsystem.pm b/Debian/Debhelper/Buildsystem.pm index 8fcb97e..494d229 100644 --- a/Debian/Debhelper/Buildsystem.pm +++ b/Debian/Debhelper/Buildsystem.pm @@ -57,16 +57,16 @@ sub new { my ($class, %opts)=@_; my $this = bless({ sourcedir => '.', - builddir => undef, }, $class); + builddir => undef, + cwd => Cwd::getcwd() }, $class); if (exists $opts{sourcedir}) { # Get relative sourcedir abs_path (without symlinks) - my $curdir = Cwd::getcwd(); my $abspath = Cwd::abs_path($opts{sourcedir}); - if (! -d $abspath || $abspath !~ /^\Q$curdir\E/) { + if (! -d $abspath || $abspath !~ /^\Q$this->{cwd}\E/) { error("invalid or non-existing path to the source directory: ".$opts{sourcedir}); } - $this->{sourcedir} = File::Spec->abs2rel($abspath, $curdir); + $this->{sourcedir} = File::Spec->abs2rel($abspath, $this->{cwd}); } if (exists $opts{builddir}) { $this->_set_builddir($opts{builddir}); @@ -79,17 +79,27 @@ sub new { # unset the build directory. sub _set_builddir { my $this=shift; - my $builddir=shift; - $this->{builddir} = ($builddir) ? $builddir : $this->DEFAULT_BUILD_DIRECTORY; - - # Canonicalize. If build directory ends up the same as source directory, drop it - if (defined $this->{builddir}) { - $this->{builddir} = $this->canonpath($this->{builddir}); - if ($this->{builddir} eq $this->get_sourcedir()) { - $this->{builddir} = undef; + my $builddir=shift || $this->DEFAULT_BUILD_DIRECTORY; + + if (defined $builddir) { + $builddir = $this->canonpath($builddir); # Canonicalize + + # Sanitize $builddir + if ($builddir =~ m#^\.\./#) { + # We can't handle those as relative. Make them absolute + $builddir = File::Spec->catdir($this->{cwd}, $builddir); + } + elsif ($builddir =~ /\Q$this->{cwd}\E/) { + $builddir = File::Spec::abs2rel($builddir, $this->{cwd}); + } + + # If build directory ends up the same as source directory, drop it + if ($builddir eq $this->get_sourcedir()) { + $builddir = undef; } } - return $this->{builddir}; + $this->{builddir} = $builddir; + return $builddir; } # This instance method is called to check if the build system is able @@ -167,16 +177,23 @@ sub canonpath { return (@canon + $back > 0) ? join('/', ('..')x$back, @canon) : '.'; } -# Given both $path and $base are relative to the same directory, -# converts and returns path of $path being relative the $base. +# Given both $path and $base are relative to the $root, converts and +# returns path of $path being relative to the $base. If either $path or +# $base is absolute, returns another $path (converted to) absolute. sub _rel2rel { my ($this, $path, $base, $root)=@_; - $root = "/tmp" if !defined $root; - - return File::Spec->abs2rel( - File::Spec->rel2abs($path, $root), - File::Spec->rel2abs($base, $root) - ); + $root = $this->{cwd} unless defined $root; + + if (File::Spec->file_name_is_absolute($path)) { + return $path; + } elsif (File::Spec->file_name_is_absolute($base)) { + return File::Spec->rel2abs($path, $root); + } else { + return File::Spec->abs2rel( + File::Spec->rel2abs($path, $root), + File::Spec->rel2abs($base, $root) + ); + } } # Get path to the source directory @@ -274,10 +291,9 @@ sub doit_in_sourcedir { my $this=shift; if ($this->get_sourcedir() ne '.') { my $sourcedir = $this->get_sourcedir(); - my $curdir = Cwd::getcwd(); $this->_cd($sourcedir); doit(@_); - $this->_cd($this->_rel2rel($curdir, $sourcedir, $curdir)); + $this->_cd($this->_rel2rel($this->{cwd}, $sourcedir)); } else { doit(@_); @@ -292,10 +308,9 @@ sub doit_in_builddir { my $this=shift; if ($this->get_buildpath() ne '.') { my $buildpath = $this->get_buildpath(); - my $curdir = Cwd::getcwd(); $this->_cd($buildpath); doit(@_); - $this->_cd($this->_rel2rel($curdir, $buildpath, $curdir)); + $this->_cd($this->_rel2rel($this->{cwd}, $buildpath)); } else { doit(@_); @@ -319,10 +334,12 @@ sub rmdir_builddir { doit("rm", "-rf", $buildpath); pop @spdir; } - # If build directory had 2 or more levels, delete empty - # parent directories until the source directory level. - while (($peek=pop(@spdir)) && $peek ne '.' && $peek ne '..') { - last if ! rmdir($this->get_sourcepath(File::Spec->catdir(@spdir, $peek))); + # If build directory is relative and had 2 or more levels, delete + # empty parent directories until the source directory level. + if (not File::Spec->file_name_is_absolute($buildpath)) { + while (($peek=pop(@spdir)) && $peek ne '.' && $peek ne '..') { + last if ! rmdir($this->get_sourcepath(File::Spec->catdir(@spdir, $peek))); + } } } return 1; diff --git a/t/buildsystems/buildsystem_tests b/t/buildsystems/buildsystem_tests index e54663c..c432d3e 100755 --- a/t/buildsystems/buildsystem_tests +++ b/t/buildsystems/buildsystem_tests @@ -1,6 +1,6 @@ #!/usr/bin/perl -use Test::More tests => 228; +use Test::More tests => 230; use strict; use warnings; @@ -66,14 +66,18 @@ is( $BS_CLASS->canonpath("path/to/../../../somewhere"), is( $BS_CLASS->canonpath("./"), ".", "canonpath no4" ); is( $BS_CLASS->canonpath("/absolute/path/./somewhere/../to/nowhere"), "/absolute/path/to/nowhere", "canonpath no5" ); -is( $BS_CLASS->_rel2rel("path/my/file", "path/my"), +is( $BS_CLASS->_rel2rel("path/my/file", "path/my", "/tmp"), "file", "_rel2rel no1" ); -is( $BS_CLASS->_rel2rel("path/dir/file", "path/my"), +is( $BS_CLASS->_rel2rel("path/dir/file", "path/my", "/tmp"), "../dir/file", "_rel2rel no2" ); is( $BS_CLASS->_rel2rel("file", "/root/path/my", "/root"), - "../../file", "_rel2rel no3" ); -is( $BS_CLASS->_rel2rel(".", "."), ".", "_rel2rel no4" ); -is( $BS_CLASS->_rel2rel("path", "path/"), ".", "_rel2rel no5" ); + "/root/file", "_rel2rel abs no3" ); +is( $BS_CLASS->_rel2rel(".", ".", "/tmp"), ".", "_rel2rel no4" ); +is( $BS_CLASS->_rel2rel("path", "path/", "/tmp"), ".", "_rel2rel no5" ); +is( $BS_CLASS->_rel2rel("/absolute/path", "anybase", "/tmp"), + "/absolute/path", "_rel2rel abs no6"); +is( $BS_CLASS->_rel2rel("relative/path", "/absolute/base", "/tmp"), + "/tmp/relative/path", "_rel2rel abs no7"); ### Test Buildsystem class path API methods under different configurations sub test_buildsystem_paths_api { @@ -355,17 +359,18 @@ if (defined \$bs) { EOF } +$tmp = Cwd::getcwd(); is_deeply( process_stdout("$^X -- - --builddirectory='autoconf/bld dir' --sourcedirectory autoconf", get_load_bs_source(undef, "configure")), - [ 'NAME=autoconf', 'builddir=autoconf/bld dir', 'makecmd=make', 'sourcedir=autoconf' ], + [ 'NAME=autoconf', 'builddir=autoconf/bld dir', "cwd=$tmp", 'makecmd=make', 'sourcedir=autoconf' ], "autoconf autoselection and sourcedir/builddir" ); is_deeply( process_stdout("$^X -- - -Sautoconf -D autoconf", get_load_bs_source("autoconf", "build")), - [ 'NAME=autoconf', 'builddir=undef', 'makecmd=make', 'sourcedir=autoconf' ], + [ 'NAME=autoconf', 'builddir=undef', "cwd=$tmp", 'makecmd=make', 'sourcedir=autoconf' ], "forced autoconf and sourcedir" ); is_deeply( process_stdout("$^X -- - -B -Sautoconf", get_load_bs_source("autoconf", "build")), - [ 'NAME=autoconf', "builddir=$default_builddir", 'makecmd=make', 'sourcedir=.' ], + [ 'NAME=autoconf', "builddir=$default_builddir", "cwd=$tmp", 'makecmd=make', 'sourcedir=.' ], "forced autoconf and default build directory" ); # Build the autoconf test package -- 2.39.2