# A debhelper build system class for building Python libraries
#
# Copyright: © 2012-2013 Piotr Ożarowski
# License: GPL-2+

# TODO:
# * save check_auto_buildable's result and pass it later via --system to speed things up
# * support for dh --parallel

package Debian::Debhelper::Buildsystem::pybuild;

use strict;
use Cwd ();
use Debian::Debhelper::Dh_Lib qw(error);
use base 'Debian::Debhelper::Buildsystem';

sub DESCRIPTION {
	"Python pybuild"
}

sub check_auto_buildable {
	my $this=shift;
	return $this->doit_in_sourcedir('pybuild', '--detect', '--really-quiet');
}

sub new {
	my $class=shift;
	my $this=$class->SUPER::new(@_);
	$this->enforce_in_source_building();

	if (!$ENV{'PYBUILD_INTERPRETERS'}) {
		$this->{pydef} = `pyversions -vd 2>/dev/null`;
		$this->{pydef} =~ s/\s+$//;
		$this->{pyvers} = `pyversions -vr 2>/dev/null`;
		$this->{pyvers} =~ s/\s+$//;
		$this->{py3def} = `py3versions -vd 2>/dev/null`;
		$this->{py3def} =~ s/\s+$//;
		$this->{py3vers} = `py3versions -vr 2>/dev/null`;
		$this->{py3vers} =~ s/\s+$//;
		$this->{pypydef} = `pypy -c 'from sys import pypy_version_info as i; print("%s.%s" % (i.major, i.minor))' 2>/dev/null`;
		$this->{pypydef} =~ s/\s+$//;
	}

	return $this;
}

sub configure {
	my $this=shift;
	foreach my $command ($this->pybuild_commands('configure', @_)) {
		$this->doit_in_sourcedir($command);
	}
}

sub build {
	my $this=shift;
	foreach my $command ($this->pybuild_commands('build', @_)) {
		$this->doit_in_sourcedir($command);
	}
}

sub install {
	my $this=shift;
	my $destdir=shift;
	foreach my $command ($this->pybuild_commands('install', @_)) {
		$this->doit_in_sourcedir("$command --dest-dir '$destdir'");
	}
}

sub test {
	my $this=shift;
	foreach my $command ($this->pybuild_commands('test', @_)) {
		$this->doit_in_sourcedir($command);
	}
}

sub clean {
	my $this=shift;
	foreach my $command ($this->pybuild_commands('clean', @_)) {
		$this->doit_in_sourcedir($command);
	}
	$this->doit_in_sourcedir('rm', '-rf', '.pybuild/');
}

sub pybuild_commands {
	my $this=shift;
	my $step=shift;
	my @options = @_;
	my @result;

	if ($ENV{'PYBUILD_INTERPRETERS'}) {
		push @result, "pybuild --$step @options";
	}
	else {
		# get interpreter packages from Build-Depends{,-Indep}:
		# NOTE: possible problems with alternative/versioned dependencies
		my @deps = $this->python_build_dependencies();

		my $pyall = 0;
		my $pyalldbg = 0;
		my $py3all = 0;
		my $py3alldbg = 0;

		my $i = 'python{version}';

		# Python
		if ($this->{pyvers}) {
			if (grep {$_ eq 'python-all' or $_ eq 'python-all-dev'} @deps) {
				$pyall = 1;
				push @result, "pybuild --$step -i $i -p '$this->{pyvers}' @options";
			}
			if (grep {$_ eq 'python-all-dbg'} @deps) {
				$pyalldbg = 1;
				push @result, "pybuild --$step -i $i-dbg -p '$this->{pyvers}' @options";
			}
		}
		if ($this->{pydef}) {
			if (not $pyall and grep {$_ eq 'python' or $_ eq 'python-dev'} @deps) {
				push @result, "pybuild --$step -i $i -p '$this->{pydef}' @options";
			}
			if (not $pyalldbg and grep {$_ eq 'python-dbg'} @deps) {
				push @result, "pybuild --$step -i $i-dbg -p '$this->{pydef}' @options";
			}
		}

		# Python 3
		if ($this->{py3vers}) {
			my $i = 'python{version}';
			if (grep {$_ eq 'python3-all' or $_ eq 'python3-all-dev'} @deps) {
				$py3all = 1;
				push @result, "pybuild --$step -i $i -p '$this->{py3vers}' @options";
			}
			if (grep {$_ eq 'python3-all-dbg'} @deps) {
				$py3alldbg = 1;
				push @result, "pybuild --$step -i $i-dbg -p'$this->{py3vers}' @options";
			}
		}
		if ($this->{py3def}) {
			if (not $pyall and grep {$_ eq 'python3' or $_ eq 'python3-dev'} @deps) {
 				# TODO: "python3" case: should X-Python3-Version header in debian/control be also required here?
				push @result, "pybuild --$step -i $i -p '$this->{py3def}' @options";
			}
			if (not $pyalldbg and grep {$_ eq 'python3-dbg'} @deps) {
				push @result, "pybuild --$step -i $i-dbg -p '$this->{py3def}' @options";
			}
		}
		# TODO: pythonX.Y → `pybuild -i python{version} -p X.Y`

		# PyPy
		if ($this->{pypydef} and grep {$_ eq 'pypy'} @deps) {
			push @result, "pybuild --$step -i pypy -p '$this->{pypydef}' @options";
		}
	}
	return @result;
}

sub python_build_dependencies {
	my $this=shift;

	my @result;
	open (CONTROL, 'debian/control') || error("cannot read debian/control: $!\n");
	foreach my $builddeps (join('', <CONTROL>) =~ 
			/^Build-Depends[^:]*:.*\n(?:^[^\w\n#].*\n)*/gmi) {
		while ($builddeps =~ /[\s,](pypy|python[0-9\.]*(-all)?((-dev)|(-dbg))?)[\s,]|$/g) {
			if ($1) {push @result, $1};
		}
	}

	close CONTROL;
	return @result;
}

1
