bsd-doc-import.ksh (snapshot import script)
Giorgos Keramidas
keramida at ceid.upatras.gr
Fri Feb 1 04:09:43 EET 2008
Καλησπέρα,
Το script που ακολουθεί το έγραψα απόψε, για να αυτοματοποιήσω κάπως τη
διαδικασία του 'import' ενός 'clean' snapshot από το /home/ncvs/doc του
τοπικού CVSup μου, σε ένα hg workspace.
Η χρήση είναι απλή:
% ./bsd-doc-import.ksh ~/hg/doc/bsd-import
Στο ~/hg/doc/bsd-import έχω ένα clone από το
http://hg.hellug.gr/freebsd/doc/
που χρησιμοποιείται *μόνο* για τα imports. Δε γίνεται απευθείας commit
σε αυτό από μένα, και δεν γίνεται απευθείας push στο `hg.hellug.gr'.
Οταν τελειώσει ένα επιτυχημένο import, κάνω κάτι σαν:
% cd ~/hg/doc/bsd
% hg pull ../bsd-import
% rm -fr * ; hg up -C
% cd en_US.ISO8859-1 && make FORMATS=html-split
Κι αν πετύχει αυτό, τότε κάνω push από το ~/hg/doc/bsd στο online clone
στη διεύθυνση http://hg.hellug.gr/freebsd/doc/
Τυπικά μπορεί να αυτοματοποιηθεί και το build check, αλλά απόψε είναι
πολύ αργά πια για τέτοια.
Ακολουθεί το importer script, μήπως φανεί και σε άλλον χρήσιμο...
----- begin bsd-doc-import.ksh -----
#!/usr/bin/ksh -p
#
# Copyright (c) 2008 Giorgos Keramidas <keramida at FreeBSD.org>
# 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
# SUCH DAMAGE.
#
# This script can be run from cron to periodically import snapshots of
# the FreeBSD doc/ tree into a target Mercurial repository. The target
# repository can be specified either as a command-line argument, or as
# the local filesystem path pointed at by GATEREPO.
#
# ==================== basic script startup ==================================
# Save the original program invocation name, and the real path of the
# startup directory, for later use.
progname=$(basename "$0")
progdir=$( cd $(dirname "$0") ; /bin/pwd -P )
# If TMPDIR is not set, use /tmp as a safe fallback value.
TMPDIR="${TMPDIR:-/var/tmp}"
export TMPDIR
# ==================== useful script functions ===============================
#
# err exitval [message ...]
# Display message to stderr and log to the syslog, and exit with
# exitval as the return code of the script.
#
function err
{
exitval=$1
shift
log "${progname}: ERROR: $*"
exit "${exitval:-1}"
}
#
# warn [message ...]
# Display message to stderr and the log file, if any.
#
function warn
{
log "${progname}: WARNING: $*"
}
#
# info [message ...]
# Display informational message to stdout and to the logfile,
# if one is defined.
#
function info
{
log "${progname}: INFO: $*"
}
#
# debug [message ...]
# Output message to stderr if debug_output_enabled is set to
# 'yes', 'true' or '1'. Please AVOID calling any shell
# subroutine that may recursively call debug().
#
function debug
{
case ${debug_output_enabled} in
[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
log "${progname}: DEBUG: $*"
;;
esac
}
#
# log [message ...]
# Display time-stamped message and log it to "${LOGFILE}",
# if one is defined.
#
function log
{
__timestamp="`date -u '+%Y-%m-%d %H:%M:%S'`"
print -u2 "${__timestamp} -- $*"
if [ -n "${LOGFILE}" ]; then
print "${__timestamp} -- $*" >> "${LOGFILE}"
fi
}
#
# msg [message ...]
# Display message and log it to "${LOGFILE}", if one is defined.
#
function msg
{
print -u2 "$*"
if [ -n "${LOGFILE}" ]; then
print "$*" >> "${LOGFILE}"
fi
}
#
# compat_realpath $directory
# Use /bin/pwd to determine the real path of a directory, or print
# a warning and return non-zero.
#
function compat_realpath
{
dpath="$1"
if [ -z "${dpath}" ]; then
warn "compat_realpath: missing path."
return 1
fi
( cd "${dpath}" ; /bin/pwd -P ) 2>/dev/null
if [ $? -ne 0 ]; then
warn "${dpath}: cannot determine real path."
return 1
fi
return 0
}
# ==================== gate repository related functions =====================
#
# repo_hg_root
# Find the root of a Mercurial workspace (if it is a real Mercurial
# workspace), or return a non-zero status.
#
function repo_hg_root
{
repo="$1"
if [ -z "${repo}" ]; then
warn "Empty gate repository path."
return 1
fi
savedir=$( /bin/pwd -P )
log "Switching to repo at ${repo}"
cd "${repo}"
if [ $? -ne 0 ]; then
warn "${repo}: cannot change into directory."
cd "${savedir}"
return 1
fi
log "Locating hg root of ${repo}"
root=$( hg root 2>/dev/null )
if [ -z "${root}" ]; then
warn "${repo}: cannot locate hg root"
cd "${savedir}"
return 1
fi
realrepo=$( compat_realpath "${repo}" ) || return 1
realroot=$( compat_realpath "${root}" ) || return 1
if [ ! "${realrepo}" = "${realroot}" ]; then
warn "${repo}: Switching to real hg root at ${realroot}"
realrepo="${realroot}"
repo="${realroot}"
fi
# All seems fine; try to restore the working dir.
cd "${savedir}" || return 1
print "${repo}"
return 0
}
#
# repo_hg_import_clean $repo
# Clean all the files in a Mercurial workspace, but set the 'parent' of
# the workspace to the 'default' branch, in preparation for a new import.
#
function repo_hg_import_clean
{
repo="$1"
if [ -z "${repo}" ]; then
warn "Empty gate repository path."
return 1
fi
savedir=$( /bin/pwd -P )
repo=$( repo_hg_root "${repo}" )
if [ $? -ne 0 ]; then
cd "${savedir}"
return 1
fi
log "Cleaning up workspace at ${repo} for a new import"
( cd "${repo}" && hg up -C default && rm -fr * && \
hg debugsetparent default )
if [ $? -ne 0 ]; then
warn "Failed to clean workspace at ${repo} for a new import"
cd "${savedir}"
return 1
fi
cd "${savedir}" || return 1
return 0
}
#
# repo_cvs_import_checkout "${repo}"
# Check out a new partial snapshot of the doc/ tree from CVS, which
# contains only the sub-modules/parts of the doc tree that we are
# interested in.
#
function repo_cvs_import_checkout
{
repo="$1"
if [ -z "${repo}" ]; then
warn "Empty gate repository path."
return 1
fi
savedir=$( /bin/pwd -P )
repo=$( repo_hg_root "${repo}" )
if [ $? -ne 0 ]; then
cd "${savedir}"
return 1
fi
log "Checking out a new snapshot of the doc/ tree at ${repo}"
( cd "${repo}" && \
cvs -QR -d /home/ncvs co -d . -l doc && \
cvs -QR -d /home/ncvs update -APd * share en_US.ISO8859-1 \
el_GR.ISO8859-7 )
if [ $? -ne 0 ]; then
warn "CVS checkout of doc/ snapshot failed at ${repo}"
cd "${savedir}"
return 1
fi
cd "${savedir}" || return 1
return 0
}
#
# repo_cvs_stamp [file ...]
# Find the timestamp of the last CVS commit, and print the time in
# ISO date format to stdout. This runs 'cvs log' on all the files
# passed as arguments to the timestamp function, so it may take
# quite a while on *HUGE* CVS trees.
#
function repo_cvs_stamp
{
cvs -qR log "$@" | \
grep '^date: [0-9][0-9]*/.*state: Exp; lines:.*' | \
awk '{print $2,$3}' | sort -n | tail -1 | \
sed -e 's@/@- at g' -e 's/;//' -e 's/$/ +0000/'
}
#
# repo_validate $repo
# Validate that our only argument is the root path of a valid
# Mercurial workspace, or at least *part* of a valid Mercurial
# workspace, and that the workspace passes 'hg verify' checks.
#
function repo_validate
{
repo="$1"
if [ -z "${repo}" ]; then
warn "Empty gate repository path."
return 1
fi
savedir=$( /bin/pwd -P )
repo=$( repo_hg_root "${repo}" )
if [ $? -ne 0 ]; then
cd "${savedir}"
return 1
fi
log "Verifying hg workspace at ${repo}"
log "This may take a bit..."
hg verify
if [ $? -ne 0 ]; then
warn "Workspace verify failed at ${repo}"
cd "${savedir}"
return 1
fi
# All seems fine; try to restore the working dir.
cd "${savedir}" || return 1
return 0
}
#
# repo_import $repo
# Import a fresh snapshot of the FreeBSD doc/ tree we use for the
# Greek translation project into the Mercurial repository at $repo.
#
function repo_import
{
repo="$1"
if [ -z "${repo}" ]; then
warn "Empty gate repository path."
return 1
fi
savedir=$( /bin/pwd -P )
repo=$( repo_hg_root "${repo}" )
if [ $? -ne 0 ]; then
cd "${savedir}"
return 1
fi
repo_hg_import_clean "${repo}"
if [ $? -ne 0 ]; then
warn "Failed to clean workspace at ${repo}"
cd "${savedir}"
return 1
fi
repo_cvs_import_checkout "${repo}"
if [ $? -ne 0 ] ; then
repo_hg_import_clean "${repo}"
cd "${savedir}"
return 1
fi
#
# Try out best shot at guessing the time of the last CVS commit in the
# partial checkout at ${repo}.
#
log "Guesstimating the timestamp of the last CVS commit at ${repo}"
stamp=$( cd "${repo}" ; repo_cvs_stamp * )
if [ $? -ne 0 ]; then
warn "Failed to find CVS timestamp."
repo_hg_import_clean "${repo}"
cd "${savedir}"
return 1
else
log "CVS timestamp = ${stamp}"
fi
log "Removing CVS/ metadata subdirs at ${repo}"
( cd "${repo}" ; find * -type d -name CVS -exec rm -r {} + )
if [ $? -ne 0 ]; then
warn "Failed to delete CVS/ subdirs at ${repo}"
repo_hg_import_clean "${repo}"
cd "${savedir}"
return 1
fi
log "Pre-import workspace status at ${repo}"
( cd "${repo}" && hg status )
if [ $? -ne 0 ]; then
warn "hg status failed at ${repo}"
repo_hg_import_clean "${repo}"
cd "${savedir}"
return 1
fi
log "Hg addremoving at ${repo}"
( cd "${repo}" && hg addremove )
if [ $? -ne 0 ]; then
warn "hg addremove failed at ${repo}"
repo_hg_import_clean "${repo}"
cd "${savedir}"
return 1
fi
log "Committing new import in ${repo}"
( cd "${repo}" && hg commit -u ncvs -d "${stamp}" \
-m "Import FreeBSD doc/ snapshot at ${stamp}" )
if [ $? -ne 0 ]; then
warn "Commit error in ${repo}"
repo_hg_import_clean "${repo}"
cd "${savedir}"
return 1
fi
return 0
}
# ==================== main script body ======================================
function usage
{
print -u2 "usage: ${progname} [gaterepo]"
exit 1
}
# Start with an invalid ${GATEREPO} at first, unless it is already set
# to something in our startup environment.
GATEREPO="${GATEREPO:-/dev/null}"
if [ $# -gt 1 ]; then
usage ; exit 1
fi
if [ $# -eq 1 ]; then
GATEREPO="$1"
fi
if [ "${GATEREPO}" = ' /dev/null' ]; then
usage ; exit 1
fi
log "Validating GATEREPO at ${GATEREPO}"
repo_validate "${GATEREPO}" || err 1 "Abort."
log "Importing new bsd doc snapshot at ${GATEREPO}"
repo_import "${GATEREPO}" || err 1 "Abort."
log "Done."
exit 0
----- end bsd-doc-import.ksh -----
More information about the Freebsd-doc-el
mailing list