#!/usr/bin/perl
##
##  sCVS -- Switch CVS Repository
##  Copyright (c) 1997 Ralf S. Engelschall, All Rights Reserved.
##

require 5.004;

use Term::ANSIColor;
use File::Spec;
use IPC::Open2;
use Cwd;


##
##   1. Find .scvsrc files and read contents into %CVSROOTS hash
##

%CVSROOTS = ();

#   create list of dirs back to root
($cwd = Cwd::cwd) =~ s|/$||;
$cwdT = $cwd;
while ($cwdT) {
    push(@DIR, $cwdT);
    $cwdT =~ s|/[^/]+$||;
}

#   search for .scvsrc files
foreach $dir (reverse(@DIR)) {
    if (-f "$dir/.scvsrc") {
        $reldir = File::Spec->abs2rel($dir);
        $reldir = '.' if $reldir eq '';
        $subdir = File::Spec->abs2rel($cwd, $dir);
        $rcfile = "$reldir/.scvsrc";
        process_rcfile($rcfile, $cwd, $reldir, $subdir);
    }
}

#   process a particular .scvsrc file
sub process_rcfile {
    my ($rcfile, $cwd, $reldir, $subdir) = @_;
    my ($rc, @E, $e);

    open($rc, "<", $rcfile);
    while (<$rc>) {
        next if (m|^\s*#|);
        next if (m|^\s*$|);
        if (m|^\s*(\S+)\s*$|) {
            $CVSROOTS{$1} = '';
        }
        elsif (m|^\s*(\S+)\s+\(\s*(.+?)\s*\)\s*$|) {
            $CVSROOTS{$1} = $2;
        }
        else {
            print STDERR "sCVS:Error: $rcfile, invalid line: '$_'\n";
            exit(1);
        }
    }
    close($rc);
}


##
##  2. Check for correct location to be called and
##     determine current configured CVS repository location
##

if (not -d "./CVS") {
    print STDERR "sCVS:Error: must stay inside a checked-out CVS tree.\n";
    exit(1);
}

open($root, "<", "CVS/Root");
$locC = <$root>;
$locC =~ s|\n$||;
close($root);

##
##  3. Create iSelect page with list of available CVS repositories
##     and fire up iSelect with it
##

$pos  = 0;
$list = '';
$n    = 1;
foreach $loc (keys(%CVSROOTS)) {
    $name = $CVSROOTS{$loc};
    if ($loc eq $locC) {
        $pos = $n;
        $act = '*';
    }
    else {
        $act = '';
    }
    $arg = sprintf("%1s  %-30s  %s<S:%s>", $act, $name, $loc, $loc);
    $arg =~ s|'|\'\\\'\'|g;
    $list .= " '$arg'";
    $n++;
}
if ($pos == 0) {
    $arg = sprintf("%1s  %-30s  %s<S:%s>", '*', 'UNKNOWN', $locC, $locC);
    $arg =~ s|'|\'\\\'\'|g;
    $list .= " '$arg'";
    $pos = $n;
}
$pos += 3;

$cmd = "iselect -n 'sCVS' -t 'Switch CVS Repository'" .
       " -p$pos -P" .
       " ''" .
       " 'Available Repositories:'" .
       " ''" .
       " $list" .
       " ''" .
       " 'Use CURSOR keys and RETURN to select or \'q\' to quit.'";
$rc = `exec $cmd`;
($pos, $locN) = ($rc =~ m|^(\d+):(.*)|);

if ($locN eq '') {
    print STDERR "sCVS: Aborted\n";
    exit(1);
}
elsif ($locN eq $locC) {
    print STDERR "Repository unchanged\n";
    exit(0);
}


##
##  4. Time to switch!
##

$prefixN = $locN;
$prefixN =~ s|^[^/]+||;

open2(my $find, "<&0", 'find', '.', '-noleaf', '-depth', '-type', 'd', '-name', 'CVS', '-print');
while (<$find>) {
    $dir = $_;
    $dir =~ s|^\./||;
    $dir =~ s|\n$||;
    $dirname = $dir;
    if (length($dirname) > 60) {
        $dirname = '..'.substr($dirname, length($dirname)-60, 60);
    }
    $dirname = sprintf("%-60s", $dirname);
    print STDERR "Processing: ".colored("$dirname", 'bold')."\r";

    open(FP, "<", "$dir/Root");
    $locO = <FP>;
    $locO =~ s|\n$||;
    close(FP);
    open(FP, ">", "$dir/Root");
    print FP "$locN\n";
    close(FP);
    $prefixO = $locO;
    $prefixO =~ s|^[^/]+||;

    open(FP, "<", "$dir/Repository");
    $subdir = <FP>;
    $subdir =~ s|\n$||;
    close(FP);
    $subdir =~ s|^$prefixO|$prefixN|;
    open(FP, ">", "$dir/Repository");
    print FP "$subdir\n";
    close(FP);
}
printf STDERR "%-78s\n", "Repository switched to $locN";
