-
Notifications
You must be signed in to change notification settings - Fork 5
Add git config #77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add git config #77
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| #include <git2/config.h> | ||
| #include <git2/types.h> | ||
| #include <iostream> | ||
|
|
||
| #include <git2/remote.h> | ||
|
|
||
| #include "../utils/git_exception.hpp" | ||
| #include "../subcommand/config_subcommand.hpp" | ||
| #include "../wrapper/config_wrapper.hpp" | ||
| #include "../wrapper/repository_wrapper.hpp" | ||
|
|
||
| config_subcommand::config_subcommand(const libgit2_object&, CLI::App& app) | ||
| { | ||
| auto* config = app.add_subcommand("config", "Get and set repository or global options"); | ||
| auto* list = config->add_subcommand("list", "List all variables set in config file, along with their values."); | ||
| auto* get = config->add_subcommand("get", "Emits the value of the specified key. If key is present multiple times in the configuration, emits the last value. If --all is specified, emits all values associated with key. Returns error code 1 if key is not present."); | ||
| auto* set = config->add_subcommand("set", "Set value for one or more config options. By default, this command refuses to write multi-valued config options. Passing --all will replace all multi-valued config options with the new value, whereas --value= will replace all config options whose values match the given pattern."); | ||
| auto* unset = config->add_subcommand("unset", "Unset value for one or more config options. By default, this command refuses to unset multi-valued keys. Passing --all will unset all multi-valued config options, whereas --value will unset all config options whose values match the given pattern."); | ||
|
|
||
| get->add_option("<name>", m_name, ""); | ||
| set->add_option("<name>", m_name, ""); | ||
| set->add_option("<value>", m_value, ""); | ||
| unset->add_option("<name>", m_name, ""); | ||
|
|
||
| // TODO: | ||
| // sub->add_flag("--local", m_local_flag, ""); | ||
| // sub->add_flag("--global", m_global_flag, ""); | ||
| // sub->add_flag("--system", m_system_flag, ""); | ||
| // sub->add_flag("--worktree", m_worktree_flag, ""); | ||
|
|
||
| list->callback([this]() { this->run_list(); }); | ||
| get->callback([this]() { this->run_get(); }); | ||
| set->callback([this]() { this->run_set(); }); | ||
| unset->callback([this]() { this->run_unset(); }); | ||
| } | ||
|
|
||
| void config_subcommand::run_list() | ||
| { | ||
| auto directory = get_current_git_path(); | ||
| auto repo = repository_wrapper::open(directory); | ||
| auto cfg = repo.get_config(); | ||
|
|
||
| git_config_iterator* iter; | ||
| throw_if_error(git_config_iterator_new(&iter, cfg)); | ||
|
|
||
| git_config_entry* entry; | ||
| while (git_config_next(&entry, iter) == GIT_OK) | ||
| { | ||
| std::cout << entry->name << "=" << entry->value << std::endl; | ||
| } | ||
|
|
||
| git_config_iterator_free(iter); | ||
| } | ||
|
|
||
| void config_subcommand::run_get() | ||
| { | ||
| if (m_name.empty()) | ||
| { | ||
| std::cout << "error: wrong number of arguments, should be 1" << std::endl; | ||
| return; | ||
| } | ||
|
|
||
| auto directory = get_current_git_path(); | ||
| auto repo = repository_wrapper::open(directory); | ||
| auto cfg = repo.get_config(); | ||
|
|
||
| git_config_entry* entry = cfg.get_entry(m_name); | ||
| std::cout << entry->value << std::endl; | ||
|
|
||
| git_config_entry_free(entry); | ||
| } | ||
|
|
||
| void config_subcommand::run_set() | ||
| { | ||
| if (m_name.empty() | m_value.empty()) | ||
| { | ||
| std::cout << "error: wrong number of arguments, should be 2" << std::endl; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Exception here too. |
||
| return; | ||
| } | ||
|
|
||
| auto directory = get_current_git_path(); | ||
| auto repo = repository_wrapper::open(directory); | ||
| auto cfg = repo.get_config(); | ||
|
|
||
| cfg.set_entry(m_name, m_value); | ||
| } | ||
|
|
||
| void config_subcommand::run_unset() | ||
| { | ||
| if (m_name.empty()) | ||
| { | ||
| std::cout << "error: wrong number of arguments, should be 1" << std::endl; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Exception here too. |
||
| return; | ||
| } | ||
|
|
||
| auto directory = get_current_git_path(); | ||
| auto repo = repository_wrapper::open(directory); | ||
| auto cfg = repo.get_config(); | ||
|
|
||
| cfg.delete_entry(m_name); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| #pragma once | ||
|
|
||
| #include <CLI/CLI.hpp> | ||
|
|
||
| #include "../utils/common.hpp" | ||
|
|
||
| class config_subcommand | ||
| { | ||
| public: | ||
|
|
||
| explicit config_subcommand(const libgit2_object&, CLI::App& app); | ||
| void run_list(); | ||
| void run_set(); | ||
| void run_get(); | ||
| void run_unset(); | ||
|
|
||
| std::string m_name; | ||
| std::string m_value; | ||
|
|
||
| // TODO: | ||
| // bool m_local_flag = false; | ||
| // bool m_global_flag = false; | ||
| // bool m_system_flag = false; | ||
| // bool m_worktree_flag = false; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| #include "../wrapper/config_wrapper.hpp" | ||
| #include "../utils/git_exception.hpp" | ||
|
|
||
| config_wrapper::config_wrapper(git_config* cfg) | ||
| : base_type(cfg) | ||
| { | ||
| } | ||
|
|
||
| config_wrapper::~config_wrapper() | ||
| { | ||
| git_config_free(p_resource); | ||
| p_resource=nullptr; | ||
| } | ||
|
|
||
| git_config_entry* config_wrapper::get_entry(std::string name) | ||
| { | ||
| git_config_entry* entry; | ||
| throw_if_error(git_config_get_entry(&entry, *this, name.c_str())); | ||
| return entry; | ||
| } | ||
|
|
||
| void config_wrapper::set_entry(std::string name, std::string value) | ||
| { | ||
| throw_if_error(git_config_set_string(*this, name.c_str(), value.c_str())); | ||
| } | ||
|
|
||
| void config_wrapper::delete_entry(std::string name) | ||
| { | ||
| throw_if_error(git_config_delete_entry(*this, name.c_str())); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| #pragma once | ||
|
|
||
| #include <string> | ||
|
|
||
| #include <git2.h> | ||
|
|
||
| #include "../wrapper/wrapper_base.hpp" | ||
|
|
||
| class config_wrapper : public wrapper_base<git_config> | ||
| { | ||
| public: | ||
|
|
||
| using base_type = wrapper_base<git_config>; | ||
|
|
||
| ~config_wrapper(); | ||
|
|
||
| config_wrapper(config_wrapper&&) noexcept = default; | ||
| config_wrapper& operator=(config_wrapper&&) noexcept = default; | ||
|
|
||
| git_config_entry* get_entry(std::string name); | ||
| void set_entry(std::string name, std::string value); | ||
| void delete_entry(std::string name); | ||
|
|
||
| private: | ||
|
|
||
| config_wrapper(git_config* cfg); | ||
|
|
||
| friend class repository_wrapper; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| import subprocess | ||
|
|
||
| import pytest | ||
|
|
||
|
|
||
| def test_config_list(commit_env_config, git2cpp_path, tmp_path, monkeypatch): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't actually need the |
||
| cmd_init = [git2cpp_path, "init", "--bare", str(tmp_path)] | ||
| p_init = subprocess.run(cmd_init, capture_output=True) | ||
| assert p_init.returncode == 0 | ||
|
|
||
| cmd_list = [git2cpp_path, "config", "list"] | ||
| p_list = subprocess.run(cmd_list, capture_output=True, cwd=tmp_path, text=True) | ||
| assert p_list.returncode == 0 | ||
| assert "core.bare=true" in p_list.stdout | ||
| assert "remote" not in p_list.stdout | ||
|
|
||
|
|
||
| def test_config_get(git2cpp_path, tmp_path): | ||
| cmd_init = [git2cpp_path, "init", "--bare", str(tmp_path)] | ||
| p_init = subprocess.run(cmd_init, capture_output=True) | ||
| assert p_init.returncode == 0 | ||
|
|
||
| cmd_get = [git2cpp_path, "config", "get", "core.bare"] | ||
| p_get = subprocess.run(cmd_get, capture_output=True, cwd=tmp_path, text=True) | ||
| assert p_get.returncode == 0 | ||
| print(p_get.stdout) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Debug |
||
| assert p_get.stdout == "true\n" | ||
|
|
||
|
|
||
| def test_config_set(commit_env_config, git2cpp_path, tmp_path, monkeypatch): | ||
| cmd_init = [git2cpp_path, "init", "--bare", str(tmp_path)] | ||
| p_init = subprocess.run(cmd_init, capture_output=True) | ||
| assert p_init.returncode == 0 | ||
|
|
||
| cmd_set = [git2cpp_path, "config", "set", "code.bare", "false"] | ||
| p_set = subprocess.run(cmd_set, cwd=tmp_path, text=True) | ||
| assert p_set.returncode == 0 | ||
|
|
||
| cmd_get = [git2cpp_path, "config", "get", "code.bare"] | ||
| p_get = subprocess.run(cmd_get, capture_output=True, cwd=tmp_path, text=True) | ||
| assert p_get.returncode == 0 | ||
| assert p_get.stdout == "false\n" | ||
|
|
||
|
|
||
| def test_config_unset(git2cpp_path, tmp_path): | ||
| cmd_init = [git2cpp_path, "init", "--bare", str(tmp_path)] | ||
| p_init = subprocess.run(cmd_init, capture_output=True) | ||
| assert p_init.returncode == 0 | ||
|
|
||
| cmd_get = [git2cpp_path, "config", "unset", "core.bare"] | ||
| p_get = subprocess.run(cmd_get, capture_output=True, cwd=tmp_path, text=True) | ||
| assert p_get.returncode == 0 | ||
|
|
||
| cmd_get = [git2cpp_path, "config", "get", "core.bare"] | ||
| p_get = subprocess.run(cmd_get, capture_output=True, cwd=tmp_path, text=True) | ||
| assert p_get.returncode != 0 | ||
| assert p_get.stderr == "error: config value 'core.bare' was not found\n" | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this raise an exception rather than just write to
cout, so thatgit2cppexits with a non-zero exit code?gitgives an exit code of 129.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch