#!/bin/sh # pre-commit hook for ngcpcfg, to store metadata # implementation heavily based on etckeeper's pre-commit.d/30store-metadata set -e # ensure we're in the appropriate git directory (/etc/ngcp-config/ by default), # we don't rely on ${NGCPCTL_MAIN} just in case we're invoked directly, # e.g. via `/etc/ngcp-config/.git/hooks/pre-commit` (outside of ngcpcfg) cd "$(dirname "${0}")/../../" if ! git rev-parse --git-dir >/dev/null 2>&1 ; then echo "Warning: $(pwd) is not a git repository, ignoring $0" exit 0 fi filter_ignore() { if [ -e ".gitignore" ]; then listfile="$(mktemp -t ngcpcfg-git.XXXXXXXXXX)" (git ls-files -oi --exclude-standard; git ls-files -oi --exclude-standard --directory) | sort | uniq > "$listfile" || true sed 's/^\.\///' | grep -xFvf "$listfile" rm -f "$listfile" unset listfile else cat - fi } shellquote() { # Single quotes text, escaping existing single quotes. sed -e "s/'/'\"'\"'/g" -e "s/^/'/" -e "s/$/'/" } generate_metadata() { # This function generates the script commands to fix any file # ownerships that aren't owner=root, group=root, as well as to # store the permissions of files. # The script is produced on stdout. Errors go to stderr. # # The script can use a 'maybe' function, which only runs a command # if the file in its last argument exists. # We want files in the directory containing VCS data # but we want find to ignore the VCS files themselves. # # (Note that when using this, the find expression must end with # -print or -exec, else the excluded directories will actually be # printed!) # Keep the sort order the same at all times. LC_COLLATE=C export LC_COLLATE # git does not track directories, # so empty directories must be stored specially. find . -path ./.git -prune -o -type d -empty -print | sort | shellquote | sed -e "s/^/mkdir -p /" # Store things that don't have the default user or group. # Store all file modes, in case the user has an unusual umask. find . -path ./.git -prune -o \( -type f -or -type d \) -print | filter_ignore | sort | perl -ne ' BEGIN { $q=chr(39) } sub uidname { my $want=shift; if (exists $uidcache{$want}) { return $uidcache{$want}; } my $name=scalar getpwuid($want); return $uidcache{$want}=defined $name ? $name : $want; } sub gidname { my $want=shift; if (exists $gidcache{$want}) { return $gidcache{$want}; } my $name=scalar getgrgid($want); return $gidcache{$want}=defined $name ? $name : $want; } chomp; my @stat=stat($_); my $mode = $stat[2]; my $uid = $stat[4]; my $gid = $stat[5]; s/$q/$q"$q"$q/g; # escape single quotes s/^/$q/; s/$/$q/; if ($uid != $>) { printf "maybe chown $q%s$q %s\n", uidname($uid), $_; } if ($gid != $)) { printf "maybe chgrp $q%s$q %s\n", gidname($gid), $_; } printf "maybe chmod %04o %s\n", $mode & 07777, $_; ' } ngcpcfg_perms=$(mktemp -t ngcpcfg-perms.XXXXXXXXXX) chown root:root "${ngcpcfg_perms}" # Make sure the file is not readable by others, since it can leak # information about contents of non-readable directories chmod 700 "${ngcpcfg_perms}" echo "# Generated by ngcpcfg. Do not edit." > "${ngcpcfg_perms}" echo >> "${ngcpcfg_perms}" generate_metadata >> "${ngcpcfg_perms}" mv "${ngcpcfg_perms}" .ngcpcfg_perms git add .ngcpcfg_perms