#!/bin/sh -eu # # psvn - Wrapper to set Subversion properties automatically # # Copyright (c) 2012 Beat Gaetzi # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # # $FreeBSD$ # # MAINTAINER= mandree@FreeBSD.org # beat@ has implicit approval to change this script. # # # The psvn wrapper checkes from replaced, conflicting, missing or # untracked files. When committing it adds the needed Subversion # properties and removes unneeded ones. # There is also adds a check subcommand which just executes the # checks. # PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:${PATH} export PATH SVN="$(which svn)" LF="$(printf '\nX')" LF="${LF%X}" VERSION=$("${SVN}" --version --quiet | sed -e 's,^\(.*\)\.\(.*\)\..*,\1\2,') if [ ${VERSION} -lt 17 ] ; then echo "===> Please consider upgrading to Subversion 1.7 (or newer)" fi checkstatus () { local IFS _error _file _status _statusline - _error=0 eval "set -- $@" IFS="$LF" set -- $("${SVN}" status -- "$@") for _statusline do _status="$(printf '%.7s' "${_statusline}")" _file="${_statusline##????????}" case "${_status}" in R*) printf >&2 '===> Do not replace files as this will break the CVS exporter: "%s"\n' "${_file}" _error=1 ;; C*|?C*) printf >&2 '===> Conflict detected: \"%s\"\n' "${_file}" _error=1 ;; \~*) printf >&2 '===> Versioned item \"%s\" obstructed.\n' "${_file}" _error=1 ;; \?*) printf >&2 '===> Untracked new file "%s". Consider svn adding or deleting it.\n' "${_file}" _error=1 ;; \!*) printf >&2 '===> Missing file "%s". Consider re-adding or svn deleting it.\n' "${_file}" _error=1 ;; esac done if [ ${_error} -ne 0 ] ; then exit 1 fi } setprop () { local _file - eval "set -- $1" for _file do if [ -d "${_file}" -o ! -e "${_file}" ] ; then continue fi printf >&2 '=> Adding svn keywords to "%s"\n' "${_file}" case $(egrep -- '\$FreeBSD\$|\$[BDFSer]+:' "${_file}" >/dev/null || echo $?) in "") # matched pattern "${SVN}" -q -- propset svn:keywords "FreeBSD=%H" "${_file}" "${SVN}" -q -- propdel fbsd:nokeywords "${_file}" ;; 1) # no match "${SVN}" -q -- propset fbsd:nokeywords yes "${_file}" "${SVN}" -q -- propdel svn:keywords "${_file}" ;; *) # egrep failed exit 1 ;; esac if [ "${_file##/*}" != "bsd.port.mk" ] ; then "${SVN}" -q -- propset svn:eol-style native "${_file}" fi "${SVN}" -q -- propset svn:mime-type text/plain "${_file}" "${SVN}" -q -- propdel cvs2svn:cvs-rev "${_file}" done } # taken from "Rich's sh (POSIX shell) tricks", # a "Programming Guide[...]" at http://www.etalabs.net/sh_tricks.html savearray() { for i do printf %s\\n "$i" | sed -e "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" done echo " " } getfilequotedarray() { local varname IFS varname="$1" shift IFS="$LF" set -- $("${SVN}" status -- "$@" | sed 's/^....... //') eval "$varname=\$(savearray "\$@")" } for opt ; do case "${opt}" in -*) continue ;; esac case "${opt}" in check) shift if [ $# -gt 0 ] ; then echo >&2 "===> Unsupported option before, or garbage after command" exit 1 fi getfilequotedarray "files" "$@" checkstatus "${files}" exit 0 ;; ci|commit) savedargs=$(savearray "$@") shift while getopts :qm:F: opt do case "$opt" in q) ;; m) ;; F) ;; \?) echo >&2 "===> Unsupported option -$OPTARG encountered. Abort." exit 1 ;; :) echo >&2 "===> Missing argument to option -$OPTARG. Abort." exit 1 ;; esac done shift $(($OPTIND - 1)) getfilequotedarray "files" "$@" checkstatus "${files}" setprop "${files}" eval "set -- $savedargs" exec "${SVN}" "$@" ;; *) exec "${SVN}" "$@" ;; esac done