diff options
Diffstat (limited to 'pre-commit.d')
-rwxr-xr-x | pre-commit.d/20warn-hardlinks | 10 | ||||
-rwxr-xr-x | pre-commit.d/20warn-problem-files | 30 | ||||
-rwxr-xr-x | pre-commit.d/20warn-special-file | 12 | ||||
-rwxr-xr-x | pre-commit.d/30store-metadata | 85 |
4 files changed, 94 insertions, 43 deletions
diff --git a/pre-commit.d/20warn-hardlinks b/pre-commit.d/20warn-hardlinks deleted file mode 100755 index c1fd8f7..0000000 --- a/pre-commit.d/20warn-hardlinks +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -set -e - -if [ "$VCS" = git ] || [ "$VCS" = hg ] || [ "$VCS" = bzr ]; then - hardlinks=$(find -type f -not -links 1 | grep -v /.git/ | grep -v /.hg/ | grep -v /.bzr/) || true - if [ -n "$hardlinks" ]; then - echo "etckeeper warning: hardlinked files could cause problems with $VCS:" >&2 - echo "$hardlinks" >&2 - fi -fi diff --git a/pre-commit.d/20warn-problem-files b/pre-commit.d/20warn-problem-files new file mode 100755 index 0000000..f7c7580 --- /dev/null +++ b/pre-commit.d/20warn-problem-files @@ -0,0 +1,30 @@ +#!/bin/sh +set -e + +exclude_internal () { + egrep -v '(^|/)(.git|.hg|.bzr|_darcs)/' +} + +if [ "$VCS" = bzr ] || [ "$VCS" = darcs ]; then + special=$(find . -not -type d -not -type f -not -type l | exclude_internal) || true + hardlinks=$(find . -type f -not -links 1 | exclude_internal ) || true +elif [ "$VCS" = hg ]; then + special=$(find . -not -type d -not -type f -not -type l | exclude_internal) || true + hardlinks=$(find . -type f -not -links 1 -exec hg status {} \; | exclude_internal ) || true +elif [ "$VCS" = git ]; then + special=$(find . -not -type d -not -type f -not -type l -exec git ls-files --exclude-standard --cached --others {} \; | exclude_internal) || true + hardlinks=$(find . -type f -not -links 1 -exec git ls-files --exclude-standard --cached --others {} \; | exclude_internal) || true +else + special="" +fi + +if [ -n "$special" ] && [ -z "$AVOID_SPECIAL_FILE_WARNING" ]; then + echo "etckeeper warning: special files could cause problems with $VCS:" >&2 + echo "$special" >&2 +fi +if [ -n "$hardlinks" ] && [ -z "$AVOID_SPECIAL_FILE_WARNING" ]; then + echo "etckeeper warning: hardlinked files could cause problems with $VCS:" >&2 + echo "$hardlinks" >&2 +fi + +true diff --git a/pre-commit.d/20warn-special-file b/pre-commit.d/20warn-special-file deleted file mode 100755 index 5712bc5..0000000 --- a/pre-commit.d/20warn-special-file +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh -set -e - -if [ "$VCS" = git ] || [ "$VCS" = hg ] || [ "$VCS" = bzr ]; then - special=$(find -not -type d -not -type f -not -type l | grep -v /.git/ | grep -v /.hg/ | grep -v /.bzr/) || true - if [ -n "$special" ]; then - echo "etckeeper warning: special files could cause problems with $VCS:" >&2 - echo "$special" >&2 - fi -fi - -true diff --git a/pre-commit.d/30store-metadata b/pre-commit.d/30store-metadata index 243e019..b2a8678 100755 --- a/pre-commit.d/30store-metadata +++ b/pre-commit.d/30store-metadata @@ -14,14 +14,50 @@ filter_unknown() { done } +filter_ignore() { + if [ "$VCS" = darcs ]; then + ignorefile=.darcsignore + fi + + if [ "$VCS" = darcs ] && [ -e "$ignorefile" ]; then + patternsfile="$( mktemp -t etckeeper-$VCS.XXXXXXXXXX )" + grep -v '^[[:space:]]*\(#\|$\)' "$ignorefile" > "$patternsfile" || true + grep -Evf "$patternsfile" + rm -f "$patternsfile" + unset patternsfile + else + cat - + fi +} + +statf() { + while read statfile; do + printf "$(stat --format="$1" "$statfile") " + echo "$statfile" | shellquote + done +} + +shellquote() { + # Single quotes text, escaping existing single quotes. + sed -e "s/'/'\"'\"'/" -e "s/^/'/" -e "s/$/'/" +} + generate_metadata() { - # This function generates the script commands to fix any files - # that aren't owner=root, group=root, or mode=0644 or 0755. + # 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 maintain the permissions on the directory containing VCS data + # We want files in the directory containing VCS data # but we want find to ignore the VCS files themselves. - NOVCS='. -wholename ./.git -prune -o -wholename ./.bzr -prune -o -wholename ./.hg -prune -o' + # + # (Note that when using this, the find expression must end with + # -print or -exec, else the excluded directories will actually be + # printed!) + NOVCS='. -path ./.git -prune -o -path ./.bzr -prune -o -path ./.hg -prune -o -path ./_darcs -prune -o' # Keep the sort order the same at all times. LC_COLLATE=C @@ -30,31 +66,38 @@ generate_metadata() { if [ "$VCS" = git ] || [ "$VCS" = hg ]; then # These version control systems do not track directories, # so empty directories must be stored specially. - find -type d -empty | grep -v /.git/ | grep -v /.hg/ | grep -v /.bzr/ | - sort | sed -e "s/^/mkdir -p '/" -e "s/\$/'/" + find $NOVCS -type d -empty -print | + sort | shellquote | sed -e "s/^/mkdir -p /" fi - # Find all files and directories that don't have root as the owner - find $NOVCS \! -user root -exec stat --format="chown %U '{}'" {} \; \ - | sort | filter_unknown chown owner + if [ "$VCS" = darcs ]; then + # This version control system does not track symlinks, + # so they must be stored specially. + find $NOVCS -type l -print | sort | filter_ignore | while read link; do + dest=$( readlink "$link" ) + printf "ln -sf '%s' '%s'\n" "$(echo "$dest" | shellquote)" "$(echo "$link" | shellquote)" + done + fi + + # Find all files and directories that don't have the current user as the owner + find $NOVCS \! -user "$(id -u)" -print | statf "maybe chown %U" | sort | filter_unknown 'maybe chown' owner # Find all files and directories that don't have root as the group - find $NOVCS \! -group root -exec stat --format="chgrp %G '{}'" {} \; \ - | sort | filter_unknown chgrp group - - # Find all directories that aren't 0755 - find $NOVCS -type d \! -perm 0755 \ - -exec stat --format="chmod %a '{}'" {} \; | sort + find $NOVCS \! -group $(id -g) -print | statf "maybe chgrp %G" | sort | filter_unknown 'maybe chgrp' group - # Find all files that aren't 0644 or 0755 (we can assume the VCS will - # maintain the executable bit). - find $NOVCS -type f \! -perm 0644 \! -perm 0755 \ - -exec stat --format="chmod %a '{}'" {} \; | sort + # Store all file modes, in case the user has an unusual umask. + find $NOVCS \( -type f -or -type d \) -print | sort | perl -ne ' + BEGIN { $q=chr(39) } + chomp; + my $mode = (stat($_))[2]; + s/$q/$q"$q"$q/g; # escape single quotes + printf "maybe chmod %04o %s\n", $mode & 07777, "$q$_$q"; + ' # We don't handle xattrs. # Maybe check for getfattr/setfattr and use them if they're available? } -if [ "$VCS" = git ] || [ "$VCS" = hg ] || [ "$VCS" = bzr ]; then +if [ "$VCS" = git ] || [ "$VCS" = hg ] || [ "$VCS" = bzr ] || [ "$VCS" = darcs ]; then if [ -f .metadata ]; then # remove obsolete .metadata file # git allows fully deleting it at this point, other VCS @@ -80,6 +123,6 @@ if [ "$VCS" = git ] || [ "$VCS" = hg ] || [ "$VCS" = bzr ]; then # this will do nothing if the metadata file is unchanged. git add .etckeeper fi - # hg and bzr add not done, they will automatically + # hg, bzr and darcs add not done, they will automatically # include the file in the current commit fi |