/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5321.1.69 by Gordon Tyler
Fixed line-endings to be Unix.
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
6379.6.7 by Jelmer Vernooij
Move importing from future until after doc string, otherwise the doc string will disappear.
17
"""Utility functions for managing external merge tools such as kdiff3."""
18
6379.6.3 by Jelmer Vernooij
Use absolute_import.
19
from __future__ import absolute_import
20
5321.1.69 by Gordon Tyler
Fixed line-endings to be Unix.
21
import os
22
import shutil
23
import subprocess
24
import sys
25
import tempfile
26
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
27
from .lazy_import import lazy_import
5321.1.69 by Gordon Tyler
Fixed line-endings to be Unix.
28
lazy_import(globals(), """
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
29
from breezy import (
5321.1.69 by Gordon Tyler
Fixed line-endings to be Unix.
30
    cmdline,
5321.1.83 by Gordon Tyler
Use osutils.find_executable_on_path in is_available instead.
31
    osutils,
5321.1.69 by Gordon Tyler
Fixed line-endings to be Unix.
32
    trace,
33
)
34
""")
35
36
5321.1.108 by Gordon Tyler
Changed known merge tools into a default set of merge tools that are always defined but can be overridden by user-defined merge tools.
37
known_merge_tools = {
5321.2.8 by Vincent Ladeuil
_KNOWN_MERGE_TOOLS should be a dict (there is an hidden assumption that the merg tool is unique anyway).
38
    'bcompare': 'bcompare {this} {other} {base} {result}',
39
    'kdiff3': 'kdiff3 {base} {this} {other} -o {result}',
40
    'xdiff': 'xxdiff -m -O -M {result} {this} {base} {other}',
41
    'meld': 'meld {base} {this_temp} {other}',
42
    'opendiff': 'opendiff {this} {other} -ancestor {base} -merge {result}',
43
    'winmergeu': 'winmergeu {result}',
44
}
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
45
46
47
def check_availability(command_line):
48
    cmd_list = cmdline.split(command_line)
49
    exe = cmd_list[0]
50
    if sys.platform == 'win32':
6437.44.1 by Gordon Tyler
Backport of fix for bug 939605 to bzr 2.5 series.
51
        exe = _get_executable_path(exe)
52
        if exe is None:
53
            return False
54
        base, ext = os.path.splitext(exe)
6973.6.4 by Jelmer Vernooij
Avoid text_type()
55
        path_ext = [s.lower()
6437.44.1 by Gordon Tyler
Backport of fix for bug 939605 to bzr 2.5 series.
56
                    for s in os.getenv('PATHEXT', '').split(os.pathsep)]
57
        return os.path.exists(exe) and ext in path_ext
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
58
    else:
7143.15.2 by Jelmer Vernooij
Run autopep8.
59
        return (os.access(exe, os.X_OK) or
60
                osutils.find_executable_on_path(exe) is not None)
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
61
62
63
def invoke(command_line, filename, invoker=None):
64
    """Invokes the given merge tool command line, substituting the given
65
    filename according to the embedded substitution markers. Optionally, it
66
    will use the given invoker function instead of the default
67
    subprocess_invoker.
68
    """
69
    if invoker is None:
70
        invoker = subprocess_invoker
71
    cmd_list = cmdline.split(command_line)
6437.44.1 by Gordon Tyler
Backport of fix for bug 939605 to bzr 2.5 series.
72
    exe = _get_executable_path(cmd_list[0])
73
    if exe is not None:
74
        cmd_list[0] = exe
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
75
    args, tmp_file = _subst_filename(cmd_list, filename)
7143.15.2 by Jelmer Vernooij
Run autopep8.
76
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
77
    def cleanup(retcode):
78
        if tmp_file is not None:
7143.15.2 by Jelmer Vernooij
Run autopep8.
79
            if retcode == 0:  # on success, replace file with temp file
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
80
                shutil.move(tmp_file, filename)
7143.15.2 by Jelmer Vernooij
Run autopep8.
81
            else:  # otherwise, delete temp file
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
82
                os.remove(tmp_file)
83
    return invoker(args[0], args[1:], cleanup)
84
85
6437.44.1 by Gordon Tyler
Backport of fix for bug 939605 to bzr 2.5 series.
86
def _get_executable_path(exe):
87
    if os.path.isabs(exe):
88
        return exe
89
    return osutils.find_executable_on_path(exe)
90
91
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
92
def _subst_filename(args, filename):
93
    subst_names = {
5321.1.119 by Gordon Tyler
Replace usage of format function from python 2.6 with our own very simple formatting function.
94
        'base': filename + u'.BASE',
95
        'this': filename + u'.THIS',
96
        'other': filename + u'.OTHER',
97
        'result': filename,
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
98
    }
99
    tmp_file = None
100
    subst_args = []
101
    for arg in args:
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
102
        if '{this_temp}' in arg and 'this_temp' not in subst_names:
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
103
            fh, tmp_file = tempfile.mkstemp(u"_bzr_mergetools_%s.THIS" %
104
                                            os.path.basename(filename))
105
            trace.mutter('fh=%r, tmp_file=%r', fh, tmp_file)
106
            os.close(fh)
107
            shutil.copy(filename + u".THIS", tmp_file)
108
            subst_names['this_temp'] = tmp_file
5321.1.119 by Gordon Tyler
Replace usage of format function from python 2.6 with our own very simple formatting function.
109
        arg = _format_arg(arg, subst_names)
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
110
        subst_args.append(arg)
111
    return subst_args, tmp_file
112
113
5321.1.119 by Gordon Tyler
Replace usage of format function from python 2.6 with our own very simple formatting function.
114
# This would be better implemented using format() from python 2.6
115
def _format_arg(arg, subst_names):
116
    arg = arg.replace('{base}', subst_names['base'])
117
    arg = arg.replace('{this}', subst_names['this'])
118
    arg = arg.replace('{other}', subst_names['other'])
119
    arg = arg.replace('{result}', subst_names['result'])
6619.3.1 by Jelmer Vernooij
Apply 2to3 has_key fix.
120
    if 'this_temp' in subst_names:
5321.1.119 by Gordon Tyler
Replace usage of format function from python 2.6 with our own very simple formatting function.
121
        arg = arg.replace('{this_temp}', subst_names['this_temp'])
122
    return arg
123
124
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
125
def subprocess_invoker(executable, args, cleanup):
126
    retcode = subprocess.call([executable] + args)
127
    cleanup(retcode)
128
    return retcode