diff options
author | Lorry <lorry@roadtrain.codethink.co.uk> | 2012-08-22 15:47:16 +0100 |
---|---|---|
committer | Lorry <lorry@roadtrain.codethink.co.uk> | 2012-08-22 15:47:16 +0100 |
commit | 25335618bf8755ce6b116ee14f47f5a1f2c821e9 (patch) | |
tree | d889d7ab3f9f985d0c54c534cb8052bd2e6d7163 /bzrlib/patch.py | |
download | bzr-tarball-25335618bf8755ce6b116ee14f47f5a1f2c821e9.tar.gz |
Tarball conversion
Diffstat (limited to 'bzrlib/patch.py')
-rw-r--r-- | bzrlib/patch.py | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/bzrlib/patch.py b/bzrlib/patch.py new file mode 100644 index 0000000..94d4a64 --- /dev/null +++ b/bzrlib/patch.py @@ -0,0 +1,104 @@ +# Copyright (C) 2005, 2006 Canonical Ltd +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +from __future__ import absolute_import + +import errno +import os +from subprocess import Popen, PIPE + +from bzrlib.errors import NoDiff3 +from bzrlib.textfile import check_text_path + +"""Diff and patch functionality""" + +__docformat__ = "restructuredtext" + + +_do_close_fds = True +if os.name == 'nt': + _do_close_fds = False + + +def write_to_cmd(args, input=""): + """Spawn a process, and wait for the result + + If the process is killed, an exception is raised + + :param args: The command line, the first entry should be the program name + :param input: [optional] The text to send the process on stdin + :return: (stdout, stderr, status) + """ + process = Popen(args, bufsize=len(input), stdin=PIPE, stdout=PIPE, + stderr=PIPE, close_fds=_do_close_fds) + stdout, stderr = process.communicate(input) + status = process.wait() + if status < 0: + raise Exception("%s killed by signal %i" (args[0], -status)) + return stdout, stderr, status + + +def patch(patch_contents, filename, output_filename=None, reverse=False): + """Apply a patch to a file, to produce another output file. This is should + be suitable for our limited purposes. + + :param patch_contents: The contents of the patch to apply + :type patch_contents: str + :param filename: the name of the file to apply the patch to + :type filename: str + :param output_filename: The filename to produce. If None, file is \ + modified in-place + :type output_filename: str or NoneType + :param reverse: If true, apply the patch in reverse + :type reverse: bool + :return: 0 on success, 1 if some hunks failed + """ + args = ["patch", "-f", "-s", "--posix", "--binary"] + if reverse: + args.append("--reverse") + if output_filename is not None: + args.extend(("-o", output_filename)) + args.append(filename) + stdout, stderr, status = write_to_cmd(args, patch_contents) + return status + + +def diff3(out_file, mine_path, older_path, yours_path): + def add_label(args, label): + args.extend(("-L", label)) + check_text_path(mine_path) + check_text_path(older_path) + check_text_path(yours_path) + args = ['diff3', "-E", "--merge"] + add_label(args, "TREE") + add_label(args, "ANCESTOR") + add_label(args, "MERGE-SOURCE") + args.extend((mine_path, older_path, yours_path)) + try: + output, stderr, status = write_to_cmd(args) + except OSError, e: + if e.errno == errno.ENOENT: + raise NoDiff3 + else: + raise + if status not in (0, 1): + raise Exception(stderr) + f = open(out_file, 'wb') + try: + f.write(output) + finally: + f.close() + return status |