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

  • Committer: Robert Collins
  • Date: 2010-05-06 11:08:10 UTC
  • mto: This revision was merged to the branch mainline in revision 5223.
  • Revision ID: robertc@robertcollins.net-20100506110810-h3j07fh5gmw54s25
Cleaner matcher matching revised unlocking protocol.

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
15
14
# along with this program; if not, write to the Free Software
16
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
16
 
18
 
from __future__ import absolute_import
19
 
 
20
 
"""Diff and patch functionality"""
21
17
 
22
18
import errno
23
19
import os
24
20
from subprocess import Popen, PIPE
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
 
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"
44
28
 
45
29
 
46
30
_do_close_fds = True
104
88
    args.extend((mine_path, older_path, yours_path))
105
89
    try:
106
90
        output, stderr, status = write_to_cmd(args)
107
 
    except OSError as e:
 
91
    except OSError, e:
108
92
        if e.errno == errno.ENOENT:
109
93
            raise NoDiff3
110
94
        else:
117
101
    finally:
118
102
        f.close()
119
103
    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