-
Notifications
You must be signed in to change notification settings - Fork 119
/
copy.py
136 lines (106 loc) · 5.27 KB
/
copy.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
from django.core.exceptions import MultipleObjectsReturned
from django.db import transaction
from django.db.models import Q
from pulpcore.plugin.models import Content, RepositoryVersion
from pulp_rpm.app.depsolving import Solver
from pulp_rpm.app.models import UpdateRecord, Package, RpmRepository, Modulemd
def find_children_of_content(content, repository_version):
"""Finds the content referenced directly by other content and returns it all together.
Finds RPMs referenced by Advisory/Errata content.
Args:
content (iterable): Content for which to resolve children
repository_version (pulpcore.models.RepositoryVersion): Source repo version
Returns: Queryset of Content objects that are children of the intial set of content
"""
# Advisories that were selected to be copied
advisory_ids = content.filter(pulp_type=UpdateRecord.get_pulp_type()).only('pk')
# All packages in the source repository version
package_ids = repository_version.content.filter(
pulp_type=Package.get_pulp_type()).only('pk')
# All modules in the source repository version
module_ids = repository_version.content.filter(
pulp_type=Modulemd.get_pulp_type()).only('pk')
advisories = UpdateRecord.objects.filter(pk__in=advisory_ids)
packages = Package.objects.filter(pk__in=package_ids)
modules = Modulemd.objects.filter(pk__in=module_ids)
children = set()
for advisory in advisories:
# Find rpms referenced by Advisories/Errata
package_nevras = advisory.get_pkglist()
for nevra in package_nevras:
(name, epoch, version, release, arch) = nevra
try:
package = packages.get(
name=name, epoch=epoch, version=version, release=release, arch=arch)
children.add(package.pk)
except Package.DoesNotExist:
raise
except MultipleObjectsReturned:
raise
module_nsvcas = advisory.get_module_list()
for nsvca in module_nsvcas:
(name, stream, version, context, arch) = nsvca
try:
module = modules.get(
name=name, stream=stream, version=version, context=context, arch=arch)
children.add(module.pk)
except Modulemd.DoesNotExist:
raise
except MultipleObjectsReturned:
raise
# TODO: Find rpms referenced by PackageGroups,
# PackageGroups referenced by PackageCategories, etc.
return Content.objects.filter(pk__in=children)
@transaction.atomic
def copy_content(config, dependency_solving):
"""
Copy content from one repo to another.
Args:
source_repo_version_pk: repository version primary key to copy units from
dest_repo_pk: repository primary key to copy units into
criteria: a dict that maps type to a list of criteria to filter content by. Note that this
criteria MUST be validated before being passed to this task.
content_pks: a list of content pks to copy from source to destination
"""
for entry in config:
source_repo_version = RepositoryVersion.objects.get(pk=entry["source_repo_version"])
dest_repo = RpmRepository.objects.get(pk=entry["dest_repo"])
dest_version_provided = bool(entry.get("dest_base_version"))
if dest_version_provided:
dest_repo_version = RepositoryVersion.objects.get(pk=entry["dest_base_version"])
else:
dest_repo_version = dest_repo.latest_version()
if entry.get("content"):
content_filter = Q(pk__in=entry.get("content"))
else:
content_filter = Q()
if not dependency_solving:
content_to_copy = source_repo_version.content.filter(content_filter)
content_to_copy |= find_children_of_content(content_to_copy, source_repo_version)
base_version = dest_repo_version if dest_version_provided else None
with dest_repo.new_version(base_version=base_version) as new_version:
new_version.add_content(content_to_copy)
continue
# Dependency Solving Branch
# =========================
content_to_copy = {}
# TODO: add lookaside repos here
repo_mapping = {source_repo_version: dest_repo_version}
libsolv_repo_names = {}
solver = Solver()
for src in repo_mapping.keys():
repo_name = solver.load_source_repo(src)
libsolv_repo_names[repo_name] = src
content = src.content.filter(content_filter)
children = find_children_of_content(content, src)
content_to_copy[repo_name] = content | children
for tgt in repo_mapping.values():
solver.load_target_repo(tgt)
solver.finalize()
content_to_copy = solver.resolve_dependencies(content_to_copy)
for from_repo, units in content_to_copy.items():
src_repo_version = libsolv_repo_names[from_repo]
dest_repo_version = repo_mapping[src_repo_version]
base_version = dest_repo_version if dest_version_provided else None
with dest_repo_version.repository.new_version(base_version=base_version) as new_version:
new_version.add_content(Content.objects.filter(pk__in=units))