Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,18 @@ set(GIT2CPP_SRC
${GIT2CPP_SOURCE_DIR}/subcommand/clone_subcommand.hpp
${GIT2CPP_SOURCE_DIR}/subcommand/commit_subcommand.cpp
${GIT2CPP_SOURCE_DIR}/subcommand/commit_subcommand.hpp
${GIT2CPP_SOURCE_DIR}/subcommand/fetch_subcommand.cpp
${GIT2CPP_SOURCE_DIR}/subcommand/fetch_subcommand.hpp
${GIT2CPP_SOURCE_DIR}/subcommand/init_subcommand.cpp
${GIT2CPP_SOURCE_DIR}/subcommand/init_subcommand.hpp
${GIT2CPP_SOURCE_DIR}/subcommand/log_subcommand.cpp
${GIT2CPP_SOURCE_DIR}/subcommand/log_subcommand.hpp
${GIT2CPP_SOURCE_DIR}/subcommand/merge_subcommand.cpp
${GIT2CPP_SOURCE_DIR}/subcommand/merge_subcommand.hpp
${GIT2CPP_SOURCE_DIR}/subcommand/push_subcommand.cpp
${GIT2CPP_SOURCE_DIR}/subcommand/push_subcommand.hpp
${GIT2CPP_SOURCE_DIR}/subcommand/remote_subcommand.cpp
${GIT2CPP_SOURCE_DIR}/subcommand/remote_subcommand.hpp
${GIT2CPP_SOURCE_DIR}/subcommand/reset_subcommand.cpp
${GIT2CPP_SOURCE_DIR}/subcommand/reset_subcommand.hpp
${GIT2CPP_SOURCE_DIR}/subcommand/status_subcommand.cpp
Expand All @@ -82,6 +88,8 @@ set(GIT2CPP_SRC
${GIT2CPP_SOURCE_DIR}/wrapper/object_wrapper.hpp
${GIT2CPP_SOURCE_DIR}/wrapper/refs_wrapper.cpp
${GIT2CPP_SOURCE_DIR}/wrapper/refs_wrapper.hpp
${GIT2CPP_SOURCE_DIR}/wrapper/remote_wrapper.cpp
${GIT2CPP_SOURCE_DIR}/wrapper/remote_wrapper.hpp
${GIT2CPP_SOURCE_DIR}/wrapper/repository_wrapper.cpp
${GIT2CPP_SOURCE_DIR}/wrapper/repository_wrapper.hpp
${GIT2CPP_SOURCE_DIR}/wrapper/signature_wrapper.cpp
Expand Down
6 changes: 6 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@
#include "subcommand/checkout_subcommand.hpp"
#include "subcommand/clone_subcommand.hpp"
#include "subcommand/commit_subcommand.hpp"
#include "subcommand/fetch_subcommand.hpp"
#include "subcommand/init_subcommand.hpp"
#include "subcommand/log_subcommand.hpp"
#include "subcommand/merge_subcommand.hpp"
#include "subcommand/push_subcommand.hpp"
#include "subcommand/remote_subcommand.hpp"
#include "subcommand/reset_subcommand.hpp"
#include "subcommand/status_subcommand.hpp"

Expand All @@ -35,9 +38,12 @@ int main(int argc, char** argv)
checkout_subcommand checkout(lg2_obj, app);
clone_subcommand clone(lg2_obj, app);
commit_subcommand commit(lg2_obj, app);
fetch_subcommand fetch(lg2_obj, app);
reset_subcommand reset(lg2_obj, app);
log_subcommand log(lg2_obj, app);
merge_subcommand merge(lg2_obj, app);
push_subcommand push(lg2_obj, app);
remote_subcommand remote(lg2_obj, app);

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

Expand Down
121 changes: 121 additions & 0 deletions src/subcommand/fetch_subcommand.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#include <iostream>
#include <iomanip>

#include <git2/remote.h>

#include "../subcommand/fetch_subcommand.hpp"
#include "../wrapper/repository_wrapper.hpp"
#include "../wrapper/remote_wrapper.hpp"
#include "../utils/output.hpp"
#include "../utils/git_exception.hpp"

namespace
{
int sideband_progress(const char* str, int len, void*)
{
printf("remote: %.*s", len, str);
fflush(stdout);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer C++ standard streams.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think the agent adopted some of the style of the codebase which uses printf:

ag printf                              
src/subcommand/clone_subcommand.cpp
21:        printf("remote: %.*s", len, str);

src/subcommand/merge_subcommand.cpp
173:            printf("Merge made\n");

return 0;
}

int fetch_progress(const git_indexer_progress* stats, void* payload)
{
static bool done = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notice that this will prevent to use this function with many fetches . Since we're not going to implement it in this PR, I think it's fine for now, but you should add a note about it, stating this needs refactoring in order to be usable from mutiple fetches.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. The agent must have taken some inspiration from those current uses.


auto* pr = reinterpret_cast<git_indexer_progress*>(payload);
*pr = *stats;

if (done)
{
return 0;
}

int network_percent = pr->total_objects > 0 ?
(100 * pr->received_objects / pr->total_objects)
: 0;
size_t mbytes = pr->received_bytes / (1024*1024);

std::cout << "Receiving objects: " << std::setw(4) << network_percent
<< "% (" << pr->received_objects << "/" << pr->total_objects << "), "
<< mbytes << " MiB";

if (pr->received_objects == pr->total_objects)
{
std::cout << ", done." << std::endl;
done = true;
}
else
{
std::cout << '\r';
}
return 0;
}

int update_refs(const char* refname, const git_oid* a, const git_oid* b, git_refspec*, void*)
{
char a_str[GIT_OID_SHA1_HEXSIZE+1], b_str[GIT_OID_SHA1_HEXSIZE+1];

git_oid_fmt(b_str, b);
b_str[GIT_OID_SHA1_HEXSIZE] = '\0';

if (git_oid_is_zero(a))
{
printf("[new] %.20s %s\n", b_str, refname);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer C++ standard streams.

}
else
{
git_oid_fmt(a_str, a);
a_str[GIT_OID_SHA1_HEXSIZE] = '\0';
printf("[updated] %.10s..%.10s %s\n", a_str, b_str, refname);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

}

return 0;
}
}

fetch_subcommand::fetch_subcommand(const libgit2_object&, CLI::App& app)
{
auto* sub = app.add_subcommand("fetch", "Download objects and refs from another repository");

sub->add_option("<remote>", m_remote_name, "The remote to fetch from")
->default_val("origin");

sub->callback([this]() { this->run(); });
}

void fetch_subcommand::run()
{
auto directory = get_current_git_path();
auto repo = repository_wrapper::open(directory);

// Find the remote (default to origin if not specified)
std::string remote_name = m_remote_name.empty() ? "origin" : m_remote_name;
auto remote = repo.find_remote(remote_name);

git_indexer_progress pd = {0};
git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT;
fetch_opts.callbacks.sideband_progress = sideband_progress;
fetch_opts.callbacks.transfer_progress = fetch_progress;
fetch_opts.callbacks.payload = &pd;
fetch_opts.callbacks.update_refs = update_refs;

cursor_hider ch;

// Perform the fetch
throw_if_error(git_remote_fetch(remote, nullptr, &fetch_opts, "fetch"));

// Show statistics
const git_indexer_progress* stats = git_remote_stats(remote);
if (stats->local_objects > 0)
{
std::cout << "\rReceived " << stats->indexed_objects << "/" << stats->total_objects
<< " objects in " << stats->received_bytes << " bytes (used "
<< stats->local_objects << " local objects)" << std::endl;
}
else
{
std::cout << "\rReceived " << stats->indexed_objects << "/" << stats->total_objects
<< " objects in " << stats->received_bytes << " bytes" << std::endl;
}
}

23 changes: 23 additions & 0 deletions src/subcommand/fetch_subcommand.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once

#include <string>

#include <CLI/CLI.hpp>

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

class fetch_subcommand
{
public:

explicit fetch_subcommand(const libgit2_object&, CLI::App& app);
void run();

private:

std::string m_remote_name;
};



72 changes: 72 additions & 0 deletions src/subcommand/push_subcommand.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#include <iostream>

#include <git2/remote.h>

#include "../subcommand/push_subcommand.hpp"
#include "../wrapper/repository_wrapper.hpp"
#include "../wrapper/remote_wrapper.hpp"
#include "../utils/git_exception.hpp"
#include "../utils/common.hpp"

namespace
{
int push_transfer_progress(unsigned int current, unsigned int total, size_t bytes, void*)
{
if (total > 0)
{
int percent = (100 * current) / total;
std::cout << "Writing objects: " << percent << "% (" << current
<< "/" << total << "), " << bytes << " bytes\r";
}
return 0;
}

int push_update_reference(const char* refname, const char* status, void*)
{
if (status)
{
std::cout << " " << refname << " " << status << std::endl;
}
else
{
std::cout << " " << refname << std::endl;
}
return 0;
}
}

push_subcommand::push_subcommand(const libgit2_object&, CLI::App& app)
{
auto* sub = app.add_subcommand("push", "Update remote refs along with associated objects");

sub->add_option("<remote>", m_remote_name, "The remote to push to")
->default_val("origin");

sub->add_option("<refspec>", m_refspecs, "The refspec(s) to push");

sub->callback([this]() { this->run(); });
}

void push_subcommand::run()
{
auto directory = get_current_git_path();
auto repo = repository_wrapper::open(directory);

std::string remote_name = m_remote_name.empty() ? "origin" : m_remote_name;
auto remote = repo.find_remote(remote_name);

git_push_options push_opts = GIT_PUSH_OPTIONS_INIT;
push_opts.callbacks.push_transfer_progress = push_transfer_progress;
push_opts.callbacks.push_update_reference = push_update_reference;

git_strarray_wrapper refspecs_wrapper(m_refspecs);
git_strarray* refspecs_ptr = nullptr;
if (!m_refspecs.empty())
{
refspecs_ptr = refspecs_wrapper;
}

throw_if_error(git_remote_push(remote, refspecs_ptr, &push_opts));
std::cout << "Pushed to " << remote_name << std::endl;
}

25 changes: 25 additions & 0 deletions src/subcommand/push_subcommand.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include <string>
#include <vector>

#include <CLI/CLI.hpp>

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

class push_subcommand
{
public:

explicit push_subcommand(const libgit2_object&, CLI::App& app);
void run();

private:

std::string m_remote_name;
std::vector<std::string> m_refspecs;
};



Loading