# HG changeset patch # User Louis Opter # Date 1269031229 -3600 # Node ID 186968f53947a3f155282d757202fb886465fb6d Initial Import diff -r 000000000000 -r 186968f53947 backup-trac-project --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/backup-trac-project Fri Mar 19 21:40:29 2010 +0100 @@ -0,0 +1,111 @@ +#!/usr/bin/env python + +# The MIT License +# +# Copyright (c) 2010 Louis Opter +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +import errno +import os +import shutil +import subprocess +import sys +import tarfile +import tempfile + +class TempDir(object): + """Wrap tempfile.mkdtemp to use the with statement""" + + def __init__(self): + pass + + def __enter__(self): + self.__path = tempfile.mkdtemp() + return self.__path + + def __exit__(self, exc_type, exc_value, traceback): + shutil.rmtree(self.__path) + +def status(message): + print '%s: %s.' % (os.path.basename(sys.argv[0]), message) + +def die(message): + status(message) + status('a log has been recorded in %s' % log_path) + sys.exit(1) + +def hotcopy_repo(): + """Use trac-admin to hotcopy the trac environnement into `root'""" + + dest = os.path.join(root, name) + if subprocess.call(['sudo', 'trac-admin', trac_env_root, 'hotcopy', dest], + stdout=log, stderr=log) != 0: + die('error while copying the Trac environnement into a temporary directory') + + subprocess.call(['sudo', 'chown', '-R', 'ubuntu:ubuntu', dest]) + + status('Trac environnement copied') + +def archive_repo(): + """Create a tar bzipped archive of the trac environnement""" + + try: + archive = tarfile.open(os.path.join(root, archive_name), 'w:bz2') + archive.add(os.path.join(root, name), 'backup-tracenv-%s' % name) + archive.close() + except tarfile.TarError, ex: + die('Can\'t create the tar archive %s: %s' % (archive_name, str(ex))) + + status('Archive %s created' % archive_name) + +def send_repo(): + """Send the tar to archive using scp""" + + dest = sys.argv[2] + archive = os.path.join(root, archive_name) + if subprocess.call(['scp', archive, dest]) != 0: + die('error while scpying %s to %s' % (archive_name, dest)) + + status('Archive %s copied to "%s"' % (archive_name, dest)) + +if __name__ == '__main__': + if len(sys.argv) != 3 or sys.argv[1] == '--help': + print 'Usage: %s project-name [[user@]host:]path' % os.path.basename(sys.argv[0]) + sys.exit(0) + + # globals + name = sys.argv[1] + archive_name = 'backup-tracenv-%s.tar.bz2' % name + log_path = os.path.join(os.getenv('TMP') or '/tmp/', name + '.log') + trac_env_root = os.path.join('/var/trac/envs/', name) + + if not os.path.exists(trac_env_root): + status('%s: %s' % (name, os.strerror(errno.ENOENT))) + sys.exit(1) + + with open(log_path, 'w') as log: + with TempDir() as root: + status('root=%s' % root) + hotcopy_repo() + archive_repo() + send_repo() + os.remove(log_path) + + sys.exit(0)