Back to index

moin  1.9.0~rc2
12_to_13_mig02.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 """
00003     migration from moin 1.3 < patch-78 to moin 1.3 >= patch-78
00004     * switch quoting mechanism from (xx)(xx) to (xxxx)
00005     * charset isn't changed, it was utf-8 before and will be utf-8 after
00006 
00007     Steps for a successful migration:
00008         1. stop your wiki and make a backup
00009         2. make a copy of the wiki's "data" directory to your working dir
00010         3. run this script from your working dir
00011         4. if there was no error, you will find:
00012             data.pre-mig2 (the script renames your data directory copy to that name)
00013             data (result, converted)
00014         5. verify conversion results (number of pages, size of logs, attachments,
00015            number of backup copies) - everything should be reasonable before
00016            you proceed.
00017         6. copy additional files from data.pre-mig2 to data (maybe intermaps, logs,
00018            etc.). Be aware that the file contents AND file names of wiki content
00019            may have changed, so DO NOT copy the cache/ directory, but let
00020            the wiki recreate it.
00021         7. replace the data directory your wiki uses with the data directory
00022            you created by previous steps. DO NOT simply copy the converted stuff
00023            into the original or you will duplicate pages and create chaos!
00024         8. test it. if something has gone wrong, you still have your backup.
00025         9. if you use dictionaries for spellchecking, you have to convert them
00026            to config.charset, too. Remove your dict.cache before re-starting
00027            your wiki.
00028 
00029     @copyright: 2004 Thomas Waldmann
00030     @license: GPL, see COPYING for details
00031 """
00032 
00033 from_encoding = 'utf-8'
00034 to_encoding = 'utf-8'
00035 
00036 import os.path, sys, shutil, urllib
00037 
00038 sys.path.insert(0, '../../../..')
00039 from MoinMoin import wikiutil
00040 
00041 from MoinMoin.script.migration.migutil import opj, listdir, copy_file, copy_dir
00042 
00043 # this is a copy of the wikiutil.unquoteWikiname of moin--main--1.3--patch-77
00044 def unquoteWikinameOld(filename, charsets=[from_encoding, ]):
00045     """
00046     Return decoded original filename when given an encoded filename.
00047     @param filename: encoded filename
00048     @rtype: string
00049     @return: decoded, original filename
00050     """
00051     if isinstance(filename, type(u'')): # from some places we get called with unicode
00052         filename = filename.encode(from_encoding)
00053     fn = ''
00054     i = 0
00055     while i < len(filename):
00056         c = filename[i]
00057         if c == '(':
00058             c1 = filename[i+1]
00059             c2 = filename[i+2]
00060             close = filename[i+3]
00061             if close != ')':
00062                 raise Exception('filename encoding invalid')
00063             i += 4
00064             fn = fn + chr(16 * int(c1, 16) + int(c2, 16))
00065         else:
00066             fn = fn + c
00067             i += 1
00068     return wikiutil.decodeUserInput(fn, charsets)
00069 
00070 
00071 def convert_string(str, enc_from, enc_to):
00072     return str.decode(enc_from).encode(enc_to)
00073 
00074 
00075 def qf_convert_string(str, enc_from, enc_to):
00076     """ Convert filename from pre patch 78 quoting to new quoting
00077 
00078     The old quoting function from patch 77 can convert name ONLY from
00079     the old way to the new, so if you have a partially converted
00080     directory, as it the situation as of moin--main--1.3--patch-86,
00081     it does not work.
00082 
00083     The new unquoting function is backward compatible, and can unquote
00084     both post and pre patch 78 file names.
00085     """
00086     str = wikiutil.unquoteWikiname(str, [enc_from])
00087     str = wikiutil.quoteWikinameFS(str, enc_to)
00088     return str
00089 
00090 
00091 def convert_file(fname_from, fname_to, enc_from, enc_to):
00092     print "%s -> %s" % (fname_from, fname_to)
00093     file_from = open(fname_from)
00094     file_to = open(fname_to, "w")
00095     for line in file_from:
00096         file_to.write(convert_string(line, enc_from, enc_to))
00097     file_to.close()
00098     file_from.close()
00099     st = os.stat(fname_from)
00100     os.utime(fname_to, (st.st_atime, st.st_mtime))
00101 
00102 
00103 def convert_textdir(dir_from, dir_to, enc_from, enc_to, is_backupdir=0):
00104     os.mkdir(dir_to)
00105     for fname_from in listdir(dir_from):
00106         if is_backupdir:
00107             fname, timestamp = fname_from.split('.')
00108         else:
00109             fname = fname_from
00110         fname = qf_convert_string(fname, enc_from, enc_to)
00111         if is_backupdir:
00112             fname_to = '.'.join([fname, timestamp])
00113         else:
00114             fname_to = fname
00115         convert_file(opj(dir_from, fname_from), opj(dir_to, fname_to),
00116                      enc_from, enc_to)
00117 
00118 
00119 def convert_pagedir(dir_from, dir_to, enc_from, enc_to):
00120     os.mkdir(dir_to)
00121     for dname_from in listdir(dir_from):
00122         dname_to = qf_convert_string(dname_from, enc_from, enc_to)
00123         print "%s -> %s" % (dname_from, dname_to)
00124         shutil.copytree(opj(dir_from, dname_from), opj(dir_to, dname_to), 1)
00125         try:
00126             convert_editlog(opj(dir_from, dname_from, 'last-edited'),
00127                             opj(dir_to, dname_to, 'last-edited'),
00128                             enc_from, enc_to)
00129         except IOError:
00130             pass # we ignore if it doesnt exist
00131 
00132 def convert_userdir(dir_from, dir_to, enc_from, enc_to):
00133     os.mkdir(dir_to)
00134     for fname in listdir(dir_from):
00135         convert_file(opj(dir_from, fname), opj(dir_to, fname),
00136                      enc_from, enc_to)
00137 
00138 
00139 def convert_editlog(log_from, log_to, enc_from, enc_to):
00140         file_from = open(log_from)
00141         file_to = open(log_to, "w")
00142         for line in file_from:
00143             fields = line.split('\t')
00144             fields[0] = qf_convert_string(fields[0], enc_from, enc_to)
00145             fields[5] = convert_string(fields[5], enc_from, enc_to)
00146             line = '\t'.join(fields)
00147             file_to.write(line)
00148 
00149 origdir = 'data.pre-mig2'
00150 
00151 # Backup original dir and create new empty dir
00152 try:
00153     os.rename('data', origdir)
00154     os.mkdir('data')
00155 except OSError:
00156     print "You need to be in the directory where your copy of the 'data' directory is located."
00157     sys.exit(1)
00158 
00159 convert_textdir(opj(origdir, 'text'), opj('data', 'text'), from_encoding, to_encoding)
00160 
00161 convert_textdir(opj(origdir, 'backup'), opj('data', 'backup'), from_encoding, to_encoding, 1)
00162 
00163 convert_pagedir(opj(origdir, 'pages'), opj('data', 'pages'), from_encoding, to_encoding)
00164 
00165 convert_userdir(opj(origdir, 'user'), opj('data', 'user'), from_encoding, to_encoding)
00166 
00167 convert_editlog(opj(origdir, 'editlog'), opj('data', 'editlog'), from_encoding, to_encoding)
00168 
00169 copy_file(opj(origdir, 'event.log'), opj('data', 'event.log'))
00170 
00171 copy_dir(opj(origdir, 'plugin'), opj('data', 'plugin'))
00172 
00173 copy_file(opj(origdir, 'intermap.txt'), opj('data', 'intermap.txt'))
00174