diff --git a/tools/__init__.py b/tools/__init__.py index 91a320065..2fe372e57 100644 --- a/tools/__init__.py +++ b/tools/__init__.py @@ -215,6 +215,8 @@ def __init__( env_root_path=None, conda_cache_path=None, patches=None, + post_install_command=None, + post_install_ret=0 ): # if the executable name is specifed, use it; otherwise use the package name self.executable = executable or package @@ -225,6 +227,9 @@ def __init__( else: self.version = CondaPackageVersion(version) + self.post_install_command = post_install_command + self.post_install_ret = post_install_ret + self.verifycmd = verifycmd self.verifycode = verifycode self.require_executability = require_executability @@ -411,6 +416,7 @@ def _attempt_install(self): _log.debug("Attempting install...") self.install_package() self.verify_install() + self.post_install() def get_installed_version(self): # If we ever use conda to install pip packages as tools, "-c" needs to be removed @@ -537,6 +543,17 @@ def install_package(self): # we were able to create the environment and install the package _log.debug("Conda environment created and package installed.") + def post_install(self): + """ + Runs a shell command after package installation, + relative to the directory containing the executable + """ + if self.post_install_command: + destination_dir = os.path.dirname(os.path.realpath(self.executable_path())) + return_code = os.system('cd "{}" && {}'.format(destination_dir, self.post_install_command)) + if self.post_install_ret is not None: + assert return_code == self.post_install_ret + class DownloadPackage(InstallMethod): ''' This is an install method for downloading, unpacking, and post- diff --git a/tools/novoalign.py b/tools/novoalign.py index 2ef53b667..525d97701 100644 --- a/tools/novoalign.py +++ b/tools/novoalign.py @@ -39,7 +39,10 @@ def __init__(self, path=None): require_executability=True ) ) - install_methods.append(tools.CondaPackage(TOOL_NAME, version=TOOL_VERSION)) + if os.environ.get("NOVOALIGN_LICENSE_PATH"): + install_methods.append(tools.CondaPackage(TOOL_NAME, version=TOOL_VERSION, post_install_command="cp $NOVOALIGN_LICENSE_PATH ./")) + else: + install_methods.append(tools.CondaPackage(TOOL_NAME, version=TOOL_VERSION)) tools.Tool.__init__(self, install_methods=install_methods) def version(self): @@ -50,7 +53,7 @@ def version(self): def _get_tool_version(self): tmpf = util.file.mkstempfname('.novohelp.txt') with open(tmpf, 'wt') as outf: - util.misc.run_and_save([self.install_and_get_path()], outf=outf) + util.misc.run_and_save([self.install_and_get_path(), "-V"], outf=outf, check=False) with open(tmpf, 'rt') as inf: self.tool_version = inf.readline().strip().split()[1] os.unlink(tmpf) diff --git a/util/misc.py b/util/misc.py index c2f0a35bb..0ec53c40e 100644 --- a/util/misc.py +++ b/util/misc.py @@ -265,7 +265,7 @@ def run_and_print(args, stdout=None, stderr=None, def run_and_save(args, stdout=None, stdin=None, outf=None, stderr=None, preexec_fn=None, - close_fds=False, shell=False, cwd=None, env=None): + close_fds=False, shell=False, cwd=None, env=None, check=True): assert outf is not None sp = subprocess.Popen(args, @@ -283,7 +283,7 @@ def run_and_save(args, stdout=None, stdin=None, if err: sys.stdout.write(err.decode("UTF-8")) - if sp.returncode != 0: + if sp.returncode != 0 and check: raise subprocess.CalledProcessError(sp.returncode, str(args[0])) return sp @@ -378,4 +378,18 @@ def available_cpu_count(): except IOError: pass - return multiprocessing.cpu_count() \ No newline at end of file + return multiprocessing.cpu_count() + +def which(application_binary_name): + """ + Similar to the *nix "which" command, + this function finds the first executable binary present + in the system PATH for the binary specified. + It differs in that it resolves symlinks. + """ + path=os.getenv('PATH') + for path in path.split(os.path.pathsep): + full_path=os.path.join(path, application_binary_name) + if os.path.exists(full_path) and os.access(full_path, os.X_OK): + link_resolved_path = os.path.realpath(full_path) + return link_resolved_path \ No newline at end of file