Merge pull request 'Export the built tree as git repo' (#9) from add_export into main
Reviewed-on: https://gitea.opensuse.org/importers/git-importer/pulls/9
This commit is contained in:
commit
6ac0f90ec7
@ -3,20 +3,20 @@
|
||||
import argparse
|
||||
import logging
|
||||
import pathlib
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
import osc.core
|
||||
|
||||
from lib.exporter import Exporter
|
||||
from lib.git_exporter import GitExporter
|
||||
from lib.importer import Importer
|
||||
from lib.test_exporter import TestExporter
|
||||
|
||||
URL_OBS = "https://api.opensuse.org"
|
||||
URL_IBS = "https://api.suse.de"
|
||||
|
||||
# The order is relevant (from older to newer initial codebase)
|
||||
# TODO: make something with these, for now we look purely at openSUSE:Factory
|
||||
PROJECTS = [
|
||||
("openSUSE:Factory", "factory", URL_OBS),
|
||||
# ("SUSE:SLE-12:GA", "SLE_12", URL_IBS),
|
||||
# ("SUSE:SLE-12:Update", "SLE_12", URL_IBS),
|
||||
# ("SUSE:SLE-12-SP1:GA", "SLE_12_SP1", URL_IBS),
|
||||
@ -52,24 +52,6 @@ def main():
|
||||
type=pathlib.Path,
|
||||
help="Local git repository directory",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-f",
|
||||
"--force",
|
||||
action="store_true",
|
||||
help="If the repository directory exists, remove it",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-a",
|
||||
"--search-ancestor",
|
||||
action="store_true",
|
||||
help="Search closest ancestor candidate for initial commit",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-d",
|
||||
"--rebase-devel",
|
||||
action="store_true",
|
||||
help="The devel project with be rebased after a merge",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-g",
|
||||
"--gc",
|
||||
@ -84,15 +66,10 @@ def main():
|
||||
default="INFO",
|
||||
help="logging level",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--db",
|
||||
action="store_true",
|
||||
help="Import revisions into database only",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--export",
|
||||
action="store_true",
|
||||
help="Export database fields for the given package as JSON",
|
||||
help="Export database fields for the given package as YAML",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
@ -110,28 +87,17 @@ def main():
|
||||
requests_log.propagate = True
|
||||
|
||||
if args.export:
|
||||
Exporter(args.package).run()
|
||||
TestExporter(args.package).run()
|
||||
return
|
||||
|
||||
if not args.repodir:
|
||||
args.repodir = pathlib.Path(args.package)
|
||||
args.repodir = pathlib.Path("repos/" + args.package)
|
||||
|
||||
if args.repodir.exists() and not args.force:
|
||||
print(f"Repository {args.repodir} already present")
|
||||
sys.exit(-1)
|
||||
elif args.repodir.exists() and args.force:
|
||||
logging.info(f"Removing old repository {args.repodir}")
|
||||
shutil.rmtree(args.repodir)
|
||||
|
||||
# TODO: use a CLI parameter to describe the projects
|
||||
importer = Importer(
|
||||
PROJECTS, args.package, args.repodir, args.search_ancestor, args.rebase_devel
|
||||
)
|
||||
|
||||
if args.db:
|
||||
importer.import_into_db()
|
||||
return
|
||||
importer.import_all_revisions(args.gc)
|
||||
importer = Importer(URL_OBS, "openSUSE:Factory", args.package)
|
||||
importer.import_into_db()
|
||||
exporter = GitExporter(URL_OBS, "openSUSE:Factory", args.package, args.repodir)
|
||||
exporter.set_gc_interval(args.gc)
|
||||
exporter.export_as_git()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
6
lib/abstract_walker.py
Normal file
6
lib/abstract_walker.py
Normal file
@ -0,0 +1,6 @@
|
||||
class AbstractWalker:
|
||||
"""Just a duck type, most likely not needed by python, but I
|
||||
find interface classes preferable (java school)"""
|
||||
|
||||
def call(self, node, is_source):
|
||||
pass
|
@ -1,5 +1,10 @@
|
||||
from hashlib import md5
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from hashlib import md5
|
||||
from typing import Optional
|
||||
|
||||
from lib.db import DB
|
||||
from lib.request import Request
|
||||
|
||||
|
||||
@ -25,7 +30,7 @@ class DBRevision:
|
||||
self._files = None
|
||||
|
||||
def short_string(self):
|
||||
return f"Rev {self.project}/{self.package}/{self.rev}"
|
||||
return f"{self.project}/{self.package}/{self.rev}"
|
||||
|
||||
def __str__(self):
|
||||
return f"Rev {self.project}/{self.package}/{self.rev} Md5 {self.unexpanded_srcmd5} {self.commit_time} {self.userid} {self.request_number}"
|
||||
@ -202,6 +207,29 @@ class DBRevision:
|
||||
self._files.sort(key=lambda x: x["name"])
|
||||
return self._files
|
||||
|
||||
def calc_delta(self, db: DB, current_rev: Optional[DBRevision]):
|
||||
"""Calculate the list of files to download and to delete.
|
||||
Param current_rev is the revision that's currently checked out.
|
||||
If it's None, the repository is empty.
|
||||
"""
|
||||
to_download = []
|
||||
to_delete = []
|
||||
if current_rev:
|
||||
old_files = {
|
||||
e["name"]: f"{e['md5']}-{e['size']}" for e in current_rev.files_list(db)
|
||||
}
|
||||
else:
|
||||
old_files = dict()
|
||||
for entry in self.files_list(db):
|
||||
if old_files.get(entry["name"]) != f"{entry['md5']}-{entry['size']}":
|
||||
logging.debug(f"Download {entry['name']}")
|
||||
to_download.append((entry["name"], entry["md5"]))
|
||||
old_files.pop(entry["name"], None)
|
||||
for entry in old_files.keys():
|
||||
logging.debug(f"Delete {entry}")
|
||||
to_delete.append(entry)
|
||||
return to_download, to_delete
|
||||
|
||||
@staticmethod
|
||||
def requests_to_fetch(db):
|
||||
with db.cursor() as cur:
|
||||
|
57
lib/flat_walker.py
Normal file
57
lib/flat_walker.py
Normal file
@ -0,0 +1,57 @@
|
||||
from lib.abstract_walker import AbstractWalker
|
||||
|
||||
|
||||
class FlatNode:
|
||||
def __init__(self, branch, commit, parent1=None, parent2=None) -> None:
|
||||
self.branch = branch
|
||||
self.commit = commit
|
||||
self.parent1 = parent1
|
||||
self.parent2 = parent2
|
||||
|
||||
def __str__(self) -> str:
|
||||
p1_str = ""
|
||||
if self.parent1:
|
||||
p1_str = f" p1:{self.parent1.short_string()}"
|
||||
p2_str = ""
|
||||
if self.parent2:
|
||||
p2_str = f" p2:{self.parent2.short_string()}"
|
||||
return f"{self.branch} c:{self.commit.short_string()}{p1_str}{p2_str}"
|
||||
|
||||
|
||||
class FlatTreeWalker(AbstractWalker):
|
||||
"""While walking the tree, record the commits to do one after the other. These
|
||||
FlatNodes are in the end in the flats array."""
|
||||
|
||||
def __init__(self, rebase_devel=False) -> None:
|
||||
super().__init__()
|
||||
self.flats = []
|
||||
# the rebase_devel won't work as such as rebasing the branch needs an explicit action
|
||||
self.rebase_devel = rebase_devel
|
||||
# remember the last merge point so we can know the parent of it for the root of the sources
|
||||
self.last_merge = None
|
||||
|
||||
def add(self, branch, commit, parent1=None, parent2=None):
|
||||
self.flats.append(FlatNode(branch, commit, parent1, parent2))
|
||||
|
||||
def handle_source_node(self, node) -> None:
|
||||
if self.rebase_devel and node.parent and node.parent.merged_into:
|
||||
self.add("devel", node.revision, node.parent.merged_into.revision)
|
||||
return
|
||||
if node.parent:
|
||||
self.add("devel", node.revision, node.parent.revision)
|
||||
elif self.last_merge:
|
||||
self.add("devel", node.revision, self.last_merge.parent.revision)
|
||||
|
||||
def call(self, node, is_source) -> None:
|
||||
if is_source:
|
||||
self.handle_source_node(node)
|
||||
return
|
||||
if not node.parent:
|
||||
self.add("factory", node.revision)
|
||||
return
|
||||
if not node.merged:
|
||||
self.add("factory", node.revision, node.parent.revision)
|
||||
return
|
||||
self.add("factory", node.revision, node.parent.revision, node.merged.revision)
|
||||
|
||||
self.last_merge = node
|
@ -181,8 +181,11 @@ class Git:
|
||||
except:
|
||||
return None
|
||||
|
||||
def branch_head(self, branch):
|
||||
return self.repo.references["refs/heads/" + branch].target
|
||||
|
||||
def gc(self):
|
||||
logging.info(f"Garbage recollec and repackage {self.path}")
|
||||
logging.info(f"Garbage recollect and repackage {self.path}")
|
||||
subprocess.run(
|
||||
["git", "gc", "--auto"],
|
||||
cwd=self.path,
|
||||
|
171
lib/git_exporter.py
Normal file
171
lib/git_exporter.py
Normal file
@ -0,0 +1,171 @@
|
||||
import logging
|
||||
import os
|
||||
|
||||
import yaml
|
||||
|
||||
from lib.binary import is_binary_or_large
|
||||
from lib.db import DB
|
||||
from lib.git import Git
|
||||
from lib.obs import OBS
|
||||
from lib.proxy_sha256 import ProxySHA256, md5
|
||||
from lib.tree_builder import TreeBuilder
|
||||
|
||||
|
||||
class GitExporter:
|
||||
def __init__(self, api_url, project, package, repodir):
|
||||
self.obs = OBS()
|
||||
self.project = project
|
||||
self.package = package
|
||||
# TODO: Store the api url in the revision
|
||||
self.obs.change_url(api_url)
|
||||
self.proxy_sha256 = ProxySHA256(self.obs, enabled=True)
|
||||
self.git = Git(
|
||||
repodir,
|
||||
committer="Git OBS Bridge",
|
||||
committer_email="obsbridge@suse.de",
|
||||
).create()
|
||||
self.state_file = os.path.join(self.git.path, ".git", "_flat_state.yaml")
|
||||
self.gc_interval = 200
|
||||
|
||||
def download(self, revision):
|
||||
obs_files = self.obs.files(revision.project, revision.package, revision.srcmd5)
|
||||
git_files = {
|
||||
(f.name, f.stat().st_size, md5(f))
|
||||
for f in self.git.path.iterdir()
|
||||
if f.is_file() and f.name not in (".gitattributes")
|
||||
}
|
||||
|
||||
# Overwrite ".gitattributes" with the
|
||||
self.git.add_default_lfs_gitattributes(force=True)
|
||||
|
||||
# Download each file in OBS if it is not a binary (or large)
|
||||
# file
|
||||
for (name, size, file_md5) in obs_files:
|
||||
# this file creates easily 100k commits and is just useless data :(
|
||||
# unfortunately it's stored in the same meta package as the project config
|
||||
if revision.package == "_project" and name == "_staging_workflow":
|
||||
continue
|
||||
# have such files been detected as text mimetype before?
|
||||
is_text = self.proxy_sha256.is_text(name)
|
||||
if not is_text and is_binary_or_large(name, size):
|
||||
file_sha256 = self.proxy_sha256.get_or_put(
|
||||
revision.project,
|
||||
revision.package,
|
||||
name,
|
||||
revision.srcmd5,
|
||||
file_md5,
|
||||
size,
|
||||
)
|
||||
self.git.add_lfs(name, file_sha256["sha256"], size)
|
||||
else:
|
||||
if (name, size, file_md5) not in git_files:
|
||||
logging.debug(f"Download {name}")
|
||||
self.obs.download(
|
||||
revision.project,
|
||||
revision.package,
|
||||
name,
|
||||
revision.srcmd5,
|
||||
self.git.path,
|
||||
file_md5=file_md5,
|
||||
)
|
||||
# Validate the MD5 of the downloaded file
|
||||
if md5(self.git.path / name) != file_md5:
|
||||
raise Exception(f"Download error in {name}")
|
||||
self.git.add(name)
|
||||
|
||||
# Remove extra files
|
||||
obs_names = {n for (n, _, _) in obs_files}
|
||||
git_names = {n for (n, _, _) in git_files}
|
||||
for name in git_names - obs_names:
|
||||
logging.debug(f"Remove {name}")
|
||||
self.git.remove(name)
|
||||
|
||||
def set_gc_interval(self, gc):
|
||||
self.gc_interval = gc
|
||||
|
||||
def export_as_git(self):
|
||||
db = DB()
|
||||
tree = TreeBuilder(db).build(self.project, self.package)
|
||||
flats = tree.as_flat_list()
|
||||
|
||||
branch_state = {"factory": None, "devel": None}
|
||||
state_data = dict()
|
||||
if os.path.exists(self.state_file):
|
||||
with open(self.state_file, "r") as f:
|
||||
state_data = yaml.safe_load(f)
|
||||
if type(state_data) != dict:
|
||||
state_data = {}
|
||||
left_to_commit = []
|
||||
for flat in reversed(flats):
|
||||
found_state = False
|
||||
for branch in ["factory", "devel"]:
|
||||
if flat.commit.dbid == state_data.get(branch):
|
||||
branch_state[branch] = flat.commit
|
||||
flat.commit.git_commit = self.git.branch_head(branch)
|
||||
logging.debug(
|
||||
f"Found {self.git.path}'s {branch} branch in state {flat}"
|
||||
)
|
||||
left_to_commit = []
|
||||
found_state = True
|
||||
if not found_state:
|
||||
left_to_commit.append(flat)
|
||||
|
||||
gc_cnt = self.gc_interval
|
||||
if len(left_to_commit) > 0:
|
||||
self.git.gc()
|
||||
for flat in left_to_commit:
|
||||
gc_cnt -= 1
|
||||
if gc_cnt <= 0 and self.gc_interval:
|
||||
self.git.gc()
|
||||
gc_cnt = self.gc_interval
|
||||
logging.debug(f"Committing {flat}")
|
||||
self.commit_flat(db, flat, branch_state)
|
||||
|
||||
def limit_download(self, file):
|
||||
if file.endswith(".spec") or file.endswith(".changes"):
|
||||
return True
|
||||
return False
|
||||
|
||||
def commit_flat(self, db, flat, branch_state):
|
||||
parents = []
|
||||
self.git.checkout(flat.branch)
|
||||
if flat.parent1:
|
||||
parents.append(flat.parent1.git_commit)
|
||||
if flat.parent2:
|
||||
parents.append(flat.parent2.git_commit)
|
||||
to_download, to_delete = flat.commit.calc_delta(db, branch_state[flat.branch])
|
||||
for file in to_delete:
|
||||
if not self.limit_download(file):
|
||||
continue
|
||||
self.git.remove(file)
|
||||
for file, md5 in to_download:
|
||||
if not self.limit_download(file):
|
||||
continue
|
||||
self.obs.download(
|
||||
flat.commit.project,
|
||||
flat.commit.package,
|
||||
file,
|
||||
flat.commit.expanded_srcmd5,
|
||||
self.git.path,
|
||||
file_md5=md5,
|
||||
)
|
||||
self.git.add(file)
|
||||
|
||||
commit = self.git.commit(
|
||||
f"OBS User {flat.commit.userid}",
|
||||
"null@suse.de",
|
||||
flat.commit.commit_time,
|
||||
# TODO: Normalize better the commit message
|
||||
f"{flat.commit.comment}\n\n{flat.commit}",
|
||||
allow_empty=True,
|
||||
parents=parents,
|
||||
)
|
||||
flat.commit.git_commit = commit
|
||||
branch_state[flat.branch] = flat.commit
|
||||
with open(self.state_file, "w") as f:
|
||||
data = {}
|
||||
for branch in ["factory", "devel"]:
|
||||
commit = branch_state[branch]
|
||||
if commit:
|
||||
data[branch] = commit.dbid
|
||||
yaml.dump(data, f)
|
106
lib/history.py
106
lib/history.py
@ -1,106 +0,0 @@
|
||||
import itertools
|
||||
import logging
|
||||
import re
|
||||
|
||||
from lib.obs_revision import OBSRevision
|
||||
|
||||
|
||||
class History:
|
||||
"""Store the history of revisions of a package in different
|
||||
projects.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, obs, package):
|
||||
self.obs = obs
|
||||
self.package = package
|
||||
|
||||
self.revisions = {}
|
||||
|
||||
def __contains__(self, project):
|
||||
return project in self.revisions
|
||||
|
||||
def __getitem__(self, project):
|
||||
return self.revisions[project]
|
||||
|
||||
def _extract_copypac(self, comment):
|
||||
original_project = re.findall(
|
||||
r"osc copypac from project:(.*) package:", comment
|
||||
)
|
||||
return original_project[0] if original_project else None
|
||||
|
||||
def _fetch_revisions(self, project, **params):
|
||||
root = self.obs._history(project, self.package, **params)
|
||||
if root is not None:
|
||||
return [
|
||||
OBSRevision(self.obs, self, project, self.package).parse(r)
|
||||
for r in root.findall("revision")
|
||||
]
|
||||
|
||||
def fetch_revisions(self, project, follow_copypac=False):
|
||||
"""Get the revision history of a package"""
|
||||
if project in self:
|
||||
return
|
||||
|
||||
revs = self._fetch_revisions(project)
|
||||
self.revisions[project] = revs
|
||||
# while (
|
||||
# revs
|
||||
# and follow_copypac
|
||||
# and (copypac_project := self._extract_copypac(revs[0].comment))
|
||||
# ):
|
||||
# # Add the history pre-copypac
|
||||
# # TODO: missing the old project name
|
||||
# revs = self._fetch_revisions(copypac_project, deleted=1)
|
||||
# self.revisions[project] = (
|
||||
# revs + self.revisions[project]
|
||||
# )
|
||||
|
||||
def fetch_all_revisions(self, projects):
|
||||
"""Pre-populate the history"""
|
||||
for project, _, api_url in projects:
|
||||
self.obs.change_url(api_url)
|
||||
self.fetch_revisions(project)
|
||||
|
||||
def sort_all_revisions(self):
|
||||
"""Sort revisions for all projects, from older to newer"""
|
||||
return sorted(itertools.chain(*self.revisions.values()), key=lambda x: x.time)
|
||||
|
||||
def find_revision(self, project, revisionid, accepted_at):
|
||||
last_commited_revision = None
|
||||
for r in self.revisions.get(project, []):
|
||||
logging.debug(f"Find revision {revisionid} [{accepted_at}]: {r}")
|
||||
if str(r.rev) == str(revisionid) or r.srcmd5 == revisionid:
|
||||
if r.ignored:
|
||||
logging.debug(
|
||||
f"{r} fits but is ignored, returning {last_commited_revision}"
|
||||
)
|
||||
return last_commited_revision
|
||||
else:
|
||||
logging.debug(f"{r} fits")
|
||||
return r
|
||||
if r.time > accepted_at:
|
||||
# if we can't find the right revision, we take the last
|
||||
# commit. Before ~2012 the data was tracked really loosely
|
||||
# (e.g. using different timezones and the state field was
|
||||
# only introduced in 2016...)
|
||||
logging.warning(
|
||||
f"Deploying workaround for missing request revision - returning {last_commited_revision}"
|
||||
)
|
||||
return last_commited_revision
|
||||
if r.commit:
|
||||
last_commited_revision = r
|
||||
logging.info("No commited revision found, returning None")
|
||||
return None
|
||||
|
||||
def find_last_rev_after_time(self, project, time):
|
||||
# revs = self.projects.get(project, [])
|
||||
# return next((r for r in reversed(revs) if r.time <= time), None)
|
||||
prev = None
|
||||
for rev in self.revisions.get(project, []):
|
||||
if rev.time > time:
|
||||
return prev
|
||||
if rev.time == time:
|
||||
return rev
|
||||
prev = rev
|
||||
return prev
|
400
lib/importer.py
400
lib/importer.py
@ -1,132 +1,23 @@
|
||||
import functools
|
||||
import logging
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
import psycopg2
|
||||
|
||||
from lib.binary import is_binary_or_large
|
||||
from lib.db import DB
|
||||
from lib.db_revision import DBRevision
|
||||
from lib.git import Git
|
||||
from lib.history import History
|
||||
from lib.obs import OBS
|
||||
from lib.obs_revision import OBSRevision
|
||||
from lib.proxy_sha256 import ProxySHA256, md5, sha256
|
||||
from lib.tree_builder import TreeBuilder
|
||||
from lib.user import User
|
||||
|
||||
|
||||
def _files_hash(hash_alg, dirpath):
|
||||
"""List of (filepath, md5) for a directory"""
|
||||
# TODO: do it async or multythread
|
||||
files = [f for f in dirpath.iterdir() if f.is_file()]
|
||||
return [(f.parts[-1], hash_alg(f)) for f in files]
|
||||
|
||||
|
||||
files_md5 = functools.partial(_files_hash, md5)
|
||||
files_sha256 = functools.partial(_files_hash, sha256)
|
||||
|
||||
|
||||
class Importer:
|
||||
def __init__(self, projects, package, repodir, search_ancestor, rebase_devel):
|
||||
# The idea is to create each commit in order, and draw the
|
||||
# same graph described by the revisions timeline. For that we
|
||||
# need first to fetch all the revisions and sort them
|
||||
# linearly, based on the timestamp.
|
||||
#
|
||||
# After that we recreate the commits, and if one revision is a
|
||||
# request that contains a target inside the projects in the
|
||||
# "history", we create a merge commit.
|
||||
#
|
||||
# Optionally, if a flag is set, we will try to find a common
|
||||
# "Initial commit" from a reference branch (the first one in
|
||||
# "projects", that is safe to assume to be "openSUSE:Factory".
|
||||
# This is not always a good idea. For example, in a normal
|
||||
# situation the "devel" project history is older than
|
||||
# "factory", and we can root the tree on it. But for some
|
||||
# other projects we lost partially the "devel" history project
|
||||
# (could be moved), and "factory" is not the root.
|
||||
|
||||
def __init__(self, api_url, project, package):
|
||||
# Import a Factory package into the database
|
||||
self.package = package
|
||||
self.search_ancestor = search_ancestor
|
||||
self.rebase_devel = rebase_devel
|
||||
self.project = project
|
||||
|
||||
self.obs = OBS()
|
||||
self.git = Git(
|
||||
repodir,
|
||||
committer="Git OBS Bridge",
|
||||
committer_email="obsbridge@suse.de",
|
||||
).create()
|
||||
self.proxy_sha256 = ProxySHA256(self.obs, enabled=True)
|
||||
|
||||
self.history = History(self.obs, self.package)
|
||||
|
||||
# Add the "devel" project
|
||||
(project, branch, api_url) = projects[0]
|
||||
assert project == "openSUSE:Factory"
|
||||
self.obs.change_url(api_url)
|
||||
devel_project = self.obs.devel_project(project, package)
|
||||
if devel_project:
|
||||
self.projects = [(devel_project, "devel", api_url)] + projects
|
||||
else:
|
||||
self.projects = projects
|
||||
|
||||
# Associate the branch and api_url information per project
|
||||
self.projects_info = {
|
||||
project: (branch, api_url) for (project, branch, api_url) in self.projects
|
||||
}
|
||||
|
||||
def download(self, revision):
|
||||
obs_files = self.obs.files(revision.project, revision.package, revision.srcmd5)
|
||||
git_files = {
|
||||
(f.name, f.stat().st_size, md5(f))
|
||||
for f in self.git.path.iterdir()
|
||||
if f.is_file() and f.name not in (".gitattributes")
|
||||
}
|
||||
|
||||
# Overwrite ".gitattributes" with the
|
||||
self.git.add_default_lfs_gitattributes(force=True)
|
||||
|
||||
# Download each file in OBS if it is not a binary (or large)
|
||||
# file
|
||||
for (name, size, file_md5) in obs_files:
|
||||
# this file creates easily 100k commits and is just useless data :(
|
||||
# unfortunately it's stored in the same meta package as the project config
|
||||
if revision.package == "_project" and name == "_staging_workflow":
|
||||
continue
|
||||
# have such files been detected as text mimetype before?
|
||||
is_text = self.proxy_sha256.is_text(name)
|
||||
if not is_text and is_binary_or_large(name, size):
|
||||
file_sha256 = self.proxy_sha256.get_or_put(
|
||||
revision.project,
|
||||
revision.package,
|
||||
name,
|
||||
revision.srcmd5,
|
||||
file_md5,
|
||||
size,
|
||||
)
|
||||
self.git.add_lfs(name, file_sha256["sha256"], size)
|
||||
else:
|
||||
if (name, size, file_md5) not in git_files:
|
||||
print(f"Download {name}")
|
||||
self.obs.download(
|
||||
revision.project,
|
||||
revision.package,
|
||||
name,
|
||||
revision.srcmd5,
|
||||
self.git.path,
|
||||
)
|
||||
# Validate the MD5 of the downloaded file
|
||||
if md5(self.git.path / name) != file_md5:
|
||||
raise Exception(f"Download error in {name}")
|
||||
self.git.add(name)
|
||||
|
||||
# Remove extra files
|
||||
obs_names = {n for (n, _, _) in obs_files}
|
||||
git_names = {n for (n, _, _) in git_files}
|
||||
for name in git_names - obs_names:
|
||||
print(f"Remove {name}")
|
||||
self.git.remove(name)
|
||||
self.refreshed_packages = set()
|
||||
|
||||
def update_db_package(self, db, project, package):
|
||||
root = self.obs._history(project, package)
|
||||
@ -134,7 +25,7 @@ class Importer:
|
||||
return
|
||||
latest = DBRevision.latest_revision(db, project, package)
|
||||
for r in root.findall("revision"):
|
||||
rev = OBSRevision(self.obs, self, project, package).parse(r)
|
||||
rev = OBSRevision(self.obs, project, package).parse(r)
|
||||
if not latest or rev.rev > latest.rev:
|
||||
dbrev = DBRevision.import_obs_rev(db, rev)
|
||||
try:
|
||||
@ -175,7 +66,8 @@ class Importer:
|
||||
)
|
||||
for row in cur.fetchall():
|
||||
(lproject, lpackage) = row
|
||||
self.update_db_package(db, lproject, lpackage)
|
||||
# recurse
|
||||
self.refresh_package(db, lproject, lpackage)
|
||||
|
||||
def find_fake_revisions(self, db):
|
||||
with db.cursor() as cur:
|
||||
@ -259,20 +151,8 @@ class Importer:
|
||||
)
|
||||
return [DBRevision(row) for row in cur.fetchall()]
|
||||
|
||||
def import_into_db(self):
|
||||
db = DB()
|
||||
for project, _, api_url in self.projects:
|
||||
self.obs.change_url(api_url)
|
||||
self.update_db_package(db, project, self.package)
|
||||
self.fetch_all_linked_packages(db, project, self.package)
|
||||
# all remaining, no filtering here
|
||||
self.find_linked_revs(db)
|
||||
|
||||
missing_users = User.missing_users(db)
|
||||
for userid in missing_users:
|
||||
missing_user = self.obs.user(userid)
|
||||
if missing_user:
|
||||
missing_user.import_into_db(db)
|
||||
def fill_file_lists(self, db):
|
||||
self.find_linked_revs(db)
|
||||
|
||||
self.find_fake_revisions(db)
|
||||
for rev in self.revisions_without_files(db):
|
||||
@ -299,241 +179,35 @@ class Importer:
|
||||
else:
|
||||
rev.set_broken(db)
|
||||
|
||||
def refresh_package(self, db, project, package):
|
||||
key = f"{project}/{package}"
|
||||
if key in self.refreshed_packages:
|
||||
# refreshing once is good enough
|
||||
return
|
||||
self.refreshed_packages.add(key)
|
||||
self.update_db_package(db, project, package)
|
||||
self.fetch_all_linked_packages(db, project, package)
|
||||
|
||||
def import_into_db(self):
|
||||
db = DB()
|
||||
|
||||
self.refresh_package(db, self.project, self.package)
|
||||
for number in DBRevision.requests_to_fetch(db):
|
||||
self.obs.request(number).import_into_db(db)
|
||||
with db.cursor() as cur:
|
||||
cur.execute(
|
||||
"""SELECT DISTINCT source_project,source_package FROM requests
|
||||
WHERE id IN (SELECT request_id FROM revisions WHERE project=%s and package=%s);""",
|
||||
(self.project, self.package),
|
||||
)
|
||||
for project, package in cur.fetchall():
|
||||
self.refresh_package(db, project, package)
|
||||
|
||||
missing_users = User.missing_users(db)
|
||||
for userid in missing_users:
|
||||
missing_user = self.obs.user(userid)
|
||||
if missing_user:
|
||||
missing_user.import_into_db(db)
|
||||
|
||||
self.fill_file_lists(db)
|
||||
db.conn.commit()
|
||||
TreeBuilder(db).build(self.package).print()
|
||||
|
||||
def import_all_revisions(self, gc):
|
||||
# Fetch all the requests and sort them. Ideally we should
|
||||
# build the graph here, to avoid new commits before the merge.
|
||||
# For now we will sort them and invalidate the commits if
|
||||
# "rebase_devel" is set.
|
||||
self.history.fetch_all_revisions(self.projects)
|
||||
revisions = self.history.sort_all_revisions()
|
||||
|
||||
logging.debug(f"Selected import order for {self.package}")
|
||||
for revision in revisions:
|
||||
logging.debug(revision)
|
||||
|
||||
gc_cnt = gc
|
||||
for revision in revisions:
|
||||
gc_cnt -= 1
|
||||
if gc_cnt <= 0 and gc:
|
||||
self.git.gc()
|
||||
gc_cnt = gc
|
||||
self.import_revision(revision)
|
||||
|
||||
def import_new_revision_with_request(self, revision, request):
|
||||
"""Create a new branch as a result of a merge"""
|
||||
|
||||
submitted_revision = self.history.find_revision(
|
||||
request.source, request.revisionid, revision.time
|
||||
)
|
||||
if not submitted_revision:
|
||||
logging.warning(f"Request {request} does not connect to a known revision")
|
||||
return False
|
||||
|
||||
if not submitted_revision.commit:
|
||||
# If the revision appointed by the request is not part of
|
||||
# the git history, we can have an ordering problem. One
|
||||
# example is "premake4".
|
||||
self.import_revision(submitted_revision)
|
||||
|
||||
assert submitted_revision.commit is not None
|
||||
|
||||
project = revision.project
|
||||
branch, _ = self.projects_info[project]
|
||||
|
||||
# TODO: add an empty commit marking the acceptenace of the request (see discussion in PR 2858)
|
||||
self.git.branch(branch, submitted_revision.commit)
|
||||
self.git.clean()
|
||||
self.git.checkout(branch)
|
||||
|
||||
logging.info(f"Create new branch based on {submitted_revision.commit}")
|
||||
revision.commit = submitted_revision.commit
|
||||
|
||||
def _rebase_branch_history(self, project, revision):
|
||||
branch, _ = self.projects_info[project]
|
||||
history = self.history[project]
|
||||
revision_index = history.index(revision)
|
||||
for index in range(revision_index + 1, len(history)):
|
||||
revision = history[index]
|
||||
# We are done when we have one non-commited revision
|
||||
if not revision.commit:
|
||||
return
|
||||
logging.info(f"Rebasing {revision} from {branch}")
|
||||
revision.commit = None
|
||||
self.import_revision(revision)
|
||||
|
||||
def import_revision_with_request(self, revision, request):
|
||||
"""Import a single revision via a merge"""
|
||||
|
||||
submitted_revision = self.history.find_revision(
|
||||
request.source, request.revisionid, revision.time
|
||||
)
|
||||
if not submitted_revision:
|
||||
logging.warning(f"Request {request} does not connect to a known revision")
|
||||
return False
|
||||
assert submitted_revision.commit is not None
|
||||
|
||||
# TODO: detect a revision, case in point
|
||||
# Base:System/bash/284 -> rq683701 -> accept O:F/151
|
||||
# -> autocommit Base:System/bash/285
|
||||
# Revert lead to openSUSE:Factory/bash/152
|
||||
# Base:System/286 restored the reverted code in devel project
|
||||
# rq684575 was created and accepted as O:F/153
|
||||
# But the 284-285 and the 285-286 changeset is seen as empty
|
||||
# as the revert was never in Base:System, so the
|
||||
# submitted_revision of 684575 has no commit
|
||||
if submitted_revision.commit == "EMPTY":
|
||||
logging.warning("Empty commit submitted?!")
|
||||
return False
|
||||
|
||||
message = (
|
||||
f"Accepting request {revision.requestid}: {revision.comment}\n\n{revision}"
|
||||
)
|
||||
commit = self.git.merge(
|
||||
# TODO: revision.userid or request.creator?
|
||||
f"OBS User {revision.userid}",
|
||||
"null@suse.de",
|
||||
revision.time,
|
||||
message,
|
||||
submitted_revision.commit,
|
||||
)
|
||||
|
||||
if commit == "EMPTY":
|
||||
logging.warning("Empty merge. Ignoring the revision and the request")
|
||||
self.git.merge_abort()
|
||||
revision.commit = commit
|
||||
return False
|
||||
|
||||
if commit == "CONFLICT":
|
||||
logging.info("Merge conflict. Downloading revision")
|
||||
self.download(revision)
|
||||
message = f"CONFLICT {message}"
|
||||
commit = self.git.merge(
|
||||
f"OBS User {revision.userid}",
|
||||
"null@suse.de",
|
||||
revision.time,
|
||||
message,
|
||||
submitted_revision.commit,
|
||||
merged=True,
|
||||
)
|
||||
|
||||
assert commit and commit != "CONFLICT"
|
||||
logging.info(f"Merge with {submitted_revision.commit} into {commit}")
|
||||
revision.commit = commit
|
||||
|
||||
# TODO: There are more checks to do, like for example, the
|
||||
# last commit into the non-devel branch should be a merge from
|
||||
# the devel branch
|
||||
if self.rebase_devel:
|
||||
branch, _ = self.projects_info.get(request.source, (None, None))
|
||||
if branch == "devel":
|
||||
self.git.repo.references[f"refs/heads/{branch}"].set_target(commit)
|
||||
self._rebase_branch_history(request.source, submitted_revision)
|
||||
|
||||
return True
|
||||
|
||||
def matching_request(self, revision):
|
||||
request = self.obs.request(revision.requestid)
|
||||
if not request:
|
||||
return None
|
||||
|
||||
# to be handled by the caller
|
||||
if request.type() != "submit":
|
||||
return request
|
||||
|
||||
if request.source not in self.projects_info:
|
||||
logging.info("Request from a non exported project")
|
||||
return None
|
||||
|
||||
if request.target != revision.project:
|
||||
# This seems to happen when the devel project gets
|
||||
# reinitialized (for example, SR#943593 in 7zip, or
|
||||
# SR#437901 in ColorFull)
|
||||
logging.info("Request target different from current project")
|
||||
return None
|
||||
|
||||
if request.source == request.target:
|
||||
# this is not a merge, but a different way to do a
|
||||
# contribution to the (devel) project - see bindfs's rev 1
|
||||
logging.info("Request within the same project")
|
||||
return None
|
||||
|
||||
return request
|
||||
|
||||
def import_revision(self, revision):
|
||||
"""Import a single revision into git"""
|
||||
project = revision.project
|
||||
branch, api_url = self.projects_info[project]
|
||||
|
||||
logging.info(f"Importing [{revision}] to {branch}")
|
||||
|
||||
self.obs.change_url(api_url)
|
||||
|
||||
# Populate linkrev and replace srcmd5 from the linked
|
||||
# revision. If the expansion fails, the revision will be ignored
|
||||
# and not imported.
|
||||
if not revision.check_expanded():
|
||||
logging.warning(f"Broken revision")
|
||||
revision.ignored = True
|
||||
return
|
||||
|
||||
# When doing a SR, we see also a revision in the origin
|
||||
# project with the outgoing request, but without changes in
|
||||
# the project. We can ignore them.
|
||||
#
|
||||
# If there is a request ID, it will be filtered out later,
|
||||
# when the target project is different from itself.
|
||||
if revision.userid == "autobuild" and not revision.requestid:
|
||||
logging.info("Ignoring autocommit")
|
||||
revision.ignored = True
|
||||
return
|
||||
|
||||
if revision.userid == "buildservice-autocommit":
|
||||
logging.info("Ignoring autocommit")
|
||||
revision.ignored = True
|
||||
return
|
||||
|
||||
# Create the reference if the branch is new. If so return
|
||||
# True.
|
||||
new_branch = self.git.checkout(branch)
|
||||
|
||||
if revision.requestid:
|
||||
request = self.matching_request(revision)
|
||||
if request:
|
||||
if request.type() == "delete":
|
||||
# TODO: after this comes a restore, this should be collapsed
|
||||
# before even hitting git
|
||||
logging.info("Delete request ignored")
|
||||
revision.ignored = True
|
||||
return
|
||||
|
||||
logging.debug(f"Found matching request: #{revision.project} #{request}")
|
||||
if new_branch:
|
||||
self.import_new_revision_with_request(revision, request)
|
||||
return
|
||||
if self.import_revision_with_request(revision, request):
|
||||
return
|
||||
|
||||
# Import revision as a single commit (without merging)
|
||||
self.download(revision)
|
||||
|
||||
if new_branch or self.git.is_dirty():
|
||||
commit = self.git.commit(
|
||||
f"OBS User {revision.userid}",
|
||||
"null@suse.de",
|
||||
revision.time,
|
||||
# TODO: Normalize better the commit message
|
||||
f"{revision.comment}\n\n{revision}",
|
||||
# Create an empty commit only if is a new branch
|
||||
allow_empty=new_branch,
|
||||
)
|
||||
revision.commit = commit
|
||||
logging.info(f"Commit {commit}")
|
||||
else:
|
||||
logging.info("Skip empty commit")
|
||||
revision.ignored = True
|
||||
|
10
lib/obs.py
10
lib/obs.py
@ -151,7 +151,15 @@ class OBS:
|
||||
)
|
||||
return osc.core.http_GET(url)
|
||||
|
||||
def download(self, project, package, name, revision, dirpath):
|
||||
def download(
|
||||
self,
|
||||
project: str,
|
||||
package: str,
|
||||
name: str,
|
||||
revision: str,
|
||||
dirpath: str,
|
||||
file_md5: str,
|
||||
) -> None:
|
||||
with (dirpath / name).open("wb") as f:
|
||||
f.write(self._download(project, package, name, revision).read())
|
||||
|
||||
|
@ -1,14 +1,12 @@
|
||||
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):
|
||||
def __init__(self, obs, project, package):
|
||||
self.obs = obs
|
||||
self.history = history
|
||||
self.project = project
|
||||
self.package = package
|
||||
|
||||
@ -72,46 +70,3 @@ class OBSRevision:
|
||||
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
|
||||
|
@ -61,21 +61,22 @@ class Request:
|
||||
with db.cursor() as cur:
|
||||
cur.execute("""SELECT * from requests WHERE id=%s""", (request_id,))
|
||||
row = cur.fetchone()
|
||||
ret = Request()
|
||||
ret._from_db(row)
|
||||
return ret
|
||||
return Request.from_db(row)
|
||||
|
||||
def _from_db(self, row):
|
||||
@staticmethod
|
||||
def from_db(row):
|
||||
ret = Request()
|
||||
(
|
||||
self.dbid,
|
||||
self.number,
|
||||
self.creator,
|
||||
self.type_,
|
||||
self.state,
|
||||
self.source_package,
|
||||
self.source_project,
|
||||
self.source_rev,
|
||||
ret.dbid,
|
||||
ret.number,
|
||||
ret.creator,
|
||||
ret.type_,
|
||||
ret.state,
|
||||
ret.source_package,
|
||||
ret.source_project,
|
||||
ret.source_rev,
|
||||
) = row
|
||||
return ret
|
||||
|
||||
def as_dict(self):
|
||||
return {
|
||||
|
@ -6,7 +6,9 @@ from lib.db import DB
|
||||
from lib.db_revision import DBRevision
|
||||
|
||||
|
||||
class Exporter:
|
||||
class TestExporter:
|
||||
""" "Helper class to export data from production DB for tests"""
|
||||
|
||||
def __init__(self, package):
|
||||
self.package = package
|
||||
|
@ -1,7 +1,27 @@
|
||||
from typing import Dict
|
||||
from xmlrpc.client import Boolean
|
||||
|
||||
from lib.db_revision import DBRevision
|
||||
from lib.flat_walker import FlatTreeWalker
|
||||
from lib.request import Request
|
||||
|
||||
|
||||
class AbstractWalker:
|
||||
def call(self, node, is_source):
|
||||
pass
|
||||
|
||||
|
||||
class PrintWalker(AbstractWalker):
|
||||
def call(self, node, is_source):
|
||||
if is_source:
|
||||
print(" ", node.revision.short_string(), node.revision.files_hash)
|
||||
else:
|
||||
merge_str = ""
|
||||
if node.merged:
|
||||
merge_str = f"merged:{node.merged.revision.short_string()}"
|
||||
print(node.revision.short_string(), node.revision.files_hash, merge_str)
|
||||
|
||||
|
||||
class TreeNode:
|
||||
"""
|
||||
Nodes in this "tree" have either no parent (root), one parent (in a chain)
|
||||
@ -13,20 +33,30 @@ class TreeNode:
|
||||
self.merged = None
|
||||
self.revision = rev
|
||||
self.merged_into = None
|
||||
self.git_commit = None
|
||||
|
||||
def print(self):
|
||||
def walk(self, walker: AbstractWalker):
|
||||
node = self
|
||||
while node:
|
||||
print(node.revision, node.revision.files_hash)
|
||||
walker.call(node, False)
|
||||
if node.merged:
|
||||
source_node = node.merged
|
||||
while source_node:
|
||||
print(" ", source_node.revision, source_node.revision.files_hash)
|
||||
walker.call(source_node, True)
|
||||
source_node = source_node.parent
|
||||
if source_node and source_node.merged_into:
|
||||
break
|
||||
node = node.parent
|
||||
|
||||
def print(self):
|
||||
self.walk(PrintWalker())
|
||||
|
||||
def as_flat_list(self):
|
||||
"""Return the tree as git commits to do"""
|
||||
ftw = FlatTreeWalker()
|
||||
self.walk(ftw)
|
||||
return ftw.flats
|
||||
|
||||
def as_list(self):
|
||||
"""Return a list for test cases"""
|
||||
node = self
|
||||
@ -51,6 +81,8 @@ class TreeBuilder:
|
||||
self.db = db
|
||||
|
||||
def revisions_chain(self, project, package):
|
||||
"""Build a tree without branches (chain) from a project's
|
||||
history ignoring empty and broken revisions"""
|
||||
revisions = DBRevision.all_revisions(self.db, project, package)
|
||||
revisions.sort()
|
||||
prev = None
|
||||
@ -69,6 +101,8 @@ class TreeBuilder:
|
||||
return tree
|
||||
|
||||
def find_merge(self, revision, source_chain):
|
||||
"""For a given revision in the target, find the node in the source chain
|
||||
that matches the files"""
|
||||
node = source_chain
|
||||
while node:
|
||||
# exclude reverts happening after the merge
|
||||
@ -80,48 +114,101 @@ class TreeBuilder:
|
||||
node = node.parent
|
||||
|
||||
def add_merge_points(self, factory_revisions):
|
||||
source_revisions = dict()
|
||||
factory_node = factory_revisions
|
||||
while factory_node:
|
||||
if factory_node.revision.request_id:
|
||||
req = Request.find(self.db, factory_node.revision.request_id)
|
||||
"""For all target revisions that accepted a request, look up the merge
|
||||
points in the source chains (ignoring the actual revision submitted for now)"""
|
||||
|
||||
class FindRequestsWalker(AbstractWalker):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.requests = set()
|
||||
|
||||
def call(self, node: TreeNode, _: Boolean) -> None:
|
||||
if not node.revision.request_id:
|
||||
return
|
||||
self.requests.add(node.revision.request_id)
|
||||
|
||||
class FindMergeWalker(AbstractWalker):
|
||||
def __init__(self, builder: TreeBuilder, requests: Dict) -> None:
|
||||
super().__init__()
|
||||
self.source_revisions = dict()
|
||||
self.builder = builder
|
||||
self.requests = requests
|
||||
|
||||
def call(self, node, is_source) -> None:
|
||||
# not going to happen, but better safe
|
||||
if is_source:
|
||||
return
|
||||
if not node.revision.request_id:
|
||||
return
|
||||
req = self.requests.get(node.revision.request_id)
|
||||
key = f"{req.source_project}/{req.source_package}"
|
||||
if key not in source_revisions:
|
||||
source_revisions[key] = self.revisions_chain(
|
||||
if key not in self.source_revisions:
|
||||
self.source_revisions[key] = self.builder.revisions_chain(
|
||||
req.source_project, req.source_package
|
||||
)
|
||||
factory_node.merged = self.find_merge(
|
||||
factory_node.revision, source_revisions[key]
|
||||
node.merged = self.builder.find_merge(
|
||||
node.revision, self.source_revisions[key]
|
||||
)
|
||||
# add a reverse lookup
|
||||
if factory_node.merged:
|
||||
factory_node.merged.merged_into = factory_node
|
||||
if node.merged:
|
||||
node.merged.merged_into = node
|
||||
|
||||
factory_node = factory_node.parent
|
||||
# walk the tree twice. First we collect all requests to be looked up
|
||||
# to avoid going into the DB a thousand times
|
||||
frqs = FindRequestsWalker()
|
||||
factory_revisions.walk(frqs)
|
||||
requests = dict()
|
||||
with self.db.cursor() as cur:
|
||||
cur.execute(
|
||||
"SELECT * from requests WHERE id = ANY(%s)", (list(frqs.requests),)
|
||||
)
|
||||
for row in cur.fetchall():
|
||||
req = Request.from_db(row)
|
||||
requests[req.dbid] = req
|
||||
sw = FindMergeWalker(self, requests)
|
||||
factory_revisions.walk(sw)
|
||||
|
||||
def prune_loose_end(self, factory_node):
|
||||
"""Look for source revisions that end in a new root and prune them"""
|
||||
merge_before_last = None
|
||||
last_merge = None
|
||||
while factory_node:
|
||||
if factory_node.merged:
|
||||
source_node = factory_node.merged
|
||||
ended_without_merge = False
|
||||
while source_node:
|
||||
source_node = source_node.parent
|
||||
if source_node and source_node.merged_into:
|
||||
ended_without_merge = True
|
||||
break
|
||||
if not ended_without_merge:
|
||||
factory_node.merged = None
|
||||
if last_merge:
|
||||
last_merge.parent = None
|
||||
else:
|
||||
last_merge = factory_node.merged
|
||||
merge_before_last = last_merge
|
||||
last_merge = factory_node
|
||||
factory_node = factory_node.parent
|
||||
|
||||
def build(self, package):
|
||||
factory_revisions = self.revisions_chain("openSUSE:Factory", package)
|
||||
self.add_merge_points(factory_revisions)
|
||||
# a package without requests
|
||||
if not last_merge:
|
||||
return
|
||||
if merge_before_last:
|
||||
# we need to find the last merged_into that didn't end nowhere
|
||||
# and cut the rope there
|
||||
node = merge_before_last.merged
|
||||
last_node = None
|
||||
while node:
|
||||
last_node = node
|
||||
node = node.parent
|
||||
if node and node.merged_into:
|
||||
break
|
||||
if last_node:
|
||||
last_node.parent = None
|
||||
|
||||
if not last_merge.parent:
|
||||
last_merge.parent = last_merge.merged
|
||||
last_merge.merged.merged_into = None
|
||||
last_merge.merged = None
|
||||
|
||||
def build(self, project, package):
|
||||
"""Create a Factory tree (returning the top)"""
|
||||
factory_revisions = self.revisions_chain(project, package)
|
||||
self.add_merge_points(factory_revisions)
|
||||
# factory_revisions.print()
|
||||
self.prune_loose_end(factory_revisions)
|
||||
# factory_revisions.print()
|
||||
return factory_revisions
|
||||
|
36
lib/user.py
36
lib/user.py
@ -1,10 +1,25 @@
|
||||
FAKE_ACCOUNTS = ("unknown", "buildservice-autocommit", "autobuild", "_service")
|
||||
FAKE_ACCOUNTS = (
|
||||
"unknown",
|
||||
"buildservice-autocommit",
|
||||
"autobuild",
|
||||
"_service",
|
||||
"admin",
|
||||
"jg",
|
||||
"mrdocs",
|
||||
"AdrianSuSE",
|
||||
"$user",
|
||||
"embar-",
|
||||
"michel_mno",
|
||||
"guinux",
|
||||
)
|
||||
|
||||
|
||||
class User:
|
||||
def parse(self, xml, userid):
|
||||
self.userid = userid
|
||||
self.realname = xml.find("realname").text
|
||||
if self.realname is None:
|
||||
self.realname = ""
|
||||
self.email = xml.find("email").text
|
||||
if self.email is None:
|
||||
self.email = ""
|
||||
@ -40,13 +55,24 @@ class User:
|
||||
|
||||
@staticmethod
|
||||
def missing_users(db):
|
||||
missing_users = set()
|
||||
with db.cursor() as cur:
|
||||
cur.execute(
|
||||
"""SELECT DISTINCT revisions.userid
|
||||
FROM revisions LEFT JOIN users ON revisions.userid = users.userid
|
||||
"""SELECT DISTINCT revisions.userid
|
||||
FROM revisions LEFT JOIN users ON revisions.userid = users.userid
|
||||
WHERE users.userid IS NULL AND revisions.userid NOT IN {}""".format(
|
||||
FAKE_ACCOUNTS
|
||||
)
|
||||
)
|
||||
missing_users = [row[0] for row in cur.fetchall()]
|
||||
return missing_users
|
||||
for row in cur.fetchall():
|
||||
missing_users.add(row[0])
|
||||
cur.execute(
|
||||
"""SELECT DISTINCT requests.creator
|
||||
FROM requests LEFT JOIN users ON requests.creator=users.userid
|
||||
WHERE users.userid IS NULL AND requests.creator NOT IN {}""".format(
|
||||
FAKE_ACCOUNTS
|
||||
)
|
||||
)
|
||||
for row in cur.fetchall():
|
||||
missing_users.add(row[0])
|
||||
return sorted(missing_users)
|
||||
|
1
repos/.gitignore
vendored
Normal file
1
repos/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
*
|
@ -3,7 +3,6 @@ import xml.etree.ElementTree as ET
|
||||
|
||||
from lib.db import DB
|
||||
from lib.db_revision import DBRevision
|
||||
from lib.history import History
|
||||
from lib.obs import OBS
|
||||
from lib.obs_revision import OBSRevision
|
||||
|
||||
@ -12,10 +11,9 @@ class TestDBMethods(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.db = DB(section="test")
|
||||
self.obs = OBS()
|
||||
self.history = History(self.obs, "xz")
|
||||
|
||||
def test_import(self):
|
||||
test_rev = OBSRevision(self.obs, self.history, "openSUSE:Factory", "xz")
|
||||
test_rev = OBSRevision(self.obs, "openSUSE:Factory", "xz")
|
||||
test_rev.parse(
|
||||
ET.fromstring(
|
||||
"""<revision rev="70" vrev="1">
|
||||
|
8120
tests/fixtures/000update-repos-data.yaml
vendored
Normal file
8120
tests/fixtures/000update-repos-data.yaml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
12
tests/fixtures/000update-repos-expected-list.yaml
vendored
Normal file
12
tests/fixtures/000update-repos-expected-list.yaml
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
- factory c:openSUSE:Factory/000update-repos/12.0 p1:openSUSE:Factory/000update-repos/11.0
|
||||
- factory c:openSUSE:Factory/000update-repos/11.0 p1:openSUSE:Factory/000update-repos/10.0
|
||||
- factory c:openSUSE:Factory/000update-repos/10.0 p1:openSUSE:Factory/000update-repos/9.0
|
||||
- factory c:openSUSE:Factory/000update-repos/9.0 p1:openSUSE:Factory/000update-repos/8.0
|
||||
- factory c:openSUSE:Factory/000update-repos/8.0 p1:openSUSE:Factory/000update-repos/7.0
|
||||
- factory c:openSUSE:Factory/000update-repos/7.0 p1:openSUSE:Factory/000update-repos/6.0
|
||||
- factory c:openSUSE:Factory/000update-repos/6.0 p1:openSUSE:Factory/000update-repos/5.0
|
||||
- factory c:openSUSE:Factory/000update-repos/5.0 p1:openSUSE:Factory/000update-repos/4.0
|
||||
- factory c:openSUSE:Factory/000update-repos/4.0 p1:openSUSE:Factory/000update-repos/3.0
|
||||
- factory c:openSUSE:Factory/000update-repos/3.0 p1:openSUSE:Factory/000update-repos/2.0
|
||||
- factory c:openSUSE:Factory/000update-repos/2.0 p1:openSUSE:Factory/000update-repos/1.0
|
||||
- factory c:openSUSE:Factory/000update-repos/1.0
|
12
tests/fixtures/000update-repos-expected-tree.yaml
vendored
Normal file
12
tests/fixtures/000update-repos-expected-tree.yaml
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
- commit: openSUSE:Factory/000update-repos/12.0
|
||||
- commit: openSUSE:Factory/000update-repos/11.0
|
||||
- commit: openSUSE:Factory/000update-repos/10.0
|
||||
- commit: openSUSE:Factory/000update-repos/9.0
|
||||
- commit: openSUSE:Factory/000update-repos/8.0
|
||||
- commit: openSUSE:Factory/000update-repos/7.0
|
||||
- commit: openSUSE:Factory/000update-repos/6.0
|
||||
- commit: openSUSE:Factory/000update-repos/5.0
|
||||
- commit: openSUSE:Factory/000update-repos/4.0
|
||||
- commit: openSUSE:Factory/000update-repos/3.0
|
||||
- commit: openSUSE:Factory/000update-repos/2.0
|
||||
- commit: openSUSE:Factory/000update-repos/1.0
|
189
tests/fixtures/2048-cli-data.yaml
vendored
Normal file
189
tests/fixtures/2048-cli-data.yaml
vendored
Normal file
@ -0,0 +1,189 @@
|
||||
revisions:
|
||||
- broken: false
|
||||
comment: Initial package for 2048-cli
|
||||
commit_time: 2019-01-17 13:24:10
|
||||
expanded_srcmd5: bf00cfcbc357fc8a22140cb976cb1831
|
||||
files:
|
||||
- md5: fc83599e3bee1ca6e801c0345972e0db
|
||||
mtime: 1547497445
|
||||
name: 2048-cli-0.9.1+git.20181118.tar.xz
|
||||
size: 11264
|
||||
- md5: 0e55db8b846331b0419de91b9b4adeed
|
||||
mtime: 1547497445
|
||||
name: 2048-cli-link-against-correct-curses-lib.patch
|
||||
size: 599
|
||||
- md5: f5163dd8a1eeba70ab548a94abe5c2e8
|
||||
mtime: 1547497445
|
||||
name: 2048-cli-use-proper-gettext-header.patch
|
||||
size: 295
|
||||
- md5: 66545f46846337395fef1a73ac8adc4b
|
||||
mtime: 1547497445
|
||||
name: 2048-cli.changes
|
||||
size: 160
|
||||
- md5: 664c5dde51c1aed237647f5ee3f33eb1
|
||||
mtime: 1547497446
|
||||
name: 2048-cli.spec
|
||||
size: 1912
|
||||
- md5: 19fd04edbcba9d5dd847987cb6a252f9
|
||||
mtime: 1547497446
|
||||
name: _service
|
||||
size: 576
|
||||
- md5: 17e4e2499ed0511542a3f1119f0e7f73
|
||||
mtime: 1547497446
|
||||
name: _servicedata
|
||||
size: 237
|
||||
files_hash: 43709daf58d28446064513690987c5bb
|
||||
package: 2048-cli
|
||||
project: games
|
||||
request:
|
||||
creator: mnhauke
|
||||
number: 666053
|
||||
source_package: 2048-cli
|
||||
source_project: home:mnhauke:games
|
||||
source_rev: '1'
|
||||
state: accepted
|
||||
type: submit
|
||||
rev: 1.0
|
||||
unexpanded_srcmd5: d5865fc419f6c88f7e53304ad653a5fe
|
||||
userid: dstoecker
|
||||
- broken: false
|
||||
comment: '- Generalize description, and adjust summary grammar.'
|
||||
commit_time: 2019-01-17 16:47:56
|
||||
expanded_srcmd5: 9403af9dd3f07b99bee5230c36d73c55
|
||||
files:
|
||||
- md5: fc83599e3bee1ca6e801c0345972e0db
|
||||
mtime: 1547497445
|
||||
name: 2048-cli-0.9.1+git.20181118.tar.xz
|
||||
size: 11264
|
||||
- md5: 0e55db8b846331b0419de91b9b4adeed
|
||||
mtime: 1547497445
|
||||
name: 2048-cli-link-against-correct-curses-lib.patch
|
||||
size: 599
|
||||
- md5: f5163dd8a1eeba70ab548a94abe5c2e8
|
||||
mtime: 1547497445
|
||||
name: 2048-cli-use-proper-gettext-header.patch
|
||||
size: 295
|
||||
- md5: a84bd74cb2fff9e88a53763a90e5dac3
|
||||
mtime: 1547737525
|
||||
name: 2048-cli.changes
|
||||
size: 348
|
||||
- md5: ae75b0d87d1636964684ec9312b5e5a4
|
||||
mtime: 1547737525
|
||||
name: 2048-cli.spec
|
||||
size: 1980
|
||||
- md5: 19fd04edbcba9d5dd847987cb6a252f9
|
||||
mtime: 1547497446
|
||||
name: _service
|
||||
size: 576
|
||||
- md5: 17e4e2499ed0511542a3f1119f0e7f73
|
||||
mtime: 1547497446
|
||||
name: _servicedata
|
||||
size: 237
|
||||
files_hash: 376a74bc69d432aa5d9880a23bb1b1a3
|
||||
package: 2048-cli
|
||||
project: games
|
||||
request:
|
||||
creator: jengelh
|
||||
number: 666761
|
||||
source_package: 2048-cli
|
||||
source_project: home:jengelh:branches:games
|
||||
source_rev: '2'
|
||||
state: accepted
|
||||
type: submit
|
||||
rev: 2.0
|
||||
unexpanded_srcmd5: f523f3b5b7fbb3f1d27139eaed4d89d3
|
||||
userid: mnhauke
|
||||
- broken: false
|
||||
comment: initialized devel package after accepting 666812
|
||||
commit_time: 2019-01-24 14:11:01
|
||||
expanded_srcmd5: f29bf05261449d7e67e13ad64c4e2c03
|
||||
files:
|
||||
- md5: fc83599e3bee1ca6e801c0345972e0db
|
||||
mtime: 1547497445
|
||||
name: 2048-cli-0.9.1+git.20181118.tar.xz
|
||||
size: 11264
|
||||
- md5: 0e55db8b846331b0419de91b9b4adeed
|
||||
mtime: 1547497445
|
||||
name: 2048-cli-link-against-correct-curses-lib.patch
|
||||
size: 599
|
||||
- md5: f5163dd8a1eeba70ab548a94abe5c2e8
|
||||
mtime: 1547497445
|
||||
name: 2048-cli-use-proper-gettext-header.patch
|
||||
size: 295
|
||||
- md5: a84bd74cb2fff9e88a53763a90e5dac3
|
||||
mtime: 1547737525
|
||||
name: 2048-cli.changes
|
||||
size: 348
|
||||
- md5: ae75b0d87d1636964684ec9312b5e5a4
|
||||
mtime: 1547737525
|
||||
name: 2048-cli.spec
|
||||
size: 1980
|
||||
- md5: 19fd04edbcba9d5dd847987cb6a252f9
|
||||
mtime: 1547497446
|
||||
name: _service
|
||||
size: 576
|
||||
- md5: 17e4e2499ed0511542a3f1119f0e7f73
|
||||
mtime: 1547497446
|
||||
name: _servicedata
|
||||
size: 237
|
||||
files_hash: 376a74bc69d432aa5d9880a23bb1b1a3
|
||||
package: 2048-cli
|
||||
project: games
|
||||
request:
|
||||
creator: jengelh
|
||||
number: 666812
|
||||
source_package: 2048-cli
|
||||
source_project: games
|
||||
source_rev: '2'
|
||||
state: accepted
|
||||
type: submit
|
||||
rev: 3.0
|
||||
unexpanded_srcmd5: 6caa3b7070b6f2c5c7772d00c6ac8712
|
||||
userid: dimstar_suse
|
||||
- broken: false
|
||||
comment: ''
|
||||
commit_time: 2019-01-24 14:11:01
|
||||
expanded_srcmd5: 00f1a7cd03864ac8f34c66c4a028d175
|
||||
files:
|
||||
- md5: fc83599e3bee1ca6e801c0345972e0db
|
||||
mtime: 1547497445
|
||||
name: 2048-cli-0.9.1+git.20181118.tar.xz
|
||||
size: 11264
|
||||
- md5: 0e55db8b846331b0419de91b9b4adeed
|
||||
mtime: 1547497445
|
||||
name: 2048-cli-link-against-correct-curses-lib.patch
|
||||
size: 599
|
||||
- md5: f5163dd8a1eeba70ab548a94abe5c2e8
|
||||
mtime: 1547497445
|
||||
name: 2048-cli-use-proper-gettext-header.patch
|
||||
size: 295
|
||||
- md5: a84bd74cb2fff9e88a53763a90e5dac3
|
||||
mtime: 1547737525
|
||||
name: 2048-cli.changes
|
||||
size: 348
|
||||
- md5: ae75b0d87d1636964684ec9312b5e5a4
|
||||
mtime: 1547737525
|
||||
name: 2048-cli.spec
|
||||
size: 1980
|
||||
- md5: 19fd04edbcba9d5dd847987cb6a252f9
|
||||
mtime: 1547497446
|
||||
name: _service
|
||||
size: 576
|
||||
- md5: 17e4e2499ed0511542a3f1119f0e7f73
|
||||
mtime: 1547497446
|
||||
name: _servicedata
|
||||
size: 237
|
||||
files_hash: 376a74bc69d432aa5d9880a23bb1b1a3
|
||||
package: 2048-cli
|
||||
project: openSUSE:Factory
|
||||
request:
|
||||
creator: jengelh
|
||||
number: 666812
|
||||
source_package: 2048-cli
|
||||
source_project: games
|
||||
source_rev: '2'
|
||||
state: accepted
|
||||
type: submit
|
||||
rev: 1.0
|
||||
unexpanded_srcmd5: 63aac027654e164c683fa5c6684a2e00
|
||||
userid: dimstar_suse
|
3
tests/fixtures/2048-cli-expected-list.yaml
vendored
Normal file
3
tests/fixtures/2048-cli-expected-list.yaml
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
- factory c:openSUSE:Factory/2048-cli/1.0 p1:games/2048-cli/2.0
|
||||
- factory c:games/2048-cli/2.0 p1:games/2048-cli/1.0
|
||||
- factory c:games/2048-cli/1.0
|
3
tests/fixtures/2048-cli-expected-tree.yaml
vendored
Normal file
3
tests/fixtures/2048-cli-expected-tree.yaml
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
- commit: openSUSE:Factory/2048-cli/1.0
|
||||
- commit: games/2048-cli/2.0
|
||||
- commit: games/2048-cli/1.0
|
2167
tests/fixtures/CoreFreq-data.yaml
vendored
Normal file
2167
tests/fixtures/CoreFreq-data.yaml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
38
tests/fixtures/CoreFreq-expected-list.yaml
vendored
Normal file
38
tests/fixtures/CoreFreq-expected-list.yaml
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
- factory c:openSUSE:Factory/CoreFreq/15.0 p1:openSUSE:Factory/CoreFreq/14.0 p2:hardware/CoreFreq/32.0
|
||||
- devel c:hardware/CoreFreq/32.0 p1:hardware/CoreFreq/31.0
|
||||
- devel c:hardware/CoreFreq/31.0 p1:hardware/CoreFreq/29.0
|
||||
- factory c:openSUSE:Factory/CoreFreq/14.0 p1:openSUSE:Factory/CoreFreq/13.0 p2:hardware/CoreFreq/29.0
|
||||
- devel c:hardware/CoreFreq/29.0 p1:hardware/CoreFreq/27.0
|
||||
- factory c:openSUSE:Factory/CoreFreq/13.0 p1:openSUSE:Factory/CoreFreq/12.0 p2:hardware/CoreFreq/27.0
|
||||
- devel c:hardware/CoreFreq/27.0 p1:hardware/CoreFreq/26.0
|
||||
- devel c:hardware/CoreFreq/26.0 p1:hardware/CoreFreq/25.0
|
||||
- factory c:openSUSE:Factory/CoreFreq/12.0 p1:openSUSE:Factory/CoreFreq/11.0 p2:hardware/CoreFreq/25.0
|
||||
- devel c:hardware/CoreFreq/25.0 p1:hardware/CoreFreq/24.0
|
||||
- devel c:hardware/CoreFreq/24.0 p1:hardware/CoreFreq/23.0
|
||||
- factory c:openSUSE:Factory/CoreFreq/11.0 p1:openSUSE:Factory/CoreFreq/10.0 p2:hardware/CoreFreq/23.0
|
||||
- devel c:hardware/CoreFreq/23.0 p1:hardware/CoreFreq/22.0
|
||||
- factory c:openSUSE:Factory/CoreFreq/10.0 p1:openSUSE:Factory/CoreFreq/9.0 p2:hardware/CoreFreq/22.0
|
||||
- devel c:hardware/CoreFreq/22.0 p1:hardware/CoreFreq/21.0
|
||||
- factory c:openSUSE:Factory/CoreFreq/9.0 p1:openSUSE:Factory/CoreFreq/8.0 p2:hardware/CoreFreq/21.0
|
||||
- devel c:hardware/CoreFreq/21.0 p1:hardware/CoreFreq/20.0
|
||||
- factory c:openSUSE:Factory/CoreFreq/8.0 p1:openSUSE:Factory/CoreFreq/7.0 p2:hardware/CoreFreq/20.0
|
||||
- devel c:hardware/CoreFreq/20.0 p1:hardware/CoreFreq/18.0
|
||||
- factory c:openSUSE:Factory/CoreFreq/7.0 p1:openSUSE:Factory/CoreFreq/6.0 p2:hardware/CoreFreq/18.0
|
||||
- devel c:hardware/CoreFreq/18.0 p1:hardware/CoreFreq/16.0
|
||||
- factory c:openSUSE:Factory/CoreFreq/6.0 p1:openSUSE:Factory/CoreFreq/5.0 p2:hardware/CoreFreq/16.0
|
||||
- devel c:hardware/CoreFreq/16.0 p1:hardware/CoreFreq/15.0
|
||||
- devel c:hardware/CoreFreq/15.0 p1:hardware/CoreFreq/13.0
|
||||
- factory c:openSUSE:Factory/CoreFreq/5.0 p1:openSUSE:Factory/CoreFreq/4.0 p2:hardware/CoreFreq/13.0
|
||||
- devel c:hardware/CoreFreq/13.0 p1:hardware/CoreFreq/11.0
|
||||
- factory c:openSUSE:Factory/CoreFreq/4.0 p1:openSUSE:Factory/CoreFreq/3.0 p2:hardware/CoreFreq/11.0
|
||||
- devel c:hardware/CoreFreq/11.0 p1:hardware/CoreFreq/9.0
|
||||
- factory c:openSUSE:Factory/CoreFreq/3.0 p1:openSUSE:Factory/CoreFreq/2.0 p2:hardware/CoreFreq/9.0
|
||||
- devel c:hardware/CoreFreq/9.0 p1:hardware/CoreFreq/8.0
|
||||
- devel c:hardware/CoreFreq/8.0 p1:hardware/CoreFreq/7.0
|
||||
- devel c:hardware/CoreFreq/7.0 p1:hardware/CoreFreq/6.0
|
||||
- devel c:hardware/CoreFreq/6.0 p1:hardware/CoreFreq/4.0
|
||||
- factory c:openSUSE:Factory/CoreFreq/2.0 p1:openSUSE:Factory/CoreFreq/1.0 p2:hardware/CoreFreq/4.0
|
||||
- devel c:hardware/CoreFreq/4.0 p1:openSUSE:Factory/CoreFreq/1.0
|
||||
- factory c:openSUSE:Factory/CoreFreq/1.0 p1:hardware/CoreFreq/2.0
|
||||
- factory c:hardware/CoreFreq/2.0 p1:hardware/CoreFreq/1.0
|
||||
- factory c:hardware/CoreFreq/1.0
|
52
tests/fixtures/CoreFreq-expected-tree.yaml
vendored
Normal file
52
tests/fixtures/CoreFreq-expected-tree.yaml
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
- commit: openSUSE:Factory/CoreFreq/15.0
|
||||
merged:
|
||||
- hardware/CoreFreq/32.0
|
||||
- hardware/CoreFreq/31.0
|
||||
- commit: openSUSE:Factory/CoreFreq/14.0
|
||||
merged:
|
||||
- hardware/CoreFreq/29.0
|
||||
- commit: openSUSE:Factory/CoreFreq/13.0
|
||||
merged:
|
||||
- hardware/CoreFreq/27.0
|
||||
- hardware/CoreFreq/26.0
|
||||
- commit: openSUSE:Factory/CoreFreq/12.0
|
||||
merged:
|
||||
- hardware/CoreFreq/25.0
|
||||
- hardware/CoreFreq/24.0
|
||||
- commit: openSUSE:Factory/CoreFreq/11.0
|
||||
merged:
|
||||
- hardware/CoreFreq/23.0
|
||||
- commit: openSUSE:Factory/CoreFreq/10.0
|
||||
merged:
|
||||
- hardware/CoreFreq/22.0
|
||||
- commit: openSUSE:Factory/CoreFreq/9.0
|
||||
merged:
|
||||
- hardware/CoreFreq/21.0
|
||||
- commit: openSUSE:Factory/CoreFreq/8.0
|
||||
merged:
|
||||
- hardware/CoreFreq/20.0
|
||||
- commit: openSUSE:Factory/CoreFreq/7.0
|
||||
merged:
|
||||
- hardware/CoreFreq/18.0
|
||||
- commit: openSUSE:Factory/CoreFreq/6.0
|
||||
merged:
|
||||
- hardware/CoreFreq/16.0
|
||||
- hardware/CoreFreq/15.0
|
||||
- commit: openSUSE:Factory/CoreFreq/5.0
|
||||
merged:
|
||||
- hardware/CoreFreq/13.0
|
||||
- commit: openSUSE:Factory/CoreFreq/4.0
|
||||
merged:
|
||||
- hardware/CoreFreq/11.0
|
||||
- commit: openSUSE:Factory/CoreFreq/3.0
|
||||
merged:
|
||||
- hardware/CoreFreq/9.0
|
||||
- hardware/CoreFreq/8.0
|
||||
- hardware/CoreFreq/7.0
|
||||
- hardware/CoreFreq/6.0
|
||||
- commit: openSUSE:Factory/CoreFreq/2.0
|
||||
merged:
|
||||
- hardware/CoreFreq/4.0
|
||||
- commit: openSUSE:Factory/CoreFreq/1.0
|
||||
- commit: hardware/CoreFreq/2.0
|
||||
- commit: hardware/CoreFreq/1.0
|
10
tests/fixtures/clapper-expected-list.yaml
vendored
Normal file
10
tests/fixtures/clapper-expected-list.yaml
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
- factory c:openSUSE:Factory/clapper/3.0 p1:openSUSE:Factory/clapper/2.0 p2:multimedia:apps/clapper/9.0
|
||||
- devel c:multimedia:apps/clapper/9.0 p1:multimedia:apps/clapper/7.0
|
||||
- factory c:openSUSE:Factory/clapper/2.0 p1:openSUSE:Factory/clapper/1.0 p2:multimedia:apps/clapper/7.0
|
||||
- devel c:multimedia:apps/clapper/7.0 p1:multimedia:apps/clapper/6.0
|
||||
- devel c:multimedia:apps/clapper/6.0 p1:multimedia:apps/clapper/5.0
|
||||
- devel c:multimedia:apps/clapper/5.0 p1:openSUSE:Factory/clapper/1.0
|
||||
- factory c:openSUSE:Factory/clapper/1.0 p1:multimedia:apps/clapper/3.0
|
||||
- factory c:multimedia:apps/clapper/3.0 p1:multimedia:apps/clapper/2.0
|
||||
- factory c:multimedia:apps/clapper/2.0 p1:multimedia:apps/clapper/1.0
|
||||
- factory c:multimedia:apps/clapper/1.0
|
15
tests/fixtures/clapper-expected-tree.yaml
vendored
15
tests/fixtures/clapper-expected-tree.yaml
vendored
@ -1,7 +1,12 @@
|
||||
- commit: Rev openSUSE:Factory/clapper/3.0
|
||||
- commit: openSUSE:Factory/clapper/3.0
|
||||
merged:
|
||||
- Rev multimedia:apps/clapper/9.0
|
||||
- commit: Rev openSUSE:Factory/clapper/2.0
|
||||
- multimedia:apps/clapper/9.0
|
||||
- commit: openSUSE:Factory/clapper/2.0
|
||||
merged:
|
||||
- Rev multimedia:apps/clapper/7.0
|
||||
- commit: Rev openSUSE:Factory/clapper/1.0
|
||||
- multimedia:apps/clapper/7.0
|
||||
- multimedia:apps/clapper/6.0
|
||||
- multimedia:apps/clapper/5.0
|
||||
- commit: openSUSE:Factory/clapper/1.0
|
||||
- commit: multimedia:apps/clapper/3.0
|
||||
- commit: multimedia:apps/clapper/2.0
|
||||
- commit: multimedia:apps/clapper/1.0
|
||||
|
9030
tests/fixtures/llvm13-data.yaml
vendored
Normal file
9030
tests/fixtures/llvm13-data.yaml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
38
tests/fixtures/llvm13-expected-list.yaml
vendored
Normal file
38
tests/fixtures/llvm13-expected-list.yaml
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
- factory c:openSUSE:Factory/llvm13/12.0 p1:openSUSE:Factory/llvm13/11.0 p2:devel:tools:compiler/llvm13/30.0
|
||||
- devel c:devel:tools:compiler/llvm13/30.0 p1:devel:tools:compiler/llvm13/28.0
|
||||
- factory c:openSUSE:Factory/llvm13/11.0 p1:openSUSE:Factory/llvm13/10.0 p2:devel:tools:compiler/llvm13/28.0
|
||||
- devel c:devel:tools:compiler/llvm13/28.0 p1:devel:tools:compiler/llvm13/26.0
|
||||
- factory c:openSUSE:Factory/llvm13/10.0 p1:openSUSE:Factory/llvm13/9.0 p2:devel:tools:compiler/llvm13/26.0
|
||||
- devel c:devel:tools:compiler/llvm13/26.0 p1:devel:tools:compiler/llvm13/25.0
|
||||
- devel c:devel:tools:compiler/llvm13/25.0 p1:devel:tools:compiler/llvm13/24.0
|
||||
- devel c:devel:tools:compiler/llvm13/24.0 p1:devel:tools:compiler/llvm13/22.0
|
||||
- factory c:openSUSE:Factory/llvm13/9.0 p1:openSUSE:Factory/llvm13/8.0 p2:devel:tools:compiler/llvm13/22.0
|
||||
- devel c:devel:tools:compiler/llvm13/22.0 p1:devel:tools:compiler/llvm13/21.0
|
||||
- devel c:devel:tools:compiler/llvm13/21.0 p1:devel:tools:compiler/llvm13/20.0
|
||||
- devel c:devel:tools:compiler/llvm13/20.0 p1:devel:tools:compiler/llvm13/19.0
|
||||
- devel c:devel:tools:compiler/llvm13/19.0 p1:devel:tools:compiler/llvm13/18.0
|
||||
- devel c:devel:tools:compiler/llvm13/18.0 p1:devel:tools:compiler/llvm13/17.0
|
||||
- devel c:devel:tools:compiler/llvm13/17.0 p1:devel:tools:compiler/llvm13/16.0
|
||||
- devel c:devel:tools:compiler/llvm13/16.0 p1:devel:tools:compiler/llvm13/15.0
|
||||
- devel c:devel:tools:compiler/llvm13/15.0 p1:devel:tools:compiler/llvm13/14.0
|
||||
- devel c:devel:tools:compiler/llvm13/14.0 p1:devel:tools:compiler/llvm13/13.0
|
||||
- factory c:openSUSE:Factory/llvm13/8.0 p1:openSUSE:Factory/llvm13/7.0 p2:devel:tools:compiler/llvm13/13.0
|
||||
- devel c:devel:tools:compiler/llvm13/13.0 p1:devel:tools:compiler/llvm13/12.0
|
||||
- devel c:devel:tools:compiler/llvm13/12.0 p1:devel:tools:compiler/llvm13/11.0
|
||||
- devel c:devel:tools:compiler/llvm13/11.0 p1:devel:tools:compiler/llvm13/10.0
|
||||
- factory c:openSUSE:Factory/llvm13/7.0 p1:openSUSE:Factory/llvm13/6.0 p2:devel:tools:compiler/llvm13/10.0
|
||||
- devel c:devel:tools:compiler/llvm13/10.0 p1:devel:tools:compiler/llvm13/9.0
|
||||
- factory c:openSUSE:Factory/llvm13/6.0 p1:openSUSE:Factory/llvm13/5.0 p2:devel:tools:compiler/llvm13/9.0
|
||||
- devel c:devel:tools:compiler/llvm13/9.0 p1:devel:tools:compiler/llvm13/8.0
|
||||
- devel c:devel:tools:compiler/llvm13/8.0 p1:devel:tools:compiler/llvm13/7.0
|
||||
- factory c:openSUSE:Factory/llvm13/5.0 p1:openSUSE:Factory/llvm13/4.0 p2:devel:tools:compiler/llvm13/7.0
|
||||
- devel c:devel:tools:compiler/llvm13/7.0 p1:devel:tools:compiler/llvm13/6.0
|
||||
- factory c:openSUSE:Factory/llvm13/4.0 p1:openSUSE:Factory/llvm13/3.0 p2:devel:tools:compiler/llvm13/6.0
|
||||
- devel c:devel:tools:compiler/llvm13/6.0 p1:devel:tools:compiler/llvm13/5.0
|
||||
- factory c:openSUSE:Factory/llvm13/3.0 p1:openSUSE:Factory/llvm13/2.0 p2:devel:tools:compiler/llvm13/5.0
|
||||
- devel c:devel:tools:compiler/llvm13/5.0 p1:devel:tools:compiler/llvm13/4.0
|
||||
- factory c:openSUSE:Factory/llvm13/2.0 p1:openSUSE:Factory/llvm13/1.0 p2:devel:tools:compiler/llvm13/4.0
|
||||
- devel c:devel:tools:compiler/llvm13/4.0 p1:devel:tools:compiler/llvm13/3.0
|
||||
- devel c:devel:tools:compiler/llvm13/3.0 p1:openSUSE:Factory/llvm13/1.0
|
||||
- factory c:openSUSE:Factory/llvm13/1.0 p1:devel:tools:compiler/llvm13/1.0
|
||||
- factory c:devel:tools:compiler/llvm13/1.0
|
49
tests/fixtures/llvm13-expected-tree.yaml
vendored
Normal file
49
tests/fixtures/llvm13-expected-tree.yaml
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
- commit: openSUSE:Factory/llvm13/12.0
|
||||
merged:
|
||||
- devel:tools:compiler/llvm13/30.0
|
||||
- commit: openSUSE:Factory/llvm13/11.0
|
||||
merged:
|
||||
- devel:tools:compiler/llvm13/28.0
|
||||
- commit: openSUSE:Factory/llvm13/10.0
|
||||
merged:
|
||||
- devel:tools:compiler/llvm13/26.0
|
||||
- devel:tools:compiler/llvm13/25.0
|
||||
- devel:tools:compiler/llvm13/24.0
|
||||
- commit: openSUSE:Factory/llvm13/9.0
|
||||
merged:
|
||||
- devel:tools:compiler/llvm13/22.0
|
||||
- devel:tools:compiler/llvm13/21.0
|
||||
- devel:tools:compiler/llvm13/20.0
|
||||
- devel:tools:compiler/llvm13/19.0
|
||||
- devel:tools:compiler/llvm13/18.0
|
||||
- devel:tools:compiler/llvm13/17.0
|
||||
- devel:tools:compiler/llvm13/16.0
|
||||
- devel:tools:compiler/llvm13/15.0
|
||||
- devel:tools:compiler/llvm13/14.0
|
||||
- commit: openSUSE:Factory/llvm13/8.0
|
||||
merged:
|
||||
- devel:tools:compiler/llvm13/13.0
|
||||
- devel:tools:compiler/llvm13/12.0
|
||||
- devel:tools:compiler/llvm13/11.0
|
||||
- commit: openSUSE:Factory/llvm13/7.0
|
||||
merged:
|
||||
- devel:tools:compiler/llvm13/10.0
|
||||
- commit: openSUSE:Factory/llvm13/6.0
|
||||
merged:
|
||||
- devel:tools:compiler/llvm13/9.0
|
||||
- devel:tools:compiler/llvm13/8.0
|
||||
- commit: openSUSE:Factory/llvm13/5.0
|
||||
merged:
|
||||
- devel:tools:compiler/llvm13/7.0
|
||||
- commit: openSUSE:Factory/llvm13/4.0
|
||||
merged:
|
||||
- devel:tools:compiler/llvm13/6.0
|
||||
- commit: openSUSE:Factory/llvm13/3.0
|
||||
merged:
|
||||
- devel:tools:compiler/llvm13/5.0
|
||||
- commit: openSUSE:Factory/llvm13/2.0
|
||||
merged:
|
||||
- devel:tools:compiler/llvm13/4.0
|
||||
- devel:tools:compiler/llvm13/3.0
|
||||
- commit: openSUSE:Factory/llvm13/1.0
|
||||
- commit: devel:tools:compiler/llvm13/1.0
|
4020
tests/fixtures/zsh-data.yaml
vendored
4020
tests/fixtures/zsh-data.yaml
vendored
File diff suppressed because it is too large
Load Diff
206
tests/fixtures/zsh-expected-list.yaml
vendored
Normal file
206
tests/fixtures/zsh-expected-list.yaml
vendored
Normal file
@ -0,0 +1,206 @@
|
||||
- factory c:openSUSE:Factory/zsh/87.0 p1:openSUSE:Factory/zsh/86.0 p2:shells/zsh/210.0
|
||||
- devel c:shells/zsh/210.0 p1:shells/zsh/209.0
|
||||
- devel c:shells/zsh/209.0 p1:shells/zsh/208.0
|
||||
- devel c:shells/zsh/208.0 p1:shells/zsh/207.0
|
||||
- devel c:shells/zsh/207.0 p1:shells/zsh/205.0
|
||||
- factory c:openSUSE:Factory/zsh/86.0 p1:openSUSE:Factory/zsh/85.0 p2:shells/zsh/205.0
|
||||
- devel c:shells/zsh/205.0 p1:shells/zsh/204.0
|
||||
- devel c:shells/zsh/204.0 p1:shells/zsh/202.0
|
||||
- factory c:openSUSE:Factory/zsh/85.0 p1:openSUSE:Factory/zsh/84.0 p2:shells/zsh/202.0
|
||||
- devel c:shells/zsh/202.0 p1:shells/zsh/201.0
|
||||
- devel c:shells/zsh/201.0 p1:shells/zsh/199.0
|
||||
- factory c:openSUSE:Factory/zsh/84.0 p1:openSUSE:Factory/zsh/83.0 p2:shells/zsh/199.0
|
||||
- devel c:shells/zsh/199.0 p1:shells/zsh/198.0
|
||||
- devel c:shells/zsh/198.0 p1:shells/zsh/197.0
|
||||
- devel c:shells/zsh/197.0 p1:shells/zsh/195.0
|
||||
- factory c:openSUSE:Factory/zsh/83.0 p1:openSUSE:Factory/zsh/82.0 p2:shells/zsh/195.0
|
||||
- devel c:shells/zsh/195.0 p1:shells/zsh/194.0
|
||||
- devel c:shells/zsh/194.0 p1:shells/zsh/193.0
|
||||
- devel c:shells/zsh/193.0 p1:shells/zsh/192.0
|
||||
- devel c:shells/zsh/192.0 p1:shells/zsh/191.0
|
||||
- devel c:shells/zsh/191.0 p1:shells/zsh/189.0
|
||||
- factory c:openSUSE:Factory/zsh/82.0 p1:openSUSE:Factory/zsh/81.0 p2:shells/zsh/189.0
|
||||
- devel c:shells/zsh/189.0 p1:shells/zsh/187.0
|
||||
- factory c:openSUSE:Factory/zsh/81.0 p1:openSUSE:Factory/zsh/80.0 p2:shells/zsh/187.0
|
||||
- devel c:shells/zsh/187.0 p1:shells/zsh/186.0
|
||||
- devel c:shells/zsh/186.0 p1:shells/zsh/184.0
|
||||
- factory c:openSUSE:Factory/zsh/80.0 p1:openSUSE:Factory/zsh/79.0 p2:shells/zsh/184.0
|
||||
- devel c:shells/zsh/184.0 p1:shells/zsh/182.0
|
||||
- factory c:openSUSE:Factory/zsh/79.0 p1:openSUSE:Factory/zsh/78.0 p2:shells/zsh/182.0
|
||||
- devel c:shells/zsh/182.0 p1:shells/zsh/180.0
|
||||
- factory c:openSUSE:Factory/zsh/78.0 p1:openSUSE:Factory/zsh/77.0 p2:shells/zsh/180.0
|
||||
- devel c:shells/zsh/180.0 p1:shells/zsh/178.0
|
||||
- factory c:openSUSE:Factory/zsh/77.0 p1:openSUSE:Factory/zsh/76.0 p2:shells/zsh/178.0
|
||||
- devel c:shells/zsh/178.0 p1:shells/zsh/177.0
|
||||
- devel c:shells/zsh/177.0 p1:shells/zsh/175.0
|
||||
- factory c:openSUSE:Factory/zsh/76.0 p1:openSUSE:Factory/zsh/75.0 p2:shells/zsh/175.0
|
||||
- devel c:shells/zsh/175.0 p1:shells/zsh/173.0
|
||||
- factory c:openSUSE:Factory/zsh/75.0 p1:openSUSE:Factory/zsh/74.0 p2:shells/zsh/173.0
|
||||
- devel c:shells/zsh/173.0 p1:shells/zsh/171.0
|
||||
- factory c:openSUSE:Factory/zsh/74.0 p1:openSUSE:Factory/zsh/73.0 p2:shells/zsh/171.0
|
||||
- devel c:shells/zsh/171.0 p1:shells/zsh/170.0
|
||||
- devel c:shells/zsh/170.0 p1:shells/zsh/168.0
|
||||
- factory c:openSUSE:Factory/zsh/73.0 p1:openSUSE:Factory/zsh/72.0 p2:shells/zsh/168.0
|
||||
- devel c:shells/zsh/168.0 p1:shells/zsh/166.0
|
||||
- factory c:openSUSE:Factory/zsh/72.0 p1:openSUSE:Factory/zsh/71.0 p2:shells/zsh/166.0
|
||||
- devel c:shells/zsh/166.0 p1:shells/zsh/164.0
|
||||
- factory c:openSUSE:Factory/zsh/71.0 p1:openSUSE:Factory/zsh/70.0 p2:shells/zsh/164.0
|
||||
- devel c:shells/zsh/164.0 p1:shells/zsh/162.0
|
||||
- factory c:openSUSE:Factory/zsh/70.0 p1:openSUSE:Factory/zsh/69.0 p2:shells/zsh/162.0
|
||||
- devel c:shells/zsh/162.0 p1:shells/zsh/160.0
|
||||
- factory c:openSUSE:Factory/zsh/69.0 p1:openSUSE:Factory/zsh/68.0 p2:shells/zsh/160.0
|
||||
- devel c:shells/zsh/160.0 p1:shells/zsh/159.0
|
||||
- devel c:shells/zsh/159.0 p1:shells/zsh/158.0
|
||||
- devel c:shells/zsh/158.0 p1:shells/zsh/156.0
|
||||
- factory c:openSUSE:Factory/zsh/68.0 p1:openSUSE:Factory/zsh/67.0 p2:shells/zsh/156.0
|
||||
- devel c:shells/zsh/156.0 p1:shells/zsh/154.0
|
||||
- factory c:openSUSE:Factory/zsh/67.0 p1:openSUSE:Factory/zsh/66.0 p2:shells/zsh/154.0
|
||||
- devel c:shells/zsh/154.0 p1:shells/zsh/153.0
|
||||
- devel c:shells/zsh/153.0 p1:shells/zsh/151.0
|
||||
- factory c:openSUSE:Factory/zsh/66.0 p1:openSUSE:Factory/zsh/65.0 p2:shells/zsh/151.0
|
||||
- devel c:shells/zsh/151.0 p1:shells/zsh/150.0
|
||||
- devel c:shells/zsh/150.0 p1:shells/zsh/148.0
|
||||
- factory c:openSUSE:Factory/zsh/65.0 p1:openSUSE:Factory/zsh/64.0 p2:shells/zsh/148.0
|
||||
- devel c:shells/zsh/148.0 p1:shells/zsh/146.0
|
||||
- factory c:openSUSE:Factory/zsh/64.0 p1:openSUSE:Factory/zsh/63.0 p2:shells/zsh/146.0
|
||||
- devel c:shells/zsh/146.0 p1:shells/zsh/145.0
|
||||
- devel c:shells/zsh/145.0 p1:shells/zsh/144.0
|
||||
- devel c:shells/zsh/144.0 p1:shells/zsh/142.0
|
||||
- factory c:openSUSE:Factory/zsh/63.0 p1:openSUSE:Factory/zsh/62.0 p2:shells/zsh/142.0
|
||||
- devel c:shells/zsh/142.0 p1:shells/zsh/140.0
|
||||
- factory c:openSUSE:Factory/zsh/62.0 p1:openSUSE:Factory/zsh/61.0 p2:shells/zsh/140.0
|
||||
- devel c:shells/zsh/140.0 p1:shells/zsh/138.0
|
||||
- factory c:openSUSE:Factory/zsh/61.0 p1:openSUSE:Factory/zsh/60.0 p2:shells/zsh/138.0
|
||||
- devel c:shells/zsh/138.0 p1:shells/zsh/137.0
|
||||
- devel c:shells/zsh/137.0 p1:shells/zsh/135.0
|
||||
- factory c:openSUSE:Factory/zsh/60.0 p1:openSUSE:Factory/zsh/59.0 p2:shells/zsh/135.0
|
||||
- devel c:shells/zsh/135.0 p1:shells/zsh/133.0
|
||||
- factory c:openSUSE:Factory/zsh/59.0 p1:openSUSE:Factory/zsh/57.0 p2:shells/zsh/133.0
|
||||
- devel c:shells/zsh/133.0 p1:shells/zsh/131.0
|
||||
- factory c:openSUSE:Factory/zsh/57.0 p1:openSUSE:Factory/zsh/56.0 p2:shells/zsh/131.0
|
||||
- devel c:shells/zsh/131.0 p1:shells/zsh/129.0
|
||||
- factory c:openSUSE:Factory/zsh/56.0 p1:openSUSE:Factory/zsh/55.0 p2:shells/zsh/129.0
|
||||
- devel c:shells/zsh/129.0 p1:shells/zsh/127.0
|
||||
- factory c:openSUSE:Factory/zsh/55.0 p1:openSUSE:Factory/zsh/54.0 p2:shells/zsh/127.0
|
||||
- devel c:shells/zsh/127.0 p1:shells/zsh/125.0
|
||||
- factory c:openSUSE:Factory/zsh/54.0 p1:openSUSE:Factory/zsh/53.0 p2:shells/zsh/125.0
|
||||
- devel c:shells/zsh/125.0 p1:shells/zsh/123.0
|
||||
- factory c:openSUSE:Factory/zsh/53.0 p1:openSUSE:Factory/zsh/51.0 p2:shells/zsh/123.0
|
||||
- devel c:shells/zsh/123.0 p1:shells/zsh/121.0
|
||||
- factory c:openSUSE:Factory/zsh/51.0 p1:openSUSE:Factory/zsh/50.0 p2:shells/zsh/121.0
|
||||
- devel c:shells/zsh/121.0 p1:shells/zsh/119.0
|
||||
- factory c:openSUSE:Factory/zsh/50.0 p1:openSUSE:Factory/zsh/49.0 p2:shells/zsh/119.0
|
||||
- devel c:shells/zsh/119.0 p1:shells/zsh/117.0
|
||||
- factory c:openSUSE:Factory/zsh/49.0 p1:openSUSE:Factory/zsh/48.0 p2:shells/zsh/117.0
|
||||
- devel c:shells/zsh/117.0 p1:shells/zsh/115.0
|
||||
- factory c:openSUSE:Factory/zsh/48.0 p1:openSUSE:Factory/zsh/46.0 p2:shells/zsh/115.0
|
||||
- devel c:shells/zsh/115.0 p1:shells/zsh/113.0
|
||||
- factory c:openSUSE:Factory/zsh/46.0 p1:openSUSE:Factory/zsh/45.0 p2:shells/zsh/113.0
|
||||
- devel c:shells/zsh/113.0 p1:shells/zsh/111.0
|
||||
- factory c:openSUSE:Factory/zsh/45.0 p1:openSUSE:Factory/zsh/44.0 p2:shells/zsh/111.0
|
||||
- devel c:shells/zsh/111.0 p1:shells/zsh/109.0
|
||||
- factory c:openSUSE:Factory/zsh/44.0 p1:openSUSE:Factory/zsh/43.0 p2:shells/zsh/109.0
|
||||
- devel c:shells/zsh/109.0 p1:shells/zsh/107.0
|
||||
- factory c:openSUSE:Factory/zsh/43.0 p1:openSUSE:Factory/zsh/42.0 p2:shells/zsh/107.0
|
||||
- devel c:shells/zsh/107.0 p1:shells/zsh/105.0
|
||||
- factory c:openSUSE:Factory/zsh/42.0 p1:openSUSE:Factory/zsh/41.0 p2:shells/zsh/105.0
|
||||
- devel c:shells/zsh/105.0 p1:shells/zsh/103.0
|
||||
- factory c:openSUSE:Factory/zsh/41.0 p1:openSUSE:Factory/zsh/39.0 p2:shells/zsh/103.0
|
||||
- devel c:shells/zsh/103.0 p1:shells/zsh/102.0
|
||||
- devel c:shells/zsh/102.0 p1:shells/zsh/100.0
|
||||
- factory c:openSUSE:Factory/zsh/39.0 p1:openSUSE:Factory/zsh/38.0 p2:shells/zsh/100.0
|
||||
- devel c:shells/zsh/100.0 p1:shells/zsh/98.0
|
||||
- factory c:openSUSE:Factory/zsh/38.0 p1:openSUSE:Factory/zsh/37.0 p2:shells/zsh/98.0
|
||||
- devel c:shells/zsh/98.0 p1:shells/zsh/95.0
|
||||
- factory c:openSUSE:Factory/zsh/37.0 p1:openSUSE:Factory/zsh/36.0 p2:shells/zsh/95.0
|
||||
- devel c:shells/zsh/95.0 p1:shells/zsh/94.0
|
||||
- devel c:shells/zsh/94.0 p1:shells/zsh/91.0
|
||||
- devel c:shells/zsh/91.0 p1:shells/zsh/90.0
|
||||
- factory c:openSUSE:Factory/zsh/36.0 p1:openSUSE:Factory/zsh/35.0 p2:shells/zsh/90.0
|
||||
- devel c:shells/zsh/90.0 p1:shells/zsh/89.0
|
||||
- devel c:shells/zsh/89.0 p1:shells/zsh/88.0
|
||||
- devel c:shells/zsh/88.0 p1:shells/zsh/87.0
|
||||
- devel c:shells/zsh/87.0 p1:shells/zsh/84.0
|
||||
- factory c:openSUSE:Factory/zsh/35.0 p1:openSUSE:Factory/zsh/34.0 p2:shells/zsh/84.0
|
||||
- devel c:shells/zsh/84.0 p1:shells/zsh/83.0
|
||||
- devel c:shells/zsh/83.0 p1:shells/zsh/82.0
|
||||
- devel c:shells/zsh/82.0 p1:shells/zsh/81.0
|
||||
- devel c:shells/zsh/81.0 p1:shells/zsh/80.0
|
||||
- devel c:shells/zsh/80.0 p1:shells/zsh/77.0
|
||||
- factory c:openSUSE:Factory/zsh/34.0 p1:openSUSE:Factory/zsh/32.0 p2:shells/zsh/77.0
|
||||
- devel c:shells/zsh/77.0 p1:shells/zsh/76.032
|
||||
- devel c:shells/zsh/76.032 p1:shells/zsh/75.0
|
||||
- factory c:openSUSE:Factory/zsh/32.0 p1:openSUSE:Factory/zsh/31.0
|
||||
- factory c:openSUSE:Factory/zsh/31.0 p1:openSUSE:Factory/zsh/30.0 p2:shells/zsh/75.0
|
||||
- devel c:shells/zsh/75.0 p1:shells/zsh/74.0
|
||||
- devel c:shells/zsh/74.0 p1:shells/zsh/73.0
|
||||
- devel c:shells/zsh/73.0 p1:shells/zsh/72.03
|
||||
- devel c:shells/zsh/72.03 p1:shells/zsh/71.0
|
||||
- factory c:openSUSE:Factory/zsh/30.0 p1:openSUSE:Factory/zsh/29.0
|
||||
- factory c:openSUSE:Factory/zsh/29.0 p1:openSUSE:Factory/zsh/28.0 p2:shells/zsh/71.0
|
||||
- devel c:shells/zsh/71.0 p1:shells/zsh/69.0
|
||||
- factory c:openSUSE:Factory/zsh/28.0 p1:openSUSE:Factory/zsh/27.0 p2:shells/zsh/69.0
|
||||
- devel c:shells/zsh/69.0 p1:shells/zsh/68.0
|
||||
- devel c:shells/zsh/68.0 p1:shells/zsh/67.027
|
||||
- devel c:shells/zsh/67.027 p1:shells/zsh/66.0
|
||||
- factory c:openSUSE:Factory/zsh/27.0 p1:openSUSE:Factory/zsh/26.0
|
||||
- factory c:openSUSE:Factory/zsh/26.0 p1:openSUSE:Factory/zsh/25.0 p2:shells/zsh/66.0
|
||||
- devel c:shells/zsh/66.0 p1:shells/zsh/65.0
|
||||
- devel c:shells/zsh/65.0 p1:shells/zsh/64.0
|
||||
- devel c:shells/zsh/64.0 p1:shells/zsh/63.0
|
||||
- devel c:shells/zsh/63.0 p1:shells/zsh/62.0
|
||||
- devel c:shells/zsh/62.0 p1:shells/zsh/61.0
|
||||
- devel c:shells/zsh/61.0 p1:shells/zsh/60.0
|
||||
- devel c:shells/zsh/60.0 p1:shells/zsh/59.0
|
||||
- devel c:shells/zsh/59.0 p1:shells/zsh/58.0
|
||||
- devel c:shells/zsh/58.0 p1:shells/zsh/57.0
|
||||
- devel c:shells/zsh/57.0 p1:shells/zsh/56.0
|
||||
- devel c:shells/zsh/56.0 p1:shells/zsh/55.0
|
||||
- devel c:shells/zsh/55.0 p1:shells/zsh/54.0
|
||||
- devel c:shells/zsh/54.0 p1:shells/zsh/53.0
|
||||
- devel c:shells/zsh/53.0 p1:shells/zsh/52.0
|
||||
- devel c:shells/zsh/52.0 p1:shells/zsh/51.0
|
||||
- devel c:shells/zsh/51.0 p1:shells/zsh/50.0
|
||||
- devel c:shells/zsh/50.0 p1:shells/zsh/49.0
|
||||
- devel c:shells/zsh/49.0 p1:shells/zsh/48.0
|
||||
- devel c:shells/zsh/48.0 p1:shells/zsh/47.0
|
||||
- devel c:shells/zsh/47.0 p1:shells/zsh/46.025
|
||||
- devel c:shells/zsh/46.025 p1:shells/zsh/45.0
|
||||
- factory c:openSUSE:Factory/zsh/25.0 p1:openSUSE:Factory/zsh/24.0
|
||||
- factory c:openSUSE:Factory/zsh/24.0 p1:openSUSE:Factory/zsh/23.0 p2:shells/zsh/45.0
|
||||
- devel c:shells/zsh/45.0 p1:shells/zsh/44.0
|
||||
- devel c:shells/zsh/44.0 p1:shells/zsh/43.023
|
||||
- devel c:shells/zsh/43.023 p1:shells/zsh/42.0
|
||||
- factory c:openSUSE:Factory/zsh/23.0 p1:openSUSE:Factory/zsh/22.0
|
||||
- factory c:openSUSE:Factory/zsh/22.0 p1:openSUSE:Factory/zsh/18.0 p2:shells/zsh/42.0
|
||||
- devel c:shells/zsh/42.0 p1:shells/zsh/41.035
|
||||
- devel c:shells/zsh/41.035 p1:shells/zsh/41.017
|
||||
- factory c:openSUSE:Factory/zsh/18.0 p1:openSUSE:Factory/zsh/17.0
|
||||
- factory c:openSUSE:Factory/zsh/17.0 p1:openSUSE:Factory/zsh/16.0 p2:shells/zsh/41.017
|
||||
- devel c:shells/zsh/41.017 p1:shells/zsh/41.0
|
||||
- devel c:shells/zsh/41.0 p1:shells/zsh/40.0
|
||||
- devel c:shells/zsh/40.0 p1:shells/zsh/39.0
|
||||
- devel c:shells/zsh/39.0 p1:shells/zsh/38.0
|
||||
- devel c:shells/zsh/38.0 p1:shells/zsh/37.0
|
||||
- devel c:shells/zsh/37.0 p1:shells/zsh/36.014
|
||||
- factory c:openSUSE:Factory/zsh/16.0 p1:openSUSE:Factory/zsh/14.0
|
||||
- factory c:openSUSE:Factory/zsh/14.0 p1:openSUSE:Factory/zsh/13.0 p2:shells/zsh/36.014
|
||||
- devel c:shells/zsh/36.014 p1:shells/zsh/36.0
|
||||
- devel c:shells/zsh/36.0 p1:shells/zsh/35.0
|
||||
- devel c:shells/zsh/35.0 p1:shells/zsh/34.0
|
||||
- factory c:openSUSE:Factory/zsh/13.0 p1:openSUSE:Factory/zsh/12.0 p2:shells/zsh/34.0
|
||||
- devel c:shells/zsh/34.0 p1:shells/zsh/33.0
|
||||
- devel c:shells/zsh/33.0 p1:shells/zsh/32.0
|
||||
- devel c:shells/zsh/32.0 p1:openSUSE:Factory/zsh/12.0
|
||||
- factory c:openSUSE:Factory/zsh/12.0 p1:openSUSE:Factory/zsh/11.0
|
||||
- factory c:openSUSE:Factory/zsh/11.0 p1:openSUSE:Factory/zsh/10.0
|
||||
- factory c:openSUSE:Factory/zsh/10.0 p1:openSUSE:Factory/zsh/9.0
|
||||
- factory c:openSUSE:Factory/zsh/9.0 p1:openSUSE:Factory/zsh/8.0
|
||||
- factory c:openSUSE:Factory/zsh/8.0 p1:openSUSE:Factory/zsh/7.0
|
||||
- factory c:openSUSE:Factory/zsh/7.0 p1:openSUSE:Factory/zsh/6.0
|
||||
- factory c:openSUSE:Factory/zsh/6.0 p1:openSUSE:Factory/zsh/5.0
|
||||
- factory c:openSUSE:Factory/zsh/5.0 p1:openSUSE:Factory/zsh/4.0
|
||||
- factory c:openSUSE:Factory/zsh/4.0 p1:openSUSE:Factory/zsh/3.0
|
||||
- factory c:openSUSE:Factory/zsh/3.0 p1:openSUSE:Factory/zsh/2.0
|
||||
- factory c:openSUSE:Factory/zsh/2.0 p1:openSUSE:Factory/zsh/1.0
|
||||
- factory c:openSUSE:Factory/zsh/1.0
|
493
tests/fixtures/zsh-expected-tree.yaml
vendored
493
tests/fixtures/zsh-expected-tree.yaml
vendored
@ -1,300 +1,265 @@
|
||||
- commit: Rev openSUSE:Factory/zsh/98.0
|
||||
- commit: openSUSE:Factory/zsh/87.0
|
||||
merged:
|
||||
- Rev shells/zsh/236.0
|
||||
- commit: Rev openSUSE:Factory/zsh/97.0
|
||||
- shells/zsh/210.0
|
||||
- shells/zsh/209.0
|
||||
- shells/zsh/208.0
|
||||
- shells/zsh/207.0
|
||||
- commit: openSUSE:Factory/zsh/86.0
|
||||
merged:
|
||||
- Rev shells/zsh/234.0
|
||||
- commit: Rev openSUSE:Factory/zsh/96.0
|
||||
- shells/zsh/205.0
|
||||
- shells/zsh/204.0
|
||||
- commit: openSUSE:Factory/zsh/85.0
|
||||
merged:
|
||||
- Rev shells/zsh/232.0
|
||||
- commit: Rev openSUSE:Factory/zsh/95.0
|
||||
- shells/zsh/202.0
|
||||
- shells/zsh/201.0
|
||||
- commit: openSUSE:Factory/zsh/84.0
|
||||
merged:
|
||||
- Rev shells/zsh/230.0
|
||||
- commit: Rev openSUSE:Factory/zsh/94.0
|
||||
- shells/zsh/199.0
|
||||
- shells/zsh/198.0
|
||||
- shells/zsh/197.0
|
||||
- commit: openSUSE:Factory/zsh/83.0
|
||||
merged:
|
||||
- Rev shells/zsh/228.0
|
||||
- Rev shells/zsh/227.0
|
||||
- commit: Rev openSUSE:Factory/zsh/93.0
|
||||
- shells/zsh/195.0
|
||||
- shells/zsh/194.0
|
||||
- shells/zsh/193.0
|
||||
- shells/zsh/192.0
|
||||
- shells/zsh/191.0
|
||||
- commit: openSUSE:Factory/zsh/82.0
|
||||
merged:
|
||||
- Rev shells/zsh/225.0
|
||||
- Rev shells/zsh/224.0
|
||||
- Rev shells/zsh/223.0
|
||||
- commit: Rev openSUSE:Factory/zsh/92.0
|
||||
- shells/zsh/189.0
|
||||
- commit: openSUSE:Factory/zsh/81.0
|
||||
merged:
|
||||
- Rev shells/zsh/221.0
|
||||
- commit: Rev openSUSE:Factory/zsh/91.0
|
||||
- shells/zsh/187.0
|
||||
- shells/zsh/186.0
|
||||
- commit: openSUSE:Factory/zsh/80.0
|
||||
merged:
|
||||
- Rev shells/zsh/219.0
|
||||
- commit: Rev openSUSE:Factory/zsh/90.0
|
||||
- shells/zsh/184.0
|
||||
- commit: openSUSE:Factory/zsh/79.0
|
||||
merged:
|
||||
- Rev shells/zsh/217.0
|
||||
- commit: Rev openSUSE:Factory/zsh/89.0
|
||||
- shells/zsh/182.0
|
||||
- commit: openSUSE:Factory/zsh/78.0
|
||||
merged:
|
||||
- Rev shells/zsh/215.0
|
||||
- Rev shells/zsh/214.0
|
||||
- commit: Rev openSUSE:Factory/zsh/88.0
|
||||
- shells/zsh/180.0
|
||||
- commit: openSUSE:Factory/zsh/77.0
|
||||
merged:
|
||||
- Rev shells/zsh/212.0
|
||||
- commit: Rev openSUSE:Factory/zsh/87.0
|
||||
- shells/zsh/178.0
|
||||
- shells/zsh/177.0
|
||||
- commit: openSUSE:Factory/zsh/76.0
|
||||
merged:
|
||||
- Rev shells/zsh/210.0
|
||||
- Rev shells/zsh/209.0
|
||||
- Rev shells/zsh/208.0
|
||||
- Rev shells/zsh/207.0
|
||||
- commit: Rev openSUSE:Factory/zsh/86.0
|
||||
- shells/zsh/175.0
|
||||
- commit: openSUSE:Factory/zsh/75.0
|
||||
merged:
|
||||
- Rev shells/zsh/205.0
|
||||
- Rev shells/zsh/204.0
|
||||
- commit: Rev openSUSE:Factory/zsh/85.0
|
||||
- shells/zsh/173.0
|
||||
- commit: openSUSE:Factory/zsh/74.0
|
||||
merged:
|
||||
- Rev shells/zsh/202.0
|
||||
- Rev shells/zsh/201.0
|
||||
- commit: Rev openSUSE:Factory/zsh/84.0
|
||||
- shells/zsh/171.0
|
||||
- shells/zsh/170.0
|
||||
- commit: openSUSE:Factory/zsh/73.0
|
||||
merged:
|
||||
- Rev shells/zsh/199.0
|
||||
- Rev shells/zsh/198.0
|
||||
- Rev shells/zsh/197.0
|
||||
- commit: Rev openSUSE:Factory/zsh/83.0
|
||||
- shells/zsh/168.0
|
||||
- commit: openSUSE:Factory/zsh/72.0
|
||||
merged:
|
||||
- Rev shells/zsh/195.0
|
||||
- Rev shells/zsh/194.0
|
||||
- Rev shells/zsh/193.0
|
||||
- Rev shells/zsh/192.0
|
||||
- Rev shells/zsh/191.0
|
||||
- commit: Rev openSUSE:Factory/zsh/82.0
|
||||
- shells/zsh/166.0
|
||||
- commit: openSUSE:Factory/zsh/71.0
|
||||
merged:
|
||||
- Rev shells/zsh/189.0
|
||||
- commit: Rev openSUSE:Factory/zsh/81.0
|
||||
- shells/zsh/164.0
|
||||
- commit: openSUSE:Factory/zsh/70.0
|
||||
merged:
|
||||
- Rev shells/zsh/187.0
|
||||
- Rev shells/zsh/186.0
|
||||
- commit: Rev openSUSE:Factory/zsh/80.0
|
||||
- shells/zsh/162.0
|
||||
- commit: openSUSE:Factory/zsh/69.0
|
||||
merged:
|
||||
- Rev shells/zsh/184.0
|
||||
- commit: Rev openSUSE:Factory/zsh/79.0
|
||||
- shells/zsh/160.0
|
||||
- shells/zsh/159.0
|
||||
- shells/zsh/158.0
|
||||
- commit: openSUSE:Factory/zsh/68.0
|
||||
merged:
|
||||
- Rev shells/zsh/182.0
|
||||
- commit: Rev openSUSE:Factory/zsh/78.0
|
||||
- shells/zsh/156.0
|
||||
- commit: openSUSE:Factory/zsh/67.0
|
||||
merged:
|
||||
- Rev shells/zsh/180.0
|
||||
- commit: Rev openSUSE:Factory/zsh/77.0
|
||||
- shells/zsh/154.0
|
||||
- shells/zsh/153.0
|
||||
- commit: openSUSE:Factory/zsh/66.0
|
||||
merged:
|
||||
- Rev shells/zsh/178.0
|
||||
- Rev shells/zsh/177.0
|
||||
- commit: Rev openSUSE:Factory/zsh/76.0
|
||||
- shells/zsh/151.0
|
||||
- shells/zsh/150.0
|
||||
- commit: openSUSE:Factory/zsh/65.0
|
||||
merged:
|
||||
- Rev shells/zsh/175.0
|
||||
- commit: Rev openSUSE:Factory/zsh/75.0
|
||||
- shells/zsh/148.0
|
||||
- commit: openSUSE:Factory/zsh/64.0
|
||||
merged:
|
||||
- Rev shells/zsh/173.0
|
||||
- commit: Rev openSUSE:Factory/zsh/74.0
|
||||
- shells/zsh/146.0
|
||||
- shells/zsh/145.0
|
||||
- shells/zsh/144.0
|
||||
- commit: openSUSE:Factory/zsh/63.0
|
||||
merged:
|
||||
- Rev shells/zsh/171.0
|
||||
- Rev shells/zsh/170.0
|
||||
- commit: Rev openSUSE:Factory/zsh/73.0
|
||||
- shells/zsh/142.0
|
||||
- commit: openSUSE:Factory/zsh/62.0
|
||||
merged:
|
||||
- Rev shells/zsh/168.0
|
||||
- commit: Rev openSUSE:Factory/zsh/72.0
|
||||
- shells/zsh/140.0
|
||||
- commit: openSUSE:Factory/zsh/61.0
|
||||
merged:
|
||||
- Rev shells/zsh/166.0
|
||||
- commit: Rev openSUSE:Factory/zsh/71.0
|
||||
- shells/zsh/138.0
|
||||
- shells/zsh/137.0
|
||||
- commit: openSUSE:Factory/zsh/60.0
|
||||
merged:
|
||||
- Rev shells/zsh/164.0
|
||||
- commit: Rev openSUSE:Factory/zsh/70.0
|
||||
- shells/zsh/135.0
|
||||
- commit: openSUSE:Factory/zsh/59.0
|
||||
merged:
|
||||
- Rev shells/zsh/162.0
|
||||
- commit: Rev openSUSE:Factory/zsh/69.0
|
||||
- shells/zsh/133.0
|
||||
- commit: openSUSE:Factory/zsh/57.0
|
||||
merged:
|
||||
- Rev shells/zsh/160.0
|
||||
- Rev shells/zsh/159.0
|
||||
- Rev shells/zsh/158.0
|
||||
- commit: Rev openSUSE:Factory/zsh/68.0
|
||||
- shells/zsh/131.0
|
||||
- commit: openSUSE:Factory/zsh/56.0
|
||||
merged:
|
||||
- Rev shells/zsh/156.0
|
||||
- commit: Rev openSUSE:Factory/zsh/67.0
|
||||
- shells/zsh/129.0
|
||||
- commit: openSUSE:Factory/zsh/55.0
|
||||
merged:
|
||||
- Rev shells/zsh/154.0
|
||||
- Rev shells/zsh/153.0
|
||||
- commit: Rev openSUSE:Factory/zsh/66.0
|
||||
- shells/zsh/127.0
|
||||
- commit: openSUSE:Factory/zsh/54.0
|
||||
merged:
|
||||
- Rev shells/zsh/151.0
|
||||
- Rev shells/zsh/150.0
|
||||
- commit: Rev openSUSE:Factory/zsh/65.0
|
||||
- shells/zsh/125.0
|
||||
- commit: openSUSE:Factory/zsh/53.0
|
||||
merged:
|
||||
- shells/zsh/123.0
|
||||
- commit: openSUSE:Factory/zsh/51.0
|
||||
merged:
|
||||
- Rev shells/zsh/148.0
|
||||
- commit: Rev openSUSE:Factory/zsh/64.0
|
||||
- shells/zsh/121.0
|
||||
- commit: openSUSE:Factory/zsh/50.0
|
||||
merged:
|
||||
- Rev shells/zsh/146.0
|
||||
- Rev shells/zsh/145.0
|
||||
- Rev shells/zsh/144.0
|
||||
- commit: Rev openSUSE:Factory/zsh/63.0
|
||||
- shells/zsh/119.0
|
||||
- commit: openSUSE:Factory/zsh/49.0
|
||||
merged:
|
||||
- Rev shells/zsh/142.0
|
||||
- commit: Rev openSUSE:Factory/zsh/62.0
|
||||
merged:
|
||||
- Rev shells/zsh/140.0
|
||||
- commit: Rev openSUSE:Factory/zsh/61.0
|
||||
merged:
|
||||
- Rev shells/zsh/138.0
|
||||
- Rev shells/zsh/137.0
|
||||
- commit: Rev openSUSE:Factory/zsh/60.0
|
||||
merged:
|
||||
- Rev shells/zsh/135.0
|
||||
- commit: Rev openSUSE:Factory/zsh/59.0
|
||||
merged:
|
||||
- Rev shells/zsh/133.0
|
||||
- commit: Rev openSUSE:Factory/zsh/57.0
|
||||
merged:
|
||||
- Rev shells/zsh/131.0
|
||||
- commit: Rev openSUSE:Factory/zsh/56.0
|
||||
merged:
|
||||
- Rev shells/zsh/129.0
|
||||
- commit: Rev openSUSE:Factory/zsh/55.0
|
||||
merged:
|
||||
- Rev shells/zsh/127.0
|
||||
- commit: Rev openSUSE:Factory/zsh/54.0
|
||||
merged:
|
||||
- Rev shells/zsh/125.0
|
||||
- commit: Rev openSUSE:Factory/zsh/53.0
|
||||
merged:
|
||||
- Rev shells/zsh/123.0
|
||||
- commit: Rev openSUSE:Factory/zsh/51.0
|
||||
merged:
|
||||
- Rev shells/zsh/121.0
|
||||
- commit: Rev openSUSE:Factory/zsh/50.0
|
||||
merged:
|
||||
- Rev shells/zsh/119.0
|
||||
- commit: Rev openSUSE:Factory/zsh/49.0
|
||||
merged:
|
||||
- Rev shells/zsh/117.0
|
||||
- commit: Rev openSUSE:Factory/zsh/48.0
|
||||
merged:
|
||||
- Rev shells/zsh/115.0
|
||||
- commit: Rev openSUSE:Factory/zsh/46.0
|
||||
merged:
|
||||
- Rev shells/zsh/113.0
|
||||
- commit: Rev openSUSE:Factory/zsh/45.0
|
||||
merged:
|
||||
- Rev shells/zsh/111.0
|
||||
- commit: Rev openSUSE:Factory/zsh/44.0
|
||||
merged:
|
||||
- Rev shells/zsh/109.0
|
||||
- commit: Rev openSUSE:Factory/zsh/43.0
|
||||
merged:
|
||||
- Rev shells/zsh/107.0
|
||||
- commit: Rev openSUSE:Factory/zsh/42.0
|
||||
merged:
|
||||
- Rev shells/zsh/105.0
|
||||
- commit: Rev openSUSE:Factory/zsh/41.0
|
||||
merged:
|
||||
- Rev shells/zsh/103.0
|
||||
- Rev shells/zsh/102.0
|
||||
- commit: Rev openSUSE:Factory/zsh/39.0
|
||||
merged:
|
||||
- Rev shells/zsh/100.0
|
||||
- commit: Rev openSUSE:Factory/zsh/38.0
|
||||
merged:
|
||||
- Rev shells/zsh/98.0
|
||||
- commit: Rev openSUSE:Factory/zsh/37.0
|
||||
merged:
|
||||
- Rev shells/zsh/95.0
|
||||
- Rev shells/zsh/94.0
|
||||
- Rev shells/zsh/91.0
|
||||
- commit: Rev openSUSE:Factory/zsh/36.0
|
||||
merged:
|
||||
- Rev shells/zsh/90.0
|
||||
- Rev shells/zsh/89.0
|
||||
- Rev shells/zsh/88.0
|
||||
- Rev shells/zsh/87.0
|
||||
- commit: Rev openSUSE:Factory/zsh/35.0
|
||||
merged:
|
||||
- Rev shells/zsh/84.0
|
||||
- Rev shells/zsh/83.0
|
||||
- Rev shells/zsh/82.0
|
||||
- Rev shells/zsh/81.0
|
||||
- Rev shells/zsh/80.0
|
||||
- commit: Rev openSUSE:Factory/zsh/34.0
|
||||
merged:
|
||||
- Rev shells/zsh/77.0
|
||||
- Rev shells/zsh/76.032
|
||||
- commit: Rev openSUSE:Factory/zsh/32.0
|
||||
- commit: Rev openSUSE:Factory/zsh/31.0
|
||||
merged:
|
||||
- Rev shells/zsh/75.0
|
||||
- Rev shells/zsh/74.0
|
||||
- Rev shells/zsh/73.0
|
||||
- Rev shells/zsh/72.03
|
||||
- commit: Rev openSUSE:Factory/zsh/30.0
|
||||
- commit: Rev openSUSE:Factory/zsh/29.0
|
||||
merged:
|
||||
- Rev shells/zsh/71.0
|
||||
- commit: Rev openSUSE:Factory/zsh/28.0
|
||||
merged:
|
||||
- Rev shells/zsh/69.0
|
||||
- Rev shells/zsh/68.0
|
||||
- Rev shells/zsh/67.027
|
||||
- commit: Rev openSUSE:Factory/zsh/27.0
|
||||
- commit: Rev openSUSE:Factory/zsh/26.0
|
||||
merged:
|
||||
- Rev shells/zsh/66.0
|
||||
- Rev shells/zsh/65.0
|
||||
- Rev shells/zsh/64.0
|
||||
- Rev shells/zsh/63.0
|
||||
- Rev shells/zsh/62.0
|
||||
- Rev shells/zsh/61.0
|
||||
- Rev shells/zsh/60.0
|
||||
- Rev shells/zsh/59.0
|
||||
- Rev shells/zsh/58.0
|
||||
- Rev shells/zsh/57.0
|
||||
- Rev shells/zsh/56.0
|
||||
- Rev shells/zsh/55.0
|
||||
- Rev shells/zsh/54.0
|
||||
- Rev shells/zsh/53.0
|
||||
- Rev shells/zsh/52.0
|
||||
- Rev shells/zsh/51.0
|
||||
- Rev shells/zsh/50.0
|
||||
- Rev shells/zsh/49.0
|
||||
- Rev shells/zsh/48.0
|
||||
- Rev shells/zsh/47.0
|
||||
- Rev shells/zsh/46.025
|
||||
- commit: Rev openSUSE:Factory/zsh/25.0
|
||||
- commit: Rev openSUSE:Factory/zsh/24.0
|
||||
merged:
|
||||
- Rev shells/zsh/45.0
|
||||
- Rev shells/zsh/44.0
|
||||
- Rev shells/zsh/43.023
|
||||
- commit: Rev openSUSE:Factory/zsh/23.0
|
||||
- commit: Rev openSUSE:Factory/zsh/22.0
|
||||
merged:
|
||||
- Rev shells/zsh/42.0
|
||||
- Rev shells/zsh/41.035
|
||||
- commit: Rev openSUSE:Factory/zsh/18.0
|
||||
- commit: Rev openSUSE:Factory/zsh/17.0
|
||||
merged:
|
||||
- Rev shells/zsh/41.017
|
||||
- Rev shells/zsh/41.0
|
||||
- Rev shells/zsh/40.0
|
||||
- Rev shells/zsh/39.0
|
||||
- Rev shells/zsh/38.0
|
||||
- Rev shells/zsh/37.0
|
||||
- commit: Rev openSUSE:Factory/zsh/16.0
|
||||
- commit: Rev openSUSE:Factory/zsh/14.0
|
||||
merged:
|
||||
- Rev shells/zsh/36.014
|
||||
- Rev shells/zsh/36.0
|
||||
- Rev shells/zsh/35.0
|
||||
- commit: Rev openSUSE:Factory/zsh/13.0
|
||||
merged:
|
||||
- Rev shells/zsh/34.0
|
||||
- commit: Rev openSUSE:Factory/zsh/12.0
|
||||
- commit: Rev openSUSE:Factory/zsh/11.0
|
||||
- commit: Rev openSUSE:Factory/zsh/10.0
|
||||
- commit: Rev openSUSE:Factory/zsh/9.0
|
||||
- commit: Rev openSUSE:Factory/zsh/8.0
|
||||
- commit: Rev openSUSE:Factory/zsh/7.0
|
||||
- commit: Rev openSUSE:Factory/zsh/6.0
|
||||
- commit: Rev openSUSE:Factory/zsh/5.0
|
||||
- commit: Rev openSUSE:Factory/zsh/4.0
|
||||
- commit: Rev openSUSE:Factory/zsh/3.0
|
||||
- commit: Rev openSUSE:Factory/zsh/2.0
|
||||
- commit: Rev openSUSE:Factory/zsh/1.0
|
||||
- shells/zsh/117.0
|
||||
- commit: openSUSE:Factory/zsh/48.0
|
||||
merged:
|
||||
- shells/zsh/115.0
|
||||
- commit: openSUSE:Factory/zsh/46.0
|
||||
merged:
|
||||
- shells/zsh/113.0
|
||||
- commit: openSUSE:Factory/zsh/45.0
|
||||
merged:
|
||||
- shells/zsh/111.0
|
||||
- commit: openSUSE:Factory/zsh/44.0
|
||||
merged:
|
||||
- shells/zsh/109.0
|
||||
- commit: openSUSE:Factory/zsh/43.0
|
||||
merged:
|
||||
- shells/zsh/107.0
|
||||
- commit: openSUSE:Factory/zsh/42.0
|
||||
merged:
|
||||
- shells/zsh/105.0
|
||||
- commit: openSUSE:Factory/zsh/41.0
|
||||
merged:
|
||||
- shells/zsh/103.0
|
||||
- shells/zsh/102.0
|
||||
- commit: openSUSE:Factory/zsh/39.0
|
||||
merged:
|
||||
- shells/zsh/100.0
|
||||
- commit: openSUSE:Factory/zsh/38.0
|
||||
merged:
|
||||
- shells/zsh/98.0
|
||||
- commit: openSUSE:Factory/zsh/37.0
|
||||
merged:
|
||||
- shells/zsh/95.0
|
||||
- shells/zsh/94.0
|
||||
- shells/zsh/91.0
|
||||
- commit: openSUSE:Factory/zsh/36.0
|
||||
merged:
|
||||
- shells/zsh/90.0
|
||||
- shells/zsh/89.0
|
||||
- shells/zsh/88.0
|
||||
- shells/zsh/87.0
|
||||
- commit: openSUSE:Factory/zsh/35.0
|
||||
merged:
|
||||
- shells/zsh/84.0
|
||||
- shells/zsh/83.0
|
||||
- shells/zsh/82.0
|
||||
- shells/zsh/81.0
|
||||
- shells/zsh/80.0
|
||||
- commit: openSUSE:Factory/zsh/34.0
|
||||
merged:
|
||||
- shells/zsh/77.0
|
||||
- shells/zsh/76.032
|
||||
- commit: openSUSE:Factory/zsh/32.0
|
||||
- commit: openSUSE:Factory/zsh/31.0
|
||||
merged:
|
||||
- shells/zsh/75.0
|
||||
- shells/zsh/74.0
|
||||
- shells/zsh/73.0
|
||||
- shells/zsh/72.03
|
||||
- commit: openSUSE:Factory/zsh/30.0
|
||||
- commit: openSUSE:Factory/zsh/29.0
|
||||
merged:
|
||||
- shells/zsh/71.0
|
||||
- commit: openSUSE:Factory/zsh/28.0
|
||||
merged:
|
||||
- shells/zsh/69.0
|
||||
- shells/zsh/68.0
|
||||
- shells/zsh/67.027
|
||||
- commit: openSUSE:Factory/zsh/27.0
|
||||
- commit: openSUSE:Factory/zsh/26.0
|
||||
merged:
|
||||
- shells/zsh/66.0
|
||||
- shells/zsh/65.0
|
||||
- shells/zsh/64.0
|
||||
- shells/zsh/63.0
|
||||
- shells/zsh/62.0
|
||||
- shells/zsh/61.0
|
||||
- shells/zsh/60.0
|
||||
- shells/zsh/59.0
|
||||
- shells/zsh/58.0
|
||||
- shells/zsh/57.0
|
||||
- shells/zsh/56.0
|
||||
- shells/zsh/55.0
|
||||
- shells/zsh/54.0
|
||||
- shells/zsh/53.0
|
||||
- shells/zsh/52.0
|
||||
- shells/zsh/51.0
|
||||
- shells/zsh/50.0
|
||||
- shells/zsh/49.0
|
||||
- shells/zsh/48.0
|
||||
- shells/zsh/47.0
|
||||
- shells/zsh/46.025
|
||||
- commit: openSUSE:Factory/zsh/25.0
|
||||
- commit: openSUSE:Factory/zsh/24.0
|
||||
merged:
|
||||
- shells/zsh/45.0
|
||||
- shells/zsh/44.0
|
||||
- shells/zsh/43.023
|
||||
- commit: openSUSE:Factory/zsh/23.0
|
||||
- commit: openSUSE:Factory/zsh/22.0
|
||||
merged:
|
||||
- shells/zsh/42.0
|
||||
- shells/zsh/41.035
|
||||
- commit: openSUSE:Factory/zsh/18.0
|
||||
- commit: openSUSE:Factory/zsh/17.0
|
||||
merged:
|
||||
- shells/zsh/41.017
|
||||
- shells/zsh/41.0
|
||||
- shells/zsh/40.0
|
||||
- shells/zsh/39.0
|
||||
- shells/zsh/38.0
|
||||
- shells/zsh/37.0
|
||||
- commit: openSUSE:Factory/zsh/16.0
|
||||
- commit: openSUSE:Factory/zsh/14.0
|
||||
merged:
|
||||
- shells/zsh/36.014
|
||||
- shells/zsh/36.0
|
||||
- shells/zsh/35.0
|
||||
- commit: openSUSE:Factory/zsh/13.0
|
||||
merged:
|
||||
- shells/zsh/34.0
|
||||
- shells/zsh/33.0
|
||||
- shells/zsh/32.0
|
||||
- commit: openSUSE:Factory/zsh/12.0
|
||||
- commit: openSUSE:Factory/zsh/11.0
|
||||
- commit: openSUSE:Factory/zsh/10.0
|
||||
- commit: openSUSE:Factory/zsh/9.0
|
||||
- commit: openSUSE:Factory/zsh/8.0
|
||||
- commit: openSUSE:Factory/zsh/7.0
|
||||
- commit: openSUSE:Factory/zsh/6.0
|
||||
- commit: openSUSE:Factory/zsh/5.0
|
||||
- commit: openSUSE:Factory/zsh/4.0
|
||||
- commit: openSUSE:Factory/zsh/3.0
|
||||
- commit: openSUSE:Factory/zsh/2.0
|
||||
- commit: openSUSE:Factory/zsh/1.0
|
||||
|
@ -19,7 +19,7 @@ class TestTreeMethods(unittest.TestCase):
|
||||
for rev in data["revisions"]:
|
||||
DBRevision.import_fixture_dict(self.db, rev)
|
||||
|
||||
revisions = TreeBuilder(self.db).build(package)
|
||||
revisions = TreeBuilder(self.db).build("openSUSE:Factory", package)
|
||||
path = os.path.join(
|
||||
os.path.dirname(__file__), f"fixtures/{package}-expected-tree.yaml"
|
||||
)
|
||||
@ -31,6 +31,20 @@ class TestTreeMethods(unittest.TestCase):
|
||||
with open(path, "r") as f:
|
||||
data = yaml.safe_load(f)
|
||||
self.assertEqual(data, revisions.as_list())
|
||||
|
||||
# verify flat lists
|
||||
path = os.path.join(
|
||||
os.path.dirname(__file__), f"fixtures/{package}-expected-list.yaml"
|
||||
)
|
||||
flat_list = [str(x) for x in revisions.as_flat_list()]
|
||||
if os.getenv("REGENERATE_DATA"):
|
||||
with open(path, "w") as f:
|
||||
yaml.dump(flat_list, f)
|
||||
|
||||
with open(path, "r") as f:
|
||||
data = yaml.safe_load(f)
|
||||
self.assertEqual(data, flat_list)
|
||||
|
||||
self.db.conn.rollback()
|
||||
|
||||
def test_zsh_tree(self):
|
||||
@ -39,6 +53,18 @@ class TestTreeMethods(unittest.TestCase):
|
||||
def test_clapper_tree(self):
|
||||
self.verify_package("clapper")
|
||||
|
||||
def test_llvm13_tree(self):
|
||||
self.verify_package("llvm13")
|
||||
|
||||
def test_2048_cli_tree(self):
|
||||
self.verify_package("2048-cli")
|
||||
|
||||
def test_corefreq_tree(self):
|
||||
self.verify_package("CoreFreq")
|
||||
|
||||
def test_000update_repos_tree(self):
|
||||
self.verify_package("000update-repos")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
Loading…
Reference in New Issue
Block a user