~abentley/bzrtools/bzrtools.dev

611 by Aaron Bentley
Handle missing patch, fix tabs
1
# Copyright (C) 2005, 2008 Aaron Bentley, 2006 Michael Ellerman
612 by Aaron Bentley
Update email address
2
# <aaron@aaronbentley.com>
257.1.2 by Aaron Bentley
Updated GPL notices
3
#
4
#    This program is free software; you can redistribute it and/or modify
5
#    it under the terms of the GNU General Public License as published by
6
#    the Free Software Foundation; either version 2 of the License, or
7
#    (at your option) any later version.
8
#
9
#    This program is distributed in the hope that it will be useful,
10
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
#    GNU General Public License for more details.
13
#
14
#    You should have received a copy of the GNU General Public License
15
#    along with this program; if not, write to the Free Software
16
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
473 by Aaron Bentley
Clean up patch command (support http urls again)
17
import sys
610 by Aaron Bentley
Unify patch invocation
18
import subprocess
473 by Aaron Bentley
Clean up patch command (support http urls again)
19
321.2.3 by ghigo
Inform bzr of a renaming
20
from bzrlib.workingtree import WorkingTree
21
import bzrlib.add
473 by Aaron Bentley
Clean up patch command (support http urls again)
22
563 by Aaron Bentley
Allow importing directly from a URL
23
from bzrlib.plugins.bzrtools.bzrtools import open_from_url
610 by Aaron Bentley
Unify patch invocation
24
from errors import CommandError, PatchFailed, PatchInvokeError
563 by Aaron Bentley
Allow importing directly from a URL
25
496 by Aaron Bentley
Add --silent option to patch
26
def patch(tree, location, strip, quiet=False):
259 by Aaron Bentley
Got patch working with urls
27
    """Apply a patch to a branch, using patch(1).  URLs may be used."""
28
    my_file = None
29
    if location is None:
152 by Aaron Bentley
Added new bzr patch command
30
        my_file = sys.stdin
31
    else:
563 by Aaron Bentley
Allow importing directly from a URL
32
        my_file = open_from_url(location)
610 by Aaron Bentley
Unify patch invocation
33
    patches = [my_file.read()]
34
    return run_patch(tree.basedir, patches, strip, quiet=quiet)
35
36
37
def run_patch(directory, patches, strip=0, reverse=False, dry_run=False,
662 by Aaron Bentley
Add target_file param
38
              quiet=False, _patch_cmd='patch', target_file=None):
611 by Aaron Bentley
Handle missing patch, fix tabs
39
    args = [_patch_cmd, '-d', directory, '-s', '-p%d' % strip, '-f']
496 by Aaron Bentley
Add --silent option to patch
40
    if quiet:
610 by Aaron Bentley
Unify patch invocation
41
        args.append('--quiet')
42
43
    if sys.platform == "win32":
44
        args.append('--binary')
45
46
    if reverse:
47
        args.append('-R')
48
    if dry_run:
49
        if sys.platform.startswith('freebsd'):
50
            args.append('--check')
51
        else:
52
            args.append('--dry-run')
53
        stderr = subprocess.PIPE
54
    else:
55
        stderr = None
662 by Aaron Bentley
Add target_file param
56
    if target_file is not None:
57
        args.append(target_file)
610 by Aaron Bentley
Unify patch invocation
58
59
    try:
60
        process = subprocess.Popen(args, stdin=subprocess.PIPE,
61
                                   stdout=subprocess.PIPE, stderr=stderr)
611 by Aaron Bentley
Handle missing patch, fix tabs
62
    except OSError, e:
63
        raise PatchInvokeError(e)
64
    try:
610 by Aaron Bentley
Unify patch invocation
65
        for patch in patches:
66
            process.stdin.write(str(patch))
67
        process.stdin.close()
68
69
    except IOError, e:
70
        raise PatchInvokeError(e, process.stderr.read())
71
72
    result = process.wait()
73
    if not dry_run:
74
        sys.stdout.write(process.stdout.read())
75
    if result != 0:
76
        raise PatchFailed()
77
78
    return result