94 lines
3.9 KiB
Python
Raw Normal View History

#
# patch.py - Internal helper class for sponsor-patch
#
2011-09-10 21:28:28 +02:00
# Copyright (C) 2010-2011, Benjamin Drung <bdrung@ubuntu.com>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
import os
2011-09-10 21:28:28 +02:00
import re
2019-09-04 19:17:00 -03:00
import subprocess
2011-09-10 21:28:28 +02:00
from ubuntutools.sponsor_patch.question import ask_for_manual_fixing
2014-12-18 20:52:17 +00:00
from functools import reduce
import logging
Logger = logging.getLogger(__name__)
2017-05-01 00:20:03 +02:00
class Patch(object):
2011-09-10 21:28:28 +02:00
"""This object represents a patch that can be downloaded from Launchpad."""
def __init__(self, patch):
self._patch = patch
self._patch_file = re.sub(" |/", "_", patch.title)
2011-09-10 21:28:28 +02:00
if not reduce(lambda r, x: r or self._patch.title.endswith(x),
(".debdiff", ".diff", ".patch"), False):
Logger.debug("Patch %s does not have a proper file extension." %
(self._patch.title))
2011-09-10 21:28:28 +02:00
self._patch_file += ".patch"
self._full_path = os.path.realpath(self._patch_file)
self._changed_files = None
def apply(self, task):
"""Applies the patch in the current directory."""
2017-05-01 00:20:03 +02:00
assert self._changed_files is not None, "You forgot to download the patch."
2011-09-10 21:28:28 +02:00
edit = False
if self.is_debdiff():
cmd = ["patch", "--merge", "--force", "-p",
str(self.get_strip_level()), "-i", self._full_path]
Logger.debug(' '.join(cmd))
2011-09-10 21:28:28 +02:00
if subprocess.call(cmd) != 0:
Logger.error("Failed to apply debdiff %s to %s %s.",
self._patch_file, task.package, task.get_version())
if not edit:
ask_for_manual_fixing()
edit = True
else:
cmd = ["add-patch", self._full_path]
Logger.debug(' '.join(cmd))
2011-09-10 21:28:28 +02:00
if subprocess.call(cmd) != 0:
Logger.error("Failed to apply diff %s to %s %s.",
self._patch_file, task.package, task.get_version())
if not edit:
ask_for_manual_fixing()
edit = True
return edit
def download(self):
"""Downloads the patch from Launchpad."""
Logger.debug("Downloading %s." % (self._patch_file))
patch_f = open(self._patch_file, "wb")
2011-09-10 21:28:28 +02:00
patch_f.write(self._patch.data.open().read())
patch_f.close()
cmd = ["diffstat", "-l", "-p0", self._full_path]
changed_files = subprocess.check_output(cmd, encoding='utf-8')
self._changed_files = [f for f in changed_files.split("\n") if f != ""]
def get_strip_level(self):
2011-09-10 21:28:28 +02:00
"""Returns the stript level for the patch."""
2017-05-01 00:20:03 +02:00
assert self._changed_files is not None, "You forgot to download the patch."
strip_level = None
if self.is_debdiff():
2011-09-10 21:28:28 +02:00
changelog = [f for f in self._changed_files
2010-12-27 15:20:49 +01:00
if f.endswith("debian/changelog")][0]
strip_level = len(changelog.split(os.sep)) - 2
return strip_level
def is_debdiff(self):
2011-09-10 21:28:28 +02:00
"""Checks if the patch is a debdiff (= modifies debian/changelog)."""
2017-05-01 00:20:03 +02:00
assert self._changed_files is not None, "You forgot to download the patch."
2011-09-10 21:28:28 +02:00
return len([f for f in self._changed_files
2010-12-27 15:20:49 +01:00
if f.endswith("debian/changelog")]) > 0