1#!/usr/bin/env python 2""" 3Migration from moin--main--1.3 pre patch-332 to post patch-332. 4 5In patch-332 we changed the format of page lists in user data file. They 6are now tab separated instead of comma separated, and page names are not 7quoted using file system quoting. 8 9You can run the script multiple times with no damage. 10 11 12Steps for a successful migration: 13 14 1. Stop your wiki 15 16 2. Make a backup of your wiki 'data' directory 17 18 WARNING: THIS SCRIPT MIGHT CORRUPT YOUR 'DATA' DIRECTORY. DON'T 19 COMPLAIN LATER, MAKE BACKUP NOW! 20 21 3. Move the wiki's 'data' directory to your working dir 22 23 4. Run this script from your working dir 24 25 5. If there was no error, you will find: 26 data.pre-mig9 - backup of original data directory 27 data - converted data dir 28 29 6. Verify conversion results (number of pages, size of logs, 30 attachments, number of backup copies) - everything should be 31 reasonable before you proceed. 32 33 NOTE: THE CACHE DIRECTORY IS NOT COPIED - DO NOT COPY IT, IT WILL BE 34 CREATED AND FILLED BY THE WIKI AUTOMATICALLY. 35 36 7. Move the converted data directory into your wiki. Do not simply copy 37 the converted stuff into the original or you will duplicate pages 38 and create chaos! 39 40 8. Fix permissions on your data directory, see HelpOnInstalling. 41 42 9. Test it - if something has gone wrong, you still have your backup. 43 44 45@copyright: 2004 Thomas Waldmann 46@license: GPL, see COPYING for details 47""" 48 49import os, sys, codecs 50join = os.path.join 51 52# Insert THIS moin dir first into sys path, or you might run another 53# version of moin and get unpredicted results! 54sys.path.insert(0, '../../../..') 55 56from MoinMoin import wikiutil, user 57from MoinMoin.script.migration import migutil 58 59 60def convert_quicklinks(string): 61 """ Convert quicklinks from pre patch-332 to new format """ 62 # No need to convert new style list 63 if '\t' in string: 64 return string 65 66 names = [name.strip() for name in string.split(',')] 67 names = [wikiutil.unquoteWikiname(name) for name in names if name != ''] 68 string = user.encodeList(names) 69 return string 70 71 72def convert_subscribed_pages(string): 73 """ Convert subscribed pages from pre patch-332 to new format """ 74 # No need to convert new style list 75 if '\t' in string: 76 return string 77 78 # This might break pages that contain ',' in the name, we can't do 79 # anything about it. This was the reason we changed the format. 80 names = [name.strip() for name in string.split(',')] 81 string = user.encodeList(names) 82 return string 83 84 85def convertUserData(text): 86 """ Convert user data 87 88 @param text: text of user file, unicode 89 @rtype: unicode 90 @return: convected user data 91 """ 92 lines = text.splitlines() 93 for i in range(len(lines)): 94 line = lines[i] 95 try: 96 key, value = line.split('=', 1) 97 except ValueError: 98 continue 99 if key == u'quicklinks': 100 value = convert_quicklinks(value) 101 elif key == u'subscribed_pages': 102 value = convert_subscribed_pages(value) 103 lines[i] = u'%s=%s' % (key, value) 104 105 # Join back, append newline to last line 106 text = u'\n'.join(lines) + u'\n' 107 return text 108 109 110def convertUsers(srcdir, dstdir): 111 """ Convert users files 112 113 @param srcdir: old users dir 114 @param dstdir: new users dir 115 """ 116 charset = 'utf-8' 117 118 # Create dstdir 119 if not os.path.exists(dstdir): 120 try: 121 os.mkdir(dstdir) 122 except OSError: 123 migutil.fatalError("can't create user directory at '%s'" % dstdir) 124 125 if not os.path.isdir(srcdir): 126 migutil.fatalError("can't find user directory at '%s'" % srcdir) 127 128 for name in migutil.listdir(srcdir): 129 if name == 'README' or name.endswith('.trail'): 130 # Copy as is 131 migutil.copy_file(join(srcdir, name), join(dstdir, name)) 132 else: 133 srcfile = join(srcdir, name) 134 f = codecs.open(srcfile, 'rb', charset) 135 text = f.read() 136 f.close() 137 text = convertUserData(text) 138 dstfile = join(dstdir, name) 139 f = codecs.open(dstfile, 'wb', charset) 140 f.write(text) 141 f.close() 142 print "Converted '%s' to '%s'" % (srcfile, dstfile) 143 144 145if __name__ == '__main__': 146 147 # Backup original dir 148 datadir = 'data' 149 origdir = 'data.pre-mig9' 150 migutil.backup(datadir, origdir) 151 152 # Copy ALL stuff from original dir into new data dir. Don't change 153 # or drop anything from the original directory expect cache files. 154 names = ['edit-log', 'event-log', 'intermap.txt', 'pages', 'plugin'] 155 migutil.copy(names, origdir, datadir) 156 157 # Convert user directory 158 convertUsers(join(origdir, 'user'), join(datadir, 'user')) 159 160