Files
platformio-core/platformio/project/helpers.py

224 lines
7.0 KiB
Python
Raw Normal View History

2019-05-07 22:13:21 +03:00
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import json
2019-05-07 22:13:21 +03:00
import os
from hashlib import sha1
from os import walk
from os.path import (basename, dirname, expanduser, isdir, isfile, join,
realpath, splitdrive)
2019-05-07 22:13:21 +03:00
from click.testing import CliRunner
from platformio import __version__, exception
from platformio.compat import WINDOWS, hashlib_encode_data
2019-05-07 22:13:21 +03:00
from platformio.project.config import ProjectConfig
def get_project_dir():
return os.getcwd()
def is_platformio_project(project_dir=None):
if not project_dir:
project_dir = get_project_dir()
return isfile(join(project_dir, "platformio.ini"))
def find_project_dir_above(path):
if isfile(path):
path = dirname(path)
if is_platformio_project(path):
return path
if isdir(dirname(path)):
return find_project_dir_above(dirname(path))
return None
def get_project_optional_dir(name, default=None):
2019-05-30 16:38:04 +03:00
project_dir = get_project_dir()
config = ProjectConfig.get_instance(join(project_dir, "platformio.ini"))
optional_dir = config.get("platformio", name)
2019-05-30 16:38:04 +03:00
if not optional_dir:
2019-05-07 22:13:21 +03:00
return default
2019-05-30 16:38:04 +03:00
if "$PROJECT_HASH" in optional_dir:
optional_dir = optional_dir.replace(
"$PROJECT_HASH", "%s-%s" %
(basename(project_dir), sha1(
hashlib_encode_data(project_dir)).hexdigest()[:10]))
2019-05-07 22:13:21 +03:00
2019-05-30 16:38:04 +03:00
if optional_dir.startswith("~"):
optional_dir = expanduser(optional_dir)
return realpath(optional_dir)
2019-05-07 22:13:21 +03:00
def get_project_core_dir():
default = join(expanduser("~"), ".platformio")
core_dir = get_project_optional_dir(
"core_dir", get_project_optional_dir("home_dir", default))
win_core_dir = None
if WINDOWS and core_dir == default:
win_core_dir = splitdrive(core_dir)[0] + "\\.platformio"
if isdir(win_core_dir):
core_dir = win_core_dir
if not isdir(core_dir):
try:
os.makedirs(core_dir)
except OSError as e:
if win_core_dir:
os.makedirs(win_core_dir)
core_dir = win_core_dir
else:
raise e
assert isdir(core_dir)
return core_dir
def get_project_global_lib_dir():
return get_project_optional_dir("globallib_dir",
join(get_project_core_dir(), "lib"))
def get_project_platforms_dir():
return get_project_optional_dir("platforms_dir",
join(get_project_core_dir(), "platforms"))
def get_project_packages_dir():
return get_project_optional_dir("packages_dir",
join(get_project_core_dir(), "packages"))
def get_project_cache_dir():
return get_project_optional_dir("cache_dir",
join(get_project_core_dir(), ".cache"))
def get_project_workspace_dir():
return get_project_optional_dir("workspace_dir",
join(get_project_dir(), ".pio"))
def get_project_build_dir(force=False):
path = get_project_optional_dir("build_dir",
join(get_project_workspace_dir(), "build"))
try:
if not isdir(path):
os.makedirs(path)
except Exception as e: # pylint: disable=broad-except
if not force:
raise Exception(e)
return path
def get_project_libdeps_dir():
return get_project_optional_dir(
"libdeps_dir", join(get_project_workspace_dir(), "libdeps"))
2019-05-07 22:13:21 +03:00
def get_project_lib_dir():
return get_project_optional_dir("lib_dir", join(get_project_dir(), "lib"))
2019-05-07 22:13:21 +03:00
def get_project_include_dir():
2019-05-07 22:13:21 +03:00
return get_project_optional_dir("include_dir",
join(get_project_dir(), "include"))
def get_project_src_dir():
return get_project_optional_dir("src_dir", join(get_project_dir(), "src"))
def get_project_test_dir():
2019-05-07 22:13:21 +03:00
return get_project_optional_dir("test_dir", join(get_project_dir(),
"test"))
def get_project_boards_dir():
2019-05-07 22:13:21 +03:00
return get_project_optional_dir("boards_dir",
join(get_project_dir(), "boards"))
def get_project_data_dir():
2019-05-07 22:13:21 +03:00
return get_project_optional_dir("data_dir", join(get_project_dir(),
"data"))
2019-05-31 21:18:37 +03:00
def get_project_shared_dir():
return get_project_optional_dir("shared_dir",
join(get_project_dir(), "shared"))
def compute_project_checksum(config):
# rebuild when PIO Core version changes
checksum = sha1(hashlib_encode_data(__version__))
# configuration file state
checksum.update(hashlib_encode_data(config.to_json()))
# project file structure
2019-05-07 22:13:21 +03:00
check_suffixes = (".c", ".cc", ".cpp", ".h", ".hpp", ".s", ".S")
for d in (get_project_include_dir(), get_project_src_dir(),
get_project_lib_dir()):
2019-05-07 22:13:21 +03:00
if not isdir(d):
continue
chunks = []
2019-05-07 22:13:21 +03:00
for root, _, files in walk(d):
for f in files:
path = join(root, f)
if path.endswith(check_suffixes):
chunks.append(path)
if not chunks:
continue
chunks_to_str = ",".join(sorted(chunks))
if WINDOWS: # case insensitive OS
chunks_to_str = chunks_to_str.lower()
checksum.update(hashlib_encode_data(chunks_to_str))
return checksum.hexdigest()
def load_project_ide_data(project_dir, env_or_envs):
from platformio.commands.run import cli as cmd_run
assert env_or_envs
envs = env_or_envs
if not isinstance(envs, list):
envs = [envs]
args = ["--project-dir", project_dir, "--target", "idedata"]
for env in envs:
args.extend(["-e", env])
result = CliRunner().invoke(cmd_run, args)
if result.exit_code != 0 and not isinstance(result.exception,
exception.ReturnErrorCode):
raise result.exception
if '"includes":' not in result.output:
raise exception.PlatformioException(result.output)
data = {}
for line in result.output.split("\n"):
line = line.strip()
if (line.startswith('{"') and line.endswith("}")
and "env_name" in line):
_data = json.loads(line)
if "env_name" in _data:
data[_data['env_name']] = _data
if not isinstance(env_or_envs, list) and env_or_envs in data:
return data[env_or_envs]
return data or None