changeset 99:ce657f0e577b

implement restore backup subaction, with a already local backup file imported from: moin--main--1.5--patch-101
author Thomas Waldmann <tw@waldmann-edv.de>
date Sat, 15 Oct 2005 13:56:10 +0000
parents 8375a3795ff8
children 9aa2836c997b
files MoinMoin/action/WikiBackup.py MoinMoin/action/backup.py MoinMoin/multiconfig.py
diffstat 3 files changed, 159 insertions(+), 81 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/action/WikiBackup.py	Sun Oct 09 02:20:53 2005 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-# -*- coding: iso-8859-1 -*-
-"""
-    MoinMoin - make a full backup of the wiki
-
-    Triggering WikiBackup action will check if you are authorized to do
-    a backup and if yes, just send a
-    <siteid>-<date>--<time>.tar.<format> to you.
-
-    @copyright: 2005 by MoinMoin:ThomasWaldmann
-    @license: GNU GPL, see COPYING for details.
-"""
-
-import os, re, time, tarfile
-from MoinMoin.util import MoinMoinNoFooter
-
-
-defaultCompression = 'gz'
-compressionOptions = ['gz', 'bz2']
-
-
-def addFiles(path, tar, exclude):
-    """ Add files in path to tar """
-    for root, dirs, files in os.walk(path):
-        files.sort() # sorted page revs may compress better
-        for name in files:
-            path = os.path.join(root, name)
-            if exclude.search(path):
-                continue
-            tar.add(path)
-    
-
-def sendBackup(request, compression='gz'):
-    """ Send compressed tar file """    
-    tar = tarfile.open(fileobj=request, mode="w|%s" % compression)
-    # allow GNU tar's longer file/pathnames 
-    tar.posix = False           
-    exclude = re.compile("|".join(request.cfg.backup_exclude))
-    
-    for path in request.cfg.backup_include:
-        addFiles(path, tar, exclude)
-    
-    tar.close()
-
-
-def sendError(request, pagename, msg):
-    from MoinMoin import Page
-    return Page.Page(request, pagename).send_page(request, msg=msg)    
-
-
-def backupAllowed(request):
-    """ Return True if backup is allowed """
-    action = __name__.split('.')[-1]
-    user = request.user
-    return (action not in request.cfg.actions_excluded and
-            user.valid and user.name in request.cfg.backup_users)
-
-
-def execute(pagename, request):
-    _ = request.getText
-    if not backupAllowed(request):        
-        return sendError(request, pagename, 
-                         msg=_('You are not allowed to do remote backup.'))
-
-    compression = request.form.get('format', [defaultCompression])[0]
-    if compression not in compressionOptions:
-        return sendError(request, pagename, 
-                         msg=_('Unknown backup format: %s.' % compression))
-    
-    dateStamp = time.strftime("%Y-%m-%d--%H-%M-%S-UTC", time.gmtime())
-    filename = "%s-%s.tar.%s" % (request.cfg.siteid, dateStamp, compression)
-    
-    request.http_headers([
-        # TODO: use more specific tar gz/bz2 content type?
-        "Content-Type: application/octet-stream", 
-        "Content-Disposition: inline; filename=\"%s\"" % filename,])
-
-    sendBackup(request, compression)
-
-    raise MoinMoinNoFooter
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MoinMoin/action/backup.py	Sat Oct 15 13:56:10 2005 +0000
@@ -0,0 +1,155 @@
+# -*- coding: iso-8859-1 -*-
+"""
+    MoinMoin - make or restore a full backup of the wiki
+
+    Triggering backup action will check if you are authorized to do
+    a backup and if yes, just send a
+    <siteid>-<date>--<time>.tar.<format> to you.
+
+    @copyright: 2005 by MoinMoin:ThomasWaldmann
+    @license: GNU GPL, see COPYING for details.
+"""
+
+import os, re, time, tarfile
+import cStringIO
+from MoinMoin import wikiutil
+from MoinMoin.util import MoinMoinNoFooter
+
+def addFiles(path, tar, exclude):
+    """ Add files in path to tar """
+    for root, dirs, files in os.walk(path):
+        files.sort() # sorted page revs may compress better
+        for name in files:
+            path = os.path.join(root, name)
+            if exclude.search(path):
+                continue
+            tar.add(path)
+
+def sendBackup(request):
+    """ Send compressed tar file """    
+    dateStamp = time.strftime("%Y-%m-%d--%H-%M-%S-UTC", time.gmtime())
+    filename = "%s-%s.tar.%s" % (request.cfg.siteid, dateStamp, request.cfg.backup_compression)
+    request.http_headers([
+        "Content-Type: application/octet-stream", 
+        "Content-Disposition: inline; filename=\"%s\"" % filename,])
+    
+    tar = tarfile.open(fileobj=request, mode="w|%s" % request.cfg.backup_compression)
+    # allow GNU tar's longer file/pathnames 
+    tar.posix = False
+    exclude = re.compile("|".join(request.cfg.backup_exclude))
+    for path in request.cfg.backup_include:
+        addFiles(path, tar, exclude)
+    tar.close()
+    raise MoinMoinNoFooter
+
+def restoreBackup(request, pagename):
+    _ = request.getText
+    path = request.cfg.backup_storage_dir
+    filename = "%s.tar.%s" % (request.cfg.siteid, request.cfg.backup_compression)
+    filename = os.path.join(path, filename)
+    targetdir = request.cfg.backup_restore_target_dir
+    try:
+        tar = tarfile.open(fileobj=file(filename), mode="r|%s" % request.cfg.backup_compression)
+        # allow GNU tar's longer file/pathnames 
+        tar.posix = False
+        files = []
+        dirs = []
+        for m in tar:
+            if m.isdir():
+                dirs.append("%s %s %s" % (m.name, m.size, m.mtime))
+            else:
+                files.append("%s %s %s" % (m.name, m.size, m.mtime))
+            tar.extract(m, targetdir)
+        tar.close()
+        #files = "<br>".join(files)
+        filecount = len(files)
+        dircount = len(dirs)
+        return sendMsg(request, pagename, msg=_(
+            'Restored Backup: %(filename)s to target dir: %(targetdir)s.\nFiles: %(filecount)d, Directories: %(dircount)d' %
+                locals()))
+    except:
+        return sendMsg(request, pagename, msg=_("Restoring backup: %(filename)s to target dir: %(targetdir)s failed." % locals()))
+
+def sendBackupForm(request, pagename):
+    _ = request.getText
+    request.http_headers()
+    request.setContentLanguage(request.lang)
+    title = _('Wiki Backup / Restore')
+    wikiutil.send_title(request, title, form=request.form, pagename=pagename)
+    request.write(request.formatter.startContent("content"))
+    
+    request.write(_("""Some hints:
+ * To restore a backup:
+  * Restoring a backup will overwrite existing data, so be careful.
+  * Rename it to <siteid>.tar.<compression> (remove the --date--time--UTC stuff).
+  * Put the backup file into the backup_storage_dir (use scp, ftp, ...).
+  * Hit the [[GetText(Restore)]] button below.
+
+ * To make a backup, just hit the [[GetText(Backup)]] button and save the file
+   you get to a secure place.
+
+Please make sure your wiki configuration backup_* values are correct and complete:
+
+"""))
+
+# does not work, why?
+#    request.write("""<p>\
+#backup_compression = %(backup_compression)s<br>
+#backup_include = %(backup_include)r<br>
+#backup_exclude = %(backup_exclude)r<br>
+#backup_users = %(backup_users)r<br>
+#backup_storage_dir = %(backup_storage_dir)s<br>
+#backup_restore_target_dir = %(backup_restore_target_dir)s<br>
+#</p>
+#""" % request.cfg.__dict__)
+
+    request.write("""
+<form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
+<input type="hidden" name="action" value="backup">
+<input type="hidden" name="do" value="backup">
+<input type="submit" value="%(backup_button)s">
+</form>
+
+<form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
+<input type="hidden" name="action" value="backup">
+<input type="hidden" name="do" value="restore">
+<input type="submit" value="%(restore_button)s">
+</form>
+""" % {
+    'baseurl': request.getScriptname(),
+    'pagename': wikiutil.quoteWikinameURL(pagename),
+    'backup_button': _('Backup'),
+    'restore_button': _('Restore'),
+})
+    
+    request.write(request.formatter.endContent())
+    wikiutil.send_footer(request, pagename, editable=0, showactions=0, form=request.form)
+
+def sendMsg(request, pagename, msg):
+    from MoinMoin import Page
+    return Page.Page(request, pagename).send_page(request, msg=msg)    
+
+def backupAllowed(request):
+    """ Return True if backup is allowed """
+    action = __name__.split('.')[-1]
+    user = request.user
+    return (action not in request.cfg.actions_excluded and
+            user.valid and user.name in request.cfg.backup_users)
+
+def execute(pagename, request):
+    _ = request.getText
+    if not backupAllowed(request):        
+        return sendMsg(request, pagename, 
+                       msg=_('You are not allowed to do remote backup.'))
+    
+    dowhat = request.form.get('do', [None])[0]
+    if dowhat == 'backup':
+        sendBackup(request)
+    elif dowhat == 'restore':
+        restoreBackup(request, pagename)
+    elif dowhat == None:
+        sendBackupForm(request, pagename)
+    else:
+        return sendMsg(request, pagename, 
+                       msg=_('Unknown backup subaction: %s.' % dowhat))
+
--- a/MoinMoin/multiconfig.py	Sun Oct 09 02:20:53 2005 +0000
+++ b/MoinMoin/multiconfig.py	Sat Oct 15 13:56:10 2005 +0000
@@ -174,6 +174,7 @@
     attachments = None # {'dir': path, 'url': url-prefix}
     auth = [authmodule.moin_cookie]
     
+    backup_compression = 'gz'
     backup_users = []
     backup_include = []
     backup_exclude = [
@@ -182,7 +183,9 @@
         r"%(/)spages%(/)s.+%(/)scache%(/)s[^%(/)s]+$" % {'/': os.sep},
         r"%(/)s(edit-lock|event-log|\.DS_Store)$" % {'/': os.sep},
         ]
-                      
+    backup_storage_dir = '/tmp'
+    backup_restore_target_dir = '/tmp'
+    
     bang_meta = 1
     caching_formats = ['text_html']
     changed_time_fmt = '%H:%M'