diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7e99e36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.pyc \ No newline at end of file diff --git a/example/example.py b/example/example.py new file mode 100644 index 0000000..b9db850 --- /dev/null +++ b/example/example.py @@ -0,0 +1,42 @@ +import os +import logging +from patch import fromfile, fromstring + +class PatchLogHandler(logging.Handler): + def __init__(self): + logging.Handler.__init__(self, logging.DEBUG) + + def emit(self, record): + logstr = self.format(record) + print logstr + +patchlog = logging.getLogger("patch") +patchlog.handlers = [] +patchlog.addHandler(PatchLogHandler()) + +patch = fromstring("""--- /dev/null ++++ b/newfile +@@ -0,0 +0,3 @@ ++New file1 ++New file2 ++New file3 +""") + +patch.apply(root=os.getcwd(), strip=0) + + +with open("newfile", "rb") as f: + newfile = f.read() + assert "New file1\nNew file2\nNew file3\n" == newfile + +patch = fromstring("""--- a/newfile ++++ /dev/null +@@ -0,3 +0,0 @@ +-New file1 +-New file2 +-New file3 +""") + +result = patch.apply(root=os.getcwd(), strip=0) + +assert os.path.exists("newfile") is False \ No newline at end of file diff --git a/patch.py b/patch.py index 4b82af0..4857121 100755 --- a/patch.py +++ b/patch.py @@ -800,7 +800,6 @@ def diffstat(self): % (len(names), sum(insert), sum(delete), delta)) return output - def findfile(self, old, new): """ return name of file to be patched or None """ if exists(old): @@ -820,6 +819,10 @@ def findfile(self, old, new): return new return None + def _strip_prefix(self, filename): + if filename.startswith(b'a/') or filename.startswith(b'b/'): + return filename[2:] + return filename def apply(self, strip=0, root=None): """ Apply parsed patch, optionally stripping leading components @@ -857,9 +860,22 @@ def apply(self, strip=0, root=None): filename = self.findfile(old, new) if not filename: - warning("source/target file does not exist:\n --- %s\n +++ %s" % (old, new)) - errors += 1 - continue + if "dev/null" in old: + # this is a file creation + filename = self._strip_prefix(new) + # I wish there would be something more clean to get the full contents + new_file = "".join(s[1:] for s in p.hunks[0].text) + with open(filename, "wb") as f: + f.write(new_file) + continue + elif "dev/null" in new: + # this is a file removal + os.remove(self._strip_prefix(old)) + continue + else: + warning("source/target file does not exist:\n --- %s\n +++ %s" % (old, new)) + errors += 1 + continue if not isfile(filename): warning("not a file - %s" % filename) errors += 1