#!/usr/bin/perl # $NHDT-Date$ # value of nethack.setupversion we will end up with when this is done # version 1 is reserved for repos checked out before versioning was added my $version_new = 3; my $version_old = 0; # current version, if any (0 is no entry ergo new repo) use Cwd; use Getopt::Std; # Activestate Perl doesn't include File::Spec. Grr. BEGIN { eval "require File::Spec::Functions"; if($@){ die <import; } exit 1 unless(getopts('nvf')); # TODO: this can probably have better output # OS hackery my $DS = quotemeta('/'); # Directory Separator (for regex) my $DSP = '/'; # ... for printing # Temporarily disabled; there's something weird about msys # msys: POSIXish over a Windows filesystem (so / not \ but \r\n not \n). #if($^O eq "msys"){ # $/ = "\r\n"; # $\ = "\r\n"; # # NB: We don't need to do anything about File::Spec. It doesn't know # # about msys but it defaults to Unix, so we'll be ok. #} if($^O eq "MSWin32"){ $DS = quotemeta('\\'); $DSP = '\\'; } # make sure we're at the top level of a repo if(! -d ".git"){ die "This is not the top level of a git repository.\n"; } my $vtemp = `git config --local --get nethack.setupversion`; chomp($vtemp); if($vtemp > 0){ $version_old = 0+$vtemp; if($version_old != $version_new){ print STDERR "Migrating from setup version $version_old to $version_new\n" if($opt_v); } } # legacy check: if(length $vtemp == 0){ if(`git config --get merge.NHsubst.name` =~ m/^Net/){ $version_old = 1; print STDERR "Migrating to setup version 1\n" if($opt_v); } } my $gitadddir = `git config --get nethack.gitadddir`; chomp($gitadddir); if(length $gitadddir){ if(! -d $gitadddir){ die "nethack.gitadddir has invalid value '$gitadddir'\n"; } } print STDERR "nethack.gitadddir=$gitadddir\n" if($opt_v); # This is (relatively) safe because we know we're at R in R/DEVEL/nhgitset.pl my $srcdir = ($0 =~ m!^(.*)$DS!)[0]; if(! -f catfile($srcdir, 'nhgitset.pl')){ die "I can't find myself in '$srcdir'\n"; } print STDERR "Copying from: $srcdir\n" if($opt_v); if($opt_f || $version_old==0){ print STDERR "Configuring line endings\n" if($opt_v); unlink catfile('.git','index') unless($opt_n); system("git reset") unless($opt_n); system("git config --local core.safecrlf true") unless($opt_n); system("git config --local core.autocrlf false") unless($opt_n); } elsif($version_old <2){ my $xx = `git config --get --local core.safecrlf`; if($xx !~ m/true/){ print STDERR "\nNeed to 'rm .git${DSP}index;git reset'.\n"; print STDERR " When ready to proceed, re-run with -f flag.\n"; exit 2; } } print STDERR "Installing aliases\n" if($opt_v); $addpath = catfile(curdir(),'.git','hooks','NHadd'); &add_alias('nhadd', "!$addpath add"); &add_alias('nhcommit', "!$addpath commit"); my $nhsub = catfile(curdir(),'.git','hooks','nhsub'); &add_alias('nhsub', "!$nhsub"); print STDERR "Installing filter/merge\n" if($opt_v); # XXXX need it in NHadd to find nhsub??? # removed at version 3 #if($^O eq "MSWin32"){ # $cmd = '.git\\\\hooks\\\\NHtext'; #} else { # $cmd = catfile(curdir(),'.git','hooks','NHtext'); #} #&add_config('filter.NHtext.clean', "$cmd --clean %f"); #&add_config('filter.NHtext.smudge', "$cmd --smudge %f"); if($version_old == 1 or $version_old == 2){ print STDERR "Removing filter.NHtext\n" if($opt_v); system('git','config','--unset','filter.NHtext.clean') unless($opt_n); system('git','config','--unset','filter.NHtext.smudge') unless($opt_n); system('git','config','--remove-section','filter.NHtext') unless($opt_n); print STDERR "Removing NHtext\n" if($opt_v); unlink catfile(curdir(),'.git','hooks','NHtext') unless($opt_n); } $cmd = catfile(curdir(),'.git','hooks','NHsubst'); &add_config('merge.NHsubst.name', 'NetHack Keyword Substitution'); &add_config('merge.NHsubst.driver', "$cmd %O %A %B %L"); print STDERR "Running directories\n" if($opt_v); foreach my $dir ( glob("$srcdir$DS*") ){ next unless(-d $dir); my $target = catfile($dir, 'TARGET'); next unless(-f $target); open TARGET, '<', $target or die "$target: $!"; my $targetpath = ; # still have to eat all these line endings under msys, so instead of chomp use this: $targetpath =~ s![\r\n]!!g; close TARGET; print STDERR "Directory $dir -> $targetpath\n" if($opt_v); my $enddir = $dir; $enddir =~ s!.*$DS!!; if(! &process_override($enddir, "INSTEAD")){ &process_override($enddir, "PRE"); my $fnname = "do_dir_$enddir"; if(defined &$fnname){ &$fnname($dir, $targetpath); } &process_override($enddir, "POST"); } } &check_prefix; # for variable substitution if($version_old != $version_new){ print STDERR "Setting version to $version_new\n" if($opt_v); if(! $opt_n){ system("git config nethack.setupversion $version_new"); if($?){ die "Can't set nethack.setupversion $version_new: $?,$!\n"; } } } exit 0; sub process_override { my($srcdir, $plname) = @_; return 0 unless(length $gitadddir); my $plpath = catfile($gitadddir, $srcdir, $plname); #print STDERR " ",catfile($srcdir, $plname),"\n"; # save this for updating docs - list of overrides return 0 unless(-x $plpath); print STDERR "Running $plpath\n" if($opt_v); # current directory is top of target repo unless($opt_n){ system("$plpath $opt_v") and die "Callout $plpath failed: $?\n"; } return 1; } sub add_alias { my($name, $def) = @_; &add_config("alias.$name",$def); } sub add_config { my($name, $val) = @_; system('git', 'config', '--local', $name, $val) unless($opt_n); } sub check_prefix { my $lcl = `git config --local --get nethack.substprefix`; chomp($lcl); if(0==length $lcl){ my $other = `git config --get nethack.substprefix`; chomp($other); if(0==length $other){ print STDERR "ERROR: nethack.substprefix is not set anywhere. Set it and re-run.\n"; exit 2; } else { &add_config('nethack.substprefix', $other); print STDERR "Copying prefix '$other' to local repository.\n" if($opt_v); } $lcl = $other; # for display below } print "\n\nUsing prefix '$lcl' - PLEASE MAKE SURE THIS IS CORRECT\n\n"; } sub do_dir_DOTGIT { if(1){ # We are NOT going to mess with config now. return; } else { my($srcdir, $targetdir) = @_; #warn "do_dir_DOTGIT($srcdir, $targetdir)\n"; my $cname = "$srcdir/config"; if(-e $cname){ print STDERR "Appending to .git/config\n" if($opt_v); open CONFIG, ">>.git/config" or die "open .git/config: $!"; open IN, "<", $cname or die "open $cname: $!"; my @data = ; print CONFIG @data; close IN; close CONFIG; } else { print STDERR " Nothing to add to .git/config\n" if($opt_v); } # XXX are there other files in .git that we might want to handle? # So just in case: for my $file ( glob("$srcdir/*") ){ next if( $file =~ m!.*/TARGET$! ); next if( $file =~ m!.*/config$! ); die "ERROR: no handler for $file\n"; } } } sub do_dir_hooksdir { my($srcdir, $targetdir) = @_; for my $path ( glob("$srcdir$DS*") ){ next if( $path =~ m!.*${DS}TARGET$! ); my $file = $path; $file =~ s!.*$DS!!; $file = catfile($targetdir, $file); next if($opt_n); open IN, "<", $path or die "Can't open $path: $!"; open OUT, ">", "$file" or die "Can't open $file: $!"; while(){ print OUT; } close OUT; close IN; if(! -x $file){ chmod 0755 ,$file; } } } __END__ (can we change the .gitattributes syntax to include a comment character?) maybe [comment] attr.c:parse_attr_line grr - looks like # is the comment character =head1 NAME nhgitset.pl - Setup program for NetHack git repositories =head1 SYNOPSIS cd THE_REPO [git config nethack.gitadddir GITADDDIR] perl SOME_PATH/DEVEL/nhgitset.pl [-v][-n][-f] =head1 DESCRIPTION nhgitset.pl installs NetHack-specific setup after a C (or after changes to the desired configuration, which are installed by re-running nhgitset.pl). The follwing options are available: B<-f> Force. Do not use this unless the program requests it. B<-n> Make no changes. B<-v> Verbose output. =head1 CONFIG nhgitset.pl uses the following non-standard C variables: nethack.gitadddir DOTGIT/INSTEAD DOTGIT/PRE DOTGIT/POST hooksdir/INSTEAD hooksdir/PRE hooksdir/POST nethack.setupversion nethack.substprefix =head1 EXIT STATUS 0 Success. 1 Fail. 2 Intervention required.