Skip to content

Commit

Permalink
Add log command
Browse files Browse the repository at this point in the history
Add "tog log" command to view the last n commit hashes. Also
refactor tog.cpp into main.cpp, cli.cpp
  • Loading branch information
iamlucaswolf committed Nov 15, 2021
1 parent 4f35aa7 commit 0fa522b
Show file tree
Hide file tree
Showing 8 changed files with 217 additions and 127 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ find_package(CryptoPP REQUIRED)
# TODO there's probably a better way to do this with CMake
include_directories("libs/")
add_executable(
${PROJECT_NAME} src/tog.cpp src/repository.cpp src/blob.cpp src/crypto.cpp
src/tree.cpp src/commit.cpp
${PROJECT_NAME} src/main.cpp src/repository.cpp src/blob.cpp src/crypto.cpp
src/tree.cpp src/commit.cpp src/cli.cpp
)
target_link_libraries(tog PRIVATE CryptoPP::CryptoPP)
96 changes: 96 additions & 0 deletions src/cli.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include "cli.h"

#include <filesystem>
#include <iostream>
#include <string>
#include <vector>

#include "repository.h"

namespace fs = std::filesystem;

namespace tog::cli {

using namespace tog;

tog::Repository load_repository() {
const auto path = fs::current_path() / ".tog";

if (!fs::exists(path)) {
throw TogException("Not a tog repository");
}

return Repository{path};
}

void init() {
try {
Repository::init(fs::current_path());
} catch (const TogException &err) {
std::cerr << "Error " << err.what() << std::endl;
}

std::cout << "Initialized tog repository" << std::endl;
}

void commit(const std::string &message) {
try {
auto repo = load_repository();
auto hash = repo.commit(message);

std::cout << "Created commit " << hash << std::endl;

} catch (const std::exception &e) {
std::cout << "Error: " << e.what() << std::endl;
}
}

void checkout(const std::string &hash) {
try {
auto repo = load_repository();
repo.checkout(hash);

std::cout << "Checked out commit " << hash << std::endl;

} catch (const std::exception &e) {
std::cout << "Error: " << e.what() << std::endl;
}
}

void status() {
try {
auto repo = load_repository();

auto head = repo.head();
auto main = repo.main();

std::cout << "On branch main" << std::endl;

if (main) {
std::cout << "Current commit: " << *head << std::endl;
std::cout << "Latest commit: " << *main << std::endl;
} else {
std::cout << "No commits yet" << std::endl;
}
} catch (const std::exception &e) {
std::cout << "Error: " << e.what() << std::endl;
}
}

void log(int history_length) {
try {
auto repo = load_repository();
auto history = repo.history(history_length);

if (history.empty()) {
std::cout << "No commits yet" << std::endl;
}

for (const auto &hash : history) {
std::cout << hash << std::endl;
}
} catch (const std::exception &e) {
std::cout << "Error: " << e.what() << std::endl;
}
}
} // namespace tog::cli
31 changes: 31 additions & 0 deletions src/cli.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef TOG_CLI_H
#define TOG_CLI_H

#include <filesystem>
#include <string>

#include "repository.h"

namespace tog::cli {

// helper function to load reposiotries
tog::Repository load_repository();

// initializes a new tog repository
void init();

// commits the current workdir contents with the given commit message
void commit(const std::string &message);

// restores workdir contents to the commti with the given hash
void checkout(const std::string &hash);

// prints out status information about the current branch/commit
void status();

// prints the hashes of the last n commits
void log(int n);

} // namespace tog::cli

#endif // TOG_TOG_H
8 changes: 8 additions & 0 deletions src/commit.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ class Commit : public TogObject {
return _tree;
}

const std::string& message() const {
return _message;
}

const std::optional<Handle<Commit>>& parent() {
return _parent;
}

private:
// the top-level tree of the commit (i.e. the worktree)
Handle<Tree> _tree;
Expand Down
58 changes: 58 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include <CLI11/CLI11.h>
#include <tomlplusplus/toml.h>

#include <filesystem>
#include <iostream>

#include "cli.h"

int main(int argc, char **argv) {
CLI::App app{"The simple version control system", "tog"};

// Require exactly one argument (such as "init", "commit", ...)
app.require_subcommand(1);

// tog init
auto init_cmd = app.add_subcommand(
"init", "Creates a new repository in the current directory");
init_cmd->callback(tog::cli::init);

// tog commit [-m <message>]
auto commit_cmd = app.add_subcommand("commit", "Creates a new commit");
std::string commit_message;
commit_cmd->add_option("-m,--message", commit_message, "Commit message");
commit_cmd->callback(
[&commit_message]() { tog::cli::commit(commit_message); });

// tog checkout <commit>
auto checkout_cmd = app.add_subcommand("checkout", "Checkout a commit");
std::string checkout_hash;

// TODO fix formatting in .clang-format
checkout_cmd->add_option("commit", checkout_hash, "Commit hash")
->required();
checkout_cmd->callback(
[&checkout_hash]() { tog::cli::checkout(checkout_hash); });

// tog status command
auto status_cmd =
app.add_subcommand("status", "Display the current branch/commit");
status_cmd->callback(tog::cli::status);

// tog log command
auto log_cmd = app.add_subcommand("log", "Display the commit history");
int history_length;
log_cmd
->add_option("-n,--number", history_length,
"Number of commits to display")
->default_val<int>(10);
log_cmd->callback([&history_length]() { tog::cli::log(history_length); });

try {
CLI11_PARSE(app, argc, argv);
} catch (const CLI::ParseError &e) {
return app.exit(e);
}

return 0;
}
18 changes: 18 additions & 0 deletions src/repository.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,24 @@ void Repository::checkout(const std::string& hash) {
persist_ref(_togdir_path / "refs" / "head", _head);
}

std::vector<std::string> Repository::history(int n) {
std::vector<std::string> commits;

std::optional<Handle<Commit>> current = _head;

for (int i = 0; i < n; ++i) {
if (!current) {
return commits;
}

commits.push_back(current->hash());
resolve(*current);
current = (current->object()->parent());
}

return commits;
}

void Repository::resolve(Handle<Blob>& blob) {
if (blob.resolved()) {
return;
Expand Down
4 changes: 4 additions & 0 deletions src/repository.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ class Repository {
// restores the worktree to the state captured by the given commit
void checkout(const std::string& hash);

// returns the current branch's last n commit hashes in
// reverse-chronological order (newest first).
std::vector<std::string> history(int n);

// Initialized a new repository in the given directory.
static void init(const std::filesystem::path& path);

Expand Down
125 changes: 0 additions & 125 deletions src/tog.cpp

This file was deleted.

0 comments on commit 0fa522b

Please sign in to comment.