manifest: simplify and fix get_projects()

Fixes: #523

The Manifest class has these instance attributes:

- _projects_by_name: maps project names -> Projects, has 'manifest' as
  a key and the ManifestProject as a value (this is one reason why
  'manifest' is a reserved project name)

- _projects_by_rpath: maps resolve()d Paths -> Projects, has the
  manifest repository's path as a key, pointing to the ManifestProject

So get_projects() ought to just rely on these dicts to do its job.

However, it's currently got extra special-case code it doesn't need,
and the code is buggy. Specifically this part:

mpath: Optional[Path] = Path(mp.path).resolve()

This is trying to get the ManifestProject's resolved path, but it only
works if you happen to be in the workspace topdir, since mp.path is
relative.

We got "lucky" and can still find the manifest project by its relative
path because we fall back on _projects_by_rpath.

But this is still a correctness problem. When the current
directory *isn't* the topdir, but has a subdirectory or file inside it
whose name happens to match mp.path, we could return the
ManifestProject as a result, incorrectly.

Just remove all the unnecessary extra code and use _projects_by_name /
_projects_by_rpath to do the work.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This commit is contained in:
Martí Bolívar 2021-07-30 11:22:30 -07:00 committed by Marti Bolivar
parent 5451c3ae71
commit e8080e9c3f
1 changed files with 9 additions and 21 deletions

View File

@ -1384,35 +1384,23 @@ class Manifest:
# Otherwise, resolve each of the project_ids to a project,
# returning the result or raising ValueError.
mp = self.projects[MANIFEST_PROJECT_INDEX]
if mp.path is not None:
mpath: Optional[Path] = Path(mp.path).resolve()
else:
mpath = None
for pid in project_ids:
project: Optional[Project] = None
if isinstance(pid, str):
if pid == 'manifest':
project: Optional[Project] = mp
else:
project = self._projects_by_name.get(pid)
else:
project = None
project = self._projects_by_name.get(pid)
if project is None and allow_paths:
rpath = Path(pid).resolve()
if mpath is not None and rpath == mpath:
project = mp
else:
project = self._projects_by_rpath.get(rpath)
project = self._projects_by_rpath.get(Path(pid).resolve())
if project is None:
unknown.append(pid)
else:
ret.append(project)
continue
if only_cloned and not project.is_cloned():
uncloned.append(project)
ret.append(project)
if only_cloned and not project.is_cloned():
uncloned.append(project)
if unknown or (only_cloned and uncloned):
raise ValueError(unknown, uncloned)