#!/usr/bin/perl -w

# $Id$

# 20040410 stephan.duehr@suse.de
# Funktion dieses Scripts:
# Es sollen Konfigurationsdatei (z.B. in /etc und /var) im CVS gepflegt werden.
# Überprüfen welche Dateien sich gegenüber der CVS-Arbeitskopie geändert haben
# und kopiert diese auf Wunsch in das CVS-Arbeitsverzeichnis

# Parameter: CVS-Arbeitsverzeichnis
#            (dort muß die Verzeichnisstruktur bezogen auf / abgebildet sein, 
#            z.B. etc, var usw.

use strict;

use Env qw($DASSCM_PROD $DASSCM_REPO $USER $DASSCM_USER $DASSCM_PW);
use Cwd;
use POSIX qw/getpgrp tcgetpgrp/;
use File::Find;
use File::Compare;
use File::Copy;


my $cvsworkdir = $ARGV[0];
if(! defined $cvsworkdir) {
	$cvsworkdir = $DASSCM_REPO;
}
usage() if (! defined $cvsworkdir);
# Mit "." als Pfadangabe funktionieren diverse Funktionen nicht
# => ersetzen durch vollständigen absoluten Pfad
if ($cvsworkdir eq ".") {
  $cvsworkdir = $ENV{'PWD'};
}

# abschließenden "/" entfernen, falls vorhanden
$cvsworkdir =~ s/\/$//g;

(-d $cvsworkdir) || die "Fehler: $cvsworkdir ist kein Verzeichnis!";


my %changedfiles = ();

File::Find::find(\&cvscheck, $cvsworkdir);

# Liste der geänderten Files ausgeben, falls nicht leer
# Anzahl Elemente im Hash???
my @changedfiles = keys %changedfiles;

if ($#changedfiles > -1) {
  print "Geänderte Dateien:\n";
  foreach my $key (keys %changedfiles) {
    print "$key\n";
  }
  if (I_am_interactive()) {
    print "Die Dateien nach $cvsworkdir kopieren? (j/n)";
    my $line = <STDIN>;
    chomp($line);
    if ($line eq "j") {
      print "kopiere...\n";
      foreach my $key (keys %changedfiles) {
        print "$key --> $changedfiles{$key} ";
        copy($key, $changedfiles{$key}) || print "(fehlgeschlagen)";
        print "\n";
      }
      print "bitte noch manuell einen commit ... ausführen.\n";
      # CVS Environment prüfen
      #print "Hinweis: CVSROOT nicht gesetzt\n" unless defined $ENV{'CVSROOT'};
    }
  }
}
else {
  print "keine geänderten Dateien in $cvsworkdir gefunden.\n";
}
print "\n";

sub cvscheck {
  return unless -f;	# keine Directories
  return if $File::Find::dir =~ /\/CVS$/;	# ignoriere CVS-Verzeichnisse
  return if $File::Find::dir =~ /\/\.svn/;	# ignoriere Subversion Verzeichnisse (inkl. Unterverzeichnisse)
  my $cvsworkfile = "$File::Find::dir/$_";
  #print "$cvsworkfile\n";
  # Ursprungspfad ermitteln
  $cvsworkfile =~ /${cvsworkdir}\/(.+)/;
  my $realfile = "/" . $1;
  # relativer Pfad zur CVS-Arbeitsdatei
  my $relcvsworkfile = $1;
  (-r $realfile) || die("Fehler: $realfile existiert nicht oder ist nicht lesbar");
  (-r "$cvsworkfile") || die("Fehler: $cvsworkfile ist nicht lesbar");
  if (compare($cvsworkfile,$realfile) != 0) {
    # Dateien unterscheiden sich
    (-w $cvsworkfile) || die("Fehler: kein Schreibrecht auf $cvsworkfile");
    # Arbeitskopie durch Kopie ersetzen
    #copy($realfile,$cvsworkfile) || die("Fehler beim kopieren $realfile --> $cvsworkfile");
    $changedfiles{"$realfile"} = $cvsworkfile;
  }
}


sub I_am_interactive {
    local *TTY;  # local file handle
    open(TTY, "/dev/tty") or die "can't open /dev/tty: $!";
    my $tpgrp = tcgetpgrp(fileno(TTY));
    my $pgrp  = getpgrp();
    close TTY;
    return ($tpgrp == $pgrp);
}

sub usage {
print <<EOF;
Funktion dieses Scripts:
Es sollen Konfigurationsdatei (z.B. in /etc und /var) 
im Versionskontrollsystem (Subversion oder CVS) gepflegt werden.
Überprüfen welche Dateien sich gegenüber der CVS-Arbeitskopie geändert haben und kopiert diese auf Wunsch in das Subversion/CVS-Arbeitsverzeichnis

Parameter: Subversion/CVS-Arbeitsverzeichnis
           (dort muß die Verzeichnisstruktur bezogen auf / abgebildet sein, 
           z.B. etc, var usw.)
	   Alternativ kann dieses über die Umgebungsvariable
	   \$DASSCM_REPO gesetzt sein.

EOF
exit 1;
}
