2003-02-03 12:11:12 +00:00
|
|
|
#!/usr/bin/perl -w
|
|
|
|
|
|
|
|
|
|
# $Id$
|
|
|
|
|
# $Source$
|
|
|
|
|
|
2003-11-14 12:16:45 +00:00
|
|
|
#
|
|
|
|
|
# Copyright (c) 2003 Ward Wouts <ward@wouts.nl>
|
|
|
|
|
#
|
|
|
|
|
# Permission to use, copy, modify, and distribute this software for any
|
|
|
|
|
# purpose with or without fee is hereby granted, provided that the above
|
|
|
|
|
# copyright notice and this permission notice appear in all copies.
|
|
|
|
|
#
|
|
|
|
|
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
|
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
|
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
|
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
|
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
|
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
|
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
|
2003-02-03 12:11:12 +00:00
|
|
|
use strict;
|
2003-11-14 12:16:45 +00:00
|
|
|
use Sys::Hostname;
|
2003-02-03 12:11:12 +00:00
|
|
|
use Getopt::Std;
|
|
|
|
|
use File::Basename;
|
|
|
|
|
use File::Copy;
|
2003-11-14 12:16:45 +00:00
|
|
|
use Cwd;
|
|
|
|
|
use Cwd 'abs_path';
|
|
|
|
|
use vars qw(
|
2004-01-19 22:23:46 +00:00
|
|
|
$hostname
|
|
|
|
|
$cvspath
|
|
|
|
|
$editor
|
2004-01-25 15:27:10 +00:00
|
|
|
$catcmd
|
2004-01-19 22:23:46 +00:00
|
|
|
$cpcmd
|
|
|
|
|
$cvscmd
|
|
|
|
|
$mkdircmd
|
|
|
|
|
$sudocmd
|
|
|
|
|
$permsfile
|
2003-11-14 12:16:45 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$hostname = hostname();
|
|
|
|
|
#my $cvspath = "$ENV{HOME}/worktrees/systems/$hostname";
|
|
|
|
|
$editor = "vi";
|
2004-01-25 15:27:10 +00:00
|
|
|
$catcmd = "/bin/cat";
|
2003-11-14 12:16:45 +00:00
|
|
|
$cpcmd = "/bin/cp";
|
|
|
|
|
$cvscmd = "/usr/bin/cvs";
|
|
|
|
|
$mkdircmd = "/bin/mkdir";
|
|
|
|
|
$sudocmd = "/usr/bin/sudo";
|
|
|
|
|
|
|
|
|
|
&readconfig;
|
2003-02-03 12:11:12 +00:00
|
|
|
|
2004-01-19 22:23:46 +00:00
|
|
|
unless ( $permsfile ) {
|
|
|
|
|
$permsfile = $cvspath ? "$cvspath/PERMS" : "";
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-03 12:11:12 +00:00
|
|
|
my %option = ();
|
2003-11-14 12:16:45 +00:00
|
|
|
&cmdline;
|
2003-02-03 12:11:12 +00:00
|
|
|
|
2003-11-14 12:16:45 +00:00
|
|
|
if ( $cvspath ) {
|
|
|
|
|
&checkcvspath;
|
2003-02-03 12:11:12 +00:00
|
|
|
|
2003-11-14 12:16:45 +00:00
|
|
|
foreach ( @ARGV ) {
|
|
|
|
|
if ( -f $_ ) {
|
|
|
|
|
&incvs($_); # check if file exists in cvs else make it so
|
2004-01-22 20:47:12 +00:00
|
|
|
next unless &inperms($_); # check if file perms are registered or make it so
|
2003-11-14 12:16:45 +00:00
|
|
|
unless (&cmptocvs($_)) { # compare file to cvs
|
|
|
|
|
print "$_ not in sync with cvs version\n";
|
|
|
|
|
print "please fix this\n";
|
|
|
|
|
print "press enter to continue\n";
|
|
|
|
|
my $line = <>;
|
|
|
|
|
next;
|
|
|
|
|
}
|
|
|
|
|
if ( $option{e} ) {
|
|
|
|
|
&edit($_); # edit file
|
|
|
|
|
unless (&cmptocvs($_)) { # if changed... then:
|
|
|
|
|
&cvsupdate($_); # copy file to cvs & check in into cvs
|
|
|
|
|
# copy file back; don't change permissions
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2004-01-03 09:14:11 +00:00
|
|
|
if ( ! -e $_ && $option{e} ) {
|
2004-01-03 09:07:51 +00:00
|
|
|
&edit($_); # edit file
|
2004-01-03 09:14:11 +00:00
|
|
|
if ( -f $_ ) {
|
2004-01-03 09:07:51 +00:00
|
|
|
&cvsupdate($_); # copy file to cvs & check in into cvs
|
|
|
|
|
# copy file back; don't change permissions
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
print "$_ is not a file, skipping. Press enter to continue.\n";
|
|
|
|
|
my $enter = <>;
|
|
|
|
|
}
|
2003-11-14 12:16:45 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
foreach ( @ARGV ) {
|
|
|
|
|
&backup($_);
|
|
|
|
|
if ( $option{e} ) {
|
|
|
|
|
&edit;
|
2003-02-03 12:11:12 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-11-14 12:16:45 +00:00
|
|
|
sub cmdline {
|
2004-01-22 20:47:12 +00:00
|
|
|
getopts("ehp", \%option);
|
2003-11-14 12:16:45 +00:00
|
|
|
|
|
|
|
|
if ( $option{h} ) { &help; }
|
|
|
|
|
if ( scalar(@ARGV) == 0 ) { &help; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub readconfig {
|
|
|
|
|
if ( -f "$ENV{HOME}/.mycprc" && -r "$ENV{HOME}/.mycprc" ) {
|
2004-01-25 15:14:20 +00:00
|
|
|
do "$ENV{HOME}/.mycprc" or die "Couldn't parse $ENV{HOME}/.mycprc";
|
2003-11-14 12:16:45 +00:00
|
|
|
} elsif ( -f "/etc/mycp" && -r "/etc/mycp" ) {
|
2004-01-25 15:14:20 +00:00
|
|
|
do "/etc/mycp" or die "Couldn't parse /etc/mycp";
|
2003-11-14 12:16:45 +00:00
|
|
|
}
|
|
|
|
|
}
|
2003-02-03 12:11:12 +00:00
|
|
|
|
|
|
|
|
sub backup($) {
|
|
|
|
|
my $file = shift;
|
|
|
|
|
my ( $base, $dir, $backup, @stat, @timestamp, $sfx, $n );
|
|
|
|
|
$base = basename($file);
|
|
|
|
|
$dir = dirname($file);
|
|
|
|
|
my @months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
|
|
|
|
|
if ( -f $file ) {
|
|
|
|
|
@stat = stat($file);
|
|
|
|
|
@timestamp = localtime($stat[9]);
|
|
|
|
|
$timestamp[5] += 1900;
|
2003-02-03 15:57:30 +00:00
|
|
|
if ( length($timestamp[3]) < 2 ) { $timestamp[3] = "0$timestamp[3]"; }
|
2003-11-14 12:16:45 +00:00
|
|
|
|
|
|
|
|
#
|
|
|
|
|
# ouderwetse moron style
|
|
|
|
|
# sane style introduceren
|
|
|
|
|
#
|
|
|
|
|
|
2003-02-03 12:11:12 +00:00
|
|
|
$sfx = "$timestamp[3]$months[$timestamp[4]]$timestamp[5]";
|
2003-11-14 12:16:45 +00:00
|
|
|
|
|
|
|
|
print "Creating \"$dir/OLD\" directory\n";
|
|
|
|
|
unless ( -d "$dir/OLD" ) {
|
|
|
|
|
if ( -w $dir ) {
|
2004-01-25 15:14:20 +00:00
|
|
|
mkdir "$dir/OLD", 0777 or die "Couldn't create $dir/OLD: $!";
|
2003-11-14 12:16:45 +00:00
|
|
|
} else {
|
|
|
|
|
system("$sudocmd mkdir " . &escape("$dir/OLD"));
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-02-03 12:11:12 +00:00
|
|
|
$backup = "$dir/OLD/$base.$sfx";
|
|
|
|
|
|
|
|
|
|
if ( -e $backup && ! &cmp($file, $backup) ) {
|
|
|
|
|
$n = 1;
|
|
|
|
|
while ( -e "$backup-$n" && ! &cmp($file, "$backup-$n") ) {
|
|
|
|
|
$n++;
|
|
|
|
|
}
|
|
|
|
|
$backup = "$backup-$n";
|
|
|
|
|
}
|
|
|
|
|
|
2003-11-14 12:16:45 +00:00
|
|
|
if ( -w $file || -w &fullpath($file) ) {
|
2004-01-25 15:14:20 +00:00
|
|
|
copy("$file", "$backup") or die "Couldn't copy $file to $backup: $!";
|
2003-11-14 12:16:45 +00:00
|
|
|
} else {
|
|
|
|
|
system("$sudocmd $cpcmd " . &escape($file) . " " . &escape($backup));
|
|
|
|
|
}
|
2003-02-03 12:11:12 +00:00
|
|
|
|
|
|
|
|
} else {
|
2004-01-25 15:14:20 +00:00
|
|
|
die "No such file: $file";
|
2003-02-03 12:11:12 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-11-14 12:16:45 +00:00
|
|
|
sub incvs($) {
|
|
|
|
|
my $file = shift;
|
|
|
|
|
my $path = &fullpath($file);
|
|
|
|
|
if ( -f "$cvspath/$path/" . basename($file) ) {
|
|
|
|
|
return 1;
|
|
|
|
|
} else {
|
|
|
|
|
&cvsadd($file);
|
|
|
|
|
&checkin($file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-19 22:23:46 +00:00
|
|
|
sub inperms($) {
|
|
|
|
|
my $file = shift;
|
|
|
|
|
my $path = &fullpath($file);
|
|
|
|
|
my $fullname = "$path/" . basename($file);
|
|
|
|
|
my @stats = stat $fullname;
|
|
|
|
|
my $user = (getpwuid($stats[4]))[0];
|
|
|
|
|
my $group = (getgrgid($stats[5]))[0];
|
|
|
|
|
my $mode = sprintf "%lo", $stats[2];
|
|
|
|
|
$mode =~ s/.*(\d{4})$/$1/;
|
|
|
|
|
|
|
|
|
|
unless ( -f $permsfile ) {
|
2004-01-25 13:53:32 +00:00
|
|
|
open FH, ">$permsfile";
|
|
|
|
|
print FH <<EOT;
|
2004-01-19 22:23:46 +00:00
|
|
|
# \$Id\$
|
|
|
|
|
# \$Source\$
|
|
|
|
|
|
|
|
|
|
EOT
|
2004-01-25 13:53:32 +00:00
|
|
|
close FH;
|
2004-01-25 14:10:09 +00:00
|
|
|
my $cwd = cwd;
|
|
|
|
|
chdir dirname($permsfile);
|
2004-01-25 14:19:36 +00:00
|
|
|
system("$cvscmd add " . basename($permsfile));
|
|
|
|
|
system("$cvscmd ci -m initial " . basename($permsfile));
|
2004-01-25 14:10:09 +00:00
|
|
|
chdir $cwd;
|
2004-01-19 22:23:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
my $perms = &slurp($permsfile);
|
|
|
|
|
|
2004-01-25 16:25:32 +00:00
|
|
|
if ( $perms =~ /^(\d{4}):([^-:][^:]*):([^:]+?):($fullname)$/m ) {
|
2004-01-22 20:47:12 +00:00
|
|
|
if ( $1 eq $mode && $2 eq $user && $3 eq $group ) {
|
|
|
|
|
return 1;
|
|
|
|
|
} elsif ( $option{p} ){
|
2004-01-25 16:25:32 +00:00
|
|
|
$perms =~ s/^(\d{4}):([^-:][^:]*):([^:]+?):$fullname$/$mode:$user:$group:$fullname/m;
|
2004-01-22 20:47:12 +00:00
|
|
|
open(FH, ">>$permsfile");
|
|
|
|
|
print FH $perms;
|
|
|
|
|
close FH;
|
|
|
|
|
return 1;
|
|
|
|
|
} else {
|
|
|
|
|
print "$_ perms not in sync with registered version\n";
|
|
|
|
|
print "please fix this\n";
|
|
|
|
|
print "press enter to continue\n";
|
|
|
|
|
my $line = <>;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2004-01-19 22:23:46 +00:00
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
open(FH, ">>$permsfile");
|
|
|
|
|
print FH "$mode:$user:$group:$fullname\n";
|
|
|
|
|
close FH;
|
2004-01-25 15:43:29 +00:00
|
|
|
my $cwd = cwd;
|
|
|
|
|
chdir dirname($permsfile);
|
|
|
|
|
system("$cvscmd ci -m \"adding $fullname\" " . basename($permsfile));
|
|
|
|
|
chdir $cwd;
|
2004-01-22 20:47:12 +00:00
|
|
|
return 1;
|
2004-01-19 22:23:46 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-11-14 12:16:45 +00:00
|
|
|
sub edit($) {
|
|
|
|
|
if ( exists $ENV{'EDITOR'} ) {
|
|
|
|
|
$editor = $ENV{'EDITOR'};
|
|
|
|
|
}
|
|
|
|
|
if ( -w $_ ) {
|
|
|
|
|
system("$editor " . &escape($_));
|
|
|
|
|
} else {
|
|
|
|
|
system("$sudocmd $editor ". &escape($_));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub checkcvspath($) {
|
|
|
|
|
unless ( -d $cvspath ) {
|
|
|
|
|
print "$cvspath is not a directory. Set up cvs environment first.\n";
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub cvsadd($) {
|
|
|
|
|
my $file = shift;
|
|
|
|
|
my $cwd = cwd;
|
|
|
|
|
my $path = &fullpath($file);
|
|
|
|
|
$path =~ s|^\/||;
|
|
|
|
|
my $checkpath = $cvspath;
|
|
|
|
|
my $parent = $cvspath;
|
|
|
|
|
print "PATH: $path\n";
|
|
|
|
|
foreach my $i (split '/', $path) {
|
|
|
|
|
$checkpath .= "/$i";
|
|
|
|
|
if ( -d $checkpath ) {
|
|
|
|
|
print "$i issa dir\n";
|
|
|
|
|
} elsif ( -e $checkpath ) {
|
|
|
|
|
print "$i is not a dir, PROBLEM. Fix this by hand.\n";
|
|
|
|
|
exit;
|
|
|
|
|
} else {
|
|
|
|
|
print "making $checkpath\n";
|
|
|
|
|
mkdir $checkpath;
|
|
|
|
|
print "cd $parent\n";
|
|
|
|
|
chdir $parent;
|
|
|
|
|
system("$cvscmd add " . &escape($i));
|
|
|
|
|
}
|
|
|
|
|
$parent = $checkpath;
|
|
|
|
|
}
|
|
|
|
|
print "FILE: $file\n";
|
|
|
|
|
print "PATH: $checkpath\n";
|
2003-12-13 15:03:29 +00:00
|
|
|
chdir $cwd;
|
2004-01-25 15:14:20 +00:00
|
|
|
copy($file, $checkpath) || die "error copying file to cvstree: $!";
|
2003-11-14 12:16:45 +00:00
|
|
|
chdir $checkpath;
|
|
|
|
|
system("$cvscmd add " . &escape(basename($file)));
|
|
|
|
|
chdir $cwd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub cvsupdate($) {
|
|
|
|
|
my $file = shift;
|
|
|
|
|
©tocvs($file);
|
|
|
|
|
&checkin($file);
|
|
|
|
|
©fromcvs($file);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub copytocvs($) {
|
|
|
|
|
my $file = shift;
|
|
|
|
|
my $cwd = cwd;
|
|
|
|
|
my $path = "$cvspath/" . &fullpath($file);
|
|
|
|
|
copy($file, $path);
|
|
|
|
|
chdir($path);
|
|
|
|
|
system("$cvscmd ci " . &escape(basename($file)));
|
|
|
|
|
chdir $cwd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub checkin($) {
|
|
|
|
|
my $file = shift;
|
|
|
|
|
my $cwd = cwd;
|
|
|
|
|
my $path = &fullpath($file);
|
|
|
|
|
chdir "$cvspath/$path";
|
|
|
|
|
system("$cvscmd ci " . &escape(basename($file)));
|
|
|
|
|
chdir $cwd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub copyfromcvs($) {
|
|
|
|
|
my $file = shift;
|
|
|
|
|
my $path = &fullpath($file);
|
|
|
|
|
my $fullname = "$path/" . basename($file);
|
|
|
|
|
if ( -w $fullname) {
|
|
|
|
|
copy("$cvspath/$fullname", $fullname);
|
|
|
|
|
} else {
|
|
|
|
|
system("$sudocmd $cpcmd " . &escape("$cvspath/$fullname") . " " . &escape($fullname));
|
|
|
|
|
}
|
|
|
|
|
# also check file permissions
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub cmptocvs($) {
|
|
|
|
|
my $file = shift;
|
|
|
|
|
my $path = &fullpath($file);
|
|
|
|
|
my $fullname = "$path/" . basename($file);
|
|
|
|
|
return &cmp("$cvspath/$fullname", $fullname);
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-03 12:11:12 +00:00
|
|
|
sub cmp($$) {
|
|
|
|
|
my $source = shift;
|
|
|
|
|
my $target = shift;
|
2004-01-25 15:27:10 +00:00
|
|
|
my $sf = &slurp($source);
|
|
|
|
|
my $tf = &slurp($target);
|
2003-02-03 12:11:12 +00:00
|
|
|
$tf eq $sf;
|
|
|
|
|
}
|
|
|
|
|
|
2003-11-14 12:16:45 +00:00
|
|
|
sub askyn($) {
|
|
|
|
|
my $question = shift;
|
|
|
|
|
while (1) {
|
|
|
|
|
print "$question [y/n]? ";
|
|
|
|
|
my $line = <>;
|
|
|
|
|
if ( $line =~ /^y$/ ) {
|
|
|
|
|
return 1;
|
|
|
|
|
} elsif ( $line =~ /^n$/ ) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub escape($) {
|
|
|
|
|
my $string = shift;
|
|
|
|
|
$string =~ s/([ \&\;\`\'\\\"\|\*\?\~\<\>\^\(\)\[\]\{\}\$\010\013\020\011])/\\${1}/g;
|
|
|
|
|
return $string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub fullpath($) {
|
|
|
|
|
my $file = shift;
|
|
|
|
|
my $path = dirname($file);
|
|
|
|
|
if ( $path =~ /^\// ) {
|
|
|
|
|
return $path;
|
|
|
|
|
} elsif ( $path =~ /^\.$/ ) {
|
|
|
|
|
return cwd;
|
|
|
|
|
} else {
|
|
|
|
|
$path = cwd . "/" . dirname($file);
|
|
|
|
|
$path = abs_path($path);
|
|
|
|
|
return $path;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-19 22:23:46 +00:00
|
|
|
sub slurp($) {
|
|
|
|
|
my $file = shift;
|
2004-01-25 15:27:10 +00:00
|
|
|
if ( -r $file) {
|
|
|
|
|
open(FH, "<$file") or die "Couldn't open $file: $!";
|
|
|
|
|
} else {
|
|
|
|
|
open(FH, "$sudocmd $catcmd $file|") or die "Couldn't exec $sudocmd $catcmd $file: $!";
|
|
|
|
|
}
|
2004-01-19 22:23:46 +00:00
|
|
|
my $result = do { local $/; <FH>; };
|
|
|
|
|
close FH;
|
|
|
|
|
return $result;
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-03 12:11:12 +00:00
|
|
|
sub help {
|
|
|
|
|
print <<EOT;
|
|
|
|
|
|
|
|
|
|
Usage: mycp [-e] [-h] <file1> [file2] ...";
|
|
|
|
|
|
|
|
|
|
EOT
|
|
|
|
|
exit;
|
|
|
|
|
}
|