Hi all!
I find it awkward to backup my PostgreSQL-based Trac by running two separate commands. I was browsing Trac source code repository and found out that proper backup was implemented into Trac 0.13 almost two years ago (see:
http://trac.edgewall.org/changeset/10387/). I'm running running Trac 0.12.3 on Centos, but don't want to update into latest beta to get the new backup.
My solution for this is to backport the already implemented proper backup -feature into existing 0.12.3. See my patch(es) below.
If anybody want's my RPM/SRPM they are available
here. Both contain the below backup backport-patch for proper hotcopy.
Regards,
Jari Turkia
Suggested patch for 0.12.3:
--- trac/env.py.orig 2012-02-06 22:53:52.000000000 +0200
+++ trac/env.py 2012-08-29 17:14:41.734463460 +0300
@@ -687,8 +687,12 @@
yield ('deploy', '<directory>',
'Extract static resources from Trac and all plugins',
None, self._do_deploy)
- yield ('hotcopy', '<backupdir>',
- 'Make a hot backup copy of an environment',
+ yield ('hotcopy', '<backupdir> [--no-database]',
+ """Make a hot backup copy of an environment
+
+ The database is backed up to the 'db' directory of the
+ destination, unless the --no-database option is specified.
+ """,
None, self._do_hotcopy)
yield ('upgrade', '',
'Upgrade database to current version',
@@ -732,7 +736,11 @@
finally:
out.close()
- def _do_hotcopy(self, dest):
+ def _do_hotcopy(self, dest, no_db=None):
+ if no_db not in (None, '--no-database'):
+ raise AdminCommandError(_("Invalid argument '%(arg)s'", arg=no_db),
+ show_usage=True)
+
if os.path.exists(dest):
raise TracError(_("hotcopy can't overwrite existing '%(dest)s'",
dest=path_to_unicode(dest)))
@@ -749,12 +757,15 @@
dst=path_to_unicode(dest)))
db_str = self.env.config.get('trac', 'database')
prefix, db_path = db_str.split(':', 1)
+ skip = []
+
if prefix == 'sqlite':
+ db_path = os.path.join(self.env.path, os.path.normpath(db_path))
# don't copy the journal (also, this would fail on Windows)
- db = os.path.join(self.env.path, os.path.normpath(db_path))
- skip = [db + '-journal', db + '-stmtjrnl']
- else:
skip = []
+ skip = [db_path + '-journal', db_path + '-stmtjrnl']
+ if no_db:
+ skip.append(db_path)
try:
copytree(self.env.path, dest, symlinks=1, skip=skip)
retval = 0
@@ -767,6 +778,14 @@
printerr(' %s' % err)
else:
printerr(" %s: '%s'" % (err, path_to_unicode(src)))
+
+ # db backup for non-sqlite
+ if prefix != 'sqlite' and not no_db:
+ printout(_("Backing up database ..."))
+ sql_backup = os.path.join(dest, 'db',
+ '%s-db-backup.sql' % prefix)
+ self.env.backup(sql_backup)
+
finally:
# Unlock database
cnx.rollback()
Suggested patch for 0.12.2:
--- trac/env.py.orig 2011-02-01 00:05:49.000000000 +0200
+++ trac/env.py 2012-08-29 16:16:27.796852902 +0300
@@ -684,8 +684,12 @@
yield ('deploy', '<directory>',
'Extract static resources from Trac and all plugins',
None, self._do_deploy)
- yield ('hotcopy', '<backupdir>',
- 'Make a hot backup copy of an environment',
+ yield ('hotcopy', '<backupdir> [--no-database]',
+ """Make a hot backup copy of an environment
+
+ The database is backed up to the 'db' directory of the
+ destination, unless the --no-database option is specified.
+ """,
None, self._do_hotcopy)
yield ('upgrade', '',
'Upgrade database to current version',
@@ -729,7 +733,11 @@
finally:
out.close()
- def _do_hotcopy(self, dest):
+ def _do_hotcopy(self, dest, no_db=None):
+ if no_db not in (None, '--no-database'):
+ raise AdminCommandError(_("Invalid argument '%(arg)s'", arg=no_db),
+ show_usage=True)
+
if os.path.exists(dest):
raise TracError(_("hotcopy can't overwrite existing '%(dest)s'",
dest=dest))
@@ -745,12 +753,15 @@
src=self.env.path, dst=dest))
db_str = self.env.config.get('trac', 'database')
prefix, db_path = db_str.split(':', 1)
+ skip = []
+
if prefix == 'sqlite':
+ db_path = os.path.join(self.env.path, os.path.normpath(db_path))
# don't copy the journal (also, this would fail on Windows)
- db = os.path.join(self.env.path, os.path.normpath(db_path))
- skip = [db + '-journal', db + '-stmtjrnl']
- else:
skip = []
+ skip = [db_path + '-journal', db_path + '-stmtjrnl']
+ if no_db:
+ skip.append(db_path)
try:
copytree(self.env.path, dest, symlinks=1, skip=skip)
retval = 0
@@ -763,6 +774,14 @@
printerr(' %s' % err)
else:
printerr(" %s: '%s'" % (err, src))
+
+ # db backup for non-sqlite
+ if prefix != 'sqlite' and not no_db:
+ printout(_("Backing up database ..."))
+ sql_backup = os.path.join(dest, 'db',
+ '%s-db-backup.sql' % prefix)
+ self.env.backup(sql_backup)
+
finally:
# Unlock database
cnx.rollback()