/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/patch.py

  • Committer: Jelmer Vernooij
  • Date: 2018-05-06 11:48:54 UTC
  • mto: This revision was merged to the branch mainline in revision 6960.
  • Revision ID: jelmer@jelmer.uk-20180506114854-h4qd9ojaqy8wxjsd
Move .mailmap to root.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2005, 2006 Canonical Ltd
2
 
# Copyright (C) 2005, 2008 Aaron Bentley, 2006 Michael Ellerman
3
2
#
4
3
# This program is free software; you can redistribute it and/or modify
5
4
# it under the terms of the GNU General Public License as published by
17
16
 
18
17
from __future__ import absolute_import
19
18
 
20
 
"""Diff and patch functionality"""
21
 
 
22
19
import errno
23
20
import os
24
21
from subprocess import Popen, PIPE
25
 
import sys
26
 
import tempfile
27
22
 
28
 
from .errors import NoDiff3, BzrError
 
23
from .errors import NoDiff3
29
24
from .textfile import check_text_path
30
25
 
31
 
class PatchFailed(BzrError):
32
 
 
33
 
    _fmt = """Patch application failed"""
34
 
 
35
 
 
36
 
class PatchInvokeError(BzrError):
37
 
 
38
 
    _fmt = """Error invoking patch: %(errstr)s%(stderr)s"""
39
 
    internal_error = False
40
 
 
41
 
    def __init__(self, e, stderr=''):
42
 
        self.exception = e
43
 
        self.errstr = os.strerror(e.errno)
44
 
        self.stderr = '\n' + stderr
 
26
"""Diff and patch functionality"""
 
27
 
 
28
__docformat__ = "restructuredtext"
45
29
 
46
30
 
47
31
_do_close_fds = True
63
47
    stdout, stderr = process.communicate(input)
64
48
    status = process.wait()
65
49
    if status < 0:
66
 
        raise Exception("%s killed by signal %i" % (args[0], -status))
 
50
        raise Exception("%s killed by signal %i" (args[0], -status))
67
51
    return stdout, stderr, status
68
52
 
69
53
 
112
96
            raise
113
97
    if status not in (0, 1):
114
98
        raise Exception(stderr)
115
 
    with open(out_file, 'wb') as f:
 
99
    f = open(out_file, 'wb')
 
100
    try:
116
101
        f.write(output)
 
102
    finally:
 
103
        f.close()
117
104
    return status
118
 
 
119
 
 
120
 
def patch_tree(tree, patches, strip=0, reverse=False, dry_run=False,
121
 
               quiet=False, out=None):
122
 
    """Apply a patch to a tree.
123
 
 
124
 
    Args:
125
 
      tree: A MutableTree object
126
 
      patches: list of patches as bytes
127
 
      strip: Strip X segments of paths
128
 
      reverse: Apply reversal of patch
129
 
      dry_run: Dry run
130
 
    """
131
 
    return run_patch(tree.basedir, patches, strip, reverse, dry_run,
132
 
                     quiet, out=out)
133
 
 
134
 
 
135
 
def run_patch(directory, patches, strip=0, reverse=False, dry_run=False,
136
 
              quiet=False, _patch_cmd='patch', target_file=None, out=None):
137
 
    args = [_patch_cmd, '-d', directory, '-s', '-p%d' % strip, '-f']
138
 
    if quiet:
139
 
        args.append('--quiet')
140
 
 
141
 
    if sys.platform == "win32":
142
 
        args.append('--binary')
143
 
 
144
 
    if reverse:
145
 
        args.append('-R')
146
 
    if dry_run:
147
 
        if sys.platform.startswith('freebsd'):
148
 
            args.append('--check')
149
 
        else:
150
 
            args.append('--dry-run')
151
 
        stderr = PIPE
152
 
    else:
153
 
        stderr = None
154
 
    if target_file is not None:
155
 
        args.append(target_file)
156
 
 
157
 
    try:
158
 
        process = Popen(args, stdin=PIPE, stdout=PIPE, stderr=stderr)
159
 
    except OSError as e:
160
 
        raise PatchInvokeError(e)
161
 
    try:
162
 
        for patch in patches:
163
 
            process.stdin.write(bytes(patch))
164
 
        process.stdin.close()
165
 
 
166
 
    except IOError as e:
167
 
        raise PatchInvokeError(e, process.stderr.read())
168
 
 
169
 
    result = process.wait()
170
 
    if not dry_run:
171
 
        if out is not None:
172
 
            out.write(process.stdout.read())
173
 
        else:
174
 
            process.stdout.read()
175
 
    if result != 0:
176
 
        raise PatchFailed()
177
 
 
178
 
    return result
179
 
 
180
 
 
181
 
def iter_patched_from_hunks(orig_lines, hunks):
182
 
    """Iterate through a series of lines with a patch applied.
183
 
    This handles a single file, and does exact, not fuzzy patching.
184
 
 
185
 
    :param orig_lines: The unpatched lines.
186
 
    :param hunks: An iterable of Hunk instances.
187
 
 
188
 
    This is different from breezy.patches in that it invokes the patch
189
 
    command.
190
 
    """
191
 
    with tempfile.NamedTemporaryFile() as f:
192
 
        f.writelines(orig_lines)
193
 
        f.flush()
194
 
        # TODO(jelmer): Stream patch contents to command, rather than
195
 
        # serializing the entire patch upfront.
196
 
        serialized = b''.join([hunk.as_bytes() for hunk in hunks])
197
 
        args = ["patch", "-f", "-s", "--posix", "--binary",
198
 
                "-o", "-", f.name, "-r", "-"]
199
 
        stdout, stderr, status = write_to_cmd(args, serialized)
200
 
    if status == 0:
201
 
        return [stdout]
202
 
    raise PatchFailed(stderr)