Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Groups2 #662

Merged
merged 8 commits into from
Aug 14, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 29 additions & 23 deletions lib/pavilion/clean.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
import shutil
from functools import partial
from pathlib import Path
from typing import List
from typing import List, Tuple

from pavilion import dir_db
from pavilion import groups
from pavilion import lockfile
from pavilion import utils
from pavilion.builder import TestBuilder
Expand Down Expand Up @@ -39,7 +40,7 @@ def delete_series(pav_cfg, id_dir: Path, verbose: bool = False) -> int:
return dir_db.delete(pav_cfg, id_dir, _delete_series_filter, verbose=verbose)


def delete_builds(pav_cfg, builds_dir: Path, tests_dir: Path, verbose: bool = False):
def delete_unused_builds(pav_cfg, builds_dir: Path, tests_dir: Path, verbose: bool = False):
"""Delete all build directories that are unused by any test run.

:param pav_cfg: The pavilion config.
Expand All @@ -48,27 +49,6 @@ def delete_builds(pav_cfg, builds_dir: Path, tests_dir: Path, verbose: bool = Fa
:param verbose: Bool to determine if verbose output or not.
"""

return delete_unused(pav_cfg, tests_dir, builds_dir, verbose)


def _filter_unused_builds(used_build_paths: List[Path], build_path: Path) -> bool:
"""Return whether a build is not used."""
return build_path.name not in used_build_paths


def delete_unused(pav_cfg, tests_dir: Path, builds_dir: Path, verbose: bool = False) \
-> (int, List[str]):
"""Delete all the build directories, that are unused by any test run.

:param pav_cfg: The pavilion config.
:param tests_dir: The test_runs directory path object.
:param builds_dir: The builds directory path object.
:param verbose: Print

:return int count: The number of builds that were removed.

"""

used_build_paths = _get_used_build_paths(pav_cfg, tests_dir)

filter_builds = partial(_filter_unused_builds, used_build_paths)
Expand All @@ -94,6 +74,32 @@ def delete_unused(pav_cfg, tests_dir: Path, builds_dir: Path, verbose: bool = Fa
return count, msgs


def clean_groups(pav_cfg) -> Tuple[int, List[str]]:
"""Remove members that no longer exist from groups, and delete empty groups.
Returns the number of groups deleted and a list of error messages."""

groups_dir = pav_cfg.working_dir/groups.TestGroup.GROUPS_DIR

if not groups_dir.exists():
return 0, []

msgs = []
deleted = 0
for group_path in groups_dir.iterdir():
group = groups.TestGroup(pav_cfg, group_path.name)
for error in group.clean():
msgs.append(error.pformat())
if not group.exists():
deleted += 1

return deleted, msgs


def _filter_unused_builds(used_build_paths: List[Path], build_path: Path) -> bool:
"""Return whether a build is not used."""
return build_path.name not in used_build_paths


def _get_used_build_paths(pav_cfg, tests_dir: Path) -> set:
"""Generate a set of all build paths currently used by one or more test
runs."""
Expand Down
56 changes: 42 additions & 14 deletions lib/pavilion/cmd_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@
from pavilion import config
from pavilion import dir_db
from pavilion import filters
from pavilion import groups
from pavilion import output
from pavilion import series
from pavilion import sys_vars
from pavilion import utils
from pavilion.errors import TestRunError, CommandError, TestSeriesError
from pavilion.errors import TestRunError, CommandError, TestSeriesError, TestGroupError
from pavilion.test_run import TestRun, test_run_attr_transform, load_tests
from pavilion.types import ID_Pair

Expand Down Expand Up @@ -291,29 +292,24 @@ def test_list_to_paths(pav_cfg, req_tests, errfile=None) -> List[Path]:
:return: A list of test id's.
"""

if errfile is None:
errfile = io.StringIO()

test_paths = []
for raw_id in req_tests:

if raw_id == 'last':
raw_id = series.load_user_series_id(pav_cfg, errfile)
if raw_id is None:
if errfile:
output.fprint(errfile, "User has no 'last' series for this machine.",
color=output.YELLOW)
output.fprint(errfile, "User has no 'last' series for this machine.",
color=output.YELLOW)
continue

if raw_id is None:
if raw_id is None or not raw_id:
continue

if '.' not in raw_id and raw_id.startswith('s'):
try:
test_paths.extend(
series.list_series_tests(pav_cfg, raw_id))
except TestSeriesError:
if errfile:
output.fprint(errfile, "Invalid series id '{}'".format(raw_id),
color=output.YELLOW)
else:
if '.' in raw_id or utils.is_int(raw_id):
# This is a test id.
try:
test_wd, _id = TestRun.parse_raw_id(pav_cfg, raw_id)
except TestRunError as err:
Expand All @@ -326,6 +322,38 @@ def test_list_to_paths(pav_cfg, req_tests, errfile=None) -> List[Path]:
output.fprint(errfile,
"Test run with id '{}' could not be found.".format(raw_id),
color=output.YELLOW)
elif raw_id[0] == 's' and utils.is_int(raw_id[1:]):
# A series.
try:
test_paths.extend(
series.list_series_tests(pav_cfg, raw_id))
except TestSeriesError:
output.fprint(errfile, "Invalid series id '{}'".format(raw_id),
color=output.YELLOW)
else:
# A group
try:
group = groups.TestGroup(pav_cfg, raw_id)
except TestGroupError as err:
output.fprint(
errfile,
"Invalid test group id '{}'.\n{}"
.format(raw_id, err.pformat()))
continue

if not group.exists():
output.fprint(
errfile,
"Group '{}' does not exist.".format(raw_id))
continue

try:
test_paths.extend(group.tests())
except TestGroupError as err:
output.fprint(
errfile,
"Invalid test group id '{}', could not get tests from group."
.format(raw_id))

return test_paths

Expand Down
1 change: 1 addition & 0 deletions lib/pavilion/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
'clean': 'CleanCommand',
'config': 'ConfigCommand',
'graph': 'GraphCommand',
'group': 'GroupCommand',
'list_cmd': 'ListCommand',
'log': 'LogCommand',
'ls': 'LSCommand',
Expand Down
13 changes: 11 additions & 2 deletions lib/pavilion/commands/clean.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ def run(self, pav_cfg: PavConfig, args):
builds_dir = working_dir / 'builds' # type: Path
tests_dir = working_dir / 'test_runs'
output.fprint(self.outfile, "Removing Builds ({})".format(working_dir), end=end)
rm_builds_count, msgs = clean.delete_builds(pav_cfg, builds_dir, tests_dir,
args.verbose)
rm_builds_count, msgs = clean.delete_unused_builds(pav_cfg, builds_dir, tests_dir,
args.verbose)
msgs.extend(clean.delete_lingering_build_files(pav_cfg, builds_dir, tests_dir,
args.verbose))
if args.verbose:
Expand All @@ -104,4 +104,13 @@ def run(self, pav_cfg: PavConfig, args):
output.fprint(self.outfile, "Removed {} build(s).".format(rm_builds_count),
color=output.GREEN, clear=True)


deleted_groups, msgs = clean.clean_groups(pav_cfg)
if args.verbose:
for msg in msgs:
output.fprint(self.outfile, msg, color=output.YELLOW)
output.fprint(self.outfile,
"Removed {} test groups that became empty.".format(deleted_groups),
color=output.GREEN, clear=True)

return 0
Loading