Skip to content

Instantly share code, notes, and snippets.

@rudimeier
Created September 7, 2011 12:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rudimeier/1200424 to your computer and use it in GitHub Desktop.
Save rudimeier/1200424 to your computer and use it in GitHub Desktop.
automated package source updates on the openSUSE Build Service
#!/bin/bash
#
# obs-auto-push: - automated package source updates on the
# "openSUSE Build Service"
# - currently support for git origins only
#
# usage: - set your paths in config section below
# - see --help
#
# Copyright (C) 2011 Ruediger Meier <sweet_f_a@gmx.de>
# License: BSD 3-Clause
#### source some stuff to be used everywhere, don't touch it!
NOW_T="$(date +"%s")" || exit 1
NOW_HUMAN="$(date -d "@${NOW_T}" +"%F %T")" || exit 1
#### config section
# Note we have two macros available here, %PACKAGE% and %VERSION%. They will
# be expanded at runtime of this scripts.
# Specify your obs and snapshot (git) directories. They must exist for packages
# given as command line option.
# Warning, this scripts behaves not nice against these dirs, so don't use
# them for your regular work unless you know what you are doing.
OBS_DIR="/home/rudi/devel/osc/home:rudi_m:devel-snap/%PACKAGE%"
SNAP_DIR="/home/rudi/devel/snap/%PACKAGE%"
# The following patterns should match your naming style.
# The untarred source directory name (root of the tar ball):
TAR_PREFIX="%PACKAGE%-%VERSION%"
# Name of source tar ball ( must be .tar.gz if UPDATE_DEB=yes):
TAR_NAME="%PACKAGE%-%VERSION%.tar.xz"
# Your packages are rpm and/or debian conform?
UPDATE_RPM="yes"
UPDATE_DEB="no"
# customize osc commit message
OSC_COMMIT_MSG="obs-auto-push ${NOW_HUMAN}: update %VERSION%"
#### defaults, don't change!
PACKAGE=""
PULL_BRANCH="master"
PULL_REMOTE="origin"
# for testing, say yes to nodt push to obs
DRY_RUN="no"
# force pushing to obs even we think it's up-to-date
FORCE="no"
# do not change this! It must be calculated
VERSION="unknown"
#### funcs
function prnt_dbg()
{
echo "$@" >&2
}
function prnt_err()
{
echo "error: $@" >&2
}
function print_usage()
{
cat <<EOF
obs-auto-push 0.1.0
Usage: $0 [--branch] [--remote] [--force] [-t|--test] [--help|--version] \
[--] package
EOF
}
function parse_cmd()
{
local tmp
tmp=$(getopt -o t \
--long branch:,remote:,force,test,help,version \
-n "$0" -- "$@" \
) || return 1
eval set -- "$tmp"
while true ; do
case "$1" in
--branch)
PULL_BRANCH="$2"; shift 2;;
--remote)
PULL_REMOTE="$2"; shift 2;;
--force)
FORCE="yes"; shift 1;;
-t|--test)
DRY_RUN="yes"; shift 1;;
--help|--version)
print_usage; exit 0;;
--)
shift ; break ;;
*)
prnt_err "Internal getopt error!" ; return 1;;
esac
done
#Remaining arguments:
if test "$#" != 1 ;then
prnt_err "bad usage, try --help"
return 1
fi
PACKAGE="$1"
return 0
}
# reset obs working copy to upstream
# return 0 on success or 1 on error
function fetch_obs()
{
# Is all this safe to have a really clean working copy?
osc revert .
osc status | while read -r state file ;do
rm -rf "$file"
done
osc update || return 1
local dirty
if ! dirty="$(osc status)" || test -n "${dirty}" ;then
return 1
fi
return 0
}
# write yes/no if update is needed
# return 0 if pull was successful or 1 on error
function fetch_origin()
{
local rev_head
local rev_origin
# WTF, can't we fetch branches and tags (forced update) with one command!?
git fetch "${PULL_REMOTE}" 1>&2 || return 1
git fetch --tags "${PULL_REMOTE}" 1>&2 || return 1
rev_head="$( git rev-parse HEAD )" || return 1
rev_origin="$( git rev-parse "${PULL_REMOTE}/${PULL_BRANCH}" )" || return 1
if [ "${rev_head}" = "${rev_origin}" ] ; then
echo no
return 0
fi
# git reset or merge could be command line switches (merge would make
# you able to mix upstream and local commits)
git reset --hard "${PULL_REMOTE}/${PULL_BRANCH}" 1>&2 || return 1
echo yes
return 0
}
# write nice VERSION string
# Overwrite this function if you want other kind of versions strings or if this
# implementation doesn't work for your origin's git tag format
function get_version()
{
local ver
# get nice version, e.g. "v0.3.0-41-g0f6c" -> "0.3.0.git41.g0f6c"
ver="$( git describe --long --match "v[0-9]*" --abbrev=4 )" \
|| return 1
ver="$( echo ${ver} |sed 's/^v\(.*\)-\(.*\)-g\(.*\)/\1.git\2.\3/g' )" \
|| return 1
echo ${ver}
return 0
}
# create the new tar ball
function make_dist()
{
local compress
case "${TAR_NAME}" in
*.gz) compress="gzip -c --no-name" ;;
*.bz2) compress="bzip2 -c" ;;
*.xz) compress="xz -c" ;;
*) prnt_err "invalid TAR_NAME '${TAR_NAME}'" ; return 1;;
esac
git archive HEAD --prefix="${TAR_PREFIX}/" \
| ${compress} > "$OBS_DIR/${TAR_NAME}" || return 1
}
# helper to print "md5sum size filname"
function deb_file_info()
{
local md5
local rest
read md5 rest <<< "$( md5sum "$@" || return 1 )"
stat --format "$md5 %s %n" "$@" || return 1
return 0
}
# helper, just expand some "macros"
function expand_macro()
{
echo "$@" \
| sed -e "s/%PACKAGE%/${PACKAGE}/g" \
-e "s/%VERSION%/${VERSION}/g" \
|| return 1
return 0
}
function update_spec_rpm()
{
sed -e "s/^\(Version:[\t ]*\).*/\1${VERSION}/g" ${PACKAGE}.spec \
> "${PACKAGE}.spec_" || return 1
mv "${PACKAGE}.spec_" "${PACKAGE}.spec" || return 1
}
function update_spec_deb()
{
debfile1="$( deb_file_info "${TAR_NAME}" )" || return 1
# warning debian release -1 is hardcoded here
sed "${PACKAGE}.dsc" \
-e "s/^\(Version:[\t ]*\).*/\1${VERSION}-1/g" \
-e "s/^\([\t ]*\).* ${PACKAGE}.*.tar.gz/\1${debfile1}/g" \
> ${PACKAGE}.dsc_ || return 1
mv "${PACKAGE}.dsc_" "${PACKAGE}.dsc" || return 1
}
function update_obs()
{
if [ "${UPDATE_RPM}" = "yes" ] ; then
update_spec_rpm || return 1
fi
if [ "${UPDATE_DEB}" = "yes" ] ; then
update_spec_deb || return 1
fi
osc addremove || return 1
return 0
}
function commit_obs()
{
osc ci --skip-validation -m "${OSC_COMMIT_MSG}" || return 1
return 0
}
#### here we go
if ! parse_cmd "$@" ;then
exit 1
fi
OBS_DIR="$( expand_macro "${OBS_DIR}" )" || exit 1
SNAP_DIR="$( expand_macro "${SNAP_DIR}" )" || exit 1
# cleanup and pull obs dir
cd "${OBS_DIR}" || exit 1
if ! fetch_obs ;then
prnt_err "cannot cleanup obs working copy"
exit 1
fi
# pull from git and check for updates
cd "${SNAP_DIR}" || exit 1
NEED_UPDATE="$(fetch_origin)" || exit 1
if [ "${NEED_UPDATE}" != "yes" ] ;then
prnt_dbg "snap repo was up-to-date, no rebuild needed"
if [ "${FORCE}" != "yes" ] ;then
exit 0
else
prnt_dbg "rebuild forced"
fi
fi
VERSION="$(get_version)" || exit 1
prnt_dbg "update version ${VERSION}"
OSC_COMMIT_MSG="$( expand_macro "${OSC_COMMIT_MSG}" )" || exit 1
TAR_PREFIX="$( expand_macro "${TAR_PREFIX}" )" || exit 1
TAR_NAME="$( expand_macro "${TAR_NAME}" )" || exit 1
# TODO very unsafe, conflicting
rm -f "${OBS_DIR}/${PACKAGE}"*.tar.*z || exit 1
make_dist || exit 1
cd "${OBS_DIR}" || exit 1
update_obs || exit 1
if [ "${DRY_RUN}" != "yes" ] ;then
commit_obs || exit 1
fi
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment