~bzr-pqm/bzr/bzr.dev

1534.7.130 by Aaron Bentley
More conflict handling, test porting
1
import errno
493 by Martin Pool
- Merge aaron's merge command
2
import os
974.1.2 by Aaron Bentley
Replaced popen with subprocess in patch..py
3
from subprocess import Popen, PIPE
1534.7.130 by Aaron Bentley
More conflict handling, test porting
4
5
from bzrlib.errors import NoDiff3
493 by Martin Pool
- Merge aaron's merge command
6
"""
7
Diff and patch functionality
8
"""
9
__docformat__ = "restructuredtext"
10
974.1.2 by Aaron Bentley
Replaced popen with subprocess in patch..py
11
def write_to_cmd(args, input=""):
1185.1.40 by Robert Collins
Merge what applied of Alexander Belchenko's win32 patch.
12
    if os.name != 'nt':
13
        process = Popen(args, bufsize=len(input), stdin=PIPE, stdout=PIPE,
14
                        stderr=PIPE, close_fds=True)
15
    else:
16
        process = Popen(args, bufsize=len(input), stdin=PIPE, stdout=PIPE,
17
                        stderr=PIPE)
18
974.1.2 by Aaron Bentley
Replaced popen with subprocess in patch..py
19
    stdout, stderr = process.communicate(input)
20
    status = process.wait()
21
    if status < 0:
22
        raise Exception("%s killed by signal %i" (args[0], -status))
23
    return stdout, stderr, status
24
    
25
493 by Martin Pool
- Merge aaron's merge command
26
def patch(patch_contents, filename, output_filename=None, reverse=False):
27
    """Apply a patch to a file, to produce another output file.  This is should
28
    be suitable for our limited purposes.
29
30
    :param patch_contents: The contents of the patch to apply
31
    :type patch_contents: str
32
    :param filename: the name of the file to apply the patch to
33
    :type filename: str
34
    :param output_filename: The filename to produce.  If None, file is \
35
    modified in-place
36
    :type output_filename: str or NoneType
37
    :param reverse: If true, apply the patch in reverse
38
    :type reverse: bool
39
    :return: 0 on success, 1 if some hunks failed
40
    """
41
    args = ["patch", "-f", "-s", "--posix", "--binary"]
42
    if reverse:
43
        args.append("--reverse")
44
    if output_filename is not None:
45
        args.extend(("-o", output_filename))
46
    args.append(filename)
974.1.2 by Aaron Bentley
Replaced popen with subprocess in patch..py
47
    stdout, stderr, status = write_to_cmd(args, patch_contents)
493 by Martin Pool
- Merge aaron's merge command
48
    return status 
49
50
51
def diff3(out_file, mine_path, older_path, yours_path):
52
    def add_label(args, label):
53
        args.extend(("-L", label))
54
    args = ['diff3', "-E", "--merge"]
55
    add_label(args, "TREE")
56
    add_label(args, "ANCESTOR")
57
    add_label(args, "MERGE-SOURCE")
58
    args.extend((mine_path, older_path, yours_path))
1534.7.130 by Aaron Bentley
More conflict handling, test porting
59
    try:
60
        output, stderr, status = write_to_cmd(args)
61
    except OSError, e:
62
        if e.errno == errno.ENOENT:
63
            raise NoDiff3
64
        else:
65
            raise
493 by Martin Pool
- Merge aaron's merge command
66
    if status not in (0, 1):
974.1.2 by Aaron Bentley
Replaced popen with subprocess in patch..py
67
        raise Exception(stderr)
493 by Martin Pool
- Merge aaron's merge command
68
    file(out_file, "wb").write(output)
69
    return status