2010-12-17 17:32:38 +01:00
|
|
|
#
|
|
|
|
# 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>
|
2010-12-17 17:32:38 +01:00
|
|
|
#
|
|
|
|
# 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.
|
|
|
|
|
2023-01-30 21:28:47 +01:00
|
|
|
import logging
|
2010-12-17 17:32:38 +01:00
|
|
|
import os
|
2011-09-10 21:28:28 +02:00
|
|
|
import re
|
2019-09-04 19:17:00 -03:00
|
|
|
import subprocess
|
2014-12-18 20:52:17 +00:00
|
|
|
from functools import reduce
|
2010-12-17 17:32:38 +01:00
|
|
|
|
2023-01-30 21:28:47 +01:00
|
|
|
from ubuntutools.sponsor_patch.question import ask_for_manual_fixing
|
2023-01-30 19:45:36 +01:00
|
|
|
|
2018-10-12 18:54:07 -04:00
|
|
|
Logger = logging.getLogger(__name__)
|
|
|
|
|
2017-05-01 00:20:03 +02:00
|
|
|
|
2010-12-17 17:32:38 +01: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
|
2012-08-01 15:16:34 +02:00
|
|
|
self._patch_file = re.sub(" |/", "_", patch.title)
|
2023-01-30 19:45:36 +01: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():
|
2023-01-30 19:45:36 +01:00
|
|
|
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:
|
2023-01-30 19:45:36 +01:00
|
|
|
Logger.error(
|
|
|
|
"Failed to apply debdiff %s to %s %s.",
|
|
|
|
self._patch_file,
|
|
|
|
task.package,
|
|
|
|
task.get_version(),
|
|
|
|
)
|
2011-09-10 21:28:28 +02:00
|
|
|
if not edit:
|
|
|
|
ask_for_manual_fixing()
|
|
|
|
edit = True
|
|
|
|
else:
|
|
|
|
cmd = ["add-patch", self._full_path]
|
2023-01-30 19:45:36 +01:00
|
|
|
Logger.debug(" ".join(cmd))
|
2011-09-10 21:28:28 +02:00
|
|
|
if subprocess.call(cmd) != 0:
|
2023-01-30 19:45:36 +01:00
|
|
|
Logger.error(
|
|
|
|
"Failed to apply diff %s to %s %s.",
|
|
|
|
self._patch_file,
|
|
|
|
task.package,
|
|
|
|
task.get_version(),
|
|
|
|
)
|
2011-09-10 21:28:28 +02:00
|
|
|
if not edit:
|
|
|
|
ask_for_manual_fixing()
|
|
|
|
edit = True
|
|
|
|
return edit
|
|
|
|
|
|
|
|
def download(self):
|
|
|
|
"""Downloads the patch from Launchpad."""
|
2018-10-12 18:54:07 -04:00
|
|
|
Logger.debug("Downloading %s." % (self._patch_file))
|
2021-02-22 22:24:52 -05:00
|
|
|
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]
|
2023-01-30 19:45:36 +01:00
|
|
|
changed_files = subprocess.check_output(cmd, encoding="utf-8")
|
2018-03-08 12:56:36 +01:00
|
|
|
self._changed_files = [f for f in changed_files.split("\n") if f != ""]
|
2010-12-17 17:32:38 +01:00
|
|
|
|
|
|
|
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."
|
2010-12-17 17:32:38 +01:00
|
|
|
strip_level = None
|
|
|
|
if self.is_debdiff():
|
2023-01-30 19:45:36 +01:00
|
|
|
changelog = [f for f in self._changed_files if f.endswith("debian/changelog")][0]
|
2010-12-17 17:32:38 +01:00
|
|
|
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."
|
2023-01-30 19:45:36 +01:00
|
|
|
return len([f for f in self._changed_files if f.endswith("debian/changelog")]) > 0
|