mirror of https://github.com/ARMmbed/mbed-os.git
172 lines
6.2 KiB
Python
172 lines
6.2 KiB
Python
#
|
|
# Copyright (c) 2020-2021 Arm Limited and Contributors. All rights reserved.
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
"""Mbed Program abstraction layer."""
|
|
import logging
|
|
|
|
from pathlib import Path
|
|
from typing import Dict
|
|
from urllib.parse import urlparse
|
|
|
|
from mbed_tools.project.exceptions import ProgramNotFound, ExistingProgram, MbedOSNotFound
|
|
from mbed_tools.project._internal.project_data import (
|
|
MbedProgramFiles,
|
|
MbedOS,
|
|
MBED_OS_REFERENCE_FILE_NAME,
|
|
MBED_OS_DIR_NAME,
|
|
)
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class MbedProgram:
|
|
"""Represents an Mbed program.
|
|
|
|
An `MbedProgram` consists of:
|
|
* A copy of, or reference to, `MbedOS`
|
|
* A set of `MbedProgramFiles`
|
|
* A collection of references to external libraries, defined in .lib files located in the program source tree
|
|
"""
|
|
|
|
def __init__(self, program_files: MbedProgramFiles, mbed_os: MbedOS) -> None:
|
|
"""Initialise the program attributes.
|
|
|
|
Args:
|
|
program_files: Object holding paths to a set of files that define an Mbed program.
|
|
mbed_os: An instance of `MbedOS` holding paths to locations in the local copy of the Mbed OS source.
|
|
"""
|
|
self.files = program_files
|
|
self.root = self.files.mbed_os_ref.parent
|
|
self.mbed_os = mbed_os
|
|
|
|
@classmethod
|
|
def from_new(cls, dir_path: Path) -> "MbedProgram":
|
|
"""Create an MbedProgram from an empty directory.
|
|
|
|
Creates the directory if it doesn't exist.
|
|
|
|
Args:
|
|
dir_path: Directory in which to create the program.
|
|
|
|
Raises:
|
|
ExistingProgram: An existing program was found in the path.
|
|
"""
|
|
if _tree_contains_program(dir_path):
|
|
raise ExistingProgram(
|
|
f"An existing Mbed program was found in the directory tree {dir_path}. It is not possible to nest Mbed "
|
|
"programs. Please ensure there is no mbed-os.lib file in the cwd hierarchy."
|
|
)
|
|
|
|
logger.info(f"Creating Mbed program at path '{dir_path.resolve()}'")
|
|
dir_path.mkdir(exist_ok=True)
|
|
program_files = MbedProgramFiles.from_new(dir_path)
|
|
logger.info(f"Creating git repository for the Mbed program '{dir_path}'")
|
|
mbed_os = MbedOS.from_new(dir_path / MBED_OS_DIR_NAME)
|
|
return cls(program_files, mbed_os)
|
|
|
|
@classmethod
|
|
def from_existing(
|
|
cls, dir_path: Path, build_subdir: Path, mbed_os_path: Path = None, check_mbed_os: bool = True,
|
|
) -> "MbedProgram":
|
|
"""Create an MbedProgram from an existing program directory.
|
|
|
|
Args:
|
|
dir_path: Directory containing an Mbed program.
|
|
build_subdir: The subdirectory for the CMake build tree.
|
|
mbed_os_path: Directory containing Mbed OS.
|
|
check_mbed_os: If True causes an exception to be raised if the Mbed OS source directory does not
|
|
exist.
|
|
|
|
Raises:
|
|
ProgramNotFound: An existing program was not found in the path.
|
|
"""
|
|
if mbed_os_path is None:
|
|
program_root = _find_program_root(dir_path)
|
|
mbed_os_path = program_root / MBED_OS_DIR_NAME
|
|
else:
|
|
program_root = dir_path
|
|
|
|
logger.info(f"Found existing Mbed program at path '{program_root}'")
|
|
program = MbedProgramFiles.from_existing(program_root, build_subdir)
|
|
|
|
try:
|
|
mbed_os = MbedOS.from_existing(mbed_os_path, check_mbed_os)
|
|
except ValueError as mbed_os_err:
|
|
raise MbedOSNotFound(
|
|
f"Mbed OS was not found due to the following error: {mbed_os_err}"
|
|
"\nYou may need to resolve the mbed-os.lib reference. You can do this by performing a `deploy`."
|
|
)
|
|
|
|
return cls(program, mbed_os)
|
|
|
|
|
|
def parse_url(name_or_url: str) -> Dict[str, str]:
|
|
"""Create a valid github/armmbed url from a program name.
|
|
|
|
Args:
|
|
url: The URL, or a program name to turn into an URL.
|
|
|
|
Returns:
|
|
Dictionary containing the remote url and the destination path for the clone.
|
|
"""
|
|
url_obj = urlparse(name_or_url)
|
|
if url_obj.hostname:
|
|
url = url_obj.geturl()
|
|
elif ":" in name_or_url.split("/", maxsplit=1)[0]:
|
|
# If non-standard and no slashes before first colon, git will recognize as scp ssh syntax
|
|
url = name_or_url
|
|
else:
|
|
url = f"https://github.com/armmbed/{url_obj.path}"
|
|
# We need to create a valid directory name from the url path section.
|
|
return {"url": url, "dst_path": url_obj.path.rsplit("/", maxsplit=1)[-1].replace("/", "")}
|
|
|
|
|
|
def _tree_contains_program(path: Path) -> bool:
|
|
"""Check if the current path or its ancestors contain an mbed-os.lib file.
|
|
|
|
Args:
|
|
path: The starting path for the search. The search walks up the tree from this path.
|
|
|
|
Returns:
|
|
`True` if an mbed-os.lib file is located between `path` and filesystem root.
|
|
`False` if no mbed-os.lib file was found.
|
|
"""
|
|
try:
|
|
_find_program_root(path)
|
|
return True
|
|
except ProgramNotFound:
|
|
return False
|
|
|
|
|
|
def _find_program_root(cwd: Path) -> Path:
|
|
"""Walk up the directory tree, looking for an mbed-os.lib file.
|
|
|
|
Programs contain an mbed-os.lib file at the root of the source tree.
|
|
|
|
Args:
|
|
cwd: The directory path to search for a program.
|
|
|
|
Raises:
|
|
ProgramNotFound: No mbed-os.lib file found in the path.
|
|
|
|
Returns:
|
|
Path containing the mbed-os.lib file.
|
|
"""
|
|
potential_root = cwd.absolute().resolve()
|
|
while str(potential_root) != str(potential_root.anchor):
|
|
logger.debug(f"Searching for mbed-os.lib file at path {potential_root}")
|
|
root_file = potential_root / MBED_OS_REFERENCE_FILE_NAME
|
|
if root_file.exists() and root_file.is_file():
|
|
logger.debug(f"mbed-os.lib file found at {potential_root}")
|
|
return potential_root
|
|
|
|
potential_root = potential_root.parent
|
|
|
|
logger.debug("No mbed-os.lib file found.")
|
|
raise ProgramNotFound(
|
|
f"No program found from {cwd.resolve()} to {cwd.resolve().anchor}. Please set the directory to a program "
|
|
"directory containing an mbed-os.lib file. You can also set the directory to a program subdirectory if there "
|
|
"is an mbed-os.lib file at the root of your program's directory tree."
|
|
)
|