From 202c38b520c78e0921e9b7c4384f49eb49cf7e5a Mon Sep 17 00:00:00 2001 From: Stephen Oman Date: Sat, 6 Jun 2026 12:38:13 +0100 Subject: [PATCH] Update files in DEVEL directory and subdirectories --- DEVEL/Developer.txt | 42 +- DEVEL/VERSION | 4 + DEVEL/code_features.txt | 19 +- DEVEL/code_style.txt | 131 ++++- DEVEL/git_recipes.txt | 6 +- DEVEL/gitinfo.pl | 2 +- DEVEL/hooksdir/NHadd | 27 +- DEVEL/hooksdir/NHgithook.pm | 313 +++++++--- DEVEL/hooksdir/NHsubst | 190 ++++--- DEVEL/hooksdir/NHtext | 12 +- DEVEL/hooksdir/applypatch-msg | 2 +- DEVEL/hooksdir/commit-msg | 2 +- DEVEL/hooksdir/nhhelp | 79 +++ DEVEL/hooksdir/nhsub | 913 +++++++++++++++++++----------- DEVEL/hooksdir/post-applypatch | 8 +- DEVEL/hooksdir/post-checkout | 11 +- DEVEL/hooksdir/post-commit | 13 +- DEVEL/hooksdir/post-merge | 11 +- DEVEL/hooksdir/post-rewrite | 8 +- DEVEL/hooksdir/pre-applypatch | 8 +- DEVEL/hooksdir/pre-auto-gc | 8 +- DEVEL/hooksdir/pre-commit | 8 +- DEVEL/hooksdir/pre-push | 8 +- DEVEL/hooksdir/pre-rebase | 8 +- DEVEL/hooksdir/prepare-commit-msg | 8 +- DEVEL/nhgitset.pl | 480 ++++++++++------ 26 files changed, 1595 insertions(+), 726 deletions(-) create mode 100644 DEVEL/VERSION create mode 100644 DEVEL/hooksdir/nhhelp diff --git a/DEVEL/Developer.txt b/DEVEL/Developer.txt index 0d55a3aeb..2622ffbd6 100644 --- a/DEVEL/Developer.txt +++ b/DEVEL/Developer.txt @@ -4,7 +4,7 @@ |___/\___|\_/\___|_\___/ .__/\___|_| |_| -# NetHack 3.6 Developer.txt $NHDT-Date: 1524689668 2018/04/25 20:54:28 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.13 $ +# NetHack 3.7 Developer.txt $NHDT-Date: 1596498265 2020/08/03 23:44:25 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.19 $ # Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland # NetHack may be freely redistributed. See license for details. @@ -35,8 +35,7 @@ while. Please do not send save files, binary screen grabs, or other large things. ------------------------------------------------------------------------------ 2. git repositories -A public repository of the latest NetHack code that we've made -available can be obtained via git from either of two locations: +The public NetHack git repository is available (read-only) at: https://github.com/NetHack/NetHack or https://sourceforge.net/p/nethack/NetHack/ @@ -59,6 +58,11 @@ NOTE: These instructions assume you are on the default branch; this _is_ NOTE: The following instructions require perl. If you do not have perl on your system, please install it before proceeding. +NOTE: More information on nhgitset.pl is available before installation via: + perldoc DEVEL/nhgitset.pl + After installation, the same information is available with: + git nhhelp nhgitset + A. If you have never set up git on this machine before: (This assumes you will only be using git for NetHack. If you are going to use it for other projects as well, think before you type.) @@ -66,11 +70,24 @@ A. If you have never set up git on this machine before: git config --global user.name "MY NAME" git config --global user.email USER@EXAMPLE.COM You probably want to set up a credential cache. - Mac OS X: - git config --global credential.helper osxkeychain - Windows: - git config --global credential.helper store -XXX linux + macOS (10 or greater): + git config --global credential.helper osxkeychain + Linux: + (This will vary by distribution.) + cd /usr/share/doc/git/contrib/credential/libsecret + sudo apt-get install libglib-2.0-dev libsecret-1-dev + sudo make + git config --global credential.helper `pwd`/git-credential-libsecret + OR + sudo yum install git-credential-libsecret + git config --global credential.helper /usr/libexec/git-core/git-credential-libsecret + Windows: (The following three assume that Git for Windows is already installed on + the underlying Windows system https://git-scm.com/download/win): + git config --global credential.helper store + MSYS2 UCRT64 bash shell: + git config --global credential.helper "/c/Program\ Files/Git/mingw64/bin/git-credential-manager.exe" + Windows Subsystem for Linux 2 (WSL2) bash shell: + git config --global credential.helper "/mnt/c/Program\ Files/Git/mingw64/bin/git-credential-manager.exe" B. Specify the prefix for variable substitution: (This assumes you are not a member of DevTeam or any variant's development team. If you are, this may be wrong. Look for more specific documentation. @@ -80,10 +97,11 @@ B. Specify the prefix for variable substitution: tree you cloned from git. I use ~/nethack/GITADDDIR; for that base, create the needed directories and edit the file: ~/nethack/GITADDDIR/DOTGIT/PRE - Put this in it (if your OS is not Unix-like you may need to change - the first line): + Put this in it, adapting it to your variant (if your OS is not Unix-like + you may need to change the first line): #!/bin/sh git config nethack.substprefix MINE + git config nethack.projectname MineHack Now make it executable: chmod +x ~/nethack/GITADDDIR/DOTGIT/PRE C. Configure the repository: @@ -157,8 +175,8 @@ A. Introduction The PREFIX is the value in the git config variable nethack.substprefix. VARNAME is one of: Date - Branch (experimental) - Revision (experimental) + Branch + Revision other names will give a warning. B. Enabling variable expansion diff --git a/DEVEL/VERSION b/DEVEL/VERSION new file mode 100644 index 000000000..3788cb6d5 --- /dev/null +++ b/DEVEL/VERSION @@ -0,0 +1,4 @@ +5 +Please see "git log DEVEL" for previous changes. +Make documentation of nhgitset.pl easier to find and +find out about. diff --git a/DEVEL/code_features.txt b/DEVEL/code_features.txt index 4e89df7f5..1377515a8 100644 --- a/DEVEL/code_features.txt +++ b/DEVEL/code_features.txt @@ -1,4 +1,4 @@ -# NetHack 3.6 code_features.txt $NHDT-Date: 1524689669 2018/04/25 20:54:29 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.3 $ +# NetHack 5.0 code_features.txt $NHDT-Date: 1596498264 2020/08/03 23:44:24 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.6 $ # Copyright (c) 2015 by Michael Allison # NetHack may be freely redistributed. See license for details. @@ -101,6 +101,23 @@ engine are incompatible. Additional regular expression implementations can be written. The full interface documentation is in sys/share/posixregex.c +=========================================================== +HEADER FILE NOTES + +hack.h defines values that are available to all NetHack source files, +contains enums for use in all NetHack source files, and contains a +number of struct definitions for use in all NetHack source files. +hack.h does not contain variable declarations or variable definitions. + +decl.h and decl.c are related: decl.h contains the extern declarations +for variables that are defined in decl.c. These variables are global +and available to all NetHack source files. +decl.c variable definitions are generally laid out in much the same +order as their corresponding declarations in decl.h. + +A new header file cstd.h was added to coincide with 5.0's switch to +C99. It contains calls to some C99 standard header files. + =================== NEXT FEATURE ========================== diff --git a/DEVEL/code_style.txt b/DEVEL/code_style.txt index b17076823..574af2cc8 100644 --- a/DEVEL/code_style.txt +++ b/DEVEL/code_style.txt @@ -1,4 +1,4 @@ -# NetHack 3.6 code_style.txt $NHDT-Date: 1524689669 2018/04/25 20:54:29 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.2 $ +# NetHack 3.7 code_style.txt $NHDT-Date: 1694890786 2023/09/16 18:59:46 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.8 $ # Copyright (c) 2015 by Derek S. Ray # NetHack may be freely redistributed. See license for details. @@ -13,7 +13,8 @@ should be styled in keeping with C. The code base in C files was, close to the 3.6 release, reformatted using a version of the clang-format tool patched to support K&R-style argument declarations. Due to some incompatibilities, the patch is not publicly -available and clang-format is not expected to be regularly used. +available and clang-format is not expected to be regularly used. Since then, +function declarations and definitions have been switched to ANSI. Developers should do their best to adhere to the coding style to promote legible, easy-to-edit code. Legibility is paramount, so in some cases, it may @@ -44,17 +45,43 @@ possible: Single blank lines should be used wherever convenient to improve readability. Functions and Control Statements -------------------------------- +-------------------------------- For a function definition, the return type, declarator, and opening brace -should each appear on a line of their own. Arguments are never declared in the -function declarator, but are declared, unintended, K&R-style before the -opening brace: +should each appear on a line of their own. Arguments are defined in the following +parenthesis, per ANSI. There are two general styles. One with no comments, where +arguments are added one after another, with a wrap aligning to the first argument +if there is an overflow. void - foo(i, c) - int i; - char c; + foo(int i, char c) + { + /* function body */ + } + + void + long_function_name(int first_arg, struct long_name *second_arg, + int third_arg, int forth_arg) + { + /* function body */ + } + +Alternatively, arguments can be one per line if they are commented: + + void + long_function_name(int first_arg, /* main operation */ + struct long_name *second_arg, /* control details */ + int third_arg, /* local conditions - if + they apply */ + int forth_arg) /* remote conditions */ + { + /* function body */ + } + +If the function takes no parameters: + + int + long_function_name(void) { /* function body */ } @@ -136,6 +163,26 @@ wrapped in an additional set of parentheses for clarity: /* body */ } +Variable names to avoid +----------------------- + + near, far Some compilers and cross-compilers that target old + processors with segmented architectures may treat + those as keywords. It is safest to just avoid them. + + NEARDATA Some data is marked with this define; the Amiga port uses + it to mark data items to be used with a short addressing mode. + You don't need to use this. + +static vs staticfn +------------------ + +The staticfn macro evaluates to either "static" or to nothing (see config.h). +If possible, functions in src/*.c that would otherwise be marked static should +be marked staticfn so platforms that do not name static functions in their +stack traces can be forced to do so; this means function names cannot be +reused. Never use staticfn with data. + Spaces in Expressions --------------------- @@ -149,6 +196,63 @@ immediately inside a pair of parentheses: /* body */ } +Casts and sizeof +---------------- + +Casts should separate the cast operator and its expression with a space: + '(char *) str' +'sizeof (type)' requires the parentheses. 'sizeof expression' does not; +using them is not wrong but omitting them avoids some visual clutter. +Using them without the separating space gives the false impression of a +function call or macro-with-argument(s) expansion; 'sizeof' is an operator +and the parentheses required for '(type)' are to treat it like a cast. + +Comments +-------- + +Some block comments are undecorated, just split into reasonable width lines: + /* this is + a comment */ +They usually don't include sentence punctuation. + +Others are more elaborate: + /* + * This is + * another comment. + */ +This style is usually used with sentence punctuation, particularly if they +contain more than one sentence. + +End-of-line comments which need to span lines + somecode(); /* this comment + * is ok */ +should start every continuation line with an asterisk, otherwise clang-format +would convert them into a block comment + othercode(); /* this comment + should be avoided */ +because it would be converted into + othercode(); + /* this comment + should be avoided */ +if another bulk reformatting ever gets performed. Similarly, multiple +comments intended to read as one + morecode(); /* start of comment */ + /* more of comment */ + /* end of comment */ +are deprecated because they will end up losing the indentation of the +followup lines if reformatted. + +Many files end with + /*filename*/ +usually preceded by a blank line. This was intended as a workaround for a +comment--somewhere, possibly in Amiga or Atari code--that stated that some +compiler or other didn't always process the last line of the file. If that +last line is a comment, nothing is lost. The real issue almost certainly +was source file(s) that didn't end in newline. These days we try to force +the final newline for every file, prior to release if not always maintained +day-to-day. The name at the end can still be worthwhile when editing or +browsing multiple files. + Vim Configuration ================= @@ -168,7 +272,7 @@ ensure that indentation is done correctly: Visual Studio Configuration =========================== -In Visual Studio under Tools->Options->Text Editor->C/C++, you can set the +In Visual Studio under Tools->Options->Text Editor->C/C++, you can set the following options to obtain desired behavior: [Tabs] @@ -179,8 +283,8 @@ Insert Spaces There are a number of other options under [Formatting] that should be checked (Indentation, New Lines, Spacing, and Wrapping), but there are so -many entries that reproducing them here is impractical. Fortunately, the -options are in plain English, so walking through them with a copy of +many entries that reproducing them here is impractical. Fortunately, the +options are in plain English, so walking through them with a copy of this Guide handy and making changes as required will suffice. Emacs Configuration @@ -192,7 +296,6 @@ Putting the following in ~/.emacs.el is one (defun hook-c () (setq c-set-style "k&r") (setq c-basic-offset 4) - (setq indent-tabs-mode nil) - (c-set-offset 'knr-argdecl-intro 0)) + (setq indent-tabs-mode nil)) (add-hook 'c-mode-common-hook 'hook-c) diff --git a/DEVEL/git_recipes.txt b/DEVEL/git_recipes.txt index 04f36d6b2..e4ca94925 100644 --- a/DEVEL/git_recipes.txt +++ b/DEVEL/git_recipes.txt @@ -1,4 +1,4 @@ -# NetHack 3.6 git_recipes.txt $NHDT-Date: 1524689669 2018/04/25 20:54:29 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.9 $ +# NetHack 3.7 git_recipes.txt $NHDT-Date: 1596498266 2020/08/03 23:44:26 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.11 $ # Copyright (c) 2015 by Derek S. Ray # NetHack may be freely redistributed. See license for details. @@ -193,6 +193,10 @@ it were a patch. Does not delete the stash from the list. list: Lists all of your stashed code blobs. +======================================= +External Links +======================================= +http://pcottle.github.io/learnGitBranching ======================================= Typical workflows for common activities diff --git a/DEVEL/gitinfo.pl b/DEVEL/gitinfo.pl index 91f71e65e..f348f8e6e 100644 --- a/DEVEL/gitinfo.pl +++ b/DEVEL/gitinfo.pl @@ -1,5 +1,5 @@ #!/usr/bin/perl -# NetHack 3.6 getinfo.pl $NHDT-Date: 1524689669 2018/04/25 20:54:29 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.2 $ +# NetHack 3.7 getinfo.pl $NHDT-Date: 1596498266 2020/08/03 23:44:26 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.3 $ # Copyright (c) 2018 by Michael Allison # NetHack may be freely redistributed. See license for details. diff --git a/DEVEL/hooksdir/NHadd b/DEVEL/hooksdir/NHadd index 3e4b24b85..f4386c81d 100644 --- a/DEVEL/hooksdir/NHadd +++ b/DEVEL/hooksdir/NHadd @@ -1,5 +1,5 @@ #!/usr/bin/perl -# NetHack 3.6 NHadd $NHDT-Date: 1524689631 2018/04/25 20:53:51 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $ +# NetHack 3.7 NHadd $NHDT-Date: 1596498406 2020/08/03 23:46:46 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.2 $ # Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland # NetHack may be freely redistributed. See license for details. @@ -12,11 +12,32 @@ die "Bad subcommand '$ARGV[0]'" unless $ok{$ARGV[0]}; # we won't fail on a failure, so just system() $rv = system('.git/hooks/nhsub',"--$ARGV[0]",@ARGV[1..$#ARGV]); if($rv){ - print "warning: nhsub failed: $rv $!\n"; + print "warning: nhsub failed: $rv $!\n"; } if(length $ENV{GIT_PREFIX}){ - chdir($ENV{GIT_PREFIX}) or die "Can't chdir $ENV{GIT_PREFIX}: $!"; + chdir($ENV{GIT_PREFIX}) or die "Can't chdir $ENV{GIT_PREFIX}: $!"; } exec "git", @ARGV or die "Can't exec git: $!"; + +__END__ +=for nhgitset nhadd Add file contents to the index with NetHack additions +=for nhgitset nhcommit Record changes to the repository with NetHack additions + +=head1 NAME + +C - NetHack internal common code for nhadd and nhcommit + +=head1 SYNOPSIS + +Cgit add optionsE> + +Cgit add optionsE> + +=head1 DESCRIPTION + +Run nhsub with the given arguments, then run C or C +with the given arguments. Note that only basic arguments for those commands +are understood; more complex situations may be handled by running C +manually before running C or C. diff --git a/DEVEL/hooksdir/NHgithook.pm b/DEVEL/hooksdir/NHgithook.pm index 0c64ab12f..065fcd60a 100644 --- a/DEVEL/hooksdir/NHgithook.pm +++ b/DEVEL/hooksdir/NHgithook.pm @@ -1,5 +1,5 @@ # -# NetHack 3.6 NHgithook.pm $NHDT-Date: 1524689631 2018/04/25 20:53:51 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.6 $ +# NetHack 3.7 NHgithook.pm $NHDT-Date: 1596498406 2020/08/03 23:46:46 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.7 $ # Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland # NetHack may be freely redistributed. See license for details. @@ -16,9 +16,11 @@ my $tracefile = "/tmp/nhgitt.$$"; # OS hackery my $DS = quotemeta('/'); +my $PDS = '/'; if ($^O eq "MSWin32") { $DS = quotemeta('\\'); + $PDS = '\\'; } our %saved_env; @@ -26,25 +28,23 @@ our @saved_argv; our $saved_input; sub saveSTDIN { - @saved_input = ; + @saved_input = ; - if($trace){ - print TRACE "STDIN:\n"; - print TRACE $saved_input; - print TRACE "ENDSTDIN\n"; - } + if($trace){ + print TRACE "STDIN:\n"; + print TRACE $saved_input; + print TRACE "ENDSTDIN\n"; + } - tie *STDIN, 'NHIO::STDIN', @saved_input; + tie *STDIN, 'NHIO::STDIN', @saved_input; } -# XXX this needs a re-write (don't tie and untie, just set NEXT=0) -# (the sensitive thing is @foo = ) sub resetSTDIN{ - my $x = tied(*STDIN); - my %x = %$x; - my $data = @$x{DATA}; - untie *STDIN; - tie *STDIN, 'NHIO::STDIN', $data; + my $x = tied(*STDIN); + my %x = %$x; + my $data = @$x{DATA}; + untie *STDIN; + tie *STDIN, 'NHIO::STDIN', $data; } # don't need this now @@ -55,21 +55,142 @@ sub resetSTDIN{ #} sub PRE { - &do_hook("PRE"); + &do_hook("PRE"); } sub POST { - &do_hook("POST"); + &do_hook("POST"); +} + +### +### versioning for nhgitset and friends +### + +# values of nethack.setupversion and DEVEL/VERSION: +# 1 is reserved for repos checked out before versioning was added +# 2 used clean/smudge filter, poorly +# 3 was first production version +# 4 added the version file and version checking; nhhelp, NH_DATESUB support, etc. + +sub version_in_devel { + # (1) check for a non-null nethack.setuppath - this handles + # any repo that has already been set up (but NOT checking + # out =v4 since nethack.setuppath will exist but + # DEVEL/VERSION will not). + # XXX if the source repo has been removed, we'll fall back to + # the third case - hopefully that's ok. + # XXX there's no way to recover from a missing source repo + # without editing .git/config. + my $path = `git config --local nethack.setuppath`; + chomp $path; + $path =~ s/DEVEL$//; # NOP if config not set + + # (2) else check the local directory; that will be correct for NHsource. + if(0 == length $path){ + $path = `git rev-parse --show-toplevel`; + chomp $path; + $path = '' unless(-d "$path${PDS}DEVEL"); + } + # (3) If that doesn't exist, check using the invocation path; that will be + # correct for other repos during nhgitset (but will also fail for + # checking out 3 over 4). + if(0 == length $path){ + # strip out "DEVEL" + $path = ($0 =~ m!^(.*)${PDS}DEVEL${PDS}.*?(*nla:DEVEL)!)[0]; + } + # Uh oh? + if(0==length($path) or (! -d "$path${PDS}DEVEL")){ + die "Can't locate DEVEL directory in '$path'."; + } + + # Handle checking out version <4 over version >=4. If + # this seems to be the situation, don't revert the code. + return 0 if(! -f "$path${PDS}DEVEL${PDS}VERSION"); + + my $version; + my $verfile = "$path${PDS}DEVEL${PDS}VERSION"; + open VERFH,"<",$verfile or die "xCan't open $verfile: $!"; + $version = 0+; + my $message = join('',); + close VERFH; + die "Valid version not found in $verfile" unless($version >= 4); + return ($version,$message) if($version > 0); + return 0; +} + +sub version_in_git { + my $vtemp = `git config --local --get nethack.setupversion`; + chomp($vtemp); + return $vtemp if($vtemp > 0); + return 0; +} + +sub version_set_git { + my $version_new = $_[0]; + + system("git config nethack.setupversion $version_new"); + if($?){ + die "Can't set nethack.setupversion $version_new: $?,$!\n"; + } } ### ### store githash and gitbranch in dat/gitinfo.txt ### +# CAUTION! This is run not just from git hooks, but also from +# sys/unix/gitinfo.sh sub nhversioning { use strict; use warnings; + # See if we're (probably) in a "git pull", in which case we need to + # check for upgrades. + my $check_upgrade = 1 if($_[0]); + + # Check for pre-v4 source repo. + my $is_sourcerepo; + { + chomp($is_sourcerepo = `git config --int --get nethack.is-sourcerepo`); + if(0 == length $is_sourcerepo){ # not set - assume old repo + $is_sourcerepo = 1; + }elsif($is_sourcerepo==1){ + ; + }elsif($is_sourcerepo==0){ + ; + } + } + + # Skip the skipping tests if we're being called directly. + # NB: post-commit has no args, but that will be caught by + # the next test for non-source repos. + if($#ARGV != -1){ + # Skip this if we didn't change branches, but see if we need to warn. + if(defined($ARGV[2]) and ($ARGV[2] == 0)){ + # Because we can create an out of sync state, possibly warn. + my $ref = $ARGV[1]; + if($is_sourcerepo and (0 != 0+`git diff --name-only $ref $ref^ |grep ^DEVEL|wc -l`)){ + warn "WARNING: DEVEL directory changed. Versioning may be inconsistent\n"; + } + return + } + } + + if($check_upgrade){ + my $current_version = version_in_git(); + my($new_version,$message) = version_in_devel(); + if($new_version > $current_version){ + warn "nhgitset.pl and/or related programs have changed.\n"; + warn "Please re-run nhgitset.pl to update from version $current_version to $new_version.\n"; + if(length $message){ + warn "Additional information\n$message\n"; + } + } + } + + # Skip versioning if we aren't in a source repo. + return if(0==$is_sourcerepo); + my $git_sha = `git rev-parse HEAD`; $git_sha =~ s/\s+//g; my $git_branch = `git rev-parse --abbrev-ref HEAD`; @@ -77,7 +198,14 @@ sub nhversioning { die "git rev-parse failed" unless(length $git_sha and length $git_branch); my $exists = 0; - if (open my $fh, '<', 'dat/gitinfo.txt') { + no strict 'refs'; + no strict 'subs'; + my $file_gitinfo = "dat${PDS}gitinfo.txt"; + my $file_gittemp = "dat${PDS}TMPgitinfo.txt"; + use strict 'subs'; + use strict 'refs'; + + if (open my $fh, '<', $file_gitinfo) { $exists = 1; my $hashok = 0; my $branchok = 0; @@ -91,61 +219,71 @@ sub nhversioning { } close $fh; if ($hashok && $branchok) { - print "dat/gitinfo.txt unchanged, githash=".$git_sha."\n"; + print "$file_gitinfo unchanged, githash=".$git_sha."\n"; return; } } else { - print "WARNING: Can't find dat directory\n" unless(-d "dat"); + warn "WARNING: Can't find dat directory\n" unless(-d "dat"); + return; } - if (open my $fh, '>', 'dat/gitinfo.txt') { + if (open my $fh, '>', $file_gittemp) { my $how = ($exists ? "updated" : "created"); print $fh 'githash='.$git_sha."\n"; print $fh 'gitbranch='.$git_branch."\n"; - print "dat/gitinfo.txt ".$how.", githash=".$git_sha."\n"; + print "$file_gitinfo ".$how.", githash=".$git_sha."\n"; + if(close($fh)){ + if(rename($file_gittemp, $file_gitinfo)){ + ; # all ok + } else { + warn "WARNING: Can't rename $file_gittemp -> $file_gitinfo"; + } + } else { + warn "WARNING: Can't close temp file: $!"; + } } else { - print "WARNING: Unable to open dat/gitinfo.txt: $!\n"; + warn "WARNING: Unable to open $file_gitinfo: $!\n"; } } # PRIVATE sub do_hook { - my($p) = @_; - my $hname = $0; - $hname =~ s!^((.*$DS)|())(.*)!$1$p-$4!; - if(-x $hname){ - print TRACE "START $p: $hname\n" if($trace); + my($p) = @_; + my $hname = $0; + $hname =~ s!^((.*$DS)|())(.*)!$1$p-$4!; + if(-x $hname){ + print TRACE "START $p: $hname\n" if($trace); - open TOHOOK, "|-", $hname or die "open $hname: $!"; - print TOHOOK ; - close TOHOOK or die "close $hname: $! $?"; + open TOHOOK, "|-", $hname or die "open $hname: $!"; + print TOHOOK ; + close TOHOOK or die "close $hname: $! $?"; - print TRACE "END $p\n" if($trace); - } + print TRACE "END $p\n" if($trace); + } } sub trace_start { - return unless($trace); - my $self = shift; - open TRACE, ">>", $tracefile; - print TRACE "START CLIENT PID:$$ ARGV:\n"; - print TRACE "CWD: " . cwd() . "\n"; - print TRACE "[0] $0\n"; - my $x1; - for(my $x=0;$x $ENV{$k}\n"; - } + return unless($trace); + my $self = shift; + open TRACE, ">>", $tracefile; + print TRACE "START CLIENT PID:$$ ARGV:\n"; + print TRACE "CWD: " . cwd() . "\n"; + print TRACE "[0] $0\n"; + my $x1; + for(my $x=0;$x $ENV{$k}\n"; + } } BEGIN { - %saved_env = %ENV; - @saved_argv = @ARGV; - &trace_start; + %saved_env = %ENV; + @saved_argv = @ARGV; + &trace_start; } ### @@ -153,42 +291,41 @@ BEGIN { ### package NHIO::STDIN; sub TIEHANDLE { - my $class = shift; - my %fh; - # XXX yuck - if(ref @_[0]){ - $fh{DATA} = @_[0]; - } else { - $fh{DATA} = \@_; - } - $fh{NEXT} = 0; - return bless \%fh, $class; + my $class = shift; + my %fh; + if(ref @_[0]){ + $fh{DATA} = @_[0]; + } else { + $fh{DATA} = \@_; + } + $fh{NEXT} = 0; + return bless \%fh, $class; } sub READLINE { - my $self = shift; - return undef if($self->{EOF}); - if(wantarray){ - my $lim = $#{$self->{DATA}}; - my @ary = @{$self->{DATA}}[$self->{NEXT}..$lim]; - my @rv = @ary[$self->{NEXT}..$#ary]; - $self->{EOF} = 1; - return @rv; - } else{ - my $rv = $self->{DATA}[$self->{NEXT}]; - if(length $rv){ - $self->{NEXT}++; - return $rv; - } else { - $self->{EOF} = 1; - return undef; - } - } + my $self = shift; + return undef if($self->{EOF}); + if(wantarray){ + my $lim = $#{$self->{DATA}}; + my @ary = @{$self->{DATA}}[$self->{NEXT}..$lim]; + my @rv = @ary[$self->{NEXT}..$#ary]; + $self->{EOF} = 1; + return @rv; + } else{ + my $rv = $self->{DATA}[$self->{NEXT}]; + if(length $rv){ + $self->{NEXT}++; + return $rv; + } else { + $self->{EOF} = 1; + return undef; + } + } } sub EOF { - $self = shift; - return $self->{EOF}; + $self = shift; + return $self->{EOF}; } 1; @@ -223,11 +360,20 @@ NHgithook - common code for NetHack git hooks (and other git bits) (core hook code) &NHgithook::POST; +__END__ +=for nhgitset NHgithook Infrastructure for NetHack git hooks. + =head1 DESCRIPTION +Perl module for infrastructure of NetHack Git hooks. + Buffers call information so multiple independent actions may be coded for Git hooks and similar Git callouts. +Maintains C. + +Common routines for dealing with nethack.setupversion git config variable. + =head1 SETUP Changing the C<$trace> and C<$tracefile> variables requires editing the @@ -247,6 +393,9 @@ may be useful since multiple processes may be live at the same time. Some features not well tested, especially under Windows. +Not well documented, but almost no one needs to change (or even call) +this code. + =head1 AUTHOR Kenneth Lorber (keni@his.com) diff --git a/DEVEL/hooksdir/NHsubst b/DEVEL/hooksdir/NHsubst index 45e8297e1..93ce45fc0 100755 --- a/DEVEL/hooksdir/NHsubst +++ b/DEVEL/hooksdir/NHsubst @@ -1,5 +1,5 @@ #!/usr/bin/perl -# NetHack 3.6 NHsubst $NHDT-Date: 1524689631 2018/04/25 20:53:51 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.4 $ +# NetHack 3.7 NHsubst $NHDT-Date: 1596498407 2020/08/03 23:46:47 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.5 $ # Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland # NetHack may be freely redistributed. See license for details. @@ -17,24 +17,24 @@ my $dbgfile = ($^O eq "MSWin32") ? "$ENV{TEMP}.$$" : "/tmp/trace.$$"; open TRACE, ">>", $rawin?"/dev/tty":(($debug==0)? $sink : $dbgfile); print TRACE "TEST TRACE\n"; if($debug){ - print TRACE "START CLIENT ARGV:\n"; - print TRACE "[0] $0\n"; - my $x1; - for(my $x=0;$x $ENV{$k}\n"; - } - print TRACE "CWD: " . `pwd`; - &dumpfile($ARGV[0], "[0O]"); - &dumpfile($ARGV[1], "[1A]"); - &dumpfile($ARGV[2], "[2B]"); - print TRACE "L=$ARGV[3]\n"; - print TRACE "END\n"; + print TRACE "START CLIENT ARGV:\n"; + print TRACE "[0] $0\n"; + my $x1; + for(my $x=0;$x $ENV{$k}\n"; + } + print TRACE "CWD: " . `pwd`; + &dumpfile($ARGV[0], "[0O]"); + &dumpfile($ARGV[1], "[1A]"); + &dumpfile($ARGV[2], "[2B]"); + print TRACE "L=$ARGV[3]\n"; + print TRACE "END\n"; } my $mark_len = $ARGV[3]; @@ -47,37 +47,37 @@ my $mark_end = '>' x $mark_len; my $PREFIX; # pick up the prefix for substitutions in this repo if($rawin){ - $PREFIX = "TEST"; + $PREFIX = "TEST"; } else { - $PREFIX = `git config --local --get nethack.substprefix`; - chomp($PREFIX); + $PREFIX = `git config --local --get nethack.substprefix`; + chomp($PREFIX); } my @out; my $cntout; if($rawin){ - @out = ; + @out = ; } else { - #system "git merge-file -p .... > temp - my $tags = "-L CURRENT -L ANCESTOR -L OTHER"; # XXX should "CURRENT" be "MINE"? - @out = `git merge-file -p $tags $ARGV[1] $ARGV[0] $ARGV[2]`; + #system "git merge-file -p .... > temp + my $tags = "-L CURRENT -L ANCESTOR -L OTHER"; # XXX should "CURRENT" be "MINE"? + @out = `git merge-file -p $tags $ARGV[1] $ARGV[0] $ARGV[2]`; #NB: we don't check the exit value because it's useless - print TRACE "MERGE-FILE START\n".join("",@out)."MERGE-FILE END\n"; + print TRACE "MERGE-FILE START\n".join("",@out)."MERGE-FILE END\n"; } ($cntout,@out) = &edit_merge(@out); if($rawin){ - print "COUNT: $cntout\n"; - print @out; + print "COUNT: $cntout\n"; + print @out; } else { - # spit @out to $ARGV[1] (careful: what about EOL character?) - open OUT, ">$ARGV[1]" or die "Can't open $ARGV[1]"; - print OUT @out; - close OUT; + # spit @out to $ARGV[1] (careful: what about EOL character?) + open OUT, ">$ARGV[1]" or die "Can't open $ARGV[1]"; + print OUT @out; + close OUT; - print TRACE "WRITING START ($ARGV[1])\n".join("",@out)."WRITING END\n"; - &dumpfile($ARGV[1], "READBACK"); + print TRACE "WRITING START ($ARGV[1])\n".join("",@out)."WRITING END\n"; + &dumpfile($ARGV[1], "READBACK"); } print TRACE "COUNT: $cntout\n"; @@ -95,37 +95,37 @@ exit( ($cntout>0) ? 1 : 0); # keep failing so we don't need to keep changing the setup while building this script sub dumpfile { - my($file, $tag) = @_; - print TRACE "FILE $tag START\n"; - print TRACE `hexdump -C $file`; - print TRACE "FILE END\n"; + my($file, $tag) = @_; + print TRACE "FILE $tag START\n"; + print TRACE `hexdump -C $file`; + print TRACE "FILE END\n"; } sub edit_merge { - my(@input) = @_; - # $::count is a bit ugly XXX - local $::count = 0; # we need the number of conflicts for exit() - my @out; - - local $_; - while($_ = shift @input){ - if(m/^$mark_start /){ - print TRACE "FOUND A CONFLICT\n"; - my @conflict; - push(@conflict, $_); - while($_ = shift @input){ - push(@conflict, $_); - if(m/^$mark_end /){ - last; - } - } - push(@out, &edit_conflict(@conflict)); - } else { - push(@out, $_); + my(@input) = @_; + # $::count is a bit ugly XXX + local $::count = 0; # we need the number of conflicts for exit() + my @out; + + local $_; + while($_ = shift @input){ + if(m/^$mark_start /){ + print TRACE "FOUND A CONFLICT\n"; + my @conflict; + push(@conflict, $_); + while($_ = shift @input){ + push(@conflict, $_); + if(m/^$mark_end /){ + last; } + } + push(@out, &edit_conflict(@conflict)); + } else { + push(@out, $_); } - print TRACE "RETURN count=$::count\n"; - return($::count, @out); + } + print TRACE "RETURN count=$::count\n"; + return($::count, @out); } sub edit_conflict { @@ -305,41 +305,41 @@ print TRACE "MVM: -$varname-$oursval-$theirval-\n"; package PREFIX; # Resolve the conflict of a single var's 2 values. Return undef to leave the conflict. sub Date { - my($PREFIX, $varname, $mine, $theirs) = @_; - my $m = ($mine =~ m/(\d+)/)[0]; - my $t = ($theirs =~ m/(\d+)/)[0]; - return undef unless ($m>0) && ($t>0); + my($PREFIX, $varname, $mine, $theirs) = @_; + my $m = ($mine =~ m/(\d+)/)[0]; + my $t = ($theirs =~ m/(\d+)/)[0]; + return undef unless ($m>0) && ($t>0); - return "\$$PREFIX-$varname: " . (($m>$t)?$mine:$theirs) .' $'; + return "\$$PREFIX-$varname: " . (($m>$t)?$mine:$theirs) .' $'; } #sub Header { #sub Author { sub Branch { - my($PREFIX, $varname, $mine, $theirs) = @_; - $mine =~ s/^\s+//; $mine =~ s/\s+$//; - $theirs =~ s/^\s+//; $theirs =~ s/\s+$//; - return "\$$PREFIX-$varname: $mine \$" if(length $mine); - return "\$$PREFIX-$varname: $theirs \$" if(length $theirs); - return "\$$PREFIX-$varname\$" if(length $theirs); + my($PREFIX, $varname, $mine, $theirs) = @_; + $mine =~ s/^\s+//; $mine =~ s/\s+$//; + $theirs =~ s/^\s+//; $theirs =~ s/\s+$//; + return "\$$PREFIX-$varname: $mine \$" if(length $mine); + return "\$$PREFIX-$varname: $theirs \$" if(length $theirs); + return "\$$PREFIX-$varname\$" if(length $theirs); } sub Revision { - my($PREFIX, $varname, $mine, $theirs) = @_; - my($m) = ($mine =~ m/1.(\d+)/); - my($t) = ($theirs =~ m/1.(\d+)/); - if($m > 0 && $t > 0){ - my $q = ($m > $t) ? $m : $t; - return "\$$PREFIX-$varname: 1.$q \$"; - } - if($m > 0){ - return "\$$PREFIX-$varname: 1.$m \$"; - } - if($t > 0){ - return "\$$PREFIX-$varname: 1.$t \$"; - } - return "\$$PREFIX-$varname\$"; + my($PREFIX, $varname, $mine, $theirs) = @_; + my($m) = ($mine =~ m/1.(\d+)/); + my($t) = ($theirs =~ m/1.(\d+)/); + if($m > 0 && $t > 0){ + my $q = ($m > $t) ? $m : $t; + return "\$$PREFIX-$varname: 1.$q \$"; + } + if($m > 0){ + return "\$$PREFIX-$varname: 1.$m \$"; + } + if($t > 0){ + return "\$$PREFIX-$varname: 1.$t \$"; + } + return "\$$PREFIX-$varname\$"; } __END__ @@ -392,7 +392,21 @@ $TEST-Branch: theirs $ TEST 8: <<< d1 -/* NetHack 3.6 objnam.c $TEST-Date$ $TEST-Branch$:$TEST-Revision$ */ +/* NetHack 5.0 objnam.c $TEST-Date$ $TEST-Branch$:$TEST-Revision$ */ === -/* NetHack 3.6 objnam.c $TEST-Date: 1426977394 2015/03/21 22:36:34 $ $TEST-Branch: master $:$TEST-Revision: 1.108 $ */ +/* NetHack 5.0 objnam.c $TEST-Date: 1426977394 2015/03/21 22:36:34 $ $TEST-Branch: master $:$TEST-Revision: 1.108 $ */ >>> d3 + +=for nhgitset NHsubst NetHack merge driver + +=head1 NAME + +C - NetHack merge driver + +=head1 SYNOPSIS + +(called from C, do not invoke directly) + +=head1 DESCRIPTION + +This is invoked by git through .git/config. diff --git a/DEVEL/hooksdir/NHtext b/DEVEL/hooksdir/NHtext index 44a70db42..01848675b 100755 --- a/DEVEL/hooksdir/NHtext +++ b/DEVEL/hooksdir/NHtext @@ -1,8 +1,10 @@ #!/usr/bin/perl -# NetHack 3.6 NHtext $NHDT-Date: 1524689631 2018/04/25 20:53:51 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.8 $ +# NetHack 3.7 NHtext $NHDT-Date: 1596498408 2020/08/03 23:46:48 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.9 $ # Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland # NetHack may be freely redistributed. See license for details. +# Not in use as of v3, but could come back in the future. + # clean/smudge filter for handling substitutions use strict; @@ -54,9 +56,9 @@ if($ARGV[0] eq "--clean"){ exit 1; } -# XXX for now, there isn't any - if we get called, we subst. No options for now. -# get relevent config info -#XXX +# XX for now, there isn't any - if we get called, we subst. No options for now. +# get relevant config info +#XX #git check-attr -a $ARGV[1] # Process stdin to stdout. @@ -109,7 +111,7 @@ sub Date { my($val, $mode, $submode) = @_; if($mode eq "c"){ if($submode==0){ - # we add this to make merge easier for now XXX + # we add this to make merge easier for now XX my $now = time; # not %s below - may not be portable # YYYY/MM/DD HH:MM:SS $val = "$now " . strftime("%Y/%m/%d %H:%M:%S", gmtime($now)); diff --git a/DEVEL/hooksdir/applypatch-msg b/DEVEL/hooksdir/applypatch-msg index 4432174ab..2318186ed 100755 --- a/DEVEL/hooksdir/applypatch-msg +++ b/DEVEL/hooksdir/applypatch-msg @@ -1,5 +1,5 @@ #!/usr/bin/perl -# NetHack 3.6 applypatch-msg $NHDT-Date: 1524689646 2018/04/25 20:54:06 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $ +# NetHack 3.7 applypatch-msg $NHDT-Date: 1596498405 2020/08/03 23:46:45 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.2 $ # Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland # NetHack may be freely redistributed. See license for details. diff --git a/DEVEL/hooksdir/commit-msg b/DEVEL/hooksdir/commit-msg index 1f2ad49a2..e4befa0e5 100755 --- a/DEVEL/hooksdir/commit-msg +++ b/DEVEL/hooksdir/commit-msg @@ -1,5 +1,5 @@ #!/usr/bin/perl -# NetHack 3.6 commit-msg $NHDT-Date: 1524689646 2018/04/25 20:54:06 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $ +# NetHack 3.7 commit-msg $NHDT-Date: 1596498405 2020/08/03 23:46:45 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.2 $ # Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland # NetHack may be freely redistributed. See license for details. diff --git a/DEVEL/hooksdir/nhhelp b/DEVEL/hooksdir/nhhelp new file mode 100644 index 000000000..90fb7d68f --- /dev/null +++ b/DEVEL/hooksdir/nhhelp @@ -0,0 +1,79 @@ +#!/usr/bin/perl +# $NHDT-Date: 1730238507 2024/10/29 21:48:27 $ $NHDT-Brev: keni-gitset:1.0 $ +# Copyright (c) 2024 by Kenneth Lorber, Kensington, Maryland +# NetHack may be freely redistributed. See license for details. + +# This deals with a git problem: there is no way to do: +# git help alias-name +# (yes, that will show the definition of the alias, but not show an actual +# help document). +# +# So we implement this: +# nhhelp +# With no arguments, run perldoc on this file. +# nhhelp FOO +# Run perldoc on .git/hooks/FOO (if it exists). + +if($#ARGV == -1){ + system("perldoc $0")==0 or die "perldoc error: $!\n"; + exit 0; +} +if($#ARGV == 0){ + if($ARGV[0] eq "-a"){ + &listhelp; + exit 0; + } + + chomp(my $target = `git config nethack.aliashelp.$ARGV[0]`); + my $file = ".git/hooks/$target"; + if(-f $file){ + system("perldoc $file")==0 or die "perldoc error: $!\n"; + } else { + print "Unknown name '$ARGV[0]'\n"; + &usage; + } + exit 0; +} +&usage; +exit 0; + +sub usage { +print <|-a] +E_O_M +} + +sub listhelp { + print "nhhelp is available for:\n"; + my @namelist = `git config --name-only --get-regexp 'nethack.aliashelp.*'`; + print "NAMELIST $?\n" if($?); + @namelist = map { + if(m/^nethack.aliashelp.(.*)/){ + chomp(my $x = `git config 'nethack.aliasdesc.$1'`); + sprintf("%-12s %s",$1,$x); + } + } sort @namelist; + print " " . join("\n ", @namelist)."\n"; + exit 0; +} + +__END__ +=for nhgitset nhhelp Help on NetHack git commands + +=head1 NAME + +C - NetHack git command for help on NetHack git commands + +=head1 SYNOPSIS + +C + +=head1 DESCRIPTION + +With no arguments, print this message. + +With one argument matching a NetHack git command, print the +documentation for that command. + +With the argument C<-a>, show all available nhhelp topics with one line +summaries. diff --git a/DEVEL/hooksdir/nhsub b/DEVEL/hooksdir/nhsub index 7e5fdbd2f..aeff30b27 100644 --- a/DEVEL/hooksdir/nhsub +++ b/DEVEL/hooksdir/nhsub @@ -1,5 +1,5 @@ #!/usr/bin/perl -# $NHDT-Date: 1524689646 2018/04/25 20:54:06 $ Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.7 $ +# $NHDT-Date: 1524689646 2018/04/25 20:54:06 $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.7 $ # Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland # NetHack may be freely redistributed. See license for details. @@ -8,9 +8,11 @@ use strict; our %opt; #cmd v n f F m (other single char, but we don't care) my $mode; # a c d f (add, commit, date, date -f) +our $count; +our $skip; if(length $ENV{GIT_PREFIX}){ - chdir($ENV{GIT_PREFIX}) or die "Can't chdir $ENV{GIT_PREFIX}: $!"; + chdir($ENV{GIT_PREFIX}) or die "Can't chdir $ENV{GIT_PREFIX}: $!"; } #SO how do we know if a file has changed? @@ -23,74 +25,78 @@ if(length $ENV{GIT_PREFIX}){ # (see "git help status" for table) # No default. Undef means something unexpected happened. my %codes = ( - 'f M'=>1, 'f D'=>1, # [MD] not updated - 'a M'=>0, 'a D'=>0, - 'd M'=>0, 'd D'=>0, - 'c M'=>0, 'c D'=>0, - - 'dM '=>0, 'dMM'=>1, 'dMD'=>0, - 'aM '=>0, 'aMM'=>1, 'aMD'=>0, - 'cM '=>0, 'cMM'=>1, 'cMD'=>0, - 'fM '=>0, 'fMM'=>1, 'fMD'=>0, - # M [ MD] updated in index - - 'dA '=>1, 'dAM'=>1, 'dAD'=>1, - 'aA '=>1, 'aAM'=>1, 'aAD'=>1, - 'cA '=>1, 'cAM'=>1, 'cAD'=>1, - 'fA '=>1, 'fAM'=>1, 'fAD'=>1, - # A [ MD] added to index - - 'dD '=>0, 'dDM'=>0, - 'aD '=>1, 'aDM'=>1, - 'cD '=>0, 'cDM'=>0, - 'fD '=>1, 'fDM'=>1, - # D [ M] deleted from index - - 'dR '=>0, 'dRM'=>1, 'dRD'=>0, - 'aR '=>0, 'aRM'=>1, 'aRD'=>0, - 'cR '=>0, 'cRM'=>1, 'cRD'=>0, - 'fR '=>0, 'fRM'=>1, 'fRD'=>0, - # R [ MD] renamed in index - - 'dC '=>0, 'dCM'=>1, 'dCD'=>0, - 'aC '=>0, 'aCM'=>1, 'aCD'=>0, - 'cC '=>0, 'cCM'=>1, 'cCD'=>0, - 'fC '=>0, 'fCM'=>1, 'fCD'=>0, - # C [ MD] copied in index - - 'aM '=>1, 'aA '=>1, 'aR '=>1, 'aC '=>1, - 'fM '=>1, 'fA '=>1, 'fR '=>1, 'fC '=>1, - # [MARC] index and work tree matches - - 'd M'=>1, 'dMM'=>1, 'dAM'=>1, 'dRM'=>1, 'dCM'=>1, - 'a M'=>1, 'aMM'=>1, 'aAM'=>1, 'aRM'=>1, 'aCM'=>1, - 'c M'=>1, 'cMM'=>1, 'cAM'=>1, 'cRM'=>1, 'cCM'=>1, - 'f M'=>1, 'fMM'=>1, 'fAM'=>1, 'fRM'=>1, 'fCM'=>1, - # [ MARC] M work tree changed since index - - 'd D'=>0, 'dMD'=>0, 'dAD'=>0, 'dRD'=>0, 'dCD'=>0, - 'a D'=>0, 'aMD'=>0, 'aAD'=>0, 'aRD'=>0, 'aCD'=>0, - 'c D'=>0, 'cMD'=>0, 'cAD'=>0, 'cRD'=>0, 'cCD'=>0, - 'f D'=>0, 'fMD'=>0, 'fAD'=>0, 'fRD'=>0, 'fCD'=>0, - # [ MARC] D deleted in work tree - - # ------------------------------------------------- - # DD unmerged, both deleted - # AU unmerged, added by us - # UD unmerged, deleted by them - # UA unmerged, added by them - # DU unmerged, deleted by us - # AA unmerged, both added - # UU unmerged, both modified - # ------------------------------------------------- - 'a??'=>1, 'f??'=>1, # ?? untracked - 'd??'=>0, 'c??'=>0, - - 'f!!'=>1, # !! ignored - 'a!!'=>0, 'd!!'=>0, 'c!!'=>0, - - 'f@@'=>1, # @@ internal ignored - 'a@@'=>0, 'd@@'=>0, 'c@@'=>0 + # [MD] not updated + 'f M'=>1, 'f D'=>1, + 'a M'=>0, 'a D'=>0, + 'd M'=>0, 'd D'=>0, + 'c M'=>0, 'c D'=>0, + + 'dM '=>0, 'dMM'=>1, 'dMD'=>0, + 'aM '=>0, 'aMM'=>1, 'aMD'=>0, + 'cM '=>0, 'cMM'=>1, 'cMD'=>0, + 'fM '=>0, 'fMM'=>1, 'fMD'=>0, + # M [ MD] updated in index + + 'dA '=>1, 'dAM'=>1, 'dAD'=>1, + 'aA '=>1, 'aAM'=>1, 'aAD'=>1, + 'cA '=>1, 'cAM'=>1, 'cAD'=>1, + 'fA '=>1, 'fAM'=>1, 'fAD'=>1, + # A [ MD] added to index + + 'dD '=>0, 'dDM'=>0, + 'aD '=>1, 'aDM'=>1, + 'cD '=>0, 'cDM'=>0, + 'fD '=>1, 'fDM'=>1, + # D [ M] deleted from index + + 'dR '=>0, 'dRM'=>1, 'dRD'=>0, + 'aR '=>0, 'aRM'=>1, 'aRD'=>0, + 'cR '=>0, 'cRM'=>1, 'cRD'=>0, + 'fR '=>0, 'fRM'=>1, 'fRD'=>0, + # R [ MD] renamed in index + + 'dC '=>0, 'dCM'=>1, 'dCD'=>0, + 'aC '=>0, 'aCM'=>1, 'aCD'=>0, + 'cC '=>0, 'cCM'=>1, 'cCD'=>0, + 'fC '=>0, 'fCM'=>1, 'fCD'=>0, + # C [ MD] copied in index + + 'aM '=>1, 'aA '=>1, 'aR '=>1, 'aC '=>1, + 'fM '=>1, 'fA '=>1, 'fR '=>1, 'fC '=>1, + # [MARC] index and work tree matches + + 'd M'=>1, 'dMM'=>1, 'dAM'=>1, 'dRM'=>1, 'dCM'=>1, + 'a M'=>1, 'aMM'=>1, 'aAM'=>1, 'aRM'=>1, 'aCM'=>1, + 'c M'=>1, 'cMM'=>1, 'cAM'=>1, 'cRM'=>1, 'cCM'=>1, + 'f M'=>1, 'fMM'=>1, 'fAM'=>1, 'fRM'=>1, 'fCM'=>1, + # [ MARC] M work tree changed since index + + 'd D'=>0, 'dMD'=>0, 'dAD'=>0, 'dRD'=>0, 'dCD'=>0, + 'a D'=>0, 'aMD'=>0, 'aAD'=>0, 'aRD'=>0, 'aCD'=>0, + 'c D'=>0, 'cMD'=>0, 'cAD'=>0, 'cRD'=>0, 'cCD'=>0, + 'f D'=>0, 'fMD'=>0, 'fAD'=>0, 'fRD'=>0, 'fCD'=>0, + # [ MARC] D deleted in work tree + + # ------------------------------------------------- + # DD unmerged, both deleted + # AU unmerged, added by us + # UD unmerged, deleted by them + # UA unmerged, added by them + # DU unmerged, deleted by us + # AA unmerged, both added + # UU unmerged, both modified + # ------------------------------------------------- + # ?? untracked + 'a??'=>1, 'f??'=>1, + 'd??'=>0, 'c??'=>0, + + # !! ignored + 'f!!'=>1, + + 'a!!'=>0, 'd!!'=>0, 'c!!'=>0, + + 'f@@'=>1, # @@ internal ignored + 'a@@'=>0, 'd@@'=>0, 'c@@'=>0 ); # OS hackery @@ -123,309 +129,430 @@ my @rawlist0 = &cmdparse(@ARGV); # Let's try this for all commands. my @rawlist; foreach my $e (@rawlist0){ - if($e =~ m/[?*[\\]/){ - my @rv = &lsfiles(undef, $e); - push(@rawlist, @rv) if(@rv); - if($opt{f}){ - my @rv = &lsfiles('-i', $e); - push(@rawlist, @rv) if(@rv); - } - } else { - push(@rawlist, $e); + if($e =~ m/[?*[\\]/){ + my @rv = &lsfiles(undef, $e); + push(@rawlist, @rv) if(@rv); + if($opt{f}){ + my @rv = &lsfiles('-i', $e); + push(@rawlist, @rv) if(@rv); } + } else { + push(@rawlist, $e); + } } push(@rawlist,'.') if($#rawlist == -1); # pick up the prefix for substitutions in this repo -#TEST my $PREFIX = &git_config('nethack','substprefix'); -my $PREFIX = "NHDT"; +my $PREFIX = &git_config('nethack','substprefix'); +die "nethack.substprefix not set in git config" unless(length($PREFIX) > 0); print "PREFIX: '$PREFIX'\n" if($opt{v}); while(@rawlist){ - my $raw = shift @rawlist; - if(-f $raw){ + my $raw = shift @rawlist; + if(-f $raw){ &schedule_work($raw); next; + } + if(-d $raw){ + if($raw =~ m!$PDS.git$!o){ + print "SKIP $raw\n" if($opt{v}>=2); + next; } - if(-d $raw){ - if($raw =~ m!$PDS.git$!o){ - print "SKIP $raw\n" if($opt{v}>=2); - next; - } - opendir RDIR,$raw or die "Can't opendir: $raw"; - local($_); # needed until perl 5.11.2 - while($_ = readdir RDIR){ - next if(m/^\.\.?$/); - if(m/^\./ && $opt{f}){ - print " IGNORE-f: $raw$PDS$_\n" if($opt{v}>=2); - next; - } - push(@rawlist, $raw.$PDS.$_); - } - closedir RDIR; + opendir RDIR,$raw or die "Can't opendir: $raw"; + local($_); # needed until perl 5.11.2 + while($_ = readdir RDIR){ + next if(m/^\.\.?$/); + if(m/^\./ && $opt{f}){ + print " IGNORE-f: $raw$PDS$_\n" if($opt{v}>=2); + next; + } + push(@rawlist, $raw.$PDS.$_); } + closedir RDIR; + } # ignore other file types - if(! -e $raw){ - print "warning: missing file $raw\n"; + if(! -e $raw){ + print "warning: missing file $raw\n"; + } +} + +sub checkattr { + my($kw, $file) = @_; + my $attr = `git check-attr $kw -- $file`; + if($attr =~ m/$kw:\s+(.*)/){ + # This is a bug in git. What if the value of an attribute is the + # string "unset"? Sigh. + if(! $opt{F}){ + if($1 eq "unset" || $1 eq "unspecified"){ + print " NOATTR: $attr" if($opt{v}>=2); + return 0; + } } + return 1; + } + return 0; } # XXX could batch things up - later - sub schedule_work { - my($file) = @_; - print "CHECK: '$file'\n" if($opt{v}>=2); - local($_) = `git status --porcelain --ignored -- $file`; - my $key = $mode . join('',(m/^(.)(.)/)); - if(length $key == 1){ + my($file) = @_; + print "CHECK: '$file'\n" if($opt{v}>=2); + local($_) = `git status --porcelain --ignored -- $file`; + my $key = $mode . join('',(m/^(.)(.)/)); + if(length $key == 1){ # Hack. An unmodified, tracked file produces no output from # git status. Treat as another version of 'ignored'. - $key .= '@@'; + $key .= '@@'; + } + $key =~ s/-/ /g; # for Keni's locally mod'ed git + if(!exists $codes{$key}){ + die "I'm lost.\nK='$key' F=$file\nST=$_"; + } + if($codes{$key}==0){ + if($opt{v}>=2){ + print " IGNORE: $_" if(length); + print " IGNORE: !! $file\n" if(!length); } - $key =~ s/-/ /g; # for Keni's locally mod'ed git - if(!exists $codes{$key}){ - die "I'm lost.\nK='$key' F=$file\nST=$_"; - } - if($codes{$key}==0){ - if($opt{v}>=2){ - print " IGNORE: $_" if(length); - print " IGNORE: !! $file\n" if(!length); - } + return; + } + if($opt{F}){ + my $ign = `git check-ignore $file`; + if($ign !~ m/^\s*$/){ + print " IGNORE-F: $ign" if($opt{v}>=2); return; - } - if($opt{F}){ - my $ign = `git check-ignore $file`; - if($ign !~ m/^\s*$/){ - print " IGNORE-F: $ign" if($opt{v}>=2); - return; - } - } -# FALLTHROUGH and continue -#print "ACCEPT TEST\n"; # XXXXXXXXXX TEST -#return; - - my $attr = `git check-attr NHSUBST -- $file`; - if($attr =~ m/NHSUBST:\s+(.*)/){ -# XXX this is a bug in git. What if the value of an attribute is the -# string "unset"? Sigh. - if(! $opt{F}){ - if($1 eq "unset" || $1 eq "unspecified"){ - print " NOATTR: $attr" if($opt{v}>=2); - return; - } - } - &process_file($file); - return; - } - die "Can't parse check-attr return: $attr\n"; + } + } + + my $do_nhsubst = &checkattr('NHSUBST', $file); + my $do_nhdatesub = &checkattr('NH_DATESUB', $file); + &process_file($file, $do_nhsubst, $do_nhdatesub); +# XXX no longer reachable - parse errors not caught properly? +# die "Can't parse check-attr return: $attr\n"; } sub process_file { - my($file) = @_; - print "DOFIL: $file\n" if($opt{v}>=1); - - # For speed we read in the entire file then do the substitutions. - local($_) = ''; - my $len; - open INFILE, "<", $file or die "Can't open $file: $!"; - while(1){ - # On at least some systems we only get 64K. - my $len = sysread(INFILE, $_, 999999, length($_)); - last if($len == 0); - die "read failed: $!" unless defined($len); - } - close INFILE; - - local $::current_file = $file; # used under handlevar - # $1 - var and value (including trailing space but not $) - # $2 - var - # $4 - value or undef -#s/\$$PREFIX-(([A-Za-z][A-Za-z0-9_]*)(: ([^\N{DOLLAR SIGN}]+))?)\$/&handlevar($2,$4)/eg; -my $count = s/\$$PREFIX-(([A-Za-z][A-Za-z0-9_]*)(: ([^\x24]+))?)\$/&handlevar($2,$4)/eg; -# XXX had o modifier, why? - return unless($count>0); - return if($opt{n}); - my $mode = 0777 & (stat($file))[2]; - - my $ofile = $file . ".nht"; - open(TOUT, ">", $ofile) or die "Can't open $ofile"; - -# die "write failed: $!" unless defined syswrite(TOUT, $_); - my $offset = 0; - my $sent; -#print STDERR "L=",length,"\n"; - while($offset < length){ - $sent = syswrite(TOUT, $_, (length($_) - $offset), $offset); - die "write failed: $!" unless defined($sent); -#print STDERR "rv=$sent\n"; - last if($sent == (length($_) - $offset)); - $offset += $sent; -#print STDERR "loop: O=$offset\n"; - } - - close TOUT or die "Can't close $ofile"; - # Do the right thing for *nix and hope for the best elsewhere: - chmod($mode, $ofile)==1 or warn "Can't set filemode on $ofile"; - rename $ofile, $file or die "Can't rename $ofile to $file"; + my($file, $do_nhsubst, $do_nhdatesub) = @_; + print "DOFIL: $file\n" if($opt{v}>=1); + $count=0; # if we don't change anything, don't re-write the file + + # For speed we read in the entire file then do the substitutions. + local($_) = ''; + my $len; + open INFILE, "<", $file or die "Can't open $file: $!"; + while(1){ + # On at least some systems we only get 64K. + my $len = sysread(INFILE, $_, 999999, length($_)); + last if($len == 0); + die "read failed: $!" unless defined($len); + } + close INFILE; + + local $::current_file = $file; # used under handle* + if($do_nhsubst){ + # TODO: This doesn't handle PREFIX-Assert. To do that, + # we need to capture an entire line, call new sub handlevars() + # and let it iterate across all PREFIX-Foo while + # maintaining $::skip and reverting (like &handledatesub does). + # Also: capture optional arg: $NHDT-Foo(arg)$ $NHDT-Foo(arg): value $ + + # $1 - var and value (including trailing space but not $) + # $2 - var + # $4 - value or undef + # \x24 == $ + s/\$$PREFIX-(([A-Za-z][A-Za-z0-9_]*)(: ([^\x24]+) )?)\$/&handlevar($2,$4,1)/eg; + } + + if($do_nhdatesub){ + # e.g: + #.\"DO NOT REMOVE NH_DATESUB .TH MAKEDEFS 6 "DATE(%-d %B %Y)" NETHACK + #.TH MAKEDEFS 6 "8 February 2022" NETHACK + + # locate the keyword and the rest of the line, capturing the rest of the line (the pattern) + # use zero width assertions so we can capture them but not replace them (DOES THIS WORK?) + #and grab the next line (the replaced text) + + # $1 - pattern + # $2 - the next line (the expanded pattern) + s/ + \sNH_DATESUB\s+ # our trigger + (.*)[\n\r]+ # save the pattern in $1 + \K # but don't replace it + (.*) # save the oldvalue in $2 + / + &handledatesub($2, $1) # replace oldvalue + /emxg; + + #/m so ^$ match at each line + #/x this will be a mess, so attempt to comment it + } + +#print STDERR "COUNT = $count\n"; + return unless($count>0); + return if($opt{n}); + + my $ofile = $file . ".nht"; + my $mode = 0777 & (stat($file))[2]; # save the original mode + open(TOUT, ">", $ofile) or die "Can't open $ofile"; + + my $offset = 0; + my $sent; + while($offset < length){ + $sent = syswrite(TOUT, $_, (length($_) - $offset), $offset); + die "write failed: $!" unless defined($sent); + last if($sent == (length($_) - $offset)); + $offset += $sent; + } + + close TOUT or die "Can't close $ofile"; + # Do the right thing for *nix and hope for the best elsewhere: + chmod($mode, $ofile)==1 or warn "Can't set filemode on $ofile"; + rename $ofile, $file or die "Can't rename $ofile to $file"; } -# XXX docs for --fixup and --squash are wrong in git's synopsis. --file missing -# --message --template -t sub cmdparse { - my(@in) = @_; - - # What are we doing? - $opt{cmd} = 'date'; # really nhsub - if($in[0] eq '--add'){ - $opt{cmd} = 'add'; - shift @in; - } - if($in[0] eq '--commit'){ - $opt{cmd} = 'commit'; - shift @in; - } + my(@in) = @_; + + # What are we doing? + $opt{cmd} = 'date'; # really nhsub + if($in[0] eq '--add'){ + $opt{cmd} = 'add'; + shift @in; + } + if($in[0] eq '--commit'){ + $opt{cmd} = 'commit'; + shift @in; + } # add: -n -v # commit: --dry-run -v # nhsub: -n -v - while($in[0] =~ m/^-/){ - local($_) = $in[0]; - if($_ eq '--'){ - shift @in; - last; + while($in[0] =~ m/^-/){ + local($_) = $in[0]; + if($_ eq '--'){ + shift @in; + last; + } + if(m/^--/){ + if($opt{cmd} eq 'add' && $_ eq '--dry-run'){ + exit 0; + } + if($opt{cmd} eq 'commit' && $_ eq '--dry-run'){ + exit 0; + } + if($opt{cmd} eq 'add' && $_ eq '--refresh'){ + exit 0; + } + shift @in; + next; + } + + if(m/^-(.*)/){ + foreach my $single ( split(//,$1) ){ + # don't do -v here from add/commit + if($single ne 'v'){ + # don't use -m from add/commit + if($opt{cmd} eq 'date' || $single ne 'm'){ + $opt{$single}++; + } + } elsif($opt{cmd} eq 'date'){ + $opt{$single}++; } - if(m/^--/){ - if($opt{cmd} eq 'add' && $_ eq '--dry-run'){ - exit 0; - } - if($opt{cmd} eq 'commit' && $_ eq '--dry-run'){ - exit 0; - } - if($opt{cmd} eq 'add' && $_ eq '--refresh'){ - exit 0; - } - shift @in; - next; + + if($opt{cmd} eq 'add' && $single eq 'n'){ + exit 0; } -# XXX this is messy - time for a rewrite? - if(m/^-(.*)/){ - foreach my $single ( split(//,$1) ){ - # don't do -v here from add/commit - if($single ne 'v'){ - # don't use -m from add/commit - if($opt{cmd} eq 'date' || $single ne 'm'){ - $opt{$single}++; - } - } elsif($opt{cmd} eq 'date'){ - $opt{$single}++; - } - - if($opt{cmd} eq 'add' && $single eq 'n'){ - exit 0; - } #need to deal with options that eat a following element (-m, -F etc etc) #add: nothing? #commit: -c -C -F -m # -u mode is optional # -S keyid is optional - if($opt{cmd} eq 'commit'){ - if($single =~ m/[uS]/){ - last; - } - if($single =~ m/[cCFm]/){ -#XXX this will be a mess if the argument is wrong, but can we tell? No. - shift @in; - last; - } - } - } + if($opt{cmd} eq 'commit'){ + if($single =~ m/[uS]/){ + last; + } + if($single =~ m/[cCFm]/){ + # This will be a mess if the argument is wrong, but can we tell? No. + shift @in; + last; + } } - shift @in; + } } + shift @in; + } + + ($mode) = ($opt{cmd} =~ m/^(.)/); + $mode = 'f' if($opt{cmd} eq 'date' && ($opt{f}||$opt{F})); + $mode = 'f' if($opt{cmd} eq 'add' && $opt{f}); + + if($opt{cmd} eq 'add' && $#in == -1){ + # "git nhadd" with no files has nothing to work on + exit 0; + } + if($opt{cmd} eq 'commit' && $#in == -1){ + # "git nhcommit" with no args handles files already + # added, we assume with "git nhadd" + exit 0; + } + if($opt{cmd} eq 'commit' && $opt{a} && $#in == -1){ + # "git commit -a" does multiple things; we only care + # about modified files. +#XXX this assumes $RS is set properly for Windows - need to check that + my @x = split(/$::RS/,`git ls-files -m`); + chomp(@x); + push(@in, @x); + } + if($opt{cmd} eq 'commit' && $opt{a} && $#in != -1){ + # Let git complain about this for us. + exit 0; + } +# "git add" doesn't have a -a option +# if($opt{cmd} eq 'add' && $opt{a} && $#in != -1){ +# exit 0; +# } +# I don't know what this was trying to do, but it's wrong. +# if($opt{cmd} eq 'add' && $opt{a}){ +# my $x = `git rev-parse --show-toplevel`; +# $x =~ s/[\n\r]+$//; +# push(@in, $x); +# } + return @in; # this is our file list +} - ($mode) = ($opt{cmd} =~ m/^(.)/); - $mode = 'f' if($opt{cmd} eq 'date' && ($opt{f}||$opt{F})); - $mode = 'f' if($opt{cmd} eq 'add' && $opt{f}); +sub git_config { + my($section, $var) = @_; + my $raw = `git config --local --get $section.$var`; + $raw =~ s/[\r\n]*$//g; + return $raw if(length $raw); + die "Missing config var: [$section] $var\n"; +} - if($opt{cmd} eq 'add' && $#in == -1){ - exit 0; - } - if($opt{cmd} eq 'commit' && $#in == -1){ - exit 0; - } - if($opt{cmd} eq 'add' && $opt{a} && $#in != -1){ - exit 0; +# (oldvalue, pattern) +sub handledatesub { + my $oldval = $_[0]; # used if assert fails + $skip = 0; # one if assert fails + my $out = $_[1]; # the pattern, which we'll edit in place +#print "OLD: '$oldval;\n"; +#print "PAT: '$out'\n"; + my $newvalue = $_[1]; + $out =~ s/ + \b # don't substitute on a partial word + (Assert|Date|Branch|Revision|Brev|Project) # $1 - keyword + \( # ( + ([^)]*) # $2 - argument + \) # ) + /&onedatesub($1,$2) + /egx; + + { + local $::x = $_[0] ne $out; + if ($::x){ + $count += $::x; +# warn "COUNT++"; } - if($opt{cmd} eq 'add' && $opt{a}){ - my $x = `git rev-parse --show-toplevel`; - $x =~ s/[\n\r]+$//; - push(@in, $x); - } - return @in; # this is our file list + } +#print STDERR "OUT SKIP=$skip count=$count\n"; +#print STDERR "OUT old='$oldval'\n new='$out'\n"; + return ($skip>0 or $count==0) ? $oldval : $out; + } -sub git_config { - my($section, $var) = @_; - my $raw = `git config --local --get $section.$var`; - $raw =~ s/[\r\n]*$//g; - return $raw if(length $raw); - die "Missing config var: [$section] $var\n"; +sub onedatesub { + my($kw, $arg) = @_; + my $sname = "PREFIX::$kw"; + die "internal error, '$sname' not defined" unless defined(&$sname); + + no strict; + my $rv = &$sname(undef, $arg); + return $rv; } +# Assert(P=prefix) +# Date(format) +# Branch() +# Revision() +# Brev() Branch:Rev (aBREViated) + sub handlevar { - my($var, $val) = @_; -# print "HIT '$var' '$val'\n" if($debug2); - - my $subname = "PREFIX::$var"; - if(defined &$subname){ - no strict; - print " SUBIN: $var '$val'\n" if($opt{v}>=3); - $val =~ s/\s+$//; - $val = &$subname($val); - print " SUBOT: $var '$val'\n" if($opt{v}>=3); - } else { - warn "No handler for \$$PREFIX-$var\n"; + my($var, $val, $wrap) = @_; +#print "HV '$var' '$val'\n"; + my $oldval = $val; + my $subname = "PREFIX::$var"; + if(defined &$subname){ + no strict; + print " SUBIN: $var '$val'\n" if($opt{v}>=3); + $val =~ s/\s+$//; + $val = &$subname($val, undef); + print " SUBOT: $var '$val'\n" if($opt{v}>=3); + { + local $::x = ($oldval ne $val); + if ($::x){ + $count += $::x; +# warn "COUNT2++ o='$oldval' v='$val'"; + } } + } else { + warn "No handler for \$$PREFIX-$var\n"; + } + if($wrap){ if(length $val){ return "\$$PREFIX-$var: $val \$"; } else { return "\$$PREFIX-$var\$"; } + } else { + return $val; + } } sub lsfiles { - my ($flags, $ps) = @_; - open RV, "-|", "git ls-files $flags '$ps'" or die "Can't ls-files"; - my @rv = ; - map { s/[\r\n]+$// } @rv; - if(!close RV){ - return undef if($! == 0); - die "close ls-files failed: $!"; - } - return undef if($#rv == -1); - return @rv; + my ($flags, $ps) = @_; + open RV, "-|", "git ls-files $flags '$ps'" or die "Can't ls-files"; + my @rv = ; + map { s/[\r\n]+$// } @rv; + if(!close RV){ + return undef if($! == 0); + die "close ls-files failed: $!"; + } + return undef if($#rv == -1); + return @rv; } package PREFIX; use POSIX qw(strftime); -# On push, put in the current date because we changed the file. -# On pull, keep the current value so we can see the last change date. sub Date { - my($val) = @_; - my $now; - if($opt{m}){ - my $hash = `git log -1 '--format=format:%H' $::current_file`; - #author keni 1429884677 -0400 - chomp($now = `git cat-file -p $hash | awk '/author/{print \$4}'`); + my(undef, $val) = @_; + my $now; + +# DONE XXX after several bug fixes, this set of ifs needs some cleanup +my $hash = `git log -1 '--format=format:%H' $::current_file`; + $now = $^T; +# if($opt{m} or not defined $hash){ + + # cope with file not yet added to git + if(not defined $hash){ + if(-f $::current_file){ + $now = (stat($::current_file))[9]; } else { - $now = time; + die "Can't find file '$::current_file'\n"; } + } elsif($opt{m}) { + #author keni 1429884677 -0400 + chomp($now = `git cat-file -p $hash | awk '/author/{print \$4}'`); + } +# } else { +# } + +# DONE XXX simplify this with %s ? +# my $fmt = length $val ? $val : "%Y/%m/%d %H:%M:%S"; + my $fmt = length $val ? $val : "%s %Y/%m/%d %H:%M:%S"; # YYYY/MM/DD HH:MM:SS - $val = "$now " . strftime("%Y/%m/%d %H:%M:%S", gmtime($now)); - return $val; +# $val = ((length $val==0)?"$now ":"") . strftime($fmt, gmtime($now)); + $val = strftime($fmt, gmtime($now)); + return $val; } #sub Header { @@ -434,26 +561,84 @@ sub Date { #} # NB: the standard-ish Revision line isn't enough - you need Branch:Revision - -# but we split it into 2 so we can use the standard processing code on Revision -# and just slip Branch in. +# but we split it into 2 so we can use the standard processing code on +# Revision and just slip Branch in. +# But see new Brev below. sub Branch { - my($val) = @_; - $val = `git symbolic-ref -q --short HEAD`; - $val =~ s/[\n\r]*$//; - $val =~ s/^\*\s*//; - $val = "(unknown)" unless($val =~ m/^[[:print:]]+$/); - return $val; + my $val; + $val = `git symbolic-ref -q --short HEAD`; + $val =~ s/[\n\r]*$//; + $val =~ s/^\*\s*//; + $val = "(unknown)" unless($val =~ m/^[[:print:]]+$/); + return $val; } sub Revision { - my($val) = @_; - my @val = `git log --follow --oneline $::current_file`; - my $ver = 0+$#val; - $ver = 0 if($ver < 0); - $val = "1.$ver"; - return $val; + my $val; + my @val = `git log --follow --oneline $::current_file`; + my $ver = 0+$#val; + $ver = 0 if($ver < 0); + $val = "1.$ver"; + return $val; } + +sub Brev { + my $branch; + $branch = `git symbolic-ref -q --short HEAD`; + $branch =~ s/[\n\r]*$//; + $branch =~ s/^\*\s*//; + $branch = "(unknown)" unless($branch =~ m/^[[:print:]]+$/); + + my @val = `git log --follow --oneline $::current_file`; + my $ver = 0+$#val; + $ver = 0 if($ver < 0); + $ver = "1.$ver"; + + my $val = "$branch:$ver"; + + return $val; +} + +sub Project { + my(undef, $arg) = @_; + my $pn = &::git_config('nethack','projectname'); + if(length $arg == 0){ + ; + } elsif($arg eq 'uc'){ + $pn = uc($pn); + } else { + warn "unknown argument '$arg' to Project()\n"; + } + return $pn; +} + + +sub Assert { + my(undef, $val) = @_; + + my($key, $arg) = ($val =~ m/^(.)=(.*)/); + if(!defined $arg){ + warn "syntax error: Assert($val)\n"; + $::skip = 1; + } + my $prefix = $2; + + # P assert arg matches saved prefix + if('P' eq $key){ + my $repoid = &::git_config('nethack','substprefix'); + if($repoid ne $prefix){ + $::skip = 1 + } + return ''; + } + + warn "Unknown Assert type '$key'\n"; + + return ''; +} + __END__ +=for nhgitset nhsub Update substitution variables =head1 NAME @@ -473,9 +658,15 @@ commands. The program re-writes those files listed on the command line; if the file is actually a directory, the program recurses into that directory tree. -Not all files found are re-written; some are ignored and those with no -substitution variables are not re-written. Unless changed by the options, -files that have not changed are not affected. +Not all files found are re-written; only those with the attribute +NHSUBST (for inline substitutions) or NH_DATESUB (for template +substitution) are considered; finally those with no substitution +variables or no changes due to substitution variables are not +re-written. Unless changed by the options, files that have not +changed are not affected. + +As a special case, a file not yet added to Git may be the target of +C. If no files are listed on the command line, the current directory is checked as if specified as C<.>. @@ -519,3 +710,83 @@ updated when last changed. (Do not use C/C after C assertions compare the current Git config variable +C +with the C and succeed if they are identical. + +=back + +=item Date(format) / PREFIX-Date + +This variable usually substitutes the current time but see C<-m> above. + +The format of the resulting date varies. For C or C with +no format, "%s %Y/%m/%d %H:%M:%S" is used. Otherwise the given strftime +format is used. + +=item Branch() / PREFIX-Branch + +This variable is replaced with the name of the currently checked out Git +branch. + +=item Revision() / PREFIX-Revision + +This variable's value emulates a RCS or CVS style revision number. +It consists of "1." followed by the number of commits affecting the +current file. + +=item Brev() / PREFIX-Brev + +This is a convenience variable that concatenates C, a colon, and +C. Short for "aBREViated". + +=item Project() + +Returns git variable nethack.projectname. If given the argument C, returns +an upper-case version of nethack.projectname. + +=back + +=head1 SUBSTITUTION STYLES + +=head2 Prefix Substitution + +If a file has the Git attribute C, any +text that looks like a RCS/CVS variable substitution will perform +that substitution. That is, either of the following forms: + + $Var$ + $Var: Value $ + +=head2 Template Substitution + +If a file has the Git attribute C, any line that has +the token C will replace the I line with the +variable expansion of everything after that token. For example: + + .\"DO NOT REMOVE NH_DATESUB .ds f2 DATE(%B %-d, %Y) + .ds f2 September 13, 2024 + +=head1 SEE ALSO + +git help gitattributes + +perldoc nhgitset.pl diff --git a/DEVEL/hooksdir/post-applypatch b/DEVEL/hooksdir/post-applypatch index ec6af70be..37170a48e 100755 --- a/DEVEL/hooksdir/post-applypatch +++ b/DEVEL/hooksdir/post-applypatch @@ -1,5 +1,5 @@ #!/usr/bin/perl -# $NHDT-Date: 1524689631 2018/04/25 20:53:51 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $ +# NetHack 3.7 post-applypatch $NHDT-Date: 1524689631 2018/04/25 20:53:51 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1 $ # Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland # NetHack may be freely redistributed. See license for details. @@ -24,7 +24,11 @@ BEGIN { chomp $gitdir; push(@INC, $gitdir.$PDS."hooks"); } -use NHgithook; +eval {use NHgithook;}; +if($@){ + warn "loading NHgithook failed: $@"; + $nogithook = 1; +} #STARTUP-END &NHgithook::PRE; diff --git a/DEVEL/hooksdir/post-checkout b/DEVEL/hooksdir/post-checkout index c7fde4f18..db8578f94 100755 --- a/DEVEL/hooksdir/post-checkout +++ b/DEVEL/hooksdir/post-checkout @@ -1,5 +1,5 @@ #!/usr/bin/perl -# NetHack 3.6 post-checkout $NHDT-Date: 1524689632 2018/04/25 20:53:52 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.2 $ +# NetHack 3.7 post-checkout $NHDT-Date: 1596498409 2020/08/03 23:46:49 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.3 $ # Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland # NetHack may be freely redistributed. See license for details. @@ -24,10 +24,15 @@ BEGIN { chomp $gitdir; push(@INC, $gitdir.$PDS."hooks"); } -use NHgithook; +eval {use NHgithook;}; +if($@){ + warn "loading NHgithook failed: $@"; + $nogithook = 1; +} #STARTUP-END &NHgithook::PRE; -&NHgithook::nhversioning; +eval { &NHgithook::nhversioning unless($nogithook) }; +warn "nhversioning failed: $@" if($@); &NHgithook::POST; exit 0; diff --git a/DEVEL/hooksdir/post-commit b/DEVEL/hooksdir/post-commit index 309eec4ce..753cb4a04 100755 --- a/DEVEL/hooksdir/post-commit +++ b/DEVEL/hooksdir/post-commit @@ -1,5 +1,5 @@ #!/usr/bin/perl -# NetHack 3.6 post-commit $NHDT-Date: 1524689632 2018/04/25 20:53:52 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.2 $ +# NetHack 3.7 post-commit $NHDT-Date: 1596498409 2020/08/03 23:46:49 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.3 $ # Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland # NetHack may be freely redistributed. See license for details. @@ -24,10 +24,17 @@ BEGIN { chomp $gitdir; push(@INC, $gitdir.$PDS."hooks"); } -use NHgithook; +eval {use NHgithook;}; +if($@){ + warn "loading NHgithook failed: $@"; + $nogithook = 1; +} #STARTUP-END &NHgithook::PRE; -&NHgithook::nhversioning; +eval { &NHgithook::nhversioning unless($nogithook) }; +warn "nhversioning failed: $@" if($@); &NHgithook::POST; exit 0; + + diff --git a/DEVEL/hooksdir/post-merge b/DEVEL/hooksdir/post-merge index 6ca8dc532..ca9e45e5f 100755 --- a/DEVEL/hooksdir/post-merge +++ b/DEVEL/hooksdir/post-merge @@ -1,5 +1,5 @@ #!/usr/bin/perl -# NetHack 3.6 post-merge $NHDT-Date: 1524689632 2018/04/25 20:53:52 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.2 $ +# NetHack 3.7 post-merge $NHDT-Date: 1596498410 2020/08/03 23:46:50 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.3 $ # Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland # NetHack may be freely redistributed. See license for details. @@ -25,10 +25,15 @@ BEGIN { push(@INC, $gitdir.$PDS."hooks"); } -use NHgithook; +eval {use NHgithook;}; +if($@){ + warn "loading NHgithook failed: $@"; + $nogithook = 1; +} #STARTUP-END &NHgithook::PRE; -&NHgithook::nhversioning; +eval { &NHgithook::nhversioning(1) unless($nogithook) }; +warn "nhversioning failed: $@" if($@); &NHgithook::POST; exit 0; diff --git a/DEVEL/hooksdir/post-rewrite b/DEVEL/hooksdir/post-rewrite index 317eddea0..3dcc7c18c 100755 --- a/DEVEL/hooksdir/post-rewrite +++ b/DEVEL/hooksdir/post-rewrite @@ -1,5 +1,5 @@ #!/usr/bin/perl -# NetHack 3.6 post-rewrite $NHDT-Date: 1524689632 2018/04/25 20:53:52 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $ +# NetHack 3.7 post-rewrite $NHDT-Date: 1596498411 2020/08/03 23:46:51 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.2 $ # Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland # NetHack may be freely redistributed. See license for details. @@ -24,7 +24,11 @@ BEGIN { chomp $gitdir; push(@INC, $gitdir.$PDS."hooks"); } -use NHgithook; +eval {use NHgithook;}; +if($@){ + warn "loading NHgithook failed: $@"; + $nogithook = 1; +} #STARTUP-END &NHgithook::saveSTDIN; diff --git a/DEVEL/hooksdir/pre-applypatch b/DEVEL/hooksdir/pre-applypatch index f71d1fda3..2ec0588a9 100755 --- a/DEVEL/hooksdir/pre-applypatch +++ b/DEVEL/hooksdir/pre-applypatch @@ -1,5 +1,5 @@ #!/usr/bin/perl -# NetHack 3.6 pre-applypatch $NHDT-Date: 1524689632 2018/04/25 20:53:52 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $ +# NetHack 3.7 pre-applypatch $NHDT-Date: 1596498411 2020/08/03 23:46:51 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.2 $ # Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland # NetHack may be freely redistributed. See license for details. @@ -24,7 +24,11 @@ BEGIN { chomp $gitdir; push(@INC, $gitdir.$PDS."hooks"); } -use NHgithook; +eval {use NHgithook;}; +if($@){ + warn "loading NHgithook failed: $@"; + $nogithook = 1; +} #STARTUP-END &NHgithook::PRE; diff --git a/DEVEL/hooksdir/pre-auto-gc b/DEVEL/hooksdir/pre-auto-gc index e1c39bebd..22e45b666 100755 --- a/DEVEL/hooksdir/pre-auto-gc +++ b/DEVEL/hooksdir/pre-auto-gc @@ -1,5 +1,5 @@ #!/usr/bin/perl -# NetHack 3.6 pre-auto-gc $NHDT-Date: 1524689632 2018/04/25 20:53:52 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $ +# NetHack 3.7 pre-auto-gc $NHDT-Date: 1596498412 2020/08/03 23:46:52 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.2 $ # Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland # NetHack may be freely redistributed. See license for details. @@ -24,7 +24,11 @@ BEGIN { chomp $gitdir; push(@INC, $gitdir.$PDS."hooks"); } -use NHgithook; +eval {use NHgithook;}; +if($@){ + warn "loading NHgithook failed: $@"; + $nogithook = 1; +} #STARTUP-END &NHgithook::PRE; diff --git a/DEVEL/hooksdir/pre-commit b/DEVEL/hooksdir/pre-commit index 83dacdd41..b19fc2fd4 100755 --- a/DEVEL/hooksdir/pre-commit +++ b/DEVEL/hooksdir/pre-commit @@ -1,5 +1,5 @@ #!/usr/bin/perl -# NetHack 3.6 pre-commit $NHDT-Date: 1524689632 2018/04/25 20:53:52 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $ +# NetHack 3.7 pre-commit $NHDT-Date: 1596498413 2020/08/03 23:46:53 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.2 $ # Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland # NetHack may be freely redistributed. See license for details. @@ -24,7 +24,11 @@ BEGIN { chomp $gitdir; push(@INC, $gitdir.$PDS."hooks"); } -use NHgithook; +eval {use NHgithook;}; +if($@){ + warn "loading NHgithook failed: $@"; + $nogithook = 1; +} #STARTUP-END &NHgithook::PRE; diff --git a/DEVEL/hooksdir/pre-push b/DEVEL/hooksdir/pre-push index d65dcbecb..a578ce529 100755 --- a/DEVEL/hooksdir/pre-push +++ b/DEVEL/hooksdir/pre-push @@ -1,5 +1,5 @@ #!/usr/bin/perl -# NetHack 3.6 pre-push $NHDT-Date: 1524689632 2018/04/25 20:53:52 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $ +# NetHack 3.7 pre-push $NHDT-Date: 1596498413 2020/08/03 23:46:53 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.2 $ # Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland # NetHack may be freely redistributed. See license for details. @@ -24,7 +24,11 @@ BEGIN { chomp $gitdir; push(@INC, $gitdir.$PDS."hooks"); } -use NHgithook; +eval {use NHgithook;}; +if($@){ + warn "loading NHgithook failed: $@"; + $nogithook = 1; +} #STARTUP-END &NHgithook::saveSTDIN; diff --git a/DEVEL/hooksdir/pre-rebase b/DEVEL/hooksdir/pre-rebase index e25f41cac..4c472ef63 100755 --- a/DEVEL/hooksdir/pre-rebase +++ b/DEVEL/hooksdir/pre-rebase @@ -1,5 +1,5 @@ #!/usr/bin/perl -# NetHack 3.6 pre-rebase $NHDT-Date: 1524689633 2018/04/25 20:53:53 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $ +# NetHack 3.7 pre-rebase $NHDT-Date: 1596498414 2020/08/03 23:46:54 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.2 $ # Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland # NetHack may be freely redistributed. See license for details. @@ -24,7 +24,11 @@ BEGIN { chomp $gitdir; push(@INC, $gitdir.$PDS."hooks"); } -use NHgithook; +eval {use NHgithook;}; +if($@){ + warn "loading NHgithook failed: $@"; + $nogithook = 1; +} #STARTUP-END &NHgithook::PRE; diff --git a/DEVEL/hooksdir/prepare-commit-msg b/DEVEL/hooksdir/prepare-commit-msg index b6813851a..a1ff14292 100755 --- a/DEVEL/hooksdir/prepare-commit-msg +++ b/DEVEL/hooksdir/prepare-commit-msg @@ -1,5 +1,5 @@ #!/usr/bin/perl -# $NHDT-Date: 1524689633 2018/04/25 20:53:53 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $ +# NetHack 3.7 prepare-commit-msg $NHDT-Date: 1524689633 2018/04/25 20:53:53 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1 $ # Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland # NetHack may be freely redistributed. See license for details. @@ -24,7 +24,11 @@ BEGIN { chomp $gitdir; push(@INC, $gitdir.$PDS."hooks"); } -use NHgithook; +eval {use NHgithook;}; +if($@){ + warn "loading NHgithook failed: $@"; + $nogithook = 1; +} #STARTUP-END &NHgithook::PRE; diff --git a/DEVEL/nhgitset.pl b/DEVEL/nhgitset.pl index 86ddfe3dc..2c4977895 100755 --- a/DEVEL/nhgitset.pl +++ b/DEVEL/nhgitset.pl @@ -1,34 +1,31 @@ #!/usr/bin/perl -# $NHDT-Date: 1524689669 2018/04/25 20:54:29 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.2 $ +# $NHDT-Date: 1693357449 2023/08/30 01:04:09 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.3 $ # Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland # NetHack may be freely redistributed. See license for details. -# 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; + } + File::Spec::Functions->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 +BEGIN { + # OS hackery + $DS = quotemeta('/'); # Directory Separator (for regex) + $PDS = '/'; # ... 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"){ @@ -37,78 +34,130 @@ BEGIN # # 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"){ + if($^O eq "MSWin32"){ $DS = quotemeta('\\'); - $DSP = '\\'; + $PDS = '\\'; + } + + # Fix @INC so we can 'use NHgithook' before it's installed. + # Set $is_sourcerepo while we're at it - same logic. + { + # Special case for running nhgitset against a different repo. + # Must precede the normal case! + # NB: we use $DEVhooksdir later in the program + $DEVhooksdir = ($0 =~ m!^(.*)$DS!)[0]; + chomp($DEVhooksdir); + $DEVhooksdir .= $PDS."hooksdir"; + push(@INC, $DEVhooksdir) if(-d $DEVhooksdir); + # This one is for the normal case (in NHsource) + my $topdir = `git rev-parse --show-toplevel`; + chomp $topdir; + $topdir .= "${PDS}DEVEL${PDS}hooksdir"; + push(@INC, $topdir) if(-d $topdir); + $is_sourcerepo = 0; + $is_sourcerepo = 1 if(-d $topdir); + } +} + +use NHgithook; + # current (installed) version, if any (0 is no entry ergo new repo) +my $version_old = NHgithook::version_in_git; + # version this program will install +my($version_new,$message_new) = NHgithook::version_in_devel; + +if(0==$version_new and !opt_f){ + # Edge case: this repo has been set up using version >= 4, but now we're running + # nhgitset after checking out DEVEL supporting version <4. + # Use -f to recover from broken DEVEL code. + print STDERR "DEVEL has version <4 code but version >=4 code already installed. Stopping.\n"; + print STDERR "(If you need to reinstall the old code, rerun with -f\n"; + exit 0; } + +die "Valid version not found in DEVEL/VERSION" unless(0==$version_new or $version_new >= 4); + # 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"; + 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); +if($version_old >= $version_new and !opt_f){ + print STDERR "Nothing to do.\n"; + exit 0; +} + +if($version_old > 0){ + if($version_old != $version_new){ + print STDERR "Migrating from setup version $version_old to $version_new\n"; + if(length $message_new){ + print STDERR "Additional information:\n$message_new\n"; } + } } + + # 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); - } +if(length $version_old == 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"; - } + 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]; +#XXX do I really want a full path for srcdir? how badly? + if(! -f catfile($srcdir, 'nhgitset.pl')){ - die "I can't find myself in '$srcdir'\n"; + 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); + print STDERR "Configuring line endings\n" if($opt_v); + system("git reset") unless($opt_n); + &add_config('core.safecrlf', 'true') unless($opt_n); + &add_config('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; - } + my $xx = `git config --get --local core.safecrlf`; + if($xx !~ m/true/){ + print STDERR "\nNeed to 'rm .git${PDS}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_help('nhadd', 'NHadd'); &add_alias('nhcommit', "!$addpath commit"); + &add_help('nhcommit', 'NHadd'); my $nhsub = catfile(curdir(),'.git','hooks','nhsub'); &add_alias('nhsub', "!$nhsub"); + &add_help('nhsub', 'nhsub'); +&add_alias('nhhelp', '!'.catfile(curdir(),'.git','hooks','nhhelp')); + &add_help('nhhelp', 'nhhelp'); + +&add_help('NHsubst', 'NHsubst'); +&add_help('NHgithook', 'NHgithook.pm'); +&add_help('nhgitset', 'gitsetdocs', '../../DEVEL/nhgitset.pl'); -print STDERR "Installing filter/merge\n" if($opt_v); -# XXXX need it in NHadd to find nhsub??? # removed at version 3 +#print STDERR "Installing filter/merge\n" if($opt_v); #if($^O eq "MSWin32"){ # $cmd = '.git\\\\hooks\\\\NHtext'; #} else { @@ -117,170 +166,211 @@ BEGIN #&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 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); + print STDERR "Removing NHtext\n" if($opt_v); + unlink catfile(curdir(),'.git','hooks','NHtext') unless($opt_n); } +&add_config('nethack.setuppath',$srcdir); +&add_config('nethack.is-sourcerepo',0+$is_sourcerepo); + $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"); +# copy directories into .git (right now that's just hooks and nhgitset.pl) +my @gitadd = length($gitadddir)?glob("$gitadddir$DS*"):undef; +foreach my $dir ( (glob("$srcdir$DS*"), @gitadd) ){ + 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"); + } } +&do_file_nhgitset(); -&check_prefix; # for variable substitution +&check_gitvars; # 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"; - } - } +if($version_old != $version_new or $opt_f){ + print STDERR "Setting version to $version_new\n" if($opt_v); + NHgithook::version_set_git($version_new) if(! $opt_n); } exit 0; +# @files: [0] is the name under .git/hooks; others are places to +# check during configuration +sub add_help { + my($cmd, @files) = @_; + + &add_config("nethack.aliashelp.$cmd", $files[0]); + # pull out =for nhgitset CMD description... + my $desc; + foreach my $file (@files){ + open my $fh, "<", "$DEVhooksdir/$file"; + if($fh){ + while(<$fh>){ + m/^=for\s+nhgitset\s+\Q$cmd\E\s+(.*)/ && do { + $desc = $1; + goto found; + } + } + close $fh; + } else { + warn "Can't open: '$DEVhooksdir/$file' ($!)\n"; + } + } +found: + + if($desc){ + &add_config("nethack.aliasdesc.$cmd", $desc); + } else { + &add_config("nethack.aliasdesc.$cmd", "(no description available)"); + } +} + sub process_override { - my($srcdir, $plname) = @_; - return 0 unless(length $gitadddir); + 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); + my $plpath = catfile($gitadddir, $srcdir, $plname); + return 0 unless(-x $plpath); - print STDERR "Running $plpath\n" if($opt_v); - # current directory is top of target repo + print STDERR "RunningOverride $plpath\n" if($opt_v); - unless($opt_n){ - system("$plpath $opt_v") and die "Callout $plpath failed: $?\n"; - } - return 1; + # 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); + my($name, $def) = @_; + &add_config("alias.$name",$def); } sub add_config { - my($name, $val) = @_; - system('git', 'config', '--local', $name, $val) unless($opt_n); + 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 check_gitvars { + &check_prefix("substprefix"); + &check_prefix("projectname"); } -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; +sub check_prefix { + my $which = $_[0]; + my $lcl = `git config --local --get nethack.$which`; + chomp($lcl); + if(0==length $lcl){ + my $other = `git config --get nethack.$which`; + chomp($other); + if(0==length $other){ + print STDERR "ERROR: nethack.$which is not set anywhere. Set it and re-run.\n"; + exit 2; } 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"; + &add_config('nethack.$which', $other); + print STDERR "Copying prefix '$other' to local repository.\n" if($opt_v); } + $lcl = $other; # for display below + } + print "Using $which '$lcl' - PLEASE MAKE SURE THIS IS CORRECT\n"; } + +sub do_dir_DOTGIT { + my($srcdir, $targetdir) = @_; + # not currently in use so just bail + return; + # 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) = @_; + my($srcdir, $targetdir) = @_; - for my $path ( glob("$srcdir$DS*") ){ + unless (-d $targetdir){ + # Older versions of git, when cloning a repo and + # the expected source templates directory does not + # exist, does not create .git/hooks. So do it here. + mkdir $targetdir; + print STDERR "WARNING: .git/hooks had to be created.\n"; + print STDERR " You may want to update git.\n"; + } - next if( $path =~ m!.*${DS}TARGET$! ); + for my $path ( glob("$srcdir$DS*") ){ + next if( $path =~ m!.*${DS}TARGET$! ); - my $file = $path; + my $file = $path; - $file =~ s!.*$DS!!; + $file =~ s!.*$DS!!; + $file = catfile($targetdir, $file); - $file = catfile($targetdir, $file); + next if($opt_n); - 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; + 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; - } + 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 - - +sub do_file_nhgitset { + my $infile = "DEVEL/nhgitset.pl"; + $infile = "$DEVhooksdir/../nhgitset.pl" unless(-f $infile); + my $outfile = ".git/hooks/gitsetdocs"; + open IN, "<", $infile or die "Can't open $infile:$!"; + open OUT, ">", $outfile or die "Can't open $outfile:$!"; + my $started; + print IN "die \"DO NOT RUN THIS FILE\n\""; + while(){ + m/^__END__/ && do {$started =1; next}; + print OUT if($started); + } + close OUT; + close IN; +} +#(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 +__END__ =head1 NAME nhgitset.pl - Setup program for NetHack git repositories @@ -293,17 +383,36 @@ =head1 SYNOPSIS =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). +nhgitset.pl installs NetHack-specific setup after a C or after +changes to the setup, which are installed by re-running nhgitset.pl. If +an upgrade is needed, you will be informed during a C or similar +operation. + +The following options are available: + +=over + +=item B<-f> + +Force. Do not use this unless the program requests it or the hooks are broken. + +=back -The follwing options are available: +=over -B<-f> Force. Do not use this unless the program requests it. +=item B<-n> -B<-n> Make no changes. +Dry-run - make no changes. -B<-v> Verbose output. +=back + +=over + +=item B<-v> + +Verbose output. + +=back =head1 CONFIG @@ -320,8 +429,35 @@ =head1 CONFIG nethack.setupversion + The version for nhgitset.pl and friends; has no relationship + to NetHack version numbers. + nethack.substprefix + The prefix this repo uses for variable substitution. + +nethack.projectname + + The name of the game being built - see C. + +nethack.is-sourcerepo + + Does this repo contain NetHack source code? (1 = yes, 0 = no) + +nethack.setuppath + + Path to (and including) the DEVEL directory used including the + copy of nhgitset.pl used to set up this repo. + +nethack.aliashelp.* + + The last element of the variable is the name used with C + and the value is the name of a file to display with C. + +nethack.aliasdesc.* + + The last element of the variable is the name used with C + and the value is short help displayed with C. =head1 EXIT STATUS @@ -330,3 +466,5 @@ =head1 EXIT STATUS 1 Fail. 2 Intervention required. + +=for nhgitset nhgitset NetHack git helper installer