diff --git a/tmt/base.py b/tmt/base.py index 52cfe54875..5761c82aad 100644 --- a/tmt/base.py +++ b/tmt/base.py @@ -3734,13 +3734,11 @@ def print_header(self) -> None: def show(self) -> None: """ Display the current status """ # Prepare absolute workdir path if --id was used - # FIXME: cast() - typeless "dispatcher" method - id_ = cast(str, self.opt('id')) root_path = Path(self.opt('workdir-root')) self.print_header() assert self._cli_context_object is not None # narrow type assert self._cli_context_object.tree is not None # narrow type - for abs_path in tmt.utils.generate_runs(root_path, id_): + for abs_path in tmt.utils.generate_runs(root_path, self.opt('id')): run = Run( logger=self._logger, id_=abs_path, @@ -3840,8 +3838,6 @@ def guests(self) -> bool: """ Clean guests of runs """ self.info('guests', color='blue') root_path = Path(self.opt('workdir-root')) - # FIXME: cast() - typeless "dispatcher" method - id_ = cast(str, self.opt('id_')) if self.opt('last'): # Pass the context containing --last to Run to choose # the correct one. @@ -3849,7 +3845,7 @@ def guests(self) -> bool: Run(logger=self._logger, cli_invocation=self.cli_invocation)) successful = True assert self._cli_context_object is not None # narrow type - for abs_path in tmt.utils.generate_runs(root_path, id_): + for abs_path in tmt.utils.generate_runs(root_path, self.opt('id_')): run = Run( logger=self._logger, id_=abs_path, @@ -3876,8 +3872,6 @@ def runs(self) -> bool: """ Clean workdirs of runs """ self.info('runs', color='blue') root_path = Path(self.opt('workdir-root')) - # FIXME: cast() - typeless "dispatcher" method - id_ = cast(str, self.opt('id_')) if self.opt('last'): # Pass the context containing --last to Run to choose # the correct one. @@ -3885,7 +3879,7 @@ def runs(self) -> bool: last_run._workdir_load(last_run._workdir_path) assert last_run.workdir is not None # narrow type return self._clean_workdir(last_run.workdir) - all_workdirs = list(tmt.utils.generate_runs(root_path, id_)) + all_workdirs = list(tmt.utils.generate_runs(root_path, self.opt('id_'))) keep = self.opt('keep') if keep is not None: # Sort by modify time of the workdirs and keep the newest workdirs diff --git a/tmt/cli.py b/tmt/cli.py index 148d547011..78ff5881c8 100644 --- a/tmt/cli.py +++ b/tmt/cli.py @@ -1718,8 +1718,8 @@ def try_command(context: Context, image_and_how: str, **kwargs: Any) -> None: @pass_context @workdir_root_options @option( - '-i', '--id', metavar="ID", - help='Run id (name or directory path) to show status of.') + '-i', '--id', metavar="ID", multiple=True, + help='Run id(name or directory path) to show status of. Can be specified multiple times.') @option( '--abandoned', is_flag=True, default=False, help='List runs which have provision step completed but finish step not yet done.') @@ -1855,8 +1855,8 @@ def perform_clean( @option( '-l', '--last', is_flag=True, help='Clean the workdir of the last run.') @option( - '-i', '--id', 'id_', metavar="ID", - help='Run id (name or directory path) to clean workdir of.') + '-i', '--id', 'id_', metavar="ID", multiple=True, + help='Run id(name or directory path) to clean workdir of. Can be specified multiple times.') @option( '-k', '--keep', type=int, default=None, help='The number of latest workdirs to keep, clean the rest.') @@ -1866,7 +1866,7 @@ def clean_runs( context: Context, workdir_root: str, last: bool, - id_: Optional[str], + id_: tuple[str, ...], keep: Optional[int], **kwargs: Any) -> None: """ @@ -1874,7 +1874,7 @@ def clean_runs( Remove all runs in '/var/tmp/tmt' by default. """ - defined = [last is True, id_ is not None, keep is not None] + defined = [last is True, bool(id_), keep is not None] if defined.count(True) > 1: raise tmt.utils.GeneralError( "Options --last, --id and --keep cannot be used together.") @@ -1900,8 +1900,8 @@ def clean_runs( @option( '-l', '--last', is_flag=True, help='Stop the guest of the last run.') @option( - '-i', '--id', 'id_', metavar="ID", default=None, - help='Run id (name or directory path) to stop the guest of.') + '-i', '--id', 'id_', metavar="ID", default=None, multiple=True, + help='Run id(name or directory path) to stop the guest of. Can be specified multiple times.') @option( '-h', '--how', metavar='METHOD', help='Stop guests of the specified provision method.') @@ -1911,14 +1911,14 @@ def clean_guests( context: Context, workdir_root: str, last: bool, - id_: Optional[int], + id_: tuple[str, ...], **kwargs: Any) -> None: """ Stop running guests of runs. Stop guests of all runs in '/var/tmp/tmt' by default. """ - if last and id_ is not None: + if last and bool(id_): raise tmt.utils.GeneralError( "Options --last and --id cannot be used together.") if not Path(workdir_root).exists(): diff --git a/tmt/utils/__init__.py b/tmt/utils/__init__.py index 916f2ea71b..85ab9dc608 100644 --- a/tmt/utils/__init__.py +++ b/tmt/utils/__init__.py @@ -4656,17 +4656,21 @@ def validate_git_status(test: 'tmt.base.Test') -> tuple[bool, str]: def generate_runs( path: Path, - id_: Optional[str] = None) -> Iterator[Path]: + id_: tuple[str, ...]) -> Iterator[Path]: """ Generate absolute paths to runs from path """ # Prepare absolute workdir path if --id was used - if id_: - run_path = Path(id_) - if '/' not in id_: - run_path = path / run_path - if run_path.is_absolute(): - if run_path.exists(): + run_path = None + for id_name in id_: + if id_name: + run_path = Path(id_name) + if '/' not in id_name: + run_path = path / run_path + if run_path.is_absolute() and run_path.exists(): yield run_path - return + else: + raise tmt.utils.GeneralError("Value of '--id' option cannot be an empty string.") + if run_path: + return if not path.exists(): return for childpath in path.iterdir(): @@ -4675,7 +4679,7 @@ def generate_runs( # is being applied). If it is defined, it has been transformed # to absolute path and must be equal to abs_path for the run # in abs_path to be generated. - invalid_id = id_ and str(abs_child_path) != id_ + invalid_id = id_ and str(abs_child_path) not in id_ invalid_run = not abs_child_path.joinpath('run.yaml').exists() if not abs_child_path.is_dir() or invalid_id or invalid_run: continue