obs-service-tar_scm/tar_scm
Adrian Schröter 6e55d7df19 Accepting request 105386 from home:aspiers:branches:openSUSE:Tools
- add new 'versionformat' option to determine how version is
  extracted via git show --pretty=... (and similar for svn /
  hg / bzr)
- support caching of cloned repositories to speed up fetch
  from upstream
- use mktemp -u because git/hg refuse to clone into an empty 
  directory on SLES11

OBS-URL: https://build.opensuse.org/request/show/105386
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Tools/obs-service-tar_scm?expand=0&rev=33
2012-02-16 11:06:33 +00:00

467 lines
10 KiB
Bash

#!/bin/bash
# A simple script to checkout or update a svn or git repo as source service
#
# (C) 2010 by Adrian Schröter <adrian@suse.de>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# See http://www.gnu.org/licenses/gpl-2.0.html for full license text.
SERVICE='tar_scm'
set_default_params () {
MYSCM=""
MYURL=""
MYVERSION="_auto_"
MYFORMAT=""
MYPREFIX=""
MYFILENAME=""
MYREVISION=""
MYPACKAGEMETA=""
# MYHISTORYDEPTH=""
INCLUDES=""
}
get_config_options () {
# config options for this host ?
if [ -f /etc/obs/services/$SERVICE ]; then
. /etc/obs/services/$SERVICE
fi
# config options for this user ?
if [ -f "$HOME"/.obs/$SERVICE ]; then
. "$HOME"/.obs/$SERVICE
fi
}
parse_params () {
while test $# -gt 0; do
case $1 in
*-scm)
MYSCM="$2"
shift
;;
*-url)
MYURL="$2"
shift
;;
*-subdir)
MYSUBDIR="$2"
shift
;;
*-revision)
MYREVISION="$2"
shift
;;
*-version)
MYVERSION="$2"
shift
;;
*-include)
INCLUDES="$INCLUDES $2"
shift
;;
*-versionformat)
MYFORMAT="$2"
shift
;;
*-versionprefix)
MYPREFIX="$2"
shift
;;
*-exclude)
EXCLUDES="$EXCLUDES --exclude=${2#/}"
shift
;;
*-filename)
MYFILENAME="${2#/}"
shift
;;
*-package-meta)
MYPACKAGEMETA="${2#/}"
shift
;;
*-outdir)
MYOUTDIR="$2"
shift
;;
*-history-depth)
echo "history-depth parameter is obsolete and will be ignored"
shift
;;
*)
echo "Unknown parameter: $1"
echo 'Usage: $SERVICE --scm $SCM --url $URL [--subdir $SUBDIR] [--revision $REVISION] [--version $VERSION] [--include $INCLUDE]* [--exclude $EXCLUDE]* [--versionformat $FORMAT] [--versionprefix $PREFIX] [--filename $FILENAME] [--package-meta $META] --outdir $OUT'
exit 1
;;
esac
shift
done
}
error () {
echo "ERROR: $*"
exit 1
}
debug () {
[ -n "$DEBUG_TAR_SCM" ] && echo "$*"
}
safe_run () {
if ! "$@"; then
error "$* failed; aborting!"
fi
}
sanitise_params () {
TAR_VERSION="$MYVERSION"
if [ -z "$MYSCM" ]; then
error "no scm is given via --scm parameter (git/svn/hg/bzr)!"
fi
if [ -z "$MYURL" ]; then
error "no checkout URL is given via --url parameter!"
fi
if [ -z "$MYOUTDIR" ]; then
error "no output directory is given via --outdir parameter!"
fi
FILE="$MYFILENAME"
WD_VERSION="$MYVERSION"
if [ -z "$MYPACKAGEMETA" ]; then
EXCLUDES="$EXCLUDES --exclude=.$MYSCM"
fi
# if [ "$MYHISTORYDEPTH" == "full" ]; then
# MYHISTORYDEPTH="999999999"
# fi
}
detect_default_filename_param () {
if [ -n "$FILE" ]; then
return
fi
case "$MYSCM" in
git)
FILE="${MYURL%/}"
FILE="${FILE##*/}"
FILE="${FILE%.git}"
FILE="${FILE#*@*:}"
;;
svn|hg|bzr)
FILE="${MYURL%/}"
FILE="${FILE##*/}"
;;
*)
error "unknown SCM '$MYSCM'"
esac
}
fetch_upstream () {
TOHASH="$MYURL"
[ "$MYSCM" = 'svn' ] && TOHASH="$TOHASH/$MYSUBDIR"
HASH=`echo "$TOHASH" | sha256sum | cut -d\ -f 1`
REPOCACHE=
if [ -n "$CACHEDIRECTORY" ]; then
REPOCACHEINCOMING="$CACHEDIRECTORY/incoming"
REPOCACHEROOT="$CACHEDIRECTORY/repo"
REPOCACHE="$REPOCACHEROOT/$HASH"
REPOURLCACHE="$CACHEDIRECTORY/repourl/$HASH"
fi
if [ -z "$MYREVISION" ]; then
case "$MYSCM" in
git)
MYREVISION=master
;;
hg)
MYREVISION=tip
;;
# bzr)
# MYREVISION=HEAD
# ;;
esac
if [ -n "$MYREVISION" ]; then
debug "no revision specified; defaulting to $MYREVISION"
fi
fi
debug "check local cache if configured"
if [ -n "$CACHEDIRECTORY" -a -d "$REPOCACHE/.$MYSCM" ]; then
debug "cache hit: $REPOCACHE/.$MYSCM"
check_cache
update_cache
REPOPATH="$REPOCACHE"
else
if [ -n "$CACHEDIRECTORY" ]; then
debug "cache miss: $REPOCACHE/.$MYSCM"
else
debug "cache not enabled"
fi
calc_dir_to_clone_to
debug "new $MYSCM checkout to $CLONE_TO"
initial_clone
if [ -n "$CACHEDIRECTORY" ]; then
cache_repo
REPOPATH="$REPOCACHE"
else
REPOPATH="$MYOUTDIR/$FILE"
fi
fi
safe_run cd "$REPOPATH"
switch_to_revision
if [ "$TAR_VERSION" == "_auto_" -o -n "$MYFORMAT" ]; then
detect_version
fi
}
calc_dir_to_clone_to () {
if [ -n "$CACHEDIRECTORY" ]; then
safe_run cd "$REPOCACHEINCOMING"
# Use dry-run mode because git/hg refuse to clone into
# an empty directory on SLES11
debug mktemp -u -d "tmp.XXXXXXXXXX"
CLONE_TO=`mktemp -u -d "tmp.XXXXXXXXXX"`
else
CLONE_TO="$FILE"
fi
}
initial_clone () {
case "$MYSCM" in
git)
# Clone with full depth; so that the revision can be found if specified
safe_run git clone "$MYURL" "$CLONE_TO"
;;
svn)
args=
[ -n "$MYREVISION" ] && args="-r$MYREVISION"
if [[ $(svn --version --quiet) > "1.5.99" ]]; then
TRUST_SERVER_CERT="--trust-server-cert"
fi
safe_run svn checkout --non-interactive $TRUST_SERVER_CERT \
$args "$MYURL/$MYSUBDIR" "$CLONE_TO"
MYSUBDIR= # repo root is subdir
;;
hg)
safe_run hg clone "$MYURL" "$CLONE_TO"
;;
bzr)
args=
[ -n "$MYREVISION" ] && args="-r $MYREVISION"
safe_run bzr checkout $args "$MYURL" "$CLONE_TO"
;;
*)
error "unknown SCM '$MYSCM'"
esac
}
cache_repo () {
if [ -e "$REPOCACHE" ]; then
error "Somebody else beat us to populating the cache for $MYURL ($REPOCACHE)"
else
# FIXME: small race window here; do source services need to be thread-safe?
debug mv2 "$CLONE_TO" "$REPOCACHE"
safe_run mv "$CLONE_TO" "$REPOCACHE"
echo "$MYURL" > "$REPOURLCACHE"
echo "cached $MYURL at $REPOCACHE"
fi
}
check_cache () {
CACHEDURL=`cat "$REPOURLCACHE"`
[ -z "$CACHEDURL" ] && CACHEDURL='<unknown URL>'
if [ "$MYURL" != "$CACHEDURL" ]; then
error "Corrupt cache: cache for repo $MYURL was recorded as being from $CACHEDURL"
fi
}
update_cache () {
safe_run cd "$REPOCACHE"
case "$MYSCM" in
git)
safe_run git fetch
;;
svn)
args=
[ -n "$MYREVISION" ] && args="-r$MYREVISION"
safe_run svn update $args
MYSUBDIR= # repo root is subdir
;;
hg)
if ! out=`hg pull`; then
if [[ "$out" == *'no changes found'* ]]; then
# Contrary to the docs, hg pull returns exit code 1 when
# there are no changes to pull, but we don't want to treat
# this as an error.
:
else
error "hg pull failed; aborting!"
fi
fi
;;
bzr)
args=
[ -n "$MYREVISION" ] && args="-r$MYREVISION"
safe_run bzr update $args
;;
*)
error "unknown SCM '$MYSCM'"
esac
}
switch_to_revision () {
case "$MYSCM" in
git)
safe_run git checkout "$MYREVISION"
if git branch | grep -q '^\* (no branch)$'; then
echo "$MYREVISION does not refer to a branch, not attempting git pull"
else
git pull
fi
;;
svn|bzr)
: # should have already happened via checkout or update
;;
hg)
safe_run hg update "$MYREVISION"
;;
# bzr)
# safe_run bzr update
# if [ -n "$MYREVISION" ]; then
# safe_run bzr revert -r "$MYREVISION"
# fi
# ;;
*)
error "unknown SCM '$MYSCM'"
esac
}
detect_version () {
if [ -z "$MYFORMAT" ]; then
case "$MYSCM" in
git)
MYFORMAT="%at"
;;
hg)
MYFORMAT="{rev}"
;;
svn|bzr)
MYFORMAT="%r"
;;
*)
error "unknown SCM '$MYSCM'"
;;
esac
fi
safe_run cd "$REPOPATH"
[ -n "$MYPREFIX" ] && MYPREFIX="$MYPREFIX."
get_version
TAR_VERSION="$MYPREFIX$version"
}
get_version () {
case "$MYSCM" in
git)
#version=`safe_run git show --pretty=format:"$MYFORMAT" | head -n 1`
version=`safe_run git log -n1 --pretty=format:"$MYFORMAT"`
;;
svn)
#rev=`LC_ALL=C safe_run svn info | awk '/^Revision:/ { print $2 }'`
rev=`LC_ALL=C safe_run svn info | sed -n 's,^Last Changed Rev: \(.*\),\1,p'`
version="${MYFORMAT//%r/$rev}"
;;
hg)
rev=`safe_run hg id -n`
version=`safe_run hg log -l1 -r$rev --template "$MYFORMAT"`
;;
bzr)
#safe_run bzr log -l1 ...
rev=`safe_run bzr revno`
version="${MYFORMAT//%r/$rev}"
;;
*)
error "unknown SCM '$MYSCM'"
esac
}
prep_tree_for_tar () {
if [ ! -e "$REPOPATH/$MYSUBDIR" ]; then
error "directory does not exist: $REPOPATH/$MYSUBDIR"
fi
if [ -z "$TAR_VERSION" ]; then
TAR_BASENAME="$FILE"
else
TAR_BASENAME="${FILE}-${TAR_VERSION}"
fi
MYINCLUDES=""
for INC in $INCLUDES; do
MYINCLUDES="$MYINCLUDES $TAR_BASENAME/$INC"
done
if [ -z "$MYINCLUDES" ]; then
MYINCLUDES="$TAR_BASENAME"
fi
safe_run cd "$MYOUTDIR"
if [ -n "$CACHEDIRECTORY" ]; then
debug cp -a "$REPOPATH/$MYSUBDIR" "$TAR_BASENAME"
safe_run cp -a "$REPOPATH/$MYSUBDIR" "$TAR_BASENAME"
else
debug mv3 "$REPOPATH/$MYSUBDIR" "$TAR_BASENAME"
safe_run mv "$REPOPATH/$MYSUBDIR" "$TAR_BASENAME"
fi
}
create_tar () {
TARFILE="${TAR_BASENAME}.tar"
TARPATH="$MYOUTDIR/$TARFILE"
debug tar cf "$TARPATH" $EXCLUDES $MYINCLUDES
safe_run tar cf "$TARPATH" $EXCLUDES $MYINCLUDES
echo "Created $TARFILE"
}
cleanup () {
debug rm -rf "$TAR_BASENAME" "$FILE"
rm -rf "$TAR_BASENAME" "$FILE"
}
main () {
set_default_params
if [ -z "$DEBUG_TAR_SCM" ]; then
get_config_options
else
# We're in test-mode, so don't let any local site-wide
# or per-user config impact the test suite.
:
fi
parse_params "$@"
sanitise_params
SRCDIR=$(pwd)
cd "$MYOUTDIR"
detect_default_filename_param
fetch_upstream
prep_tree_for_tar
create_tar
cleanup
}
main "$@"
exit 0