added git fetch and checkout

fixed has_remote trying to fetch stuff
pr: implemented remote method
This commit is contained in:
isanae
2020-11-13 18:32:28 -05:00
parent 21b6a383d7
commit cd811419cb
5 changed files with 187 additions and 70 deletions
+1 -1
View File
@@ -40,7 +40,7 @@ void help(const clipp::group& g, const std::string& more)
<< "Options:\n"
<< clipp::documentation(g, options_df)
<< "\n\n"
<< "To use global options with command options, make sure command "
<< "To use global options with command options, make sure command \n"
<< "options are together, with no global options in the middle.\n";
if (!more.empty())
+3 -3
View File
@@ -244,6 +244,7 @@ public:
protected:
clipp::group do_group() override;
std::string do_doc() override;
int do_run() override;
private:
@@ -254,13 +255,12 @@ private:
std::pair<const modorganizer*, std::string> parse_pr(
const std::string& pr) const;
int get_pr_branch();
int do_apply();
int do_remote();
int do_fetch();
url get_diff_url(const modorganizer* task, std::string pr);
nlohmann::json get_pr_info(const modorganizer* task, const std::string& pr);
url get_diff_url(const modorganizer* task, const std::string& pr);
};
+112 -56
View File
@@ -5,6 +5,13 @@
namespace mob
{
std::string read_file(const fs::path& p)
{
std::ifstream t(p);
return {std::istreambuf_iterator<char>(t), std::istreambuf_iterator<char>()};
}
pr_command::pr_command()
: command(requires_options | handle_sigint), method_("apply")
{
@@ -40,6 +47,20 @@ clipp::group pr_command::do_group()
% "PR to apply, must be `task/pr`, such as `modorganizer/123`";
}
std::string pr_command::do_doc()
{
return
"Methods:\n"
" - apply: retrieves the .diff file for this PR and runs\n"
" `git apply` with it, which patches the local repo and\n"
" leaves the changes uncommitted\n"
"\n"
" - remote: adds a new remote to the local repo that matches the \n"
" PR's origin and checks out the PR's branch from it\n"
"\n"
" - fetch: ??";
}
int pr_command::do_run()
{
if (method_ == "apply")
@@ -96,63 +117,8 @@ std::pair<const modorganizer*, std::string> pr_command::parse_pr(
return {task, pr_number};
}
int pr_command::get_pr_branch()
{
if (pr_.empty())
return 0;
if (github_token_.empty())
{
u8cerr << "missing --github-token\n";
return 1;
}
auto&& [task, pr] = parse_pr(pr_);
if (!task)
return 1;
const url u(::fmt::format(
"https://api.github.com/repos/{}/{}/pulls/{}",
task->org(), task->repo(), pr));
curl_downloader dl;
dl
.url(u)
.header("Authorization", "token " + github_token_)
.start()
.join();
if (!dl.ok())
{
u8cerr << "getting pr failed\n";
return 1;
}
const auto output = dl.steal_output();
u8cout << output << "\n";
nlohmann::json j(output);
const std::string diff_url = j["diff_url"];
return 0;
}
url pr_command::get_diff_url(const modorganizer* task, std::string pr)
{
return ::fmt::format(
"https://github.com/{}/{}/pull/{}.diff",
task->org(), task->repo(), pr);
}
int pr_command::do_apply()
{
if (pr_.empty())
return 0;
auto&& [task, pr] = parse_pr(pr_);
if (!task)
return 1;
@@ -180,7 +146,59 @@ int pr_command::do_apply()
int pr_command::do_remote()
{
return 0;
auto&& [task, pr] = parse_pr(pr_);
if (!task)
return 1;
try
{
u8cout << "looking for pr " << pr << " in " << task->name() << "\n";
//const auto json = get_pr_info(task, pr);
auto json = nlohmann::json::parse(read_file("c:\\tmp\\" + pr + ".json"));
if (json.empty())
return 1;
const std::string repo = json["head"]["repo"]["name"];
const std::string org = json["head"]["repo"]["owner"]["login"];
const std::string remote_name = org;
const std::string branch = json["head"]["ref"];
u8cout
<< "found pr: "
<< "repo=" << repo << " "
<< "org=" << org << " "
<< "branch=" << branch << "\n";
if (git::has_remote(task->this_source_path(), remote_name))
{
u8cout << "remote already exists\n";
}
else
{
u8cout << "adding remote " << remote_name << "\n";
git::add_remote(
task->this_source_path(),
remote_name, org, {}, false,
"https://github.com/{}/{}");
}
u8cout << "fetching from " << remote_name << "\n";
git::fetch(task->this_source_path(), remote_name, branch);
u8cout << "checking out " << remote_name << "/" << branch << "\n";
git::checkout(
task->this_source_path(),
::fmt::format("{}/{}", remote_name, branch));
return 0;
}
catch(std::exception& e)
{
u8cerr << e.what() << "\n";
return 1;
}
}
int pr_command::do_fetch()
@@ -188,4 +206,42 @@ int pr_command::do_fetch()
return 0;
}
url pr_command::get_diff_url(const modorganizer* task, const std::string& pr)
{
return ::fmt::format(
"https://github.com/{}/{}/pull/{}.diff",
task->org(), task->repo(), pr);
}
nlohmann::json pr_command::get_pr_info(
const modorganizer* task, const std::string& pr)
{
if (github_token_.empty())
{
u8cerr << "missing --github-token\n";
return {};
}
const url u(::fmt::format(
"https://api.github.com/repos/{}/{}/pulls/{}",
task->org(), task->repo(), pr));
curl_downloader dl;
dl
.url(u)
.header("Authorization", "token " + github_token_)
.start()
.join();
if (!dl.ok())
{
u8cerr << "failed to get pr info from github\n";
return {};
}
const auto output = dl.steal_output();
return nlohmann::json::parse(output);
}
} // namespace
+60 -8
View File
@@ -7,6 +7,8 @@ namespace mob
{
constexpr git::ops no_op(git::ops(0));
const std::string default_github_url_pattern = "git@github.com:{}/{}";
git::git(ops o)
: basic_process_runner("git"), op_(o)
@@ -68,9 +70,17 @@ void git::ignore_ts(const fs::path& repo, bool b)
.do_ignore_ts();
}
bool git::has_remote(const fs::path& repo, const std::string& name)
{
git g(no_op);
g.root(repo);
return g.has_remote(name);
}
void git::add_remote(
const fs::path& repo, const std::string& remote_name,
const std::string& username, const std::string& key, bool push_default)
const std::string& username, const std::string& key, bool push_default,
const std::string& url_pattern)
{
git g(no_op);
g.root(repo);
@@ -79,7 +89,7 @@ void git::add_remote(
if (!g.has_remote(remote_name))
{
g.add_remote(remote_name, make_url(username, gf));
g.add_remote(remote_name, make_url(username, gf, url_pattern));
if (push_default)
g.set_config("remote.pushdefault", remote_name);
@@ -130,6 +140,45 @@ void git::apply(const std::string& diff)
execute_and_join();
}
void git::fetch(
const fs::path& p, const std::string& remote, const std::string& branch)
{
git g(no_op);
g.root(p);
g.fetch(remote, branch);
}
void git::fetch(const std::string& remote, const std::string& branch)
{
process_ = make_process()
.arg("fetch")
.arg("-q")
.arg(remote)
.arg(branch)
.cwd(root_);
execute_and_join();
}
void git::checkout(const fs::path& p, const std::string& what)
{
git g(no_op);
g.root(p);
g.checkout(what);
}
void git::checkout(const std::string& what)
{
process_ = make_process()
.arg("-c", "advice.detachedHead=false")
.arg("checkout")
.arg("-q")
.arg(what)
.cwd(root_);
execute_and_join();
}
fs::path git::binary()
{
return conf::tool_by_name("git");
@@ -447,9 +496,8 @@ bool git::has_remote(const std::string& name)
process_ = make_process()
.flags(process::allow_failure)
.stderr_level(context::level::debug)
.arg("remote")
.arg("show")
.arg(name)
.arg("config")
.arg("remote." + name + ".url")
.cwd(root_);
return (execute_and_join() == 0);
@@ -613,9 +661,13 @@ std::string git::git_file()
}
std::string git::make_url(
const std::string& org, const std::string& git_file)
{
return "git@github.com:" + org + "/" + git_file;
const std::string& org, const std::string& git_file,
const std::string& url_pattern)
{
const std::string pattern =
url_pattern.empty() ? default_github_url_pattern : url_pattern;
return fmt::format(pattern, org, git_file);
}
+11 -2
View File
@@ -174,16 +174,22 @@ public:
static void ignore_ts(const fs::path& repo, bool b);
static bool has_remote(const fs::path& repo, const std::string& name);
static void add_remote(
const fs::path& repo, const std::string& remote_name,
const std::string& org, const std::string& key,
bool push_default);
bool push_default, const std::string& url_pattern={});
static bool is_git_repo(const fs::path& p);
static bool branch_exists(const mob::url& u, const std::string& name);
static void init_repo(const fs::path& p);
static void apply(const fs::path& p, const std::string& diff);
static void fetch(
const fs::path& p,
const std::string& remote, const std::string& branch);
static void checkout(const fs::path& p, const std::string& what);
git& url(const mob::url& u);
@@ -240,6 +246,8 @@ private:
void set_remote_push(const std::string& remote, const std::string& url);
void set_assume_unchanged(const fs::path& relative_file, bool on);
void apply(const std::string& diff);
void fetch(const std::string& remote, const std::string& branch);
void checkout(const std::string& what);
bool is_repo();
bool branch_exists();
bool has_uncommitted_changes();
@@ -249,7 +257,8 @@ private:
std::string git_file();
static std::string make_url(
const std::string& org, const std::string& git_file);
const std::string& org, const std::string& git_file,
const std::string& url_pattern={});
};