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)

MoinMoin: ScriptMarket/AutomatedRollback (last edited 2007-10-29 19:17:18 by localhost)