Skip to content

Commit

Permalink
Add subcommand add
Browse files Browse the repository at this point in the history
Allows users to add project dependencies to poac.toml from the commandline
  • Loading branch information
SunPodder committed Feb 24, 2024
1 parent 6ed7de9 commit 213f43c
Show file tree
Hide file tree
Showing 4 changed files with 247 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/Cmd.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "Cmd/Add.hpp"
#include "Cmd/Build.hpp"
#include "Cmd/Clean.hpp"
#include "Cmd/Fmt.hpp"
Expand Down
235 changes: 235 additions & 0 deletions src/Cmd/Add.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
#include "Add.hpp"

#include "../Logger.hpp"
#include "../Manifest.hpp"
#include "Common.hpp"

#include <algorithm>
#include <cstdlib>
#include <string>
#include <toml.hpp>
#include <vector>

static int addMain(std::span<const StringRef> args);

const Subcmd ADD_CMD =
Subcmd{ "add" }
.setDesc("Add dependencies to poac.toml")
.setArg(Arg{ "args" }
.setDesc("Dependencies to add")
.setRequired(true)
.setVariadic(true))
.addOpt(Opt{ "--sys" }.setDesc("Use system dependency"))
.addOpt(Opt{ "--version" }.setDesc(
"Dependency version (Only used with system-dependencies)"
))
.addOpt(Opt{ "--tag" }.setDesc("Specify a git tag").setPlaceholder("<TAG>"))
.addOpt(
Opt{ "--rev" }.setDesc("Specify a git revision").setPlaceholder("<REVISION>")
)
.addOpt(
Opt{ "--branch" }.setDesc("Specify a branch of the git repository").setPlaceholder("<BRANCH_NAME>")
)
.setMainFn(addMain);

std::optional<std::string>
getNextArg(
std::span<const StringRef>::iterator& itr,
const std::span<const StringRef>::iterator& end
) {
if (++itr == end) {
return std::nullopt;
}
return std::string(*itr);
}

void
handleDependency(std::vector<std::string>& newDeps, const std::string& dep) {
if (std::find(newDeps.begin(), newDeps.end(), dep) != newDeps.end()) {
logger::warn("The dependency `" + dep + "` is already in the poac.toml");
} else {
newDeps.push_back(dep);
}
}

static int
addMain(std::span<const StringRef> args) {
if (args.empty()) {
logger::error("No dependencies to add");
return 0;
}

std::vector<std::string> newDeps = {};

bool isSystemDependency = false;
std::string version; // Only used with system-dependencies

std::string tag;
std::string rev;
std::string branch;

for (auto itr = args.begin(); itr != args.end(); ++itr) {
if (const auto res = Cli::handleGlobalOpts(itr, args.end(), "add")) {
if (res.value() == Cli::CONTINUE) {
continue;
} else {
return res.value();
}
} else if (*itr == "--sys") {
isSystemDependency = true;
} else if (*itr == "--version" || *itr == "-v") {
if (auto nextArg = getNextArg(itr, args.end())) {
version = *nextArg;
} else {
return ADD_CMD.missingArgumentForOpt(*--itr);
}
} else if (*itr == "--tag") {
if (auto nextArg = getNextArg(itr, args.end())) {
tag = *nextArg;
} else {
return ADD_CMD.missingArgumentForOpt(*--itr);
}
} else if (*itr == "--rev") {
if (auto nextArg = getNextArg(itr, args.end())) {
rev = *nextArg;
} else {
return ADD_CMD.missingArgumentForOpt(*--itr);
}
} else if (*itr == "--branch") {
if (auto nextArg = getNextArg(itr, args.end())) {
branch = *nextArg;
} else {
return ADD_CMD.missingArgumentForOpt(*--itr);
}
} else {
handleDependency(newDeps, std::string(*itr));
}
}

toml::value depData = toml::table{};

if (isSystemDependency) {
if (version.empty()) {
logger::error("The `--version` option is required for system dependencies"
);
return EXIT_FAILURE;
}
depData["version"] = version;
depData["system"] = true;
} else {
if (!tag.empty()) {
depData["tag"] = tag;
}
if (!rev.empty()) {
depData["rev"] = rev;
}
if (!branch.empty()) {
depData["branch"] = branch;
}
}

auto data = toml::parse(getManifestPath());
auto& deps = toml::find<toml::table>(data, "dependencies");

for (const auto& dep : newDeps) {

if (!isSystemDependency) {
const std::string gitUrl = getDependencyGitUrl(dep);
const std::string depName = getDependencyName(dep);
if (gitUrl.empty() || depName.empty()) {
return EXIT_FAILURE;
}

deps[depName] = depData;
deps[depName]["git"] = gitUrl;
} else {
deps[dep] = depData;
}
}

std::ofstream ofs(getManifestPath());
ofs << toml::format(data);

logger::info("Added", "to the poac.toml");

return 0;
}

std::string
getDependencyGitUrl(const std::string& dep) {
if (dep.find("://") == std::string::npos) {
// check if atleast in "user/repo" format
if (dep.find('/') == std::string::npos) {
logger::error("Invalid dependency: " + dep);
return "";
}

return "https://github.com/" + dep + ".git";
}
return dep;
}

std::string
getDependencyName(const std::string& dep) {
std::string name;
if (dep.find("://") == std::string::npos) {
name = dep.substr(dep.find_last_of('/') + 1);
} else {
name = dep.substr(
dep.find_last_of('/') + 1, dep.find(".git") - dep.find_last_of('/') - 1
);
}

// Remove trailing '.git' if it exists
if (name.rfind(".git") == name.size() - 4) {
name = name.substr(0, name.size() - 4);
}

return name;
}

#ifdef POAC_TEST_OFF
// getting strange linker errors for this test
// test code looks fine though

# include "../Rustify.hpp"

namespace tests {
void
testGetDependencyGitUrl() {
assert(
getDependencyGitUrl("https://github.com/poac-dev/poac.git")
== "https://github.com/poac-dev/poac.git"
);
assert(
getDependencyGitUrl("poac-dev/poac")
== "https://github.com/poac-dev/poac.git"
);
assert(
getDependencyGitUrl("poac-dev/poac.git")
== "https://github.com/poac-dev/poac.git"
);
assert(getDependencyGitUrl("poac-dev") == "");
assert(getDependencyGitUrl("https://github.com/poac-dev") == "");

pass();
}

void
testGetDependencyName() {
assert(getDependencyName("poac-dev/poac") == "poac");
assert(getDependencyName("poac-dev/poac.git") == "poac");
assert(getDependencyName("https://github.com/poac-dev/poac") == "poac");
assert(getDependencyName("poac-dev") == "");

pass();
}
} // namespace tests

int
main() {
tests::testGetDependencyGitUrl();
tests::testGetDependencyName();
}

#endif
9 changes: 9 additions & 0 deletions src/Cmd/Add.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include "../Cli.hpp"

#include <string>

extern const Subcmd ADD_CMD;
std::string getDependencyGitUrl(const std::string& dep);
std::string getDependencyName(const std::string& dep);
3 changes: 2 additions & 1 deletion src/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ getCli() noexcept {
.addSubcmd(SEARCH_CMD)
.addSubcmd(TEST_CMD)
.addSubcmd(TIDY_CMD)
.addSubcmd(VERSION_CMD);
.addSubcmd(VERSION_CMD)
.addSubcmd(ADD_CMD);
return cli;
}

Expand Down

0 comments on commit 213f43c

Please sign in to comment.