Skip to content
Draft
Show file tree
Hide file tree
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
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ set(GIT2CPP_SRC
${GIT2CPP_SOURCE_DIR}/subcommand/revlist_subcommand.hpp
${GIT2CPP_SOURCE_DIR}/subcommand/revparse_subcommand.cpp
${GIT2CPP_SOURCE_DIR}/subcommand/revparse_subcommand.hpp
${GIT2CPP_SOURCE_DIR}/subcommand/stash_subcommand.cpp
${GIT2CPP_SOURCE_DIR}/subcommand/stash_subcommand.hpp
${GIT2CPP_SOURCE_DIR}/subcommand/status_subcommand.cpp
${GIT2CPP_SOURCE_DIR}/subcommand/status_subcommand.hpp
${GIT2CPP_SOURCE_DIR}/utils/ansi_code.cpp
Expand Down
2 changes: 2 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "subcommand/push_subcommand.hpp"
#include "subcommand/remote_subcommand.hpp"
#include "subcommand/reset_subcommand.hpp"
#include "subcommand/stash_subcommand.hpp"
#include "subcommand/status_subcommand.hpp"
#include "subcommand/revparse_subcommand.hpp"
#include "subcommand/revlist_subcommand.hpp"
Expand Down Expand Up @@ -50,6 +51,7 @@ int main(int argc, char** argv)
remote_subcommand remote(lg2_obj, app);
revparse_subcommand revparse(lg2_obj, app);
revlist_subcommand revlist(lg2_obj, app);
stash_subcommand stash(lg2_obj, app);

app.require_subcommand(/* min */ 0, /* max */ 1);

Expand Down
68 changes: 68 additions & 0 deletions src/subcommand/stash_subcommand.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#include <git2/stash.h>
#include <iostream>

#include <git2/remote.h>

#include "../subcommand/stash_subcommand.hpp"
#include "../wrapper/repository_wrapper.hpp"

stash_subcommand::stash_subcommand(const libgit2_object&, CLI::App& app)
{
auto* stash = app.add_subcommand("stash", "Stash the changes in a dirty working directory away");
auto* push = stash->add_subcommand("push", "");
auto* list = stash->add_subcommand("list", "");
auto* pop = stash->add_subcommand("pop", "");
auto* apply = stash->add_subcommand("apply", "");

push->add_option("-m", m_message, "");
pop->add_option("--index", m_index, "");
apply->add_option("--index", m_index, "");

stash->callback([this]() { this->run_push(); });
push->callback([this]() { this->run_push(); });
list->callback([this]() { this->run_list(); });
pop->callback([this]() { this->run_pop(); });
apply->callback([this]() { this->run_apply(); });
}

void stash_subcommand::run_push()
{
auto directory = get_current_git_path();
auto repo = repository_wrapper::open(directory);
auto author_committer_signatures = signature_wrapper::get_default_signature_from_env(repo);

git_oid stash_id;
git_stash_save(&stash_id, repo, author_committer_signatures.first, m_message.c_str(), GIT_STASH_DEFAULT);
auto stash = repo.find_commit(stash_id);
std::cout << "Saved working directory " << stash.summary() << std::endl;
}

static int list_stash_cb(size_t index, const char* message, const git_oid* stash_id, void* payload)
{
std::cout << "stash@{" << index << "}: " << message << std::endl;
return 0;
}

void stash_subcommand::run_list()
{
auto directory = get_current_git_path();
auto repo = repository_wrapper::open(directory);

git_stash_foreach(repo, list_stash_cb, NULL);
}

void stash_subcommand::run_pop()
{
auto directory = get_current_git_path();
auto repo = repository_wrapper::open(directory);

git_stash_pop(repo, m_index, NULL);
}

void stash_subcommand::run_apply()
{
auto directory = get_current_git_path();
auto repo = repository_wrapper::open(directory);

git_stash_apply(repo, m_index, NULL);
}
20 changes: 20 additions & 0 deletions src/subcommand/stash_subcommand.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once

#include <CLI/CLI.hpp>

#include "../utils/common.hpp"

class stash_subcommand
{
public:

explicit stash_subcommand(const libgit2_object&, CLI::App& app);
void run_push();
void run_list();
void run_pop();
void run_apply();

std::vector<std::string> m_options;
std::string m_message = "";
size_t m_index = 0;
};
6 changes: 6 additions & 0 deletions src/wrapper/commit_wrapper.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "../wrapper/commit_wrapper.hpp"
#include <git2/commit.h>

commit_wrapper::commit_wrapper(git_commit* commit)
: base_type(commit)
Expand Down Expand Up @@ -27,6 +28,11 @@ std::string commit_wrapper::commit_oid_tostr() const
return git_oid_tostr(buf, sizeof(buf), &this->oid());
}

std::string commit_wrapper::summary() const
{
return git_commit_summary(*this);
}

commit_list_wrapper commit_wrapper::get_parents_list() const
{
size_t parent_count = git_commit_parentcount(*this);
Expand Down
2 changes: 2 additions & 0 deletions src/wrapper/commit_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class commit_wrapper : public wrapper_base<git_commit>
const git_oid& oid() const;
std::string commit_oid_tostr() const;

std::string summary() const;

commit_list_wrapper get_parents_list() const;

private:
Expand Down
130 changes: 130 additions & 0 deletions test/test_stash.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import subprocess

import pytest


def test_stash_push(xtl_clone, commit_env_config, git2cpp_path, tmp_path):
assert (tmp_path / "xtl").exists()
xtl_path = tmp_path / "xtl"

p = xtl_path / "mook_file.txt"
p.write_text("")

cmd_add = [git2cpp_path, "add", "mook_file.txt"]
p_add = subprocess.run(cmd_add, cwd=xtl_path, text=True)
assert p_add.returncode == 0

cmd_status = [git2cpp_path, "status"]
p_status = subprocess.run(cmd_status, capture_output=True, cwd=xtl_path, text=True)
assert p_status.returncode == 0
assert "mook_file" in p_status.stdout

cmd_stash = [git2cpp_path, "stash"]
p_stash = subprocess.run(cmd_stash, capture_output=True, cwd=xtl_path, text=True)
assert p_stash.returncode == 0

p_status_2 = subprocess.run(
cmd_status, capture_output=True, cwd=xtl_path, text=True
)
assert p_status_2.returncode == 0
assert "mook_file" not in p_status_2.stdout


def test_stash_list(xtl_clone, commit_env_config, git2cpp_path, tmp_path):
assert (tmp_path / "xtl").exists()
xtl_path = tmp_path / "xtl"

p = xtl_path / "mook_file.txt"
p.write_text("")

cmd_add = [git2cpp_path, "add", "mook_file.txt"]
p_add = subprocess.run(cmd_add, cwd=xtl_path, text=True)
assert p_add.returncode == 0

cmd_list = [git2cpp_path, "stash", "list"]
p_list = subprocess.run(cmd_list, capture_output=True, cwd=xtl_path, text=True)
assert p_list.returncode == 0
assert "stash@" not in p_list.stdout

cmd_stash = [git2cpp_path, "stash"]
p_stash = subprocess.run(cmd_stash, capture_output=True, cwd=xtl_path, text=True)
assert p_stash.returncode == 0

# p_list_2 = subprocess.run(cmd_list, capture_output=True, cwd=xtl_path, text=True)
# assert p_list_2.returncode == 0
# print("second: \n", p_list_2.stdout, "\n\n")
# # assert "stash@{0}" in p_list_2.stdout


def test_stash_pop(xtl_clone, commit_env_config, git2cpp_path, tmp_path):
assert (tmp_path / "xtl").exists()
xtl_path = tmp_path / "xtl"

p = xtl_path / "mook_file.txt"
p.write_text("")

cmd_add = [git2cpp_path, "add", "mook_file.txt"]
p_add = subprocess.run(cmd_add, cwd=xtl_path, text=True)
assert p_add.returncode == 0

cmd_stash = [git2cpp_path, "stash"]
p_stash = subprocess.run(cmd_stash, capture_output=True, cwd=xtl_path, text=True)
assert p_stash.returncode == 0

cmd_status = [git2cpp_path, "status"]
p_status = subprocess.run(cmd_status, capture_output=True, cwd=xtl_path, text=True)
assert p_status.returncode == 0
assert "mook_file" not in p_status.stdout

# cmd_pop = [git2cpp_path, "stash", "pop"]
# p_pop = subprocess.run(cmd_pop, capture_output=True, cwd=xtl_path, text=True)
# assert p_pop.returncode == 0

# p_status_2 = subprocess.run(
# cmd_status, capture_output=True, cwd=xtl_path, text=True
# )
# assert p_status_2.returncode == 0
# print(p_status_2.stdout)
# assert "mook_file" in p_status.stdout
#
# cmd_list = [git2cpp_path, "stash", "list"]
# p_list = subprocess.run(cmd_list, capture_output=True, cwd=xtl_path, text=True)
# assert p_list.returncode == 0
# assert p_list.stdout == ""


def test_stash_apply(xtl_clone, commit_env_config, git2cpp_path, tmp_path):
assert (tmp_path / "xtl").exists()
xtl_path = tmp_path / "xtl"

p = xtl_path / "mook_file.txt"
p.write_text("")

cmd_add = [git2cpp_path, "add", "mook_file.txt"]
p_add = subprocess.run(cmd_add, cwd=xtl_path, text=True)
assert p_add.returncode == 0

cmd_stash = [git2cpp_path, "stash"]
p_stash = subprocess.run(cmd_stash, capture_output=True, cwd=xtl_path, text=True)
assert p_stash.returncode == 0

cmd_status = [git2cpp_path, "status"]
p_status = subprocess.run(cmd_status, capture_output=True, cwd=xtl_path, text=True)
assert p_status.returncode == 0
assert "mook_file" not in p_status.stdout

# cmd_pop = [git2cpp_path, "stash", "pop"]
# p_pop = subprocess.run(cmd_pop, capture_output=True, cwd=xtl_path, text=True)
# assert p_pop.returncode == 0

# p_status_2 = subprocess.run(
# cmd_status, capture_output=True, cwd=xtl_path, text=True
# )
# assert p_status_2.returncode == 0
# print(p_status_2.stdout)
# assert "mook_file" in p_status.stdout
#
# cmd_list = [git2cpp_path, "stash", "list"]
# p_list = subprocess.run(cmd_list, capture_output=True, cwd=xtl_path, text=True)
# assert p_list.returncode == 0
# assert "stash@{0}" in p_list.stdout
Loading