#!/usr/bin/perl -w
# -*- mode: perl; -*-

=head1 NAME
    
    dh-svn-release - работа с релизами в стиле "Я.Директ"

=head1 SINOPSYS

    dh-svn-release ./svnroot ./yandex-direct-qqq/debian
    dh-svn-release --no-check ./svnroot ./yandex-direct-qqq/debian
    dh-svn-release -r stable ./svnroot ./yandex-direct-qqq/debian

=head1 DESCRIPTION

    Делает следующее:
    TODO

    Параметры командной строки:
    --no-check
    --version
    --release
    --urgency

=cut                      

use strict;
use IPC::Open2;
use File::Slurp;
use Debian::Debhelper::Dh_Lib;
use Data::Dumper;
use Getopt::Long;

use Yandex::Shell;

# TODO $BRANCH_RE далее интерполируется в другом регэкспе, имеет смысл сделать его обычной строкой
my $BRANCH_RE = qr!trunk|releases/release-\d+|(?:tags|branches)/[a-z0-9\-\_\.]+|lego|limtest/[a-z0-9\-\_\.]+-\d+-\d+!i;
my $NEW_BRANCH_RE = 'trunk/arcadia/direct/perl|branches/direct/release/perl/release-[0-9]+|branches/direct/perl/[^/]+';

my $DH_SVN_RELEASE_CHECK = !$ENV{DH_SVN_RELEASE_NO_CHECK};
my $RELEASE = 'unstable';
my $URGENCY = 'low';
my $VERSION = $ENV{VERSION};
my $SVN_IGNORE = [];

GetOptions(
    "check!" => \$DH_SVN_RELEASE_CHECK,
    "release=s" => \$RELEASE,
    "urgency=s" => \$URGENCY,
    "version=s" => \$VERSION,
    "svn-ignore=s" => $SVN_IGNORE,
    "help" => sub {
        system("podselect -section NAME -section DESCRIPTION $0 | pod2text-utf8 >&2");
        exit(0);
    },  
    ) || die "Incorrect params: $!";

if ($VERSION && $VERSION !~ /^[a-z0-9\-\.\~:]+$/i) {
    die "Incorrect version: $VERSION";
}
if (@ARGV != 2) {
   die "Usage: $0 svn_root debian_root";
}
my @missing_dirs = grep { !-d $_ } @ARGV[0, 1];
if (@missing_dirs) {
    my $error_msg = join "\n", map { "No such directory: $_" } @missing_dirs;
    die $error_msg;
}

my ($svn_root, $debian_root) = @ARGV;
my $version_file = "$debian_root/version";
my $changelog_file = "$debian_root/changelog";
my $pkg = basename(dirname($debian_root));

my %SVN_INFO = svn_info($svn_root);
my $version = $SVN_INFO{Revision};
my $PROJ_SVN_ROOT;
if ($SVN_INFO{URL} =~ m!^(.*?)/($BRANCH_RE)\/?$!i
 || $SVN_INFO{URL} =~ m!^(.*?)/($NEW_BRANCH_RE)/?$!i
 ) {
    $PROJ_SVN_ROOT = $1;
    my $branch = $2;
    if ($branch eq 'trunk' || $branch eq 'lego'
     || $branch eq 'trunk/arcadia/direct/perl'
    ) {
        # trunk
        $version = "1.$version";
    } elsif ($branch =~ /^releases\/release-(\d+)$/
          || $branch =~ m!^branches/direct/release/perl/release-([0-9]+)$!
    ) {
        # releases/release-NNN
        $version = "1.$1.$version";
    } elsif ($branch =~ /^(?:branches|tags)\/(.*)$/
          || $branch =~ m!^branches/direct/perl/([^/]+)$!
    ) {
        # branches|tags
        my $name = $1;
        $name =~ s/_/-/g;
        $name =~ s!^.*/!!g;
        $version = "1.$version~$name";
    } elsif ($branch =~ m!^limtest/([a-z0-9\-\_\.]+)-(\d+)-(\d+)$!i) {
        my ($name, $base_rev, $head_rev) = ($1, $2, $3);
        # преобразуем имя бранча согласованно с tracker-limtest.pl: меняем "_" на "-" и аккуратно укорачиваем
        $name =~ s/_/-/g;
        $name = substr($name, 0, 45);
        $name =~ s/-+$//;
        $version = "1.$base_rev.$head_rev~$name";
    } else {
        die "Unrecognizable branch $branch";
    }
}
else {
    die "Incorrect SVN URL: $SVN_INFO{URL}";
}

if ($DH_SVN_RELEASE_CHECK) {
    my %DEBIAN_SVN_INFO = svn_info($debian_root);

    yash_qx( "svn-verify-working-copy", $svn_root );
    yash_qx( "svn-verify-working-copy", $debian_root, "--skip", "svnroot" );
    # svn-verify-working-copy не поймает сброшенный x-бит на скриптах
    # Надо или не полагаться, что он правильный (выставлять при сборке пакета), или восстанавливать
    # svn revert восстанавливает исполнимость, и при этом не ходит в репозиторий, это локальная операция
    # до этого все возможные заметные правки в рабочей копии уже отловили svn-verify-working-copy, так что ничего не должно потеряться при revert
    yash_qx( "svn", "revert", "-R", $svn_root );
    yash_qx( "svn", "revert", "-R", $debian_root );

    # проверяем неизменённость текущей дирректории
    unless (
        $PROJ_SVN_ROOT eq 'svn+ssh://arcadia.yandex.ru/arc' && ($DEBIAN_SVN_INFO{URL} =~ /^\Q$PROJ_SVN_ROOT\E\/($NEW_BRANCH_RE)\/(.*?)\/?$/)
        || 
        $PROJ_SVN_ROOT ne 'svn+ssh://arcadia.yandex.ru/arc' && ($DEBIAN_SVN_INFO{URL} =~ /^\Q$PROJ_SVN_ROOT\E\/($BRANCH_RE)\/(.*?)\/?$/) 
    ){
        die "debian svn url $DEBIAN_SVN_INFO{URL} mismatch with $PROJ_SVN_ROOT";
    }
}

if ($VERSION) {
    $version = $VERSION;
} elsif (-f $version_file && scalar(read_file($version_file)) =~ /\Q$version\E(?:[\-\~][\w\d\_\~]+)?\-(\d+)$/ ) {
    $version = "$version-".($1+1);
} else {
    $version = "$version-1";
}

if (!$DH_SVN_RELEASE_CHECK) {
    my $sep = $version =~ /~/ ? '-' : '~';
    my ($ver2) = $version =~ /\-(\d+)$/;                
    $ver2 ||= 1;
    $version =~ s/-([^\-]+)$/${sep}dirty-$ver2/;
}

my $changelog_author = " -- ".($ENV{DEBFULLNAME} || 'unknown')." <".($ENV{DEBEMAIL} || $ENV{EMAIL} || 'unknown@unknown.ru').">  ".`date -R`;

write_file($version_file, {atomic => 1}, $version);
write_file($changelog_file, {atomic => 1},
qq{$pkg ($version) $RELEASE; urgency=$URGENCY

  * next auto build

$changelog_author


});

sub svn_info {
    my ($path) = @_;
    return 
        map {/^([^:]+):\s*(.*)/ ? ($1 => $2) : ()}
        split /\n/, yash_qx("LC_ALL=C svn", "info", $path);
}

