44
55import logging
66import os
7+ import pathlib
78
89from okonomiyaki .versions import EnpkgVersion
910from simplesat .constraints import PrettyPackageStringParser , Requirement
1617from fusesoc .capi2 .coreparser import Core2Parser
1718from fusesoc .core import Core
1819from fusesoc .librarymanager import LibraryManager
20+ from fusesoc .lockfile import load_lockfile
21+ from fusesoc .vlnv import Vlnv , compare_relation
1922
2023logger = logging .getLogger (__name__ )
2124
@@ -33,6 +36,7 @@ class CoreDB:
3336 def __init__ (self ):
3437 self ._cores = {}
3538 self ._solver_cache = {}
39+ self ._lockfile = None
3640
3741 # simplesat doesn't allow ':', '-' or leading '_'
3842 def _package_name (self , vlnv ):
@@ -45,6 +49,7 @@ def _package_version(self, vlnv):
4549 def _parse_depend (self , depends ):
4650 # FIXME: Handle conflicts
4751 deps = []
52+
4853 _s = "{} {} {}"
4954 for d in depends :
5055 for simple in d .simpleVLNVs ():
@@ -83,6 +88,9 @@ def find(self, vlnv=None):
8388 found = list ([core ["core" ] for core in self ._cores .values ()])
8489 return found
8590
91+ def load_lockfile (self , filepath : pathlib .Path ):
92+ self ._lockfile = load_lockfile (filepath )
93+
8694 def _solver_cache_lookup (self , key ):
8795 if key in self ._solver_cache :
8896 return self ._solver_cache [key ]
@@ -110,6 +118,27 @@ def _hash_flags_dict(self, flags):
110118 h ^= hash (pair )
111119 return h
112120
121+ def _lockfile_replace (self , core : Vlnv ):
122+ """Try to pin the core version from cores defined in the lock file"""
123+ if self ._lockfile :
124+ for locked_core in self ._lockfile ["cores" ]:
125+ if locked_core .vln_str () == core .vln_str ():
126+ valid_version = compare_relation (locked_core , core .relation , core )
127+ if valid_version :
128+ core .version = locked_core .version
129+ core .revision = locked_core .revision
130+ core .relation = "=="
131+ else :
132+ # Invalid version in lockfile
133+ logger .warning (
134+ "Failed to pin core {} outside of dependency version {} {} {}" .format (
135+ str (locked_core ),
136+ core .vln_str (),
137+ core .relation ,
138+ core .version ,
139+ )
140+ )
141+
113142 def solve (self , top_core , flags ):
114143 return self ._solve (top_core , flags )
115144
@@ -195,8 +224,12 @@ def eq_vln(this, that):
195224 _flags ["is_toplevel" ] = core .name == top_core
196225 _depends = core .get_depends (_flags )
197226 if _depends :
227+ for depend in _depends :
228+ self ._lockfile_replace (depend )
198229 _s = "; depends ( {} )"
199230 package_str += _s .format (self ._parse_depend (_depends ))
231+ else :
232+ self ._lockfile_replace (top_core )
200233
201234 parser = PrettyPackageStringParser (EnpkgVersion .from_string )
202235
@@ -226,6 +259,7 @@ def eq_vln(this, that):
226259 raise DependencyError (top_core .name )
227260
228261 virtual_selection = {}
262+ partial_lockfile = False
229263 objdict = {}
230264 if len (transaction .operations ) > 1 :
231265 for op in transaction .operations :
@@ -244,6 +278,11 @@ def eq_vln(this, that):
244278 if p [0 ] in virtual_selection :
245279 # If package that implements a virtual core is required, remove from the dictionary
246280 del virtual_selection [p [0 ]]
281+ if (
282+ self ._lockfile
283+ and op .package .core .name not in self ._lockfile ["cores" ]
284+ ):
285+ partial_lockfile = True
247286 op .package .core .direct_deps = [
248287 objdict [n [0 ]] for n in op .package .install_requires
249288 ]
@@ -254,6 +293,8 @@ def eq_vln(this, that):
254293 virtual [1 ], virtual [0 ]
255294 )
256295 )
296+ if partial_lockfile :
297+ logger .warning ("Using lock file with partial list of cores" )
257298
258299 result = [op .package .core for op in transaction .operations ]
259300
0 commit comments