PageRenderTime 83ms CodeModel.GetById 40ms app.highlight 7ms RepoModel.GetById 33ms app.codeStats 0ms

/etckeeper/pre-commit.d/30store-metadata

http://github.com/brinkman83/bashrc
Shell | 130 lines | 69 code | 17 blank | 44 comment | 19 complexity | 98fa84fa386cd9c0fc210ea8a8009f26 MD5 | raw file
  1#!/bin/sh
  2set -e
  3
  4# Filters out UNKNOWN users and groups, prints a warning on stderr.
  5filter_unknown() {
  6	CMD=$1
  7	while read line; do
  8		# if the first n chars of $line equal "$CMD UNKNOWN "...
  9		if [ "$(printf %.$((9+${#CMD}))s "$line")" = "$CMD UNKNOWN " ]; then
 10			echo Bad "$2" for "$line" >&2
 11		else
 12			echo "$line"
 13		fi
 14	done
 15}
 16
 17filter_ignore() {
 18	if [ "$VCS" = darcs ]; then
 19		ignorefile=.darcsignore
 20	fi
 21
 22	if [ "$VCS" = darcs ] && [ -e "$ignorefile" ]; then
 23		# Spaces embedded into patterns would break it.
 24		# But really, why would anyone want to use ' ' instead of '\s' ?
 25		#patterns=$( grep -v '^[[:space:]]*\(#\|$\)' "$ignorefile" | xargs -n 1 printf " -e %s" )
 26		#grep -Ev $patterns
 27		#unset patterns
 28		# Alternative using a temp file
 29		patternsfile="$( mktemp -t etckeeper-$VCS.XXXXXXXXXX )"
 30		grep -v '^[[:space:]]*\(#\|$\)' "$ignorefile" > "$patternsfile" || true
 31		grep -Evf "$patternsfile"
 32		rm -f "$patternsfile"
 33		unset patternsfile
 34	else
 35		cat -
 36	fi
 37}
 38
 39generate_metadata() {
 40	# This function generates the script commands to fix any files
 41	# that aren't owner=root, group=root, or mode=0644 or 0755.
 42	# The script is produced on stdout.  Errors go to stderr.
 43	# 
 44	# The script can use a 'maybe' function, which only runs a command
 45	# if the file in its last argument exists.
 46
 47	# We maintain the permissions on the directory containing VCS data
 48	# but we want find to ignore the VCS files themselves.
 49	# 
 50	# (Note that when using this, the find expression must end with 
 51	# -print or -exec, else the excluded directories will actually be
 52	# printed!)
 53	NOVCS='. -wholename ./.git -prune -o -wholename ./.bzr -prune -o -wholename ./.hg -prune -o -wholename ./_darcs -prune -o'
 54
 55	# Keep the sort order the same at all times.
 56	LC_COLLATE=C
 57	export LC_COLLATE
 58
 59	if [ "$VCS" = git ] || [ "$VCS" = hg ]; then
 60		# These version control systems do not track directories,
 61		# so empty directories must be stored specially.
 62		find $NOVCS -type d -empty -print |
 63			sort | sed -e "s/^/mkdir -p '/" -e "s/\$/'/"
 64	fi
 65
 66	if [ "$VCS" = darcs ]; then
 67		# This version control system does not track symlinks,
 68		# so they must be stored specially.
 69		find $NOVCS -type l -print | sort | filter_ignore | while read link; do
 70			dest=$( readlink "$link" )
 71			printf "ln -sf '%s' '%s'\n" "$dest" "$link"
 72		done
 73	fi
 74
 75	# Find all files and directories that don't have the current user as the owner
 76	find $NOVCS \! -user "$(id -u)" -exec stat --format="maybe chown %U '{}'" {} \; \
 77		| sort | filter_unknown 'maybe chown' owner
 78	# Find all files and directories that don't have root as the group
 79	find $NOVCS \! -group $(id -g) -exec stat --format="maybe chgrp %G '{}'" {} \; \
 80		| sort | filter_unknown 'maybe chgrp' group
 81
 82	# Find all directories that aren't 0755
 83	find $NOVCS -type d \! -perm 0755 \
 84		-exec stat --format="maybe chmod %a '{}'" {} \; | sort
 85
 86	if [ "$VCS" = darcs ]; then
 87		# Find all files that aren't 0644 (darcs doesn't maintain
 88		# the executable bit).
 89		find $NOVCS -type f \! -perm 0644 \
 90			-exec stat --format="maybe chmod %a '{}'" {} \; | sort
 91	else
 92		# Find all files that aren't 0644 or 0755 (we can assume the VCS will
 93		# maintain the executable bit).
 94		find $NOVCS -type f \! -perm 0644 \! -perm 0755 \
 95			-exec stat --format="maybe chmod %a '{}'" {} \; | sort
 96	fi
 97
 98	# We don't handle xattrs.
 99	# Maybe check for getfattr/setfattr and use them if they're available?
100}
101
102if [ "$VCS" = git ] || [ "$VCS" = hg ] || [ "$VCS" = bzr ] || [ "$VCS" = darcs ]; then
103	if [ -f .metadata ]; then
104		# remove obsolete .metadata file
105		# git allows fully deleting it at this point, other VCS
106		# may not (the repo is locked for hg).
107		if [ "$VCS" = git ]; then
108			$VCS rm .metadata
109		else
110			rm -f .metadata
111		fi
112	fi
113
114	echo "# Generated by etckeeper.  Do not edit." > .etckeeper
115	echo >> .etckeeper
116
117	# Make sure the file is not readable by others, since it can leak
118	# information about contents of non-readable directories in /etc.
119	chmod 700 .etckeeper
120
121	generate_metadata >> .etckeeper
122
123	# stage the file as part of the current commit
124	if [ "$VCS" = git ]; then
125		# this will do nothing if the metadata file is unchanged.
126		git add .etckeeper
127	fi
128	# hg, bzr and darcs add not done, they will automatically
129	# include the file in the current commit
130fi