/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-04-06 12:28:50 UTC
  • mto: (7296.6.2 patch-silent)
  • mto: This revision was merged to the branch mainline in revision 7309.
  • Revision ID: jelmer@jelmer.uk-20190406122850-gegiroz6jkv1n9tl
Import patch code from bzrtools.

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:
101
117
    finally:
102
118
        f.close()
103
119
    return status
 
120
 
 
121
 
 
122
def patch_multi(tree, location, strip, quiet=False):
 
123
    """Apply a patch to a branch, using patch(1).  URLs may be used."""
 
124
    my_file = None
 
125
    if location is None:
 
126
        my_file = sys.stdin
 
127
    else:
 
128
        my_file = open_from_url(location)
 
129
    patches = [my_file.read()]
 
130
    return run_patch(tree.basedir, patches, strip, quiet=quiet)
 
131
 
 
132
 
 
133
def run_patch(directory, patches, strip=0, reverse=False, dry_run=False,
 
134
              quiet=False, _patch_cmd='patch', target_file=None):
 
135
    args = [_patch_cmd, '-d', directory, '-s', '-p%d' % strip, '-f']
 
136
    if quiet:
 
137
        args.append('--quiet')
 
138
 
 
139
    if sys.platform == "win32":
 
140
        args.append('--binary')
 
141
 
 
142
    if reverse:
 
143
        args.append('-R')
 
144
    if dry_run:
 
145
        if sys.platform.startswith('freebsd'):
 
146
            args.append('--check')
 
147
        else:
 
148
            args.append('--dry-run')
 
149
        stderr = PIPE
 
150
    else:
 
151
        stderr = None
 
152
    if target_file is not None:
 
153
        args.append(target_file)
 
154
 
 
155
    try:
 
156
        process = Popen(args, stdin=PIPE, stdout=PIPE, stderr=stderr)
 
157
    except OSError as e:
 
158
        raise PatchInvokeError(e)
 
159
    try:
 
160
        for patch in patches:
 
161
            process.stdin.write(str(patch))
 
162
        process.stdin.close()
 
163
 
 
164
    except IOError as e:
 
165
        raise PatchInvokeError(e, process.stderr.read())
 
166
 
 
167
    result = process.wait()
 
168
    if not dry_run:
 
169
        sys.stdout.write(process.stdout.read())
 
170
    if result != 0:
 
171
        raise PatchFailed()
 
172
 
 
173
    return result