PageRenderTime 33ms CodeModel.GetById 20ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/win32/docdiff.py

https://bitbucket.org/tortoisehg/hgtk/
Python | 109 lines | 80 code | 13 blank | 16 comment | 22 complexity | ffcf74c685907f619a7d19d52938e8c4 MD5 | raw file
  1'''
  2Binary document diff wrapper script
  3
  4This script is converted into an executable by py2exe for use in
  5TortoiseHg binary packages.  It is then used by TortoiseHg as a visual
  6diff application for binary document types.
  7
  8It takes two (diff) or four (merge) arguments, determines the file type
  9based on the file extension, then launches the appropriate document diff
 10script that THG has borrowed from the TortoiseSVN project.
 11
 12This script is quite useless outside of a TortoiseHg binary install.
 13'''
 14
 15import os
 16import sys
 17import subprocess
 18import shutil
 19import win32con
 20import win32api
 21import win32process
 22import locale
 23
 24from mercurial import util
 25
 26scripts = {
 27    'doc'  : ('diff-doc.js', 'merge-doc.js'),    # MS Word
 28    'docx' : ('diff-doc.js', 'merge-doc.js'),
 29    'docm' : ('diff-doc.js', 'merge-doc.js'),
 30    'ppt'  : ('diff-ppt.js',),                   # MS PowerPoint
 31    'pptx' : ('diff-ppt.js',),
 32    'pptm' : ('diff-ppt.js',),
 33    'xls'  : ('diff-xls.vbs',),                  # MS Excel
 34    'xlsx' : ('diff-xls.vbs',),
 35    'xlsm' : ('diff-xls.vbs',),
 36    'xlsb' : ('diff-xls.vbs',),
 37    'xlam' : ('diff-xls.vbs',),
 38    'ods'  : ('diff-odt.vbs', 'merge-ods.vbs'),  # OpenOffice Text
 39    'odt'  : ('diff-odt.vbs', 'merge-ods.vbs'),
 40    'sxw'  : ('diff-sxw.vbs', 'merge-ods.vbs'),  # OpenOffice Calc
 41    'nb'   : ('diff-nb.vbs',),                   # Mathematica Notebook
 42}
 43
 44def safe_encode(string, encoding):
 45    if isinstance(string, unicode):
 46        return string.encode(encoding)
 47
 48    return string
 49
 50def main():
 51    args = sys.argv[1:]
 52    if len(args) not in (2, 4):
 53        print 'Two or four arguments expected:'
 54        print sys.argv[0], '[local] [other]'
 55        print sys.argv[0], '[local] [base] [other] [output]'
 56        sys.exit(1)
 57    elif len(args) == 2:
 58        local, other = [os.path.abspath(f) for f in args]
 59        base, ext = os.path.splitext(local)
 60    else:
 61        local, base, other, output = [os.path.abspath(f) for f in args]
 62        base, ext = os.path.splitext(output)
 63
 64    if not ext or ext.lower()[1:] not in scripts.keys():
 65        print 'Unsupported file type', ext
 66        sys.exit(1)
 67
 68    proc = win32api.GetCurrentProcess()
 69    try:
 70        # This will fail on windows < NT
 71        filename = win32process.GetModuleFileNameEx(proc, 0)
 72    except:
 73        filename = win32api.GetModuleFileName(0)
 74    path = os.path.join(os.path.dirname(filename), 'diff-scripts')
 75    if not os.path.isdir(path):
 76        print 'Diff scripts not found at', path
 77        sys.exit(1)
 78
 79    use = scripts[ext.lower()[1:]]
 80
 81    if 'xls' in use[0] and os.path.basename(local) == os.path.basename(other):
 82        # XLS hack; Excel will not diff two files if they have the same
 83        # basename.
 84        othertmp = other+'~x1'
 85        shutil.copy(other, othertmp)
 86        other = othertmp
 87
 88    if len(args) == 2:
 89        script = os.path.join(path, use[0])
 90        cmd = ['wscript', script, other, local]
 91    elif len(use) == 1:
 92        print 'Unsupported file type for merge', local
 93        sys.exit(1)
 94    else:
 95        script = os.path.join(path, use[1])
 96        cmd = ['wscript', script, output, other, local, base]
 97
 98    encoding = locale.getpreferredencoding(do_setlocale=True)
 99    cmd = [util.shellquote(safe_encode(arg, encoding)) for arg in cmd]
100    cmdline = util.quotecommand(' '.join(cmd))
101    proc = subprocess.Popen(cmdline, shell=True,
102                            creationflags=win32con.CREATE_NO_WINDOW,
103                            stderr=subprocess.PIPE,
104                            stdout=subprocess.PIPE,
105                            stdin=subprocess.PIPE)
106    return proc.communicate()
107
108if __name__=='__main__':
109    main()