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

Fix broken dendrogram names #77

Merged
merged 5 commits into from
Mar 12, 2024
Merged
Changes from all 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
69 changes: 25 additions & 44 deletions bin/codebasin
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,9 @@ def main():
metavar="<platform>",
action="append",
default=[],
help="Add the specified platform to the analysis. "
+ "May be a name or a path to a compilation database. "
help="Include the specified platform in the analysis. "
+ "May be specified multiple times. "
+ "If not specified, all known platforms will be included.",
+ "If not specified, all platforms will be included.",
)
# The analysis-file argument is optional while we support the -c option.
parser.add_argument(
Expand Down Expand Up @@ -190,33 +189,9 @@ def main():
"Cannot use --config (-c) with TOML analysis files.",
)

# Process the -p flag first to infer wider context.
filtered_platforms = []
additional_platforms = []
for p in args.platforms:
# If it's a path, it has to be a compilation database.
if os.path.exists(p):
if not os.path.splitext(p)[1] == ".json":
raise RuntimeError(f"Platform file {p} must end in .json.")
additional_platforms.append(p)
continue

# Otherwise, treat it as a name in the configuration file.
# Explain the logic above in cases that look suspiciously like paths.
if "/" in p or os.path.splitext(p)[1] == ".json":
logging.getLogger("codebasin").warning(
f"{p} doesn't exist, so will be treated as a name.",
)
filtered_platforms.append(p)

# A legacy config file is required if:
# - No additional platforms are specified; and
# - No TOML analysis file is specified
# If no file is specified, legacy behavior checks for config.yaml
config_file = args.config_file
config_required = (
len(additional_platforms) == 0 and args.analysis_file is None
)
if config_file is None and config_required:
if args.config_file is None and args.analysis_file is None:
warnings.warn(
"Implicitly defined configuration files are deprecated.",
DeprecationWarning,
Expand Down Expand Up @@ -251,15 +226,15 @@ def main():
config_file,
rootdir,
exclude_patterns=args.excludes,
filtered_platforms=filtered_platforms,
filtered_platforms=args.platforms,
)

# Load the analysis file if it exists.
if args.analysis_file is not None:
path = os.path.realpath(args.analysis_file)
if os.path.exists(path):
if not os.path.splitext(path)[1] == ".toml":
raise RuntimeError(f"Analysis file {p} must end in .toml.")
raise RuntimeError(f"Analysis file {path} must end in .toml.")

with util.safe_open_read_nofollow(path, "rb") as f:
try:
Expand All @@ -272,23 +247,23 @@ def main():
excludes = analysis_toml["codebase"]["exclude"]
codebase["exclude_patterns"] += excludes

for name in args.platforms:
if name not in analysis_toml["platform"].keys():
raise KeyError(
f"Platform {name} requested on the command line "
+ "does not exist in the configuration file.",
)

for name in analysis_toml["platform"].keys():
if filtered_platforms and name not in filtered_platforms:
if args.platforms and name not in args.platforms:
continue
if "commands" not in analysis_toml["platform"][name]:
raise ValueError(f"Missing 'commands' for platform {name}")
p = analysis_toml["platform"][name]["commands"]
db = config.load_database(p, rootdir)
codebase["platforms"].append(name)
configuration.update({name: db})

# Extend configuration with any additional platforms.
for p in additional_platforms:
name = os.path.splitext(os.path.basename(p))[0]
if name in codebase["platforms"]:
raise RuntimeError(f"Platform name {p} conflicts with {name}.")
db = config.load_database(p, rootdir)
configuration.update({name: db})

# Parse the source tree, and determine source line associations.
# The trees and associations are housed in state.
legacy_warnings = True if config_file else False
Expand Down Expand Up @@ -331,11 +306,17 @@ def main():

# Print clustering report
if report_enabled("clustering"):
if config_file is None:
platform_names = [p[0] for p in args.platforms]
output_prefix = "-".join(platform_names)
else:
# Legacy behavior: guess prefix from YAML filename
if config_file is not None:
output_prefix = os.path.realpath(guess_project_name(config_file))

# Modern behavior: append platforms to TOML filename
else:
basename = os.path.basename(args.analysis_file)
filename = os.path.splitext(basename)[0]
platform_names = [p for p in codebase["platforms"]]
output_prefix = "-".join([filename] + platform_names)

clustering_output_name = output_prefix + "-dendrogram.png"
clustering = report.clustering(clustering_output_name, setmap)
if clustering is not None:
Expand Down
Loading