2010-12-17 17:32:38 +01:00
|
|
|
#
|
|
|
|
# bugtask.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
|
|
|
|
import re
|
2019-09-05 09:49:41 -03:00
|
|
|
from urllib.parse import unquote
|
|
|
|
from urllib.request import urlretrieve
|
2010-12-17 17:32:38 +01:00
|
|
|
|
2011-06-25 17:53:44 +02:00
|
|
|
import distro_info
|
2011-11-22 15:57:02 +02:00
|
|
|
import httplib2
|
2010-12-17 17:32:38 +01:00
|
|
|
|
2017-03-23 06:43:28 -04:00
|
|
|
from ubuntutools.version import Version
|
2011-05-23 23:41:00 +02:00
|
|
|
|
2018-10-12 18:54:07 -04:00
|
|
|
Logger = logging.getLogger(__name__)
|
|
|
|
|
2017-05-01 00:20:03 +02:00
|
|
|
|
2011-09-10 16:43:41 +02:00
|
|
|
def is_sync(bug):
|
|
|
|
"""Checks if a Launchpad bug is a sync request.
|
|
|
|
|
|
|
|
Either the title contains the word sync or the bug contains the tag sync."""
|
|
|
|
|
|
|
|
return "sync" in bug.title.lower().split(" ") or "sync" in bug.tags
|
|
|
|
|
|
|
|
|
2010-12-17 17:32:38 +01:00
|
|
|
class BugTask(object):
|
|
|
|
def __init__(self, bug_task, launchpad):
|
|
|
|
self.bug_task = bug_task
|
|
|
|
self.launchpad = launchpad
|
|
|
|
|
2018-10-06 18:04:25 +02:00
|
|
|
components = re.split(r" \(| ", self.bug_task.bug_target_name.strip(")"))
|
2010-12-17 17:32:38 +01:00
|
|
|
assert len(components) >= 1 and len(components) <= 3
|
|
|
|
if len(components) == 1:
|
|
|
|
self.package = None
|
|
|
|
self.project = components[0]
|
|
|
|
self.series = None
|
|
|
|
elif len(components) == 2:
|
|
|
|
self.package = components[0]
|
|
|
|
self.project = components[1].lower()
|
|
|
|
self.series = None
|
|
|
|
elif len(components) == 3:
|
|
|
|
self.package = components[0]
|
|
|
|
self.project = components[1].lower()
|
|
|
|
self.series = components[2].lower()
|
|
|
|
|
2012-02-15 15:05:46 +02:00
|
|
|
if self.package is None:
|
2023-01-30 19:45:36 +01:00
|
|
|
title_re = r"^Sync ([a-z0-9+.-]+) [a-z0-9.+:~-]+ \([a-z]+\) from.*"
|
2012-02-15 15:05:46 +02:00
|
|
|
match = re.match(title_re, self.get_bug_title(), re.U | re.I)
|
|
|
|
if match is not None:
|
|
|
|
self.package = match.group(1)
|
|
|
|
|
2010-12-17 17:32:38 +01:00
|
|
|
def download_source(self):
|
|
|
|
source_files = self.get_source().sourceFileUrls()
|
2011-09-10 21:28:28 +02:00
|
|
|
dsc_file = ""
|
2010-12-17 17:32:38 +01:00
|
|
|
for url in source_files:
|
2014-12-18 20:51:24 +00:00
|
|
|
filename = unquote(os.path.basename(url))
|
2023-01-31 11:13:07 +01:00
|
|
|
Logger.debug("Downloading %s...", filename)
|
2011-11-22 15:57:02 +02:00
|
|
|
# HttpLib2 isn't suitable for large files (it reads into memory),
|
|
|
|
# but we want its https certificate validation on the .dsc
|
2010-12-17 17:32:38 +01:00
|
|
|
if url.endswith(".dsc"):
|
2011-11-22 15:57:02 +02:00
|
|
|
response, data = httplib2.Http().request(url)
|
|
|
|
assert response.status == 200
|
2023-01-30 19:45:36 +01:00
|
|
|
with open(filename, "wb") as f:
|
2011-11-22 15:57:02 +02:00
|
|
|
f.write(data)
|
|
|
|
|
2011-09-10 21:28:28 +02:00
|
|
|
dsc_file = os.path.join(os.getcwd(), filename)
|
2011-11-22 15:57:02 +02:00
|
|
|
else:
|
2014-12-18 20:51:24 +00:00
|
|
|
urlretrieve(url, filename)
|
2011-09-10 21:28:28 +02:00
|
|
|
assert os.path.isfile(dsc_file), "%s does not exist." % (dsc_file)
|
|
|
|
return dsc_file
|
2010-12-17 17:32:38 +01:00
|
|
|
|
|
|
|
def get_branch_link(self):
|
2023-01-30 19:45:36 +01:00
|
|
|
return "lp:" + self.project + "/" + self.get_series() + "/" + self.package
|
2010-12-17 17:32:38 +01:00
|
|
|
|
2011-09-15 13:37:22 +02:00
|
|
|
def get_bug_title(self):
|
|
|
|
"""Returns the title of the related bug."""
|
|
|
|
return self.bug_task.bug.title
|
|
|
|
|
2010-12-17 17:32:38 +01:00
|
|
|
def get_long_info(self):
|
2023-01-30 19:45:36 +01:00
|
|
|
return (
|
|
|
|
"Bug task: "
|
|
|
|
+ str(self.bug_task)
|
|
|
|
+ "\n"
|
|
|
|
+ "Package: "
|
|
|
|
+ str(self.package)
|
|
|
|
+ "\n"
|
|
|
|
+ "Project: "
|
|
|
|
+ str(self.project)
|
|
|
|
+ "\n"
|
|
|
|
+ "Series: "
|
|
|
|
+ str(self.series)
|
|
|
|
)
|
2010-12-17 17:32:38 +01:00
|
|
|
|
2011-09-15 13:08:06 +02:00
|
|
|
def get_lp_task(self):
|
|
|
|
"""Returns the Launchpad bug task object."""
|
|
|
|
return self.bug_task
|
|
|
|
|
2010-12-17 17:32:38 +01:00
|
|
|
def get_package_and_series(self):
|
|
|
|
result = self.package
|
|
|
|
if self.series:
|
|
|
|
result += " (" + self.series + ")"
|
|
|
|
return result
|
|
|
|
|
|
|
|
def get_previous_version(self):
|
2011-09-10 16:43:41 +02:00
|
|
|
if self.is_derived_from_debian():
|
2010-12-17 17:32:38 +01:00
|
|
|
previous_version = self.get_latest_released_version()
|
|
|
|
else:
|
|
|
|
previous_version = self.get_version()
|
|
|
|
return previous_version
|
|
|
|
|
|
|
|
def get_series(self, latest_release=False):
|
|
|
|
if self.series is None or latest_release:
|
|
|
|
dist = self.launchpad.distributions[self.project]
|
|
|
|
return dist.current_series.name
|
|
|
|
else:
|
|
|
|
return self.series
|
|
|
|
|
|
|
|
def get_short_info(self):
|
|
|
|
return self.bug_task.bug_target_name + ": " + self.bug_task.status
|
|
|
|
|
|
|
|
def get_source(self, latest_release=False):
|
|
|
|
assert self.package is not None
|
|
|
|
|
2011-09-10 16:43:41 +02:00
|
|
|
if self.is_derived_from_debian() and not latest_release:
|
2010-12-17 17:32:38 +01:00
|
|
|
project = "debian"
|
2012-02-15 15:16:30 +02:00
|
|
|
series = self.get_debian_source_series()
|
2010-12-17 17:32:38 +01:00
|
|
|
else:
|
|
|
|
project = self.project
|
|
|
|
series = self.get_series(latest_release)
|
|
|
|
|
|
|
|
dist = self.launchpad.distributions[project]
|
|
|
|
archive = dist.getArchive(name="primary")
|
|
|
|
distro_series = dist.getSeries(name_or_version=series)
|
2023-01-30 19:45:36 +01:00
|
|
|
published = archive.getPublishedSources(
|
|
|
|
source_name=self.package,
|
|
|
|
distro_series=distro_series,
|
|
|
|
status="Published",
|
|
|
|
exact_match=True,
|
|
|
|
)
|
2010-12-17 17:32:38 +01:00
|
|
|
|
|
|
|
latest_source = None
|
|
|
|
for source in published:
|
2023-01-30 19:45:36 +01:00
|
|
|
if source.pocket in ("Release", "Security", "Updates", "Proposed"):
|
2010-12-17 17:32:38 +01:00
|
|
|
latest_source = source
|
|
|
|
break
|
|
|
|
return latest_source
|
|
|
|
|
|
|
|
def get_version(self):
|
|
|
|
source_package_version = self.get_source().source_package_version
|
2017-03-23 06:43:28 -04:00
|
|
|
return Version(source_package_version)
|
2010-12-17 17:32:38 +01:00
|
|
|
|
|
|
|
def get_latest_released_version(self):
|
2012-02-15 15:05:46 +02:00
|
|
|
source = self.get_source(True)
|
|
|
|
if source is None: # Not currently published in Ubuntu
|
2023-01-30 19:45:36 +01:00
|
|
|
version = "~"
|
2012-02-15 15:05:46 +02:00
|
|
|
else:
|
|
|
|
version = source.source_package_version
|
2017-03-23 06:43:28 -04:00
|
|
|
return Version(version)
|
2010-12-17 17:32:38 +01:00
|
|
|
|
2012-02-15 15:16:30 +02:00
|
|
|
def get_debian_source_series(self):
|
|
|
|
title = self.bug_task.bug.title.lower().split()
|
|
|
|
if "experimental" in title:
|
|
|
|
series = "experimental"
|
|
|
|
elif "testing" in title:
|
|
|
|
series = distro_info.DebianDistroInfo().testing()
|
|
|
|
else:
|
|
|
|
series = distro_info.DebianDistroInfo().devel()
|
|
|
|
return series
|
|
|
|
|
2010-12-17 17:32:38 +01:00
|
|
|
def is_complete(self):
|
|
|
|
return self.bug_task.is_complete
|
|
|
|
|
2011-09-10 16:43:41 +02:00
|
|
|
def is_derived_from_debian(self):
|
|
|
|
"""Checks if this task get's the source from Debian."""
|
|
|
|
return self.is_merge() or self.is_sync()
|
|
|
|
|
2010-12-17 17:32:38 +01:00
|
|
|
def is_merge(self):
|
|
|
|
bug = self.bug_task.bug
|
|
|
|
return "merge" in bug.title.lower().split(" ") or "merge" in bug.tags
|
|
|
|
|
2011-09-10 16:43:41 +02:00
|
|
|
def is_sync(self):
|
|
|
|
return is_sync(self.bug_task.bug)
|
|
|
|
|
2010-12-17 17:32:38 +01:00
|
|
|
def is_ubuntu_task(self):
|
|
|
|
return self.project == "ubuntu"
|
2011-09-15 13:37:22 +02:00
|
|
|
|
|
|
|
def title_contains(self, word):
|
|
|
|
"""Checks if the bug title contains the given word."""
|
|
|
|
return word in self.bug_task.bug.title.split(" ")
|