Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a provider for libraries in environmental folders #632

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions fusesoc/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,6 @@ def add_library(self, library):
from fusesoc.provider import get_provider

section_name = "library." + library.name

if section_name in self._cp.sections():
logger.warning(
"Not adding library. {} already exists in configuration file".format(
Expand All @@ -274,9 +273,19 @@ def add_library(self, library):
)
return

try:
provider = get_provider(library.sync_type)
except ImportError:
raise RuntimeError("Invalid sync-type '{}'".format(library["sync-type"]))

provider.init_library(library)

self._cp.add_section(section_name)

self._cp.set(section_name, "location", library.location)
# Libraries in special environmental folders may not have a fixed location, but
# if they aren't set up to auto-sync they should
if library.sync_type not in ["env"] or not library.auto_sync:
self._cp.set(section_name, "location", library.location)

if library.sync_type:
self._cp.set(section_name, "sync-uri", library.sync_uri)
Expand All @@ -288,11 +297,4 @@ def add_library(self, library):
_auto_sync = "true" if library.auto_sync else "false"
self._cp.set(section_name, "auto-sync", _auto_sync)

try:
provider = get_provider(library.sync_type)
except ImportError:
raise RuntimeError("Invalid sync-type '{}'".format(library["sync-type"]))

provider.init_library(library)

self.write()
7 changes: 7 additions & 0 deletions fusesoc/coremanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,14 @@ def __init__(self, config, library_manager=None):

def find_cores(self, library, ignored_dirs):
found_cores = []

# Resolve any environmentally-special library locations
path = os.path.expanduser(library.location)
if library.sync_type in ["env"]:
from fusesoc.provider import get_provider

path = get_provider(library.sync_type).resolve(library)

exclude = {".git"}
if os.path.isdir(path) == False:
raise OSError(path + " is not a directory")
Expand Down
6 changes: 3 additions & 3 deletions fusesoc/librarymanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def __init__(
sync_version=None,
auto_sync=True,
):
if sync_type and not sync_type in ["local", "git"]:
if sync_type and not sync_type in ["local", "git", "env"]:
raise ValueError(
"Library {} ({}) Invalid sync-type '{}'".format(
name, location, sync_type
Expand All @@ -46,8 +46,8 @@ def update(self, force=False):
def l(s):
return self.name + " : " + s

if self.sync_type == "local":
logger.info(l("sync-type is local. Ignoring update"))
if self.sync_type in ["local", "env"]:
logger.info(l(f"sync-type is {self.sync_type}. Ignoring update"))
return

# FIXME: Do an initial checkout if missing
Expand Down
2 changes: 1 addition & 1 deletion fusesoc/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ def get_parser():
parser_library_add.add_argument(
"--sync-type",
help="The provider type for the library. Defaults to 'git'.",
choices=["git", "local"],
choices=["git", "local", "env"],
dest="sync-type",
)
parser_library_add.add_argument(
Expand Down
76 changes: 76 additions & 0 deletions fusesoc/provider/env.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Copyright FuseSoC contributors
# Licensed under the 2-Clause BSD License, see LICENSE for details.
# SPDX-License-Identifier: BSD-2-Clause

import logging
import subprocess
from typing import Callable

from fusesoc.librarymanager import Library
from fusesoc.provider.provider import Provider
from fusesoc.utils import Launcher

logger = logging.getLogger(__name__)


class Env(Provider):
"""A provider for cores in locations special to the environment."""

def _resolve_poetry(library: Library) -> str:
logger.info(f"Looking for Poetry environment for library {library.name}")

err = False
envpath = None
try:
# We need to wrap Poetry in Poetry in case the environment uses a different
# Python interpreter than is currently configured through `poetry env use`. If
# the two differ, then `poetry env info -p` just gives us a blank path.
proc = Launcher("poetry", ["run", "poetry", "env", "info", "--path"])
proc = proc.run(stdout=subprocess.PIPE)
stdout, _ = proc.communicate()
envpath = stdout.decode("ascii").strip()
except subprocess.CalledProcessError as e:
logger.error("Failed to run `poetry env info`")
err = True

if envpath and len(envpath) == 0:
logger.error("Poetry returned an empty environment path")
err = True

if err:
raise RuntimeError("Could not create library from Poetry environment")

logger.info(f"Using '{envpath}'")
return envpath

_SYNC_URIS = {"poetry": _resolve_poetry}

@staticmethod
def resolve(library: Library) -> str:
resolver = Env._SYNC_URIS.get(library.sync_uri, None)
if not resolver:
raise RuntimeError(
"Unsupported sync-uri '{}' for sync-type 'env', options are: {}".format(
library.sync_uri, Env._SYNC_URIS.keys()
)
)

return resolver(library)

@staticmethod
def init_library(library):
path = Env.resolve(library)

library.location = None
if not library.auto_sync:
logger.info("Auto-sync disabled, converting to local provider")
library.location = path
library.sync_type = "local"
library.sync_uri = path

def _checkout(self, local_dir):
pass

@staticmethod
def update_library(library):
pass
16 changes: 11 additions & 5 deletions fusesoc/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import subprocess
import sys
import warnings
from typing import Any

import yaml

Expand All @@ -25,15 +26,20 @@ def __init__(self, cmd, args=[], cwd=None):
self.args = args
self.cwd = cwd

def run(self):
def run(self, **kwargs) -> subprocess.Popen:
"""Runs the cmd with args after converting them all to strings via str"""
logger.debug(self.cwd or "./")
logger.debug(" " + str(self))

cmd = map(str, [self.cmd] + self.args)
try:
subprocess.check_call(
map(str, [self.cmd] + self.args),
cwd=self.cwd,
),
proc = subprocess.Popen(args=cmd, cwd=self.cwd, **kwargs)
proc.wait()

if proc.returncode != 0:
raise subprocess.CalledProcessError(proc.returncode, cmd)

return proc
except FileNotFoundError:
raise RuntimeError(
"Command '" + self.cmd + "' not found. Make sure it is in $PATH"
Expand Down