/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: 2019-07-07 20:43:57 UTC
  • mfrom: (7370 work)
  • mto: This revision was merged to the branch mainline in revision 7378.
  • Revision ID: jelmer@jelmer.uk-20190707204357-82bayabtwikhoi0i
merge trunk.

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
2
3
#
3
4
# This program is free software; you can redistribute it and/or modify
4
5
# it under the terms of the GNU General Public License as published by
14
15
# along with this program; if not, write to the Free Software
15
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
17
 
 
18
from __future__ import absolute_import
 
19
 
 
20
"""Diff and patch functionality"""
17
21
 
18
22
import errno
19
23
import os
20
24
from subprocess import Popen, PIPE
21
 
 
22
 
from bzrlib.errors import NoDiff3
23
 
from bzrlib.textfile import check_text_path
24
 
 
25
 
"""Diff and patch functionality"""
26
 
 
27
 
__docformat__ = "restructuredtext"
 
25
import sys
 
26
 
 
27
from .errors import NoDiff3, BzrError
 
28
from .textfile import check_text_path
 
29
 
 
30
class PatchFailed(BzrError):
 
31
 
 
32
    _fmt = """Patch application failed"""
 
33
 
 
34
 
 
35
class PatchInvokeError(BzrError):
 
36
 
 
37
    _fmt = """Error invoking patch: %(errstr)s%(stderr)s"""
 
38
    internal_error = False
 
39
 
 
40
    def __init__(self, e, stderr=''):
 
41
        self.exception = e
 
42
        self.errstr = os.strerror(e.errno)
 
43
        self.stderr = '\n' + stderr
28
44
 
29
45
 
30
46
_do_close_fds = True
88
104
    args.extend((mine_path, older_path, yours_path))
89
105
    try:
90
106
        output, stderr, status = write_to_cmd(args)
91
 
    except OSError, e:
 
107
    except OSError as e:
92
108
        if e.errno == errno.ENOENT:
93
109
            raise NoDiff3
94
110
        else:
95
111
            raise
96
112
    if status not in (0, 1):
97
113
        raise Exception(stderr)
98
 
    f = open(out_file, 'wb')
99
 
    try:
 
114
    with open(out_file, 'wb') as f:
100
115
        f.write(output)
101
 
    finally:
102
 
        f.close()
103
116
    return status
 
117
 
 
118
 
 
119
def patch_tree(tree, patches, strip=0, reverse=False, dry_run=False,
 
120
               quiet=False, out=None):
 
121
    """Apply a patch to a tree.
 
122
 
 
123
    Args:
 
124
      tree: A MutableTree object
 
125
      patches: list of patches as bytes
 
126
      strip: Strip X segments of paths
 
127
      reverse: Apply reversal of patch
 
128
      dry_run: Dry run
 
129
    """
 
130
    return run_patch(tree.basedir, patches, strip, reverse, dry_run,
 
131
                     quiet, out=out)
 
132
 
 
133
 
 
134
def run_patch(directory, patches, strip=0, reverse=False, dry_run=False,
 
135
              quiet=False, _patch_cmd='patch', target_file=None, out=None):
 
136
    args = [_patch_cmd, '-d', directory, '-s', '-p%d' % strip, '-f']
 
137
    if quiet:
 
138
        args.append('--quiet')
 
139
 
 
140
    if sys.platform == "win32":
 
141
        args.append('--binary')
 
142
 
 
143
    if reverse:
 
144
        args.append('-R')
 
145
    if dry_run:
 
146
        if sys.platform.startswith('freebsd'):
 
147
            args.append('--check')
 
148
        else:
 
149
            args.append('--dry-run')
 
150
        stderr = PIPE
 
151
    else:
 
152
        stderr = None
 
153
    if target_file is not None:
 
154
        args.append(target_file)
 
155
 
 
156
    try:
 
157
        process = Popen(args, stdin=PIPE, stdout=PIPE, stderr=stderr)
 
158
    except OSError as e:
 
159
        raise PatchInvokeError(e)
 
160
    try:
 
161
        for patch in patches:
 
162
            process.stdin.write(bytes(patch))
 
163
        process.stdin.close()
 
164
 
 
165
    except IOError as e:
 
166
        raise PatchInvokeError(e, process.stderr.read())
 
167
 
 
168
    result = process.wait()
 
169
    if not dry_run:
 
170
        if out is not None:
 
171
            out.write(process.stdout.read())
 
172
        else:
 
173
            process.stdout.read()
 
174
    if result != 0:
 
175
        raise PatchFailed()
 
176
 
 
177
    return result