forked from adamm/git-importer
2784171f75
This is a rather complex operation, but whenever a package changes in Factory, the inherited package gets a shadow revision consisting of the 3-way merge. If this happens due to a request being accepted, this is actually in most cases also commited by 'buildservice-autocommit', so we're making sure this is always happening (and are actually duplicating revisions in cases that we filter out later as empty commits). To differenciate the fake revisions from the real revisions, I add a fraction part
118 lines
3.6 KiB
Python
118 lines
3.6 KiB
Python
import datetime
|
|
import logging
|
|
import re
|
|
import xml.etree.ElementTree as ET
|
|
from urllib.error import HTTPError
|
|
|
|
|
|
class OBSRevision:
|
|
def __init__(self, obs, history, project, package):
|
|
self.obs = obs
|
|
self.history = history
|
|
self.project = project
|
|
self.package = package
|
|
|
|
self.commit = None
|
|
self.ignored = False
|
|
|
|
def parse(self, xml):
|
|
self.rev = int(xml.get("rev"))
|
|
self.unexpanded_srcmd5 = xml.find("srcmd5").text
|
|
# Replaced in check_expanded
|
|
self.srcmd5 = self.unexpanded_srcmd5
|
|
|
|
time = int(xml.find("time").text)
|
|
self.time = datetime.datetime.fromtimestamp(time)
|
|
|
|
userid = xml.find("user")
|
|
if userid is not None:
|
|
self.userid = userid.text
|
|
else:
|
|
self.userid = "unknown"
|
|
|
|
comment = xml.find("comment")
|
|
if comment is not None:
|
|
self.comment = comment.text or ""
|
|
else:
|
|
self.comment = ""
|
|
|
|
# Populated by check_link
|
|
self.linkrev = None
|
|
|
|
self.request_number = None
|
|
request_number = xml.find("requestid")
|
|
if request_number is not None:
|
|
self.request_number = int(request_number.text)
|
|
else:
|
|
# Sometimes requestid is missing, but can be extracted
|
|
# from "comment"
|
|
matched = re.match(
|
|
r"^Copy from .* based on submit request (\d+) from user .*$",
|
|
self.comment,
|
|
)
|
|
if matched:
|
|
self.request_number = int(matched.group(1))
|
|
|
|
return self
|
|
|
|
def __str__(self):
|
|
return f"Rev {self.project}/{self.package}/{self.rev}.0 Md5 {self.srcmd5} {self.time} {self.userid} {self.request_number}"
|
|
|
|
def __repr__(self):
|
|
return f"[{self.__str__()}]"
|
|
|
|
def read_link(self):
|
|
try:
|
|
return self.obs._xml(
|
|
f"source/{self.project}/{self.package}/_link",
|
|
rev=self.unexpanded_srcmd5,
|
|
)
|
|
except HTTPError as e:
|
|
if e.code == 404:
|
|
logging.debug("No _link for the revision")
|
|
return None
|
|
raise e
|
|
|
|
def check_link(self):
|
|
"""Add 'linkrev' attribute into the revision. Returns False if the link is invalid"""
|
|
try:
|
|
root = self.read_link()
|
|
if root is None:
|
|
return True
|
|
target_project = root.get("project")
|
|
except ET.ParseError:
|
|
logging.error(
|
|
f"_link can't be parsed [{self.project}/{self.package} rev={self.unexpanded_srcmd5}]"
|
|
)
|
|
return False
|
|
|
|
rev = self.history.find_last_rev_after_time(target_project, self.time)
|
|
if rev:
|
|
logging.debug(f"Linkrev found: {rev}")
|
|
self.linkrev = rev.srcmd5
|
|
return True
|
|
|
|
def check_expanded(self):
|
|
# Even if it's not a link we still need to check the expanded
|
|
# srcmd5 as it's possible used in submit requests
|
|
if not self.check_link():
|
|
return False
|
|
|
|
# If there is a "linkrev", "rev" is ignored
|
|
params = {"rev": self.srcmd5, "expand": "1"}
|
|
if self.linkrev:
|
|
params["linkrev"] = self.linkrev
|
|
|
|
try:
|
|
root = self.obs._xml(f"source/{self.project}/{self.package}", **params)
|
|
except HTTPError as e:
|
|
if e.code == 400:
|
|
logging.error(
|
|
f"Package [{self.project}/{self.package} {params}] can't be expanded: {e}"
|
|
)
|
|
return False
|
|
raise e
|
|
|
|
self.srcmd5 = root.get("srcmd5")
|
|
return True
|