This is just for the case somebody nasty is doing major damage to your wiki and you have to automatically rollback to a specific point in history. Only works for moin < v1.3, not for moin >= 1.3.
# wikitimewarp MMDDhhmm[.ss] # bring back the wiki state of month MM day DD time hh:mm:ss # you must be in the "data" directory of your wiki, seeing "text" and "backup" # only show source and destination of copy command: CMD="ls -l" #activate this if you are really sure what you are doing!: #CMD="cp -f" TIMESTAMP=/tmp/timestamp.$$ echo Time warping Wiki to Time: $1 touch -t $1 $TIMESTAMP && \ find text -newer $TIMESTAMP -type f | \ sed "s,^text/\(.*\)$,find backup \! -newer $TIMESTAMP -name \1.* | sort | tail -1,g" | \ sh - | \ sed "s,^backup/\([^.]*\)\(\.[0-9]*\),$CMD backup/\1\2 text/\1,g" | \ sh -
The above script doesn't change anything in your wiki until you remove the comment sign in front of that CMD="cp -f". Please review what it would do before accidentally rolling back your wiki in some bad way.
Here is another rollback script in Python.
# # automatic rollback for moin # # by Hye-Shik Chang <perky@fallin.lv> import os, glob, sys, re import rfc822, time, urllib TEXTDIR = "text" BACKUPDIR = "backup" getstat = lambda path: os.stat(path)[-2] def unquoteWikiName(quoted): return urllib.unquote(quoted.replace('_','%')) def rollback(fname, ctime): backups = [ mtm for mtm in [ int(bk.split('.', 1)[1]) for bk in glob.glob("%s/%s.*" % (BACKUPDIR, fname)) ] if mtm <= ctime ] wikiname = unquoteWikiName(fname) if not backups: print "=> Doesn't have any backup :", wikiname return 0 else: backups.sort() dmtime = backups[-1] open("%s/%s" % (TEXTDIR, fname), "w").write( open("%s/%s.%d" % (BACKUPDIR, fname, dmtime)).read() ) os.utime("%s/%s" % (TEXTDIR, fname), (dmtime, dmtime)) # XXX: delete insane backups, too? print '=> Page rollbacked to %s : %s' % (time.asctime(time.localtime(dmtime)), wikiname) return 1 def main(argv): if len(argv) < 2: print >> sys.stderr, "usage: %s {timestamp}|{rfc822 date}|{n mins ago..}|{last ok file}" % argv[0] return carg = ' '.join(argv[1:]) ctime = rfc822.parsedate(carg) # rfc822.parsedate is more flexible than time.strptime if ctime: ctime = time.mktime(ctime) else: try: ctime = int(carg) if ctime < 525600: # 1 yr ctime = time.time() - ctime*60 except ValueError: if os.access(carg, os.F_OK): ctime = getstat(carg) else: print "invalid date format" return print "Rolling back to %s ..." % time.asctime(time.localtime(ctime)) interactive = 1 ndest, nrollbacked = 0, 0 for f in os.listdir(TEXTDIR): if getstat(os.path.join(TEXTDIR, f)) > ctime: ndest += 1 if interactive: while 1: ans = raw_input("%s [YNA] ? " % unquoteWikiName(f)) if ans and ans[0].lower() in 'yna': break if ans[0] in 'Aa': interactive = 0 elif ans[0] in 'Nn': continue # to the next file nrollbacked += rollback(f, ctime) # TODO: delete wrong editlog here? print "Rollbacked. %d / %d" % (nrollbacked, ndest) if __name__ == "__main__": import sys main(sys.argv)