mirror of
https://github.com/godotengine/godot-git-plugin.git
synced 2026-01-01 01:48:28 +03:00
Added hooks for the new diff view
This commit is contained in:
@@ -36,7 +36,7 @@ void GitAPI::_discard_file(String p_file_path) {
|
||||
}
|
||||
|
||||
void GitAPI::_commit(const String p_msg) {
|
||||
|
||||
|
||||
if (!can_commit) {
|
||||
godot::Godot::print("Git API: Cannot commit. Check previous errors.");
|
||||
return;
|
||||
@@ -95,7 +95,7 @@ void GitAPI::_commit(const String p_msg) {
|
||||
git_commit_free(fetchhead_commit);
|
||||
git_repository_state_cleanup(repo);
|
||||
}
|
||||
|
||||
|
||||
git_index_free(repo_index);
|
||||
git_signature_free(default_sign);
|
||||
git_commit_free(parent_commit);
|
||||
@@ -210,8 +210,8 @@ Dictionary GitAPI::_get_modified_files_data() {
|
||||
Dictionary diff;
|
||||
Dictionary index; // Schema is <file_path, status>
|
||||
Dictionary wt; // Schema is <file_path, status>
|
||||
diff["index"] = index;
|
||||
diff["wt"] = wt;
|
||||
diff[TREE_AREA_STAGED] = index;
|
||||
diff[TREE_AREA_UNSTAGED] = wt;
|
||||
|
||||
git_status_options opts = GIT_STATUS_OPTIONS_INIT;
|
||||
opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
|
||||
@@ -236,17 +236,17 @@ Dictionary GitAPI::_get_modified_files_data() {
|
||||
}
|
||||
|
||||
static Dictionary map_changes;
|
||||
map_changes[GIT_STATUS_WT_NEW] = 0;
|
||||
map_changes[GIT_STATUS_INDEX_NEW] = 0;
|
||||
map_changes[GIT_STATUS_WT_MODIFIED] = 1;
|
||||
map_changes[GIT_STATUS_INDEX_MODIFIED] = 1;
|
||||
map_changes[GIT_STATUS_WT_RENAMED] = 2;
|
||||
map_changes[GIT_STATUS_INDEX_RENAMED] = 2;
|
||||
map_changes[GIT_STATUS_WT_DELETED] = 3;
|
||||
map_changes[GIT_STATUS_INDEX_DELETED] = 3;
|
||||
map_changes[GIT_STATUS_WT_TYPECHANGE] = 4;
|
||||
map_changes[GIT_STATUS_INDEX_TYPECHANGE] = 4;
|
||||
map_changes[GIT_STATUS_CONFLICTED] = 5;
|
||||
map_changes[GIT_STATUS_WT_NEW] = CHANGE_TYPE_NEW;
|
||||
map_changes[GIT_STATUS_INDEX_NEW] = CHANGE_TYPE_NEW;
|
||||
map_changes[GIT_STATUS_WT_MODIFIED] = CHANGE_TYPE_MODIFIED;
|
||||
map_changes[GIT_STATUS_INDEX_MODIFIED] = CHANGE_TYPE_MODIFIED;
|
||||
map_changes[GIT_STATUS_WT_RENAMED] = CHANGE_TYPE_RENAMED;
|
||||
map_changes[GIT_STATUS_INDEX_RENAMED] = CHANGE_TYPE_RENAMED;
|
||||
map_changes[GIT_STATUS_WT_DELETED] = CHANGE_TYPE_DELETED;
|
||||
map_changes[GIT_STATUS_INDEX_DELETED] = CHANGE_TYPE_DELETED;
|
||||
map_changes[GIT_STATUS_WT_TYPECHANGE] = CHANGE_TYPE_TYPECHANGE;
|
||||
map_changes[GIT_STATUS_INDEX_TYPECHANGE] = CHANGE_TYPE_TYPECHANGE;
|
||||
map_changes[GIT_STATUS_CONFLICTED] = CHANGE_TYPE_UNMERGED;
|
||||
|
||||
const static int git_status_wt = GIT_STATUS_WT_NEW | GIT_STATUS_WT_MODIFIED | GIT_STATUS_WT_DELETED | GIT_STATUS_WT_TYPECHANGE | GIT_STATUS_WT_RENAMED | GIT_STATUS_CONFLICTED;
|
||||
const static int git_status_index = GIT_STATUS_INDEX_NEW | GIT_STATUS_INDEX_MODIFIED | GIT_STATUS_INDEX_DELETED | GIT_STATUS_INDEX_RENAMED | GIT_STATUS_INDEX_TYPECHANGE;
|
||||
@@ -317,6 +317,7 @@ Array GitAPI::_get_previous_commits() {
|
||||
git_commit *commit;
|
||||
const git_signature *sig;
|
||||
git_oid oid;
|
||||
char commit_id[GIT_OID_HEXSZ + 1];
|
||||
|
||||
git_revwalk_new(&walker, repo);
|
||||
git_revwalk_sorting(walker, GIT_SORT_TIME);
|
||||
@@ -324,14 +325,15 @@ Array GitAPI::_get_previous_commits() {
|
||||
|
||||
for (int i = 0; !git_revwalk_next(&oid, walker) && i <= max_commit_fetch; i++) {
|
||||
|
||||
GIT2_CALL_R(git_commit_lookup(&commit, repo, &oid), "Failed to lookup the commit", Array());
|
||||
GIT2_CALL_R(git_commit_lookup(&commit, repo, &oid), "Failed to lookup the commit", commits);
|
||||
|
||||
sig = git_commit_author(commit);
|
||||
|
||||
git_oid_tostr(commit_id, GIT_OID_HEXSZ + 1, git_commit_id(commit));
|
||||
Dictionary commit_info;
|
||||
commit_info["message"] = String(git_commit_message(commit));
|
||||
commit_info["author"] = String(sig->name);
|
||||
commit_info["when"] = (int64_t)sig->when.time + (int64_t)(sig->when.offset * 60); // Epoch time in seconds
|
||||
commit_info["id"] = String(commit_id);
|
||||
commits.push_back(commit_info);
|
||||
git_commit_free(commit);
|
||||
}
|
||||
@@ -467,29 +469,144 @@ bool GitAPI::_checkout_branch(String p_branch_name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Array GitAPI::_get_file_diff(const String file_path) {
|
||||
Array GitAPI::_get_file_diff(const String identifier, int area) {
|
||||
|
||||
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
|
||||
git_diff *diff;
|
||||
Array diff_contents;
|
||||
|
||||
opts.context_lines = 3;
|
||||
opts.context_lines = 2;
|
||||
opts.interhunk_lines = 0;
|
||||
opts.flags = GIT_DIFF_DISABLE_PATHSPEC_MATCH | GIT_DIFF_INCLUDE_UNTRACKED;
|
||||
|
||||
char *pathspec = file_path.alloc_c_string();
|
||||
char *pathspec = identifier.alloc_c_string();
|
||||
opts.pathspec.strings = &pathspec;
|
||||
opts.pathspec.count = 1;
|
||||
|
||||
GIT2_CALL_R(git_diff_index_to_workdir(&diff, repo, NULL, &opts), "Could not create diff for index from working directory", Array());
|
||||
switch ((TreeArea)area) {
|
||||
case TREE_AREA_UNSTAGED: {
|
||||
GIT2_CALL_R(git_diff_index_to_workdir(&diff, repo, NULL, &opts), "Could not create diff for index from working directory", diff_contents);
|
||||
} break;
|
||||
case TREE_AREA_STAGED: {
|
||||
git_object *obj = nullptr;
|
||||
git_tree *tree = nullptr;
|
||||
|
||||
diff_contents.clear();
|
||||
GIT2_CALL_R(git_diff_print(diff, GIT_DIFF_FORMAT_PATCH, diff_line_callback_function, &diff_contents), "Call to diff handler provided unsuccessful", Array());
|
||||
GIT2_CALL_R(git_revparse_single(&obj, repo, "HEAD^{tree}"), "", diff_contents);
|
||||
GIT2_CALL_R(git_tree_lookup(&tree, repo, git_object_id(obj)), "", diff_contents);
|
||||
GIT2_CALL_R(git_diff_tree_to_index(&diff, repo, tree, NULL, &opts), "Could not create diff for tree from index directory", diff_contents);
|
||||
|
||||
git_tree_free(tree);
|
||||
git_object_free(obj);
|
||||
} break;
|
||||
case TREE_AREA_COMMIT: {
|
||||
opts.pathspec = {};
|
||||
git_object *obj = nullptr;
|
||||
git_commit *commit = nullptr, *parent = nullptr;
|
||||
git_tree *commit_tree = nullptr, *parent_tree = nullptr;
|
||||
|
||||
GIT2_CALL_R(git_revparse_single(&obj, repo, pathspec), "", diff_contents);
|
||||
GIT2_CALL_R(git_commit_lookup(&commit, repo, git_object_id(obj)), "", diff_contents);
|
||||
GIT2_CALL_R(git_commit_parent(&parent, commit, 0), "", diff_contents);
|
||||
GIT2_CALL_R(git_commit_tree(&commit_tree, commit), "", diff_contents);
|
||||
GIT2_CALL_R(git_commit_tree(&parent_tree, parent), "", diff_contents);
|
||||
GIT2_CALL_R(git_diff_tree_to_tree(&diff, repo, parent_tree, commit_tree, &opts), "", diff_contents);
|
||||
|
||||
git_object_free(obj);
|
||||
git_commit_free(commit);
|
||||
git_commit_free(parent);
|
||||
git_tree_free(commit_tree);
|
||||
git_tree_free(parent_tree);
|
||||
} break;
|
||||
}
|
||||
|
||||
diff_contents = _parse_diff(diff);
|
||||
git_diff_free(diff);
|
||||
|
||||
return diff_contents;
|
||||
}
|
||||
|
||||
Array GitAPI::_parse_diff(git_diff *diff) {
|
||||
|
||||
/*
|
||||
diff_files: [
|
||||
{
|
||||
String new_file_path:
|
||||
String old_file_path:
|
||||
hunks:[
|
||||
{
|
||||
int old_start:
|
||||
int old_lines:
|
||||
int new_start:
|
||||
int new_lines:
|
||||
diff_lines: [
|
||||
{
|
||||
int old_line_no:
|
||||
int new_line_no:
|
||||
String content:
|
||||
String status:
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
*/
|
||||
Array diff_contents;
|
||||
for (int i = 0; i < git_diff_num_deltas(diff); i++) {
|
||||
git_patch *patch;
|
||||
const git_diff_delta *delta = git_diff_get_delta(diff, i); //file_cb
|
||||
git_patch_from_diff(&patch, diff, i);
|
||||
|
||||
if (delta->flags & GIT_DIFF_FLAG_BINARY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (delta->status == GIT_DELTA_UNMODIFIED || delta->status == GIT_DELTA_IGNORED || delta->status == GIT_DELTA_UNTRACKED) {
|
||||
continue;
|
||||
}
|
||||
Dictionary file_diff;
|
||||
file_diff["new_file"] = String(delta->new_file.path);
|
||||
file_diff["old_file"] = String(delta->old_file.path);
|
||||
|
||||
Array hunks;
|
||||
for (int j = 0; j < git_patch_num_hunks(patch); j++) {
|
||||
const git_diff_hunk *git_hunk;
|
||||
size_t line_count;
|
||||
git_patch_get_hunk(&git_hunk, &line_count, patch, j);
|
||||
|
||||
Dictionary hunk;
|
||||
hunk["old_start"] = git_hunk->old_start;
|
||||
hunk["new_start"] = git_hunk->new_start;
|
||||
hunk["old_lines"] = git_hunk->old_lines;
|
||||
hunk["new_lines"] = git_hunk->new_lines;
|
||||
|
||||
Array diff_lines;
|
||||
for (int k = 0; k < line_count; k++) {
|
||||
const git_diff_line *git_diff_line;
|
||||
git_patch_get_line_in_hunk(&git_diff_line, patch, j, k); //line_cb
|
||||
char *content = new char[git_diff_line->content_len + 1];
|
||||
memcpy(content, git_diff_line->content, git_diff_line->content_len);
|
||||
content[git_diff_line->content_len] = '\0';
|
||||
|
||||
Dictionary diff_line;
|
||||
diff_line["old_line_no"] = git_diff_line->old_lineno;
|
||||
diff_line["new_line_no"] = git_diff_line->new_lineno;
|
||||
diff_line["content"] = String(content);
|
||||
diff_line["status"] = String(git_diff_line->origin);
|
||||
|
||||
diff_lines.push_back(diff_line);
|
||||
}
|
||||
|
||||
hunk["diff_lines"] = diff_lines;
|
||||
hunks.push_back(hunk);
|
||||
}
|
||||
file_diff["hunks"] = hunks;
|
||||
diff_contents.push_back(file_diff);
|
||||
git_patch_free(patch);
|
||||
}
|
||||
return diff_contents;
|
||||
}
|
||||
|
||||
String GitAPI::_get_project_name() {
|
||||
|
||||
return String("project");
|
||||
|
||||
@@ -36,14 +36,13 @@ class GitAPI : public EditorVCSInterface {
|
||||
git_remote_callbacks remote_cbs;
|
||||
|
||||
bool has_merge = false;
|
||||
Array diff_contents;
|
||||
git_oid pull_merge_oid;
|
||||
Credentials creds;
|
||||
|
||||
void _commit(const String p_msg);
|
||||
bool _is_vcs_initialized();
|
||||
Dictionary _get_modified_files_data();
|
||||
Array _get_file_diff(const String file_path);
|
||||
Array _get_file_diff(const String file_path, int area);
|
||||
String _get_project_name();
|
||||
String _get_vcs_name();
|
||||
bool _initialize(const String p_project_root_path);
|
||||
@@ -60,6 +59,7 @@ class GitAPI : public EditorVCSInterface {
|
||||
void _push();
|
||||
const char *_get_current_branch_name(bool full_ref);
|
||||
void _set_up_credentials(String p_username, String p_password);
|
||||
Array _parse_diff(git_diff *diff);
|
||||
|
||||
public:
|
||||
static void _register_methods();
|
||||
|
||||
@@ -22,44 +22,6 @@ bool check_git2_errors(int error, godot::String message, godot::String function,
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" int diff_line_callback_function(const git_diff_delta *delta, const git_diff_hunk *hunk, const git_diff_line *line, void *payload) {
|
||||
|
||||
// First we NULL terminate the line text incoming
|
||||
char *content = new char[line->content_len + 1];
|
||||
memcpy(content, line->content, line->content_len);
|
||||
static int i = 0;
|
||||
content[line->content_len] = '\0';
|
||||
|
||||
godot::String prefix = "";
|
||||
switch (line->origin) {
|
||||
|
||||
case GIT_DIFF_LINE_DEL_EOFNL:
|
||||
case GIT_DIFF_LINE_DELETION:
|
||||
prefix = "-";
|
||||
break;
|
||||
|
||||
case GIT_DIFF_LINE_ADD_EOFNL:
|
||||
case GIT_DIFF_LINE_ADDITION:
|
||||
prefix = "+";
|
||||
break;
|
||||
}
|
||||
|
||||
godot::String content_str = content;
|
||||
|
||||
godot::Dictionary result;
|
||||
result["content"] = prefix + content_str;
|
||||
result["status"] = prefix;
|
||||
result["new_line_number"] = line->new_lineno;
|
||||
result["line_count"] = line->num_lines;
|
||||
result["old_line_number"] = line->old_lineno;
|
||||
result["offset"] = line->content_offset;
|
||||
|
||||
godot::Array *diff_contents = (godot::Array *)payload;
|
||||
diff_contents->push_back(result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int progress_cb(const char *str, int len, void *data) {
|
||||
(void)data;
|
||||
godot::Godot::print("remote: " + godot::String(str).strip_edges());
|
||||
|
||||
@@ -10,7 +10,6 @@ struct Credentials {
|
||||
char *password;
|
||||
};
|
||||
|
||||
extern "C" int diff_line_callback_function(const git_diff_delta *delta, const git_diff_hunk *hunk, const git_diff_line *line, void *payload);
|
||||
extern "C" int progress_cb(const char *str, int len, void *data);
|
||||
extern "C" int update_cb(const char *refname, const git_oid *a, const git_oid *b, void *data);
|
||||
extern "C" int transfer_progress_cb(const git_indexer_progress *stats, void *payload);
|
||||
|
||||
Reference in New Issue
Block a user