@@ -47,7 +47,129 @@ def logger_debug(*args):
4747 return logger .debug (" " .join (isinstance (a , str ) and a or repr (a ) for a in args ))
4848
4949
50- class SwiftShowDependenciesDepLockHandler (models .DatafileHandler ):
50+ class BaseSwiftDatafileHandler (models .DatafileHandler ):
51+ @classmethod
52+ def assemble (cls , package_data , resource , codebase , package_adder ):
53+ swift_manifest_resource = None
54+ swift_show_dependencies_resource = None
55+ swift_resolved_package_resource = None
56+ processed_package = None
57+ add_datafile_paths = []
58+ add_datasource_ids = []
59+ processed_dependencies = []
60+
61+ for r in resource .siblings (codebase ):
62+ if r .name in ("Package.swift.json" , "Package.swift.deplock" ):
63+ swift_manifest_resource = r
64+ elif r .name in ("Package.resolved" , ".package.resolved" ):
65+ swift_resolved_package_resource = r
66+ elif r .name == "swift-show-dependencies.deplock" :
67+ swift_show_dependencies_resource = r
68+
69+ # If only Package.resolved is available then yield all dependency as package.
70+ if (
71+ not swift_manifest_resource
72+ and not swift_show_dependencies_resource
73+ and resource .name in ("Package.resolved" , ".package.resolved" )
74+ ):
75+ processed_package = package_data
76+ processed_dependencies = package_data .dependencies
77+ # If no manifest but have dependency graph from `deplock` then use it construct top-level package.
78+ elif (
79+ not swift_manifest_resource
80+ and resource .name == "swift-show-dependencies.deplock"
81+ ):
82+ processed_package = package_data
83+ processed_dependencies = package_data .dependencies
84+ # If manifest is available then use the manifest to construct top-level package.
85+ elif swift_manifest_resource and resource .name in (
86+ "Package.swift.json" ,
87+ "Package.swift.deplock" ,
88+ ):
89+ processed_dependencies = package_data .dependencies
90+ # Dependencies from `swift-show-dependencies.deplock` supersedes dependencies from other datafiles.
91+ if swift_show_dependencies_resource :
92+ swift_show_dependencies_package_data = models .PackageData .from_dict (
93+ swift_show_dependencies_resource .package_data [0 ]
94+ )
95+ processed_dependencies = (
96+ swift_show_dependencies_package_data .dependencies
97+ )
98+ # Use dependencies from `Package.resolved` when `swift-show-dependencies.deplock` is not present.
99+ elif swift_resolved_package_resource :
100+ swift_resolved_package_data = (
101+ swift_resolved_package_resource .package_data
102+ )
103+
104+ resolved_dependencies = []
105+ for package in swift_resolved_package_data :
106+ version = package .get ("version" )
107+ name = package .get ("name" )
108+
109+ purl = PackageURL (
110+ type = cls .default_package_type , name = name , version = version
111+ )
112+ resolved_dependencies .append (
113+ models .DependentPackage (
114+ purl = purl .to_string (),
115+ scope = "dependencies" ,
116+ is_runtime = True ,
117+ is_optional = False ,
118+ is_resolved = True ,
119+ extracted_requirement = version ,
120+ )
121+ )
122+
123+ for dependency in processed_dependencies [:]:
124+ dependency_purl = PackageURL .from_string (dependency .purl )
125+
126+ if dependency_purl .name == name :
127+ processed_dependencies .remove (dependency )
128+
129+ processed_dependencies .extend (resolved_dependencies )
130+
131+ processed_package = package_data
132+ if swift_show_dependencies_resource :
133+ add_datafile_paths .append (swift_show_dependencies_resource .path )
134+ add_datasource_ids .append (
135+ SwiftShowDependenciesDepLockHandler .datasource_id
136+ )
137+ elif swift_resolved_package_resource :
138+ add_datafile_paths .append (swift_resolved_package_resource .path )
139+ add_datasource_ids .append (SwiftPackageResolvedHandler .datasource_id )
140+
141+ if processed_package and processed_package .purl :
142+ package = models .Package .from_package_data (
143+ package_data = processed_package ,
144+ datafile_path = resource .path ,
145+ )
146+
147+ package .datafile_paths .extend (add_datafile_paths )
148+ package .datasource_ids .extend (add_datasource_ids )
149+
150+ package .populate_license_fields ()
151+ yield package
152+
153+ parent = resource .parent (codebase )
154+ cls .assign_package_to_resources (
155+ package = package ,
156+ resource = parent ,
157+ codebase = codebase ,
158+ package_adder = package_adder ,
159+ )
160+
161+ if processed_dependencies :
162+ yield from models .Dependency .from_dependent_packages (
163+ dependent_packages = processed_dependencies ,
164+ datafile_path = resource .path ,
165+ datasource_id = processed_package .datasource_id ,
166+ package_uid = package .package_uid ,
167+ )
168+
169+ yield resource
170+
171+
172+ class SwiftShowDependenciesDepLockHandler (BaseSwiftDatafileHandler ):
51173 datasource_id = "swift_package_show_dependencies"
52174 path_patterns = ("*/swift-show-dependencies.deplock" ,)
53175 default_package_type = "swift"
@@ -86,32 +208,8 @@ def parse(cls, location, package_only=False):
86208
87209 yield cls ._parse (swift_dependency_relation , package_only )
88210
89- @classmethod
90- def assemble (
91- cls , package_data , resource , codebase , package_adder = models .add_to_package
92- ):
93- siblings = resource .siblings (codebase )
94- swift_manifest_resource = [
95- r
96- for r in siblings
97- if r .name in ("Package.swift.json" , "Package.swift.deplock" )
98- ]
99-
100- # Skip the assembly if the Swift manifest is present.
101- # SwiftManifestJsonHandler's assembly will take care of the
102- # dependencies from swift-show-dependencies.deplock file.
103- if swift_manifest_resource :
104- return []
105-
106- yield from super (SwiftShowDependenciesDepLockHandler , cls ).assemble (
107- package_data = package_data ,
108- resource = resource ,
109- codebase = codebase ,
110- package_adder = package_adder ,
111- )
112211
113-
114- class SwiftManifestJsonHandler (models .DatafileHandler ):
212+ class SwiftManifestJsonHandler (BaseSwiftDatafileHandler ):
115213 datasource_id = "swift_package_manifest_json"
116214 path_patterns = ("*/Package.swift.json" , "*/Package.swift.deplock" )
117215 default_package_type = "swift"
@@ -149,116 +247,8 @@ def parse(cls, location, package_only=False):
149247
150248 yield cls ._parse (swift_manifest , package_only )
151249
152- @classmethod
153- def assemble (
154- cls ,
155- package_data ,
156- resource ,
157- codebase ,
158- package_adder = models .add_to_package ,
159- ):
160- """
161- Use the dependencies from `Package.resolved` to create the
162- top-level package with resolved dependencies.
163- """
164- siblings = resource .siblings (codebase )
165- processed_dependencies = []
166- swift_resolved_package_resource = [
167- r for r in siblings if r .name == "Package.resolved"
168- ]
169-
170- swift_show_dependencies_resources = [
171- r for r in siblings if r .name == "swift-show-dependencies.deplock"
172- ]
173-
174- if swift_show_dependencies_resources :
175- swift_show_dependencies_resource = swift_show_dependencies_resources [0 ]
176- swift_show_dependencies_package_data = (
177- swift_show_dependencies_resource .package_data
178- )
179-
180- # Dependencies from `swift-show-dependencies.deplock` supersede dependencies from other datafiles.
181- processed_dependencies = swift_show_dependencies_package_data [0 ][
182- "dependencies"
183- ]
184- processed_dependencies = [
185- models .DependentPackage .from_dict (i ) for i in processed_dependencies
186- ]
187-
188- # Use dependencies from `Package.resolved` when `swift-show-dependencies.deplock` is not present.
189- else :
190- dependencies_from_manifest = package_data .dependencies
191-
192- if swift_resolved_package_resource :
193- swift_resolved_package_resource = swift_resolved_package_resource [0 ]
194- swift_resolved_package_data = (
195- swift_resolved_package_resource .package_data
196- )
197-
198- for package in swift_resolved_package_data :
199- version = package .get ("version" )
200- name = package .get ("name" )
201-
202- purl = PackageURL (
203- type = cls .default_package_type , name = name , version = version
204- )
205- processed_dependencies .append (
206- models .DependentPackage (
207- purl = purl .to_string (),
208- scope = "dependencies" ,
209- is_runtime = True ,
210- is_optional = False ,
211- is_resolved = True ,
212- extracted_requirement = version ,
213- )
214- )
215-
216- for dependency in dependencies_from_manifest [:]:
217- dependency_purl = PackageURL .from_string (dependency .purl )
218-
219- if dependency_purl .name == name :
220- dependencies_from_manifest .remove (dependency )
221250
222- processed_dependencies .extend (dependencies_from_manifest )
223-
224- datafile_path = resource .path
225- if package_data .purl :
226- package = models .Package .from_package_data (
227- package_data = package_data ,
228- datafile_path = datafile_path ,
229- )
230-
231- if swift_show_dependencies_resources :
232- package .datafile_paths .append (swift_show_dependencies_resource .path )
233- package .datasource_ids .append (
234- SwiftShowDependenciesDepLockHandler .datasource_id
235- )
236- elif swift_resolved_package_resource :
237- package .datafile_paths .append (swift_resolved_package_resource .path )
238- package .datasource_ids .append (SwiftPackageResolvedHandler .datasource_id )
239-
240- package .populate_license_fields ()
241- yield package
242-
243- parent = resource .parent (codebase )
244- cls .assign_package_to_resources (
245- package = package ,
246- resource = parent ,
247- codebase = codebase ,
248- package_adder = package_adder ,
249- )
250-
251- if processed_dependencies :
252- yield from models .Dependency .from_dependent_packages (
253- dependent_packages = processed_dependencies ,
254- datafile_path = datafile_path ,
255- datasource_id = package_data .datasource_id ,
256- package_uid = package .package_uid ,
257- )
258- yield resource
259-
260-
261- class SwiftPackageResolvedHandler (models .DatafileHandler ):
251+ class SwiftPackageResolvedHandler (BaseSwiftDatafileHandler ):
262252 datasource_id = "swift_package_resolved"
263253 path_patterns = ("*/Package.resolved" , "*/.package.resolved" )
264254 default_package_type = "swift"
@@ -282,30 +272,6 @@ def parse(cls, location, package_only=False):
282272 if resolved_doc_version == 1 :
283273 yield from packages_from_resolved_v1 (package_resolved )
284274
285- @classmethod
286- def assemble (
287- cls , package_data , resource , codebase , package_adder = models .add_to_package
288- ):
289- siblings = resource .siblings (codebase )
290- swift_manifest_resource = [
291- r
292- for r in siblings
293- if r .name in ("Package.swift.json" , "Package.swift.deplock" )
294- ]
295-
296- # Skip the assembly if the ``Package.swift.json`` manifest is present.
297- # SwiftManifestJsonHandler's assembly will take care of the resolved
298- # dependencies from Package.resolved file.
299- if swift_manifest_resource :
300- return []
301-
302- yield from super (SwiftPackageResolvedHandler , cls ).assemble (
303- package_data = package_data ,
304- resource = resource ,
305- codebase = codebase ,
306- package_adder = package_adder ,
307- )
308-
309275
310276def packages_from_resolved_v2_and_v3 (package_resolved ):
311277 pinned = package_resolved .get ("pins" , [])
0 commit comments