Created
March 4, 2020 08:10
-
-
Save MasterGroosha/a07a162c82adcd301c396a4afdc82a9b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is a piece of code how Commit and Revert (reset) are called | |
// m_Git is a TGitClient instance | |
void main() { | |
const auto commitMessage = "Some commit message"; | |
std::string commitError; | |
if(!m_Git.MakeCommitToRepo(commitError, commitMessage)) { | |
std::cout << "MakeCommit returned error: " << commitError << std::endl; | |
} | |
std::cout << "Commited\n"; | |
std::string revertError; | |
if (!m_Git.RevertLastCommit(revertError)) { // In reality it's reset, not "git revert", btw | |
std:cout << "could not revert: " << revertError << std::endl; | |
} else { | |
std::cout << "Reverted.\n"; | |
} | |
return; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "mod_git.h" | |
#include <iostream> | |
#include <ctime> // time_t | |
#include <sstream> | |
#include <stdlib.h> // rand, srand | |
#include "constants.h" | |
#include <chrono> | |
#include <thread> | |
using namespace std::chrono_literals; | |
// I don't really understand this code, but for me it's enough to "add everything" | |
typedef struct { /* … */ } match_data; | |
int match_cb(const char *path, const char *spec, void *payload) | |
{ | |
return 0; | |
} | |
void TGitClient::reinitRepo() { | |
// This function re-inits repository | |
git_repository_free(repo); | |
git_repository_open(&repo, repoPath.c_str()); | |
if (!repo) | |
throw std::runtime_error("Could not open repository (2). Check if the directory exists and try again."); | |
} | |
bool TGitClient::updateIndex(const git_oid *tree_id) { | |
git_index *idx = NULL; | |
int error = git_repository_index(&idx, repo); | |
if (error < 0) | |
{ | |
return false; | |
} | |
char *paths[] = {"."}; // we commit everything in folder | |
git_strarray arr = {paths, 1}; | |
match_data d = {}; // ??? | |
error = git_index_add_all(idx, &arr, 0, match_cb, &d); | |
if (error < 0) | |
{ | |
return false; | |
} | |
git_index_write(idx); | |
git_oid *tree_copy = const_cast<git_oid *>(tree_id); | |
git_index_write_tree(tree_copy, idx); | |
git_index_free(idx); | |
return true; | |
} | |
bool TGitClient::MakeCommitToRepo(std::string &errorMessage, const std::string &commitMessage) { | |
int error; | |
git_object *head_commit_obj = nullptr; | |
// Getting HEAD | |
error = git_revparse_single(&head_commit_obj, repo, "HEAD"); | |
if (error < 0) | |
{ | |
errorMessage = getLastError(error); | |
std::cout << errorMessage << std::endl; | |
return false; | |
} | |
// Convert commit object to commit itself | |
git_commit *head_commit = (git_commit *)head_commit_obj; | |
git_tree *commit_tree; | |
error = git_commit_tree(&commit_tree, head_commit); | |
if (error < 0) | |
{ | |
return false; | |
} | |
const git_oid *tree_id = git_commit_tree_id(head_commit); | |
const git_oid *head_commit_oid = git_commit_id(head_commit); | |
if(!updateIndex(tree_id)) { | |
printf("Could not update index!\n"); | |
return false; | |
} | |
git_signature *commit_author; | |
std::time_t current_time = std::time(nullptr); | |
git_signature_new(&commit_author, "root", "root@localhost", current_time, 0); | |
git_oid commit_id; | |
int commit_result = git_commit_create_v( | |
&commit_id, // new commit id | |
repo, | |
"HEAD", // update ref | |
commit_author, | |
commit_author, | |
NULL, // encoding | |
commitMessage.c_str(), | |
commit_tree, | |
1, | |
head_commit); | |
std::cout << "Commit resulted with code " << commit_result << std::endl; | |
if (commit_result < 0) | |
{ | |
return false; | |
} | |
git_signature_free(commit_author); | |
return true; | |
} | |
bool TGitClient::RevertLastCommit(std::string &errorMessage) { | |
reinitRepo(); // The issue occurs only WITHOUT this function call | |
int error; | |
// Getting the last but one commit | |
git_object *head_commit_obj = nullptr; | |
error = git_revparse_single(&head_commit_obj, repo, "HEAD~1"); | |
if (error < 0) { | |
return false; | |
} | |
int reset_result = git_reset(repo, const_cast<git_object *>(head_commit_obj), GIT_RESET_HARD, nullptr); | |
if (reset_result < 0) { | |
printf("Reset failed!\n"); | |
return false; | |
} | |
printf("Done reverting\n"); | |
return true; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class TGitClient | |
{ | |
public: | |
TGitClient(const std::string &path) { | |
repoPath = path; | |
git_repository_open(&repo, path.c_str()); | |
if (!repo) | |
throw std::runtime_error("Could not open repository. Check if the directory exists and try again."); | |
} | |
bool MakeCommitToRepo(std::string &errorMessage, const std::string &commitMessage); | |
bool RevertLastCommit(std::string &errorMessage); | |
private: | |
bool updateIndex(const git_oid *tree_id); | |
void reinitRepo(); | |
private: | |
git_repository *repo = nullptr; | |
std::string repoPath; | |
}; | |
extern TGitClient Git; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment