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)