22
33from __future__ import annotations
44
5+ import importlib .util
56import os
67import shlex
78import shutil
89import subprocess as sp
910import sys
11+ import traceback
1012import yaml
1113from concurrent .futures import Future , ThreadPoolExecutor
1214from itertools import chain
2224
2325from finn .interface import IS_POSIX
2426from finn .interface .interface_utils import debug , error , resolve_module_path
25- from finn .util .exception import FINNConfigurationError , FINNUserError
27+ from finn .util .exception import (
28+ FINNConfigurationError ,
29+ FINNDependencyInstallationError ,
30+ FINNUserError ,
31+ )
32+
2633from pydantic .networks import HttpUrl # noqa
2734
2835
@@ -302,9 +309,25 @@ def _run_silent(self, cmd: str, cwd: Path | None = None, timeout: float | None =
302309 def _git_clone (self , url : str , commit : str , target : Path ) -> bool :
303310 """Try to clone and checkout the git url to the given target directory. If something
304311 went wrong return False, True otherwise.""" # noqa
305- if self ._run_silent (f"git clone { url } { target .absolute ()} " , timeout = self .git_timeout ) != 0 :
312+ clone_result = sp .run (
313+ shlex .split (f"git clone { url } { target .absolute ()} " ),
314+ timeout = self .git_timeout ,
315+ capture_output = True ,
316+ text = True ,
317+ )
318+ if clone_result .returncode != 0 :
319+ debug (f"[{ url } ] Cloning failed! Output was:\n { clone_result .stderr } " , False )
320+ return False
321+ checkout_result = sp .run (
322+ shlex .split (f"git checkout { commit } " ),
323+ cwd = target .absolute (),
324+ capture_output = True ,
325+ text = True ,
326+ )
327+ if checkout_result .returncode != 0 :
328+ debug (f"[{ url } ] Checkout failed! Output was:\n { checkout_result .stderr } " , False )
306329 return False
307- return self . _run_silent ( f"git checkout { commit } " , cwd = target . absolute ()) == 0
330+ return True
308331
309332 def _get_git_hash (self , package_name : str ) -> str | None :
310333 """Return the hash of the given package_name dependency.
@@ -334,15 +357,24 @@ def _install_git_dependency(self, package_name: str) -> bool:
334357 package_name , "url" , "commit" , "pip_install" , "install_editable"
335358 )
336359 target = self .dep_location / package_name
360+ if target .exists () and importlib .util .find_spec (package_name .replace ("-" , "_" )) is None :
361+ debug (
362+ "Git repository seems to exist, but is not installed "
363+ "into this environment. Removing dependency and cloning again." ,
364+ False ,
365+ )
366+ shutil .rmtree (target , ignore_errors = True )
337367 if not self ._git_clone (url , commit , target ):
368+ debug (f"[{ package_name } ] Cloning or checkout failed." , False )
338369 return False
339370 if self .is_outdated (package_name ):
340371 return False
341372 if not pip_install :
342373 return True
343- debug (f"[{ package_name } ] Running pip install.." )
344374 editable_flag = "" if not install_editable else "-e"
345- self ._run_silent (f"{ sys .executable } -m pip { editable_flag } install { target } " )
375+ pip_install_command = f"{ sys .executable } -m pip install { editable_flag } { target } "
376+ debug (f"[{ package_name } ] Running pip install: { pip_install_command } " )
377+ self ._run_silent (pip_install_command )
346378
347379 # In editable install cases we need to make the package available in this run
348380 # otherwise it will only be available on the next start
@@ -431,6 +463,10 @@ def _install_finn_xsi(self) -> bool:
431463 """Install FINN XSI bindings and return if installation was successful."""
432464 debug ("[finn_xsi] Preparing LD LIBRARY PATH" , False )
433465 finn_xsi_path = Path (self .finn_xsi_str )
466+ if "XILINX_VIVADO" not in os .environ :
467+ raise FINNDependencyInstallationError (
468+ "Vivado is not available " "(or XILINX_VIVADO is not set in your " "environment)!"
469+ )
434470 vivado_path = os .environ ["XILINX_VIVADO" ]
435471 required_paths = f"/lib/x86_64-linux-gnu/:{ vivado_path } /lib/lnx64.o"
436472 if "LD_LIBRARY_PATH" not in os .environ :
@@ -518,11 +554,17 @@ def is_outdated(self, package_name: str, installed: bool = False) -> bool:
518554
519555 # If it doesnt exist yet, its definitely outdated
520556 if has_hash is None :
557+ debug (f"[{ package_name } ] No commit hash found - outdated." , False )
521558 return True
522559
523560 # Compare hashes
524561 data = cast ("GitDependency" , data )
525562 if data .commit != has_hash :
563+ debug (
564+ f"[{ package_name } ] No matching hash commits: expected "
565+ f"{ data .commit } , got { has_hash } " ,
566+ False ,
567+ )
526568 return True
527569
528570 # In some cases we do not want to check if the dependency is installed
@@ -532,11 +574,10 @@ def is_outdated(self, package_name: str, installed: bool = False) -> bool:
532574 # For pip-installable dependencies, also check if the package is accessible
533575 # in the current Python process
534576 if package_name in self .deps .git_deps and data .pip_install :
535- import importlib .util
536-
537577 # Try to find the package in the current Python environment
538578 spec = importlib .util .find_spec (package_name .replace ("-" , "_" ))
539579 if spec is None :
580+ debug (f"[{ package_name } ] is not importable!" , False )
540581 # Package is not importable, mark as outdated
541582 return True
542583
@@ -570,8 +611,15 @@ def install_wrapper(package_name: str, status: _StatusTracker) -> bool:
570611 result = self .install_dependency (package_name )
571612 status .set_finish (package_name , result )
572613 return result
573- except Exception :
614+ except FINNDependencyInstallationError as e :
615+ status .set_finish (package_name , False )
616+ status .update_status (package_name , f"Error: { e } " , "purple" )
617+ status .update_live ()
618+ return False
619+ except Exception as e :
574620 status .set_finish (package_name , False )
621+ debug (f"[{ package_name } ] Exception: { e } " , False )
622+ debug (f"[{ package_name } ] { traceback .format_exc ()} " , False )
575623 status .update_status (
576624 package_name , "Updated failed! (Internal exception!)" , "purple"
577625 )
0 commit comments