Added a new "-e, --environment" option to "platformio project init" command

This commit is contained in:
Ivan Kravets
2020-06-12 23:47:12 +03:00
parent fdb83c24be
commit 28d9f25f9a
6 changed files with 83 additions and 51 deletions

View File

@ -17,6 +17,7 @@ PlatformIO Core 4
* Added support for `custom targets <https://docs.platformio.org/page/projectconf/advanced_scripting.html#custom-targets>`__ (user cases: command shortcuts, pre/post processing based on dependencies, custom command launcher with options, etc.)
* Added support for "globstar/`**`" (recursive) pattern for the different commands and configuration options (`platformio ci <https://docs.platformio.org/page/core/userguide/cmd_ci.html>`__, `src_filter <https://docs.platformio.org/page/projectconf/section_env_build.html#src-filter>`__, `check_patterns <https://docs.platformio.org/page/projectconf/section_env_check.html#check-patterns>`__, `library.json > srcFilter <https://docs.platformio.org/page/librarymanager/config.html#srcfilter>`__). Python 3.5+ is required.
* Added a new ``-e, --environment`` option to `platformio project init <https://docs.platformio.org/page/core/userguide/project/cmd_init.html#cmdoption-platformio-project-init-e>`__ command that helps to update a PlatformIO project using existing environment
* Fixed an issue with PIO Unit Testing when running multiple environments (`issue #3523 <https://github.com/platformio/platformio-core/issues/3523>`_)
4.3.4 (2020-05-23)

2
docs

Submodule docs updated: ec54ae9917...2178afaf33

View File

@ -93,6 +93,7 @@ def validate_boards(ctx, param, value): # pylint: disable=W0613
)
@click.option("-b", "--board", multiple=True, metavar="ID", callback=validate_boards)
@click.option("--ide", type=click.Choice(ProjectGenerator.get_supported_ides()))
@click.option("-e", "--environment", help="Update using existing environment")
@click.option("-O", "--project-option", multiple=True)
@click.option("--env-prefix", default="")
@click.option("-s", "--silent", is_flag=True)
@ -102,6 +103,7 @@ def project_init(
project_dir,
board,
ide,
environment,
project_option,
env_prefix,
silent,
@ -139,7 +141,11 @@ def project_init(
)
if ide:
pg = ProjectGenerator(project_dir, ide, board)
config = ProjectConfig.get_instance(os.path.join(project_dir, "platformio.ini"))
config.validate()
pg = ProjectGenerator(
config, environment or get_best_envname(config, board), ide
)
pg.generate()
if is_new_project:
@ -444,3 +450,23 @@ def _install_dependent_platforms(ctx, platforms):
ctx.invoke(
cli_platform_install, platforms=list(set(platforms) - set(installed_platforms))
)
def get_best_envname(config, board_ids=None):
envname = None
default_envs = config.default_envs()
if default_envs:
envname = default_envs[0]
if not board_ids:
return envname
for env in config.envs():
if not board_ids:
return env
if not envname:
envname = env
items = config.items(env=env, as_dict=True)
if "board" in items and items.get("board") in board_ids:
return env
return envname

View File

@ -15,47 +15,31 @@
import codecs
import os
import sys
from os.path import basename, isdir, isfile, join, realpath, relpath
import bottle
from platformio import fs, util
from platformio.proc import where_is_program
from platformio.project.config import ProjectConfig
from platformio.project.helpers import load_project_ide_data
class ProjectGenerator(object):
def __init__(self, project_dir, ide, boards):
self.config = ProjectConfig.get_instance(join(project_dir, "platformio.ini"))
self.config.validate()
self.project_dir = project_dir
def __init__(self, config, env_name, ide):
self.config = config
self.project_dir = os.path.dirname(config.path)
self.env_name = str(env_name)
self.ide = str(ide)
self.env_name = str(self.get_best_envname(boards))
@staticmethod
def get_supported_ides():
tpls_dir = join(fs.get_source_dir(), "ide", "tpls")
return sorted([d for d in os.listdir(tpls_dir) if isdir(join(tpls_dir, d))])
def get_best_envname(self, boards=None):
envname = None
default_envs = self.config.default_envs()
if default_envs:
envname = default_envs[0]
if not boards:
return envname
for env in self.config.envs():
if not boards:
return env
if not envname:
envname = env
items = self.config.items(env=env, as_dict=True)
if "board" in items and items.get("board") in boards:
return env
return envname
tpls_dir = os.path.join(fs.get_source_dir(), "ide", "tpls")
return sorted(
[
d
for d in os.listdir(tpls_dir)
if os.path.isdir(os.path.join(tpls_dir, d))
]
)
@staticmethod
def filter_includes(includes_map, ignore_scopes=None, to_unix_path=True):
@ -75,12 +59,12 @@ class ProjectGenerator(object):
tpl_vars = {
"config": self.config,
"systype": util.get_systype(),
"project_name": basename(self.project_dir),
"project_name": os.path.basename(self.project_dir),
"project_dir": self.project_dir,
"env_name": self.env_name,
"user_home_dir": realpath(fs.expanduser("~")),
"user_home_dir": os.path.realpath(fs.expanduser("~")),
"platformio_path": sys.argv[0]
if isfile(sys.argv[0])
if os.path.isfile(sys.argv[0])
else where_is_program("platformio"),
"env_path": os.getenv("PATH"),
"env_pathsep": os.pathsep,
@ -97,7 +81,7 @@ class ProjectGenerator(object):
"src_files": self.get_src_files(),
"project_src_dir": self.config.get_optional_dir("src"),
"project_lib_dir": self.config.get_optional_dir("lib"),
"project_libdeps_dir": join(
"project_libdeps_dir": os.path.join(
self.config.get_optional_dir("libdeps"), self.env_name
),
}
@ -120,12 +104,12 @@ class ProjectGenerator(object):
with fs.cd(self.project_dir):
for root, _, files in os.walk(self.config.get_optional_dir("src")):
for f in files:
result.append(relpath(join(root, f)))
result.append(os.path.relpath(os.path.join(root, f)))
return result
def get_tpls(self):
tpls = []
tpls_dir = join(fs.get_source_dir(), "ide", "tpls", self.ide)
tpls_dir = os.path.join(fs.get_source_dir(), "ide", "tpls", self.ide)
for root, _, files in os.walk(tpls_dir):
for f in files:
if not f.endswith(".tpl"):
@ -133,7 +117,7 @@ class ProjectGenerator(object):
_relpath = root.replace(tpls_dir, "")
if _relpath.startswith(os.sep):
_relpath = _relpath[1:]
tpls.append((_relpath, join(root, f)))
tpls.append((_relpath, os.path.join(root, f)))
return tpls
def generate(self):
@ -141,12 +125,12 @@ class ProjectGenerator(object):
for tpl_relpath, tpl_path in self.get_tpls():
dst_dir = self.project_dir
if tpl_relpath:
dst_dir = join(self.project_dir, tpl_relpath)
if not isdir(dst_dir):
dst_dir = os.path.join(self.project_dir, tpl_relpath)
if not os.path.isdir(dst_dir):
os.makedirs(dst_dir)
file_name = basename(tpl_path)[:-4]
file_name = os.path.basename(tpl_path)[:-4]
contents = self._render_tpl(tpl_path, tpl_vars)
self._merge_contents(join(dst_dir, file_name), contents)
self._merge_contents(os.path.join(dst_dir, file_name), contents)
@staticmethod
def _render_tpl(tpl_path, tpl_vars):
@ -155,7 +139,7 @@ class ProjectGenerator(object):
@staticmethod
def _merge_contents(dst_path, contents):
if basename(dst_path) == ".gitignore" and isfile(dst_path):
if os.path.basename(dst_path) == ".gitignore" and os.path.isfile(dst_path):
return
with codecs.open(dst_path, "w", encoding="utf8") as fp:
fp.write(contents)

View File

@ -62,29 +62,50 @@ def test_init_ide_without_board(clirunner, tmpdir):
assert isinstance(result.exception, ProjectEnvsNotAvailableError)
def test_init_ide_atom(clirunner, validate_cliresult, tmpdir):
def test_init_ide_vscode(clirunner, validate_cliresult, tmpdir):
with tmpdir.as_cwd():
result = clirunner.invoke(
cmd_init, ["--ide", "atom", "-b", "uno", "-b", "teensy31"]
cmd_init, ["--ide", "vscode", "-b", "uno", "-b", "teensy31"]
)
validate_cliresult(result)
validate_pioproject(str(tmpdir))
assert all(
[tmpdir.join(f).check() for f in (".clang_complete", ".gcc-flags.json")]
[
tmpdir.join(".vscode").join(f).check()
for f in ("c_cpp_properties.json", "launch.json")
]
)
assert (
"framework-arduino-avr"
in tmpdir.join(".vscode").join("c_cpp_properties.json").read()
)
assert "framework-arduino" in tmpdir.join(".clang_complete").read()
# switch to NodeMCU
result = clirunner.invoke(cmd_init, ["--ide", "atom", "-b", "nodemcuv2"])
result = clirunner.invoke(cmd_init, ["--ide", "vscode", "-b", "nodemcuv2"])
validate_cliresult(result)
validate_pioproject(str(tmpdir))
assert "arduinoespressif" in tmpdir.join(".clang_complete").read()
assert (
"framework-arduinoespressif8266"
in tmpdir.join(".vscode").join("c_cpp_properties.json").read()
)
# switch to teensy31 via env name
result = clirunner.invoke(cmd_init, ["--ide", "vscode", "-e", "teensy31"])
validate_cliresult(result)
validate_pioproject(str(tmpdir))
assert (
"framework-arduinoteensy"
in tmpdir.join(".vscode").join("c_cpp_properties.json").read()
)
# switch to the first board
result = clirunner.invoke(cmd_init, ["--ide", "atom"])
result = clirunner.invoke(cmd_init, ["--ide", "vscode"])
validate_cliresult(result)
validate_pioproject(str(tmpdir))
assert "framework-arduino" in tmpdir.join(".clang_complete").read()
assert (
"framework-arduino-avr"
in tmpdir.join(".vscode").join("c_cpp_properties.json").read()
)
def test_init_ide_eclipse(clirunner, validate_cliresult):