tMerge pull request #6 from zelch/master - gitzone - git-based zone management tool for static and dynamic domains HTML git clone https://git.parazyd.org/gitzone DIR Log DIR Files DIR Refs --- DIR commit 4c0e0b9f7cb2f39d7e09c72372e010d5aa6767d0 DIR parent 528aad32d27e4f25284a408a7dd57ddde11f02d8 HTML Author: Jaromil <jaromil@dyne.org> Date: Sun, 9 Jun 2019 10:59:32 +0200 Merge pull request #6 from zelch/master Fixes for current git versions. (Plus an enhancement or two.) Diffstat: M bin/gitzone | 92 +++++++++++++++++++++++++------ M hooks/post-receive | 4 +--- 2 files changed, 76 insertions(+), 20 deletions(-) --- DIR diff --git a/bin/gitzone b/bin/gitzone t@@ -31,6 +31,8 @@ use POSIX qw/strftime/; use Cwd qw/cwd realpath/; use File::Basename qw/fileparse basename/; use File::Temp; +use File::Path; +use File::Spec; @ARGV >= 2 or die "Usage: gitzone /path/to/gitzone.conf <command>\n"; chdir '.git' if -d '.git'; t@@ -39,6 +41,7 @@ basename(realpath) eq '.git' or die "gitzone has to be run from a .git directory my $lock_file = realpath '.gitzone-lock'; my $list_file = realpath '.gitzone-list'; my $stash_file; +my $read_only = 0; chdir '..'; our $user = getpwuid $<; t@@ -129,7 +132,7 @@ sub check_what_changed { } # parse diff output, add only valid zone names to %files for parsing - $files{$1} = 0 while m,^:(?:[\w.]+\s+){5}([a-z0-9./-]+)$,gm; + $files{$1} = 0 while m,^:(?:[\w.]+\s+){5}(?:[A-Za-z0-9./-]+\s+)?([A-Za-z0-9./-]+)$,gm; } sub process_files { t@@ -137,7 +140,7 @@ sub process_files { process_file($_) for keys %files; check_zones(); - if (@changed_files) { + if (@changed_files && !$read_only) { print "adding changed files: @changed_files\n" if $verbosity >= 2; git "add @changed_files"; } t@@ -176,16 +179,22 @@ sub process_file { die "Error in $file:$n: invalid included file name, it should start with: $repo/\n"; } } + + # Try and feed INCLUDE files with relative path names into the list. + # This should allow having a common header with an AUTO_INCREMENTed serial number. + if ($inc_file =~ m|^$repo/(.*)|) { + push (@inc_by, $1); + } } else { if ($n == 1 && /^;INCLUDED_BY\s+(.*)$/) { - @inc_by = split /\s+/, $1; + push(@inc_by, split /\s+/, $1); } } push @newfile, $line; } close FILE; - if ($changed) { + if ($changed && !$read_only) { print ">>> $file changed, saving\n" if $verbosity >= 3; open FILE, '>', $file or die $!; t@@ -297,19 +306,38 @@ sub pre_receive { # nothing for master branch, exit clean_exit 0 unless $ref; - # checkout changes - git "checkout -qf $new"; + # Figure out the paths for the repo, and the temporary checkout location. + my $base_cwd = cwd; + my @dir = File::Spec->splitdir($base_cwd); + my $repo_name = $dir[$#dir]; + $dir[$#dir] .= '_tmp'; + push(@dir, $repo_name); + my $tmp_dir = join('/', @dir); + + # Do the diff and find out exactly what changed. + # This must be done before the chdir below. check_what_changed($old, $new); + + # Make the temporary directory from scratch. + File::Path->remove_tree($tmp_dir, verbose => 1); + File::Path->make_path($tmp_dir, verbose => 1); + + # Extract the new commit. + # We do this with git archive, and then extract the resulting tar in the temporary directory. + # There really should be a better way to do this, but I can't find one. + git "archive $new | tar -C $tmp_dir -xf -"; + + # chdir into the temporary directory. + chdir $tmp_dir or die $!; + + # Go read only, no actual changes in the pre-release hook. + $read_only = 1; + load_repo_config; process_files; - git "commit -nm 'auto increment: @changed_files'", 1 if @changed_files; - save_list_file; - # save new commits in a new branch - git 'branch -f new'; - git 'checkout'; - # was: git 'checkout -B new'; - # removed for back-compat with old git + # Go back to the repo. + chdir $base_cwd; } sub pre_commit { t@@ -334,17 +362,47 @@ sub pre_commit { } sub post_receive { + my ($old, $new, $ref); + + while (<STDIN>) { # <old-value> SP <new-value> SP <ref-name> LF + print if $verbosity >= 1; + next unless m,(\w+) (\w+) ([\w/]+),; + next if $3 ne 'refs/heads/master'; # only process master branch + die "Denied branch 'new', choose another name\n" if $3 eq 'refs/head/new'; + ($old, $new, $ref) = ($1, $2, $3); + } + + # nothing for master branch, exit + clean_exit 0 unless $ref; + + # Repeat the check_what_changed from the pre_receive. + check_what_changed($old, $new); + print "\n"; - # move master to new + # Grab the current master. git 'checkout -f master'; - git 'reset --hard new'; load_repo_config; - load_list_file; + + # Go through and process the files again, this time allowing changes. + # All of the AUTO_INCREMENT stuff happens here. + # The zone files are checked a second time as well. + process_files; + + # Commit any auto increment changes. + if (@changed_files) { + git "commit -nm 'auto increment: @changed_files'", 1; + } + + # Actually install the new zone files. install_zones; - print "Done. Don't forget to pull if you use auto increment.\n"; + if (@changed_files) { + print "Done. Auto increment applied, don't forget to pull.\n"; + } else { + print "Done.\n"; + } } sub post_commit { DIR diff --git a/hooks/post-receive b/hooks/post-receive t@@ -1,6 +1,4 @@ #!/bin/sh #(date; echo post-receive) >> ~/gitzone.log -if [ -f .gitzone-list ]; then - /usr/bin/gitzone /etc/gitzone.conf post-receive # 2>&1 | tee -a ~/gitzone.log -fi +/usr/bin/gitzone /etc/gitzone.conf post-receive # 2>&1 | tee -a ~/gitzone.log