west list: compatibility-breaking improvements
- The default west list format string is not particularly readable most of the time. Tweak it so it's better. - replace multi-word strings like "(not set)" with single word equivalents like "N/A", which are easier to deal with in pipelines to cut, awk, etc. - add a new {sha} format specifier that always produces a 40-character SHA, or the string N/A padded to the correct length. Signed-off-by: Marti Bolivar <marti.bolivar@nordicsemi.no>
This commit is contained in:
parent
5dbc3e9b0d
commit
4dd845d8d3
|
@ -7,6 +7,7 @@
|
|||
|
||||
import argparse
|
||||
import collections
|
||||
from functools import partial
|
||||
import os
|
||||
from os.path import join, abspath, relpath, realpath, normpath, \
|
||||
basename, dirname, normcase, exists, isdir
|
||||
|
@ -245,7 +246,7 @@ class List(WestCommand):
|
|||
by default. Use --all or the name "west" to include it.'''))
|
||||
|
||||
def do_add_parser(self, parser_adder):
|
||||
default_fmt = '{name:14} {path:18} {revision:13} {url} {cloned}'
|
||||
default_fmt = '{name:12} {path:28} {revision:40} {url}'
|
||||
return _add_parser(
|
||||
parser_adder, self,
|
||||
_arg('-a', '--all', action='store_true',
|
||||
|
@ -277,27 +278,45 @@ class List(WestCommand):
|
|||
- abspath: absolute and normalized path to the project
|
||||
- posixpath: like abspath, but in posix style, that is, with '/'
|
||||
as the separator character instead of '\\'
|
||||
- revision: project's manifest revision
|
||||
- cloned: "(cloned)" if the project has been cloned, "(not cloned)"
|
||||
- revision: project's revision as it appears in the manifest
|
||||
- sha: project's revision as a SHA
|
||||
- cloned: "cloned" if the project has been cloned, "not-cloned"
|
||||
otherwise
|
||||
- clone_depth: project clone depth if specified, "None" otherwise
|
||||
'''.format(default_fmt)))
|
||||
|
||||
def do_run(self, args, user_args):
|
||||
def sha_thunk(project):
|
||||
if project.revision:
|
||||
return _sha(project, MANIFEST_REV)
|
||||
else:
|
||||
return '{:40}'.format('N/A')
|
||||
|
||||
def cloned_thunk(project):
|
||||
return "cloned" if _cloned(project) else "not-cloned"
|
||||
|
||||
def delay(func, project):
|
||||
return DelayFormat(partial(func, project))
|
||||
|
||||
for project in _projects(args):
|
||||
# Spelling out the format keys explicitly here gives us
|
||||
# future-proofing if the internal Project representation
|
||||
# ever changes.
|
||||
#
|
||||
# Using DelayFormat delays computing derived values, such
|
||||
# as SHAs, unless they are specifically requested, and then
|
||||
# ensures they are only computed once.
|
||||
try:
|
||||
result = args.format.format(
|
||||
name=project.name,
|
||||
url=project.url,
|
||||
url=project.url or 'N/A',
|
||||
path=project.path,
|
||||
abspath=project.abspath,
|
||||
posixpath=project.posixpath,
|
||||
revision=project.revision,
|
||||
cloned="(cloned)" if _cloned(project) else "(not cloned)",
|
||||
clone_depth=project.clone_depth or "None")
|
||||
revision=project.revision or 'N/A',
|
||||
clone_depth=project.clone_depth or "None",
|
||||
cloned=delay(cloned_thunk, project),
|
||||
sha=delay(sha_thunk, project))
|
||||
except KeyError as e:
|
||||
# The raised KeyError seems to just put the first
|
||||
# invalid argument in the args tuple, regardless of
|
||||
|
@ -999,3 +1018,30 @@ MANIFEST = 'manifest'
|
|||
MANIFEST_URL_DEFAULT = 'https://github.com/zephyrproject-rtos/zephyr'
|
||||
# Default revision to check out of the manifest repository.
|
||||
MANIFEST_REV_DEFAULT = 'master'
|
||||
|
||||
#
|
||||
# Helper class for creating format string keys that are expensive or
|
||||
# undesirable to compute if not needed.
|
||||
#
|
||||
|
||||
class DelayFormat:
|
||||
'''Delays formatting an object.'''
|
||||
|
||||
def __init__(self, obj):
|
||||
'''Delay formatting `obj` until a format operation using it.
|
||||
|
||||
:param obj: object to format
|
||||
|
||||
If callable(obj) returns True, then obj() will be used as the
|
||||
string to be formatted. Otherwise, str(obj) is used.'''
|
||||
self.obj = obj
|
||||
self.as_str = None
|
||||
|
||||
def __format__(self, format_spec):
|
||||
if self.as_str is None:
|
||||
if callable(self.obj):
|
||||
self.as_str = self.obj()
|
||||
assert isinstance(self.as_str, str)
|
||||
else:
|
||||
self.as_str = str(self.obj)
|
||||
return ('{:' + format_spec + '}').format(self.as_str)
|
||||
|
|
|
@ -622,15 +622,15 @@ class Project:
|
|||
class ManifestProject(Project):
|
||||
'''Represents the manifest as a project.'''
|
||||
|
||||
def __init__(self, path=None, revision='(not set)', url='(not set)',
|
||||
def __init__(self, path=None, revision=None, url=None,
|
||||
west_commands=None):
|
||||
'''Specify a Special Project by name, and url, and optional information.
|
||||
|
||||
:param path: Relative path to the project in the west
|
||||
installation, if present in the manifest. If None,
|
||||
the project's ``name`` is used.
|
||||
:param revision: Project revision as given in the manifest, if present.
|
||||
:param url: Complete URL for special project.
|
||||
:param revision: manifest project revision, or None
|
||||
:param url: Complete URL for the manifest project, or None
|
||||
:param west_commands: path to a YAML file in the project containing
|
||||
a description of west extension commands provided
|
||||
by the project, if given. This obviously only
|
||||
|
|
|
@ -48,10 +48,10 @@ def test_list(west_update_tmpdir):
|
|||
# Projects shall be listed in the order they appear in the manifest.
|
||||
# Check the behavior for some format arguments of interest as well.
|
||||
actual = cmd('list -f "{name} {revision} {path} {cloned} {clone_depth}"')
|
||||
expected = ['zephyr (not set) zephyr (cloned) None',
|
||||
'Kconfiglib zephyr {} (cloned) None'.format(
|
||||
expected = ['zephyr N/A zephyr cloned None',
|
||||
'Kconfiglib zephyr {} cloned None'.format(
|
||||
os.path.join('subdir', 'Kconfiglib')),
|
||||
'net-tools master net-tools (cloned) None']
|
||||
'net-tools master net-tools cloned None']
|
||||
assert actual.splitlines() == expected
|
||||
|
||||
# We should be able to find projects by absolute or relative path
|
||||
|
|
Loading…
Reference in New Issue