1
1
# Copyright (C) 2005, 2006 Canonical Ltd
2
# Copyright (C) 2005, 2008 Aaron Bentley, 2006 Michael Ellerman
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
17
18
from __future__ import absolute_import
20
"""Diff and patch functionality"""
21
24
from subprocess import Popen, PIPE
23
from .errors import NoDiff3
27
from .errors import NoDiff3, BzrError
24
28
from .textfile import check_text_path
26
"""Diff and patch functionality"""
28
__docformat__ = "restructuredtext"
30
class PatchFailed(BzrError):
32
_fmt = """Patch application failed"""
35
class PatchInvokeError(BzrError):
37
_fmt = """Error invoking patch: %(errstr)s%(stderr)s"""
38
internal_error = False
40
def __init__(self, e, stderr=''):
42
self.errstr = os.strerror(e.errno)
43
self.stderr = '\n' + stderr
31
46
_do_close_fds = True
122
def patch_multi(tree, location, strip, quiet=False):
123
"""Apply a patch to a branch, using patch(1). URLs may be used."""
128
my_file = open_from_url(location)
129
patches = [my_file.read()]
130
return run_patch(tree.basedir, patches, strip, quiet=quiet)
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']
137
args.append('--quiet')
139
if sys.platform == "win32":
140
args.append('--binary')
145
if sys.platform.startswith('freebsd'):
146
args.append('--check')
148
args.append('--dry-run')
152
if target_file is not None:
153
args.append(target_file)
156
process = Popen(args, stdin=PIPE, stdout=PIPE, stderr=stderr)
158
raise PatchInvokeError(e)
160
for patch in patches:
161
process.stdin.write(str(patch))
162
process.stdin.close()
165
raise PatchInvokeError(e, process.stderr.read())
167
result = process.wait()
169
sys.stdout.write(process.stdout.read())