/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 breezy/mergetools.py

  • Committer: Gustav Hartvigsson
  • Date: 2021-01-09 21:36:27 UTC
  • Revision ID: gustav.hartvigsson@gmail.com-20210109213627-h1xwcutzy9m7a99b
Added 'Case Preserving Working Tree Use Cases' from Canonical Wiki

* Addod a page from the Canonical Bazaar wiki
  with information on the scmeatics of case
  perserving filesystems an a case insensitive
  filesystem works.
  
  * Needs re-work, but this will do as it is the
    same inforamoton as what was on the linked
    page in the currint documentation.

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
"""Utility functions for managing external merge tools such as kdiff3."""
 
18
 
 
19
import os
 
20
import shutil
 
21
import subprocess
 
22
import sys
 
23
import tempfile
 
24
 
 
25
from .lazy_import import lazy_import
 
26
lazy_import(globals(), """
 
27
from breezy import (
 
28
    cmdline,
 
29
    osutils,
 
30
    trace,
 
31
)
 
32
""")
 
33
 
 
34
 
 
35
known_merge_tools = {
 
36
    'bcompare': 'bcompare {this} {other} {base} {result}',
 
37
    'kdiff3': 'kdiff3 {base} {this} {other} -o {result}',
 
38
    'xdiff': 'xxdiff -m -O -M {result} {this} {base} {other}',
 
39
    'meld': 'meld {base} {this_temp} {other}',
 
40
    'opendiff': 'opendiff {this} {other} -ancestor {base} -merge {result}',
 
41
    'winmergeu': 'winmergeu {result}',
 
42
}
 
43
 
 
44
 
 
45
def check_availability(command_line):
 
46
    cmd_list = cmdline.split(command_line)
 
47
    exe = cmd_list[0]
 
48
    if sys.platform == 'win32':
 
49
        exe = _get_executable_path(exe)
 
50
        if exe is None:
 
51
            return False
 
52
        base, ext = os.path.splitext(exe)
 
53
        path_ext = [s.lower()
 
54
                    for s in os.getenv('PATHEXT', '').split(os.pathsep)]
 
55
        return os.path.exists(exe) and ext in path_ext
 
56
    else:
 
57
        return (os.access(exe, os.X_OK) or
 
58
                osutils.find_executable_on_path(exe) is not None)
 
59
 
 
60
 
 
61
def invoke(command_line, filename, invoker=None):
 
62
    """Invokes the given merge tool command line, substituting the given
 
63
    filename according to the embedded substitution markers. Optionally, it
 
64
    will use the given invoker function instead of the default
 
65
    subprocess_invoker.
 
66
    """
 
67
    if invoker is None:
 
68
        invoker = subprocess_invoker
 
69
    cmd_list = cmdline.split(command_line)
 
70
    exe = _get_executable_path(cmd_list[0])
 
71
    if exe is not None:
 
72
        cmd_list[0] = exe
 
73
    args, tmp_file = _subst_filename(cmd_list, filename)
 
74
 
 
75
    def cleanup(retcode):
 
76
        if tmp_file is not None:
 
77
            if retcode == 0:  # on success, replace file with temp file
 
78
                shutil.move(tmp_file, filename)
 
79
            else:  # otherwise, delete temp file
 
80
                os.remove(tmp_file)
 
81
    return invoker(args[0], args[1:], cleanup)
 
82
 
 
83
 
 
84
def _get_executable_path(exe):
 
85
    if os.path.isabs(exe):
 
86
        return exe
 
87
    return osutils.find_executable_on_path(exe)
 
88
 
 
89
 
 
90
def _subst_filename(args, filename):
 
91
    subst_names = {
 
92
        'base': filename + u'.BASE',
 
93
        'this': filename + u'.THIS',
 
94
        'other': filename + u'.OTHER',
 
95
        'result': filename,
 
96
    }
 
97
    tmp_file = None
 
98
    subst_args = []
 
99
    for arg in args:
 
100
        if '{this_temp}' in arg and 'this_temp' not in subst_names:
 
101
            fh, tmp_file = tempfile.mkstemp(u"_bzr_mergetools_%s.THIS" %
 
102
                                            os.path.basename(filename))
 
103
            trace.mutter('fh=%r, tmp_file=%r', fh, tmp_file)
 
104
            os.close(fh)
 
105
            shutil.copy(filename + u".THIS", tmp_file)
 
106
            subst_names['this_temp'] = tmp_file
 
107
        arg = _format_arg(arg, subst_names)
 
108
        subst_args.append(arg)
 
109
    return subst_args, tmp_file
 
110
 
 
111
 
 
112
# This would be better implemented using format() from python 2.6
 
113
def _format_arg(arg, subst_names):
 
114
    arg = arg.replace('{base}', subst_names['base'])
 
115
    arg = arg.replace('{this}', subst_names['this'])
 
116
    arg = arg.replace('{other}', subst_names['other'])
 
117
    arg = arg.replace('{result}', subst_names['result'])
 
118
    if 'this_temp' in subst_names:
 
119
        arg = arg.replace('{this_temp}', subst_names['this_temp'])
 
120
    return arg
 
121
 
 
122
 
 
123
def subprocess_invoker(executable, args, cleanup):
 
124
    retcode = subprocess.call([executable] + args)
 
125
    cleanup(retcode)
 
126
    return retcode