/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/mergetools.py

  • Committer: Vincent Ladeuil
  • Date: 2010-12-06 14:01:44 UTC
  • mto: (5321.1.101 mergetools)
  • mto: This revision was merged to the branch mainline in revision 5632.
  • Revision ID: v.ladeuil+lp@free.fr-20101206140144-yz3cp2paek953gp4
More cleanup.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2010 Canonical Ltd.
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
"""Registry for external merge tools, e.g. kdiff3, meld, etc."""
 
18
 
 
19
import os
 
20
import shutil
 
21
import subprocess
 
22
import sys
 
23
import tempfile
 
24
 
 
25
from bzrlib.lazy_import import lazy_import
 
26
lazy_import(globals(), """
 
27
from bzrlib import (
 
28
    cmdline,
 
29
    config,
 
30
    errors,
 
31
    osutils,
 
32
    trace,
 
33
    ui,
 
34
    workingtree,
 
35
)
 
36
""")
 
37
 
 
38
from bzrlib.commands import Command
 
39
from bzrlib.option import Option
 
40
 
 
41
 
 
42
def subprocess_invoker(executable, args, cleanup):
 
43
    retcode = subprocess.call([executable] + args)
 
44
    cleanup(retcode)
 
45
    return retcode
 
46
 
 
47
 
 
48
_WIN32_PATH_EXT = [unicode(ext.lower())
 
49
                   for ext in os.getenv('PATHEXT', '').split(';')]
 
50
 
 
51
 
 
52
class MergeTool(object):
 
53
 
 
54
    def __init__(self, name, command_line):
 
55
        """Initializes the merge tool with a name and a command-line."""
 
56
        self.name = name
 
57
        self.command_line = command_line
 
58
        self._cmd_list = cmdline.split(self.command_line)
 
59
 
 
60
    def __repr__(self):
 
61
        return '<%s(%s, %s)>' % (self.__class__, self.name, self.command_line)
 
62
 
 
63
    def is_available(self):
 
64
        exe = self._cmd_list[0]
 
65
        return (os.path.exists(exe)
 
66
                or osutils.find_executable_on_path(exe) is not None)
 
67
 
 
68
    def invoke(self, filename, invoker=None):
 
69
        if invoker is None:
 
70
            invoker = subprocess_invoker
 
71
        args, tmp_file = self._subst_filename(self._cmd_list, filename)
 
72
        def cleanup(retcode):
 
73
            if tmp_file is not None:
 
74
                if retcode == 0: # on success, replace file with temp file
 
75
                    shutil.move(tmp_file, filename)
 
76
                else: # otherwise, delete temp file
 
77
                    os.remove(tmp_file)
 
78
        return invoker(args[0], args[1:], cleanup)
 
79
 
 
80
    def _subst_filename(self, args, filename):
 
81
        subst_names = {
 
82
            u'base': filename + u'.BASE',
 
83
            u'this': filename + u'.THIS',
 
84
            u'other': filename + u'.OTHER',
 
85
            u'result': filename,
 
86
        }
 
87
        tmp_file = None
 
88
        subst_args = []
 
89
        for arg in args:
 
90
            if u'{this_temp}' in arg and not 'this_temp' in subst_names:
 
91
                tmp_file = tempfile.mktemp(u"_bzr_mergetools_%s.THIS" %
 
92
                                           os.path.basename(filename))
 
93
                shutil.copy(filename + u".THIS", tmp_file)
 
94
                subst_names['this_temp'] = tmp_file
 
95
            arg = arg.format(**subst_names)
 
96
            subst_args.append(arg)
 
97
        return subst_args, tmp_file
 
98
 
 
99
 
 
100
_KNOWN_MERGE_TOOLS = (
 
101
    u'bcompare {this} {other} {base} {result}',
 
102
    u'kdiff3 {base} {this} {other} -o {result}',
 
103
    u'xxdiff -m -O -M {result} {this} {base} {other}',
 
104
    u'meld {base} {this_temp} {other}',
 
105
    u'opendiff {this} {other} -ancestor {base} -merge {result}',
 
106
    u'winmergeu {result}',
 
107
)
 
108
 
 
109
 
 
110
def detect_merge_tools():
 
111
    tools = [MergeTool(None, commandline) for commandline in _KNOWN_MERGE_TOOLS]
 
112
    return [tool for tool in tools if tool.is_available()]
 
113