13 : similarity_table(_similarity_table) {}
16 if (
options.extra_args.size() != 2) {
17 throw CLIError(
"Git diff command expects two function name patterns.");
25 const std::string first_pattern = format_pattern(
options.extra_args[0]);
26 const std::string second_pattern = format_pattern(
options.extra_args[1]);
28 std::vector<Path> first_candidates = find_matching_paths(first_pattern);
29 std::vector<Path> second_candidates = find_matching_paths(second_pattern);
31 Path first_path = choose_single_path(first_candidates,
options.extra_args[0]);
32 Path second_path = choose_single_path(second_candidates,
options.extra_args[1]);
34 if (!similarity_table->
is_similar(first_path, second_path)) {
37 std::ostringstream ss;
38 ss << std::fixed << std::setprecision(2) << similarity;
40 throw CLIError(
"The selected functions are not flagged as duplicates in the similarity table (similarity: " + ss.str() +
").");
44 return diff_functions(first_path, second_path);
47std::vector<Path> GitDiffFunction::find_matching_paths(
const std::string& pattern)
const {
48 std::vector<Path> matches;
53 if (function.contains_given_pattern(pattern))
54 matches.push_back(path);
59const std::string GitDiffFunction::format_pattern(
const std::string& pattern)
const {
60 std::string result = pattern;
63 while ((pos = result.find(
"::", pos)) != std::string::npos) {
64 result.replace(pos, 2,
"/");
71Path GitDiffFunction::choose_single_path(
const std::vector<Path>& candidates,
const std::string& pattern)
const {
72 if (candidates.empty()) {
73 throw CLIError(
"No function found matching pattern: " + pattern);
75 if (candidates.size() > 1) {
76 std::ostringstream message;
77 message <<
"Multiple functions match the pattern '" << pattern <<
"':\n";
79 for (
const auto& path : candidates) {
83 message <<
"Please use a more specific function name pattern.";
86 return candidates.front();
89std::string GitDiffFunction::build_text_from_lines(
const std::vector<std::string>& lines) {
91 output.reserve(lines.size() * 80);
92 for (
const auto& line : lines) {
94 output.push_back(
'\n');
99bool GitDiffFunction::diff_functions(
const Path& first,
const Path& second)
const {
101 auto first_function = loader.
load(first);
102 auto second_function = loader.
load(second);
104 std::string first_text = build_text_from_lines(first_function.build_all_content());
105 std::string second_text = build_text_from_lines(second_function.build_all_content());
109 first_function.name(),
111 second_function.name(),
115 if (result.error != 0) {
116 std::cerr <<
"Failed to compute diff between functions. libgit2 error code: " << result.error <<
"\n";
120 if (!result.has_difference) {
121 std::cout <<
"No differences found between the selected functions.\n";
Base class for CLI-related errors.
const CliOption * options() const final
Function load(const Path &path)
Loads a function from a path.
Function load_metadata(const Path &path)
Loads function metadata from a path.
static std::string format_path_message_in_pair(const Function &function)
Formats path for display.
bool validate(const ParsedOptions &options) override
Validate the arguments already analyzed.
GitDiffFunction(Similarity_Table *_similarity_table)
bool run(const ParsedOptions &options) override
Executes the main logic of the command.
static DiffResult compare(std::string_view first_text, std::string_view first_name, std::string_view second_text, std::string_view second_name, std::ostream &output)
Represents a logical path to a function in the codebase.
Represents a similarity graph between functions (paths).
const std::vector< Path > & get_path_list() const
Gets list of all known paths.
bool is_similar(const Path &path1, const Path &path2)
Checks if two paths are similar.
double get_threshold_similarity() const
Gets the similarity threshold.
Provides functionality to load Function objects from external sources.
Provides utilities for printing function information and source code.