Skip to content

Instantly share code, notes, and snippets.

@MasterGroosha
Created March 4, 2020 08:10
Show Gist options
  • Save MasterGroosha/a07a162c82adcd301c396a4afdc82a9b to your computer and use it in GitHub Desktop.
Save MasterGroosha/a07a162c82adcd301c396a4afdc82a9b to your computer and use it in GitHub Desktop.
// 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;
}
#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;
}
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