/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
62
46
    stdout, stderr = process.communicate(input)
63
47
    status = process.wait()
64
48
    if status < 0:
65
 
        raise Exception("%s killed by signal %i" % (args[0], -status))
 
49
        raise Exception("%s killed by signal %i" (args[0], -status))
66
50
    return stdout, stderr, status
67
51
 
68
52
 
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:
111
95
            raise
112
96
    if status not in (0, 1):
113
97
        raise Exception(stderr)
114
 
    with open(out_file, 'wb') as f:
 
98
    f = open(out_file, 'wb')
 
99
    try:
115
100
        f.write(output)
 
101
    finally:
 
102
        f.close()
116
103
    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