Merge lp:~jelmer/brz/import-patch into lp:brz

Proposed by Jelmer Vernooij
Status: Merged
Approved by: Jelmer Vernooij
Approved revision: no longer in the source branch.
Merge reported by: The Breezy Bot
Merged at revision: not available
Proposed branch: lp:~jelmer/brz/import-patch
Merge into: lp:brz
Diff against target: 247 lines (+154/-9)
6 files modified
breezy/builtins.py (+24/-0)
breezy/patch.py (+81/-8)
breezy/tests/blackbox/__init__.py (+1/-0)
breezy/tests/blackbox/test_patch.py (+36/-0)
breezy/tests/test_patch.py (+9/-1)
doc/en/release-notes/brz-3.1.txt (+3/-0)
To merge this branch: bzr merge lp:~jelmer/brz/import-patch
Reviewer Review Type Date Requested Status
Jelmer Vernooij Approve
Review via email: mp+365618@code.launchpad.net

Commit message

Import the 'patch' command from bzrtools.

Description of the change

Import the 'patch' command from bzrtools.

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) :
review: Approve
Revision history for this message
Jelmer Vernooij (jelmer) :
review: Approve
Revision history for this message
The Breezy Bot (the-breezy-bot) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'breezy/builtins.py'
--- breezy/builtins.py 2019-05-29 05:24:46 +0000
+++ breezy/builtins.py 2019-06-01 01:20:30 +0000
@@ -7001,6 +7001,30 @@
7001 grep.versioned_grep(opts)7001 grep.versioned_grep(opts)
70027002
70037003
7004class cmd_patch(Command):
7005 """Apply a named patch to the current tree.
7006
7007 """
7008 takes_args = ['filename?']
7009 takes_options = [Option('strip', type=int, short_name='p',
7010 help=("Strip the smallest prefix containing num "
7011 "leading slashes from filenames.")),
7012 Option('silent', help='Suppress chatter.')]
7013
7014 def run(self, filename=None, strip=None, silent=False):
7015 from .patch import patch_tree
7016 wt = WorkingTree.open_containing('.')[0]
7017 if strip is None:
7018 strip = 1
7019 my_file = None
7020 if filename is None:
7021 my_file = getattr(sys.stdin, 'buffer', sys.stdin)
7022 else:
7023 my_file = open(filename, 'rb')
7024 patches = [my_file.read()]
7025 return patch_tree(wt, patches, strip, quiet=is_quiet(), out=self.outf)
7026
7027
7004class cmd_resolve_location(Command):7028class cmd_resolve_location(Command):
7005 __doc__ = """Expand a location to a full URL.7029 __doc__ = """Expand a location to a full URL.
70067030
70077031
=== modified file 'breezy/patch.py'
--- breezy/patch.py 2017-05-22 00:56:52 +0000
+++ breezy/patch.py 2019-06-01 01:20:30 +0000
@@ -1,4 +1,5 @@
1# Copyright (C) 2005, 2006 Canonical Ltd1# Copyright (C) 2005, 2006 Canonical Ltd
2# Copyright (C) 2005, 2008 Aaron Bentley, 2006 Michael Ellerman
2#3#
3# This program is free software; you can redistribute it and/or modify4# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by5# it under the terms of the GNU General Public License as published by
@@ -16,16 +17,30 @@
1617
17from __future__ import absolute_import18from __future__ import absolute_import
1819
20"""Diff and patch functionality"""
21
19import errno22import errno
20import os23import os
21from subprocess import Popen, PIPE24from subprocess import Popen, PIPE
25import sys
2226
23from .errors import NoDiff327from .errors import NoDiff3, BzrError
24from .textfile import check_text_path28from .textfile import check_text_path
2529
26"""Diff and patch functionality"""30class PatchFailed(BzrError):
2731
28__docformat__ = "restructuredtext"32 _fmt = """Patch application failed"""
33
34
35class 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
2944
3045
31_do_close_fds = True46_do_close_fds = True
@@ -96,9 +111,67 @@
96 raise111 raise
97 if status not in (0, 1):112 if status not in (0, 1):
98 raise Exception(stderr)113 raise Exception(stderr)
99 f = open(out_file, 'wb')114 with open(out_file, 'wb') as f:
100 try:
101 f.write(output)115 f.write(output)
102 finally:
103 f.close()
104 return status116 return status
117
118
119def 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
134def 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
105178
=== modified file 'breezy/tests/blackbox/__init__.py'
--- breezy/tests/blackbox/__init__.py 2019-02-24 00:57:44 +0000
+++ breezy/tests/blackbox/__init__.py 2019-06-01 01:20:30 +0000
@@ -92,6 +92,7 @@
92 'test_non_ascii',92 'test_non_ascii',
93 'test_outside_wt',93 'test_outside_wt',
94 'test_pack',94 'test_pack',
95 'test_patch',
95 'test_ping',96 'test_ping',
96 'test_plugins',97 'test_plugins',
97 'test_pull',98 'test_pull',
9899
=== added file 'breezy/tests/blackbox/test_patch.py'
--- breezy/tests/blackbox/test_patch.py 1970-01-01 00:00:00 +0000
+++ breezy/tests/blackbox/test_patch.py 2019-06-01 01:20:30 +0000
@@ -0,0 +1,36 @@
1# Copyright (C) 2019 Breezy Developers
2#
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 2 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program; if not, write to the Free Software
15# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
17
18from breezy.tests import TestCaseWithTransport
19
20
21class TestPatch(TestCaseWithTransport):
22
23 def test_patch(self):
24 self.run_bzr('init')
25 with open('myfile', 'w') as f:
26 f.write('hello')
27 self.run_bzr('add')
28 self.run_bzr('commit -m hello')
29 with open('myfile', 'w') as f:
30 f.write('goodbye')
31 with open('mypatch', 'w') as f:
32 f.write(self.run_bzr('diff -p1', retcode=1)[0])
33 self.run_bzr('revert')
34 self.assertFileEqual('hello', 'myfile')
35 self.run_bzr('patch -p1 --silent mypatch')
36 self.assertFileEqual('goodbye', 'myfile')
037
=== modified file 'breezy/tests/test_patch.py'
--- breezy/tests/test_patch.py 2018-11-11 04:08:32 +0000
+++ breezy/tests/test_patch.py 2019-06-01 01:20:30 +0000
@@ -1,4 +1,5 @@
1# Copyright (C) 2006 Canonical Ltd1# Copyright (C) 2006 Canonical Ltd
2# Copyright (C) 2008 Aaron Bentley <aaron@aaronbentley.com>
2#3#
3# This program is free software; you can redistribute it and/or modify4# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by5# it under the terms of the GNU General Public License as published by
@@ -15,7 +16,7 @@
15# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA16# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1617
17from breezy.errors import BinaryFile18from breezy.errors import BinaryFile
18from breezy.patch import diff319from breezy.patch import diff3, PatchInvokeError, run_patch
19from breezy.tests import TestCaseInTempDir20from breezy.tests import TestCaseInTempDir
2021
2122
@@ -29,3 +30,10 @@
29 with open('base', 'wb') as f:30 with open('base', 'wb') as f:
30 f.write(b'\x00')31 f.write(b'\x00')
31 self.assertRaises(BinaryFile, diff3, 'unused', 'this', 'other', 'base')32 self.assertRaises(BinaryFile, diff3, 'unused', 'this', 'other', 'base')
33
34
35class TestPatch(TestCaseInTempDir):
36
37 def test_missing_patch(self):
38 self.assertRaises(PatchInvokeError, run_patch, '.', [],
39 _patch_cmd='/unlikely/to/exist')
3240
=== modified file 'doc/en/release-notes/brz-3.1.txt'
--- doc/en/release-notes/brz-3.1.txt 2019-03-06 14:23:50 +0000
+++ doc/en/release-notes/brz-3.1.txt 2019-06-01 01:20:30 +0000
@@ -21,6 +21,9 @@
2121
22.. New commands, options, etc that users may wish to try out.22.. New commands, options, etc that users may wish to try out.
2323
24 * The 'patch' command is now bundled with brz.
25 Imported from bzrtools by Aaron Bentley. (Jelmer Vernooij)
26
24Improvements27Improvements
25************28************
2629

Subscribers

People subscribed via source and target branches