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 2d3f608
Show file tree
Hide file tree
Showing 4 changed files with 207 additions and 0 deletions.
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
200 changes: 200 additions & 0 deletions src/Cmd/Add.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
#include "Add.hpp"

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

#include <algorithm>
#include <cstdlib>
#include <fstream>
#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);

static Option<String>
getNextArg(
std::span<const StringRef>::iterator& itr,
const std::span<const StringRef>::iterator& end
) {
if (++itr == end) {
return None;
}
return String(*itr);
}

static inline std::optional<int>
handleNextArg(
std::span<const StringRef>::iterator& itr,
const std::span<const StringRef>::iterator& end, String& arg
) {
if (const auto nextArg = getNextArg(itr, end)) {
arg = *nextArg;
return std::nullopt;
} else {
return ADD_CMD.missingArgumentForOpt(*--itr);
}
}

static inline void
handleDependency(HashSet<StringRef>& newDeps, const StringRef dep) {
if (newDeps.find(dep) != newDeps.end()) {
logger::warn(
"The dependency `" + String(dep) + "` is already in the poac.toml"
);
} else {
newDeps.insert(dep);
}
}

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

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

static const String
getDependencyName(const StringRef dep) {
String name;
if (dep.find("://") == 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.ends_with(".git")) {
name = name.substr(0, name.size() - 4);
}

return name;
}

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

HashSet<StringRef> newDeps = {};

bool isSystemDependency = false;
String version; // Only used with system-dependencies

String tag;
String rev;
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 res = handleNextArg(itr, args.end(), version); res.has_value()) {
return res.value();
}
} else if (*itr == "--tag") {
if (auto res = handleNextArg(itr, args.end(), tag); res.has_value()) {
return res.value();
}
} else if (*itr == "--rev") {
if (auto res = handleNextArg(itr, args.end(), rev); res.has_value()) {
return res.value();
}
} else if (*itr == "--branch") {
if (auto res = handleNextArg(itr, args.end(), branch); res.has_value()) {
return res.value();
}
} else {
handleDependency(newDeps, *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 String gitUrl = getDependencyGitUrl(dep);
const String depName = getDependencyName(dep);

if (gitUrl.empty() || depName.empty()) {
return EXIT_FAILURE;
}

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

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

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

return EXIT_SUCCESS;
}
5 changes: 5 additions & 0 deletions src/Cmd/Add.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

#include "../Cli.hpp"

extern const Subcmd ADD_CMD;
1 change: 1 addition & 0 deletions src/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ getCli() noexcept {
.setDesc("List all subcommands")
.setGlobal(false)
.setHidden(true))
.addSubcmd(ADD_CMD)
.addSubcmd(BUILD_CMD)
.addSubcmd(CLEAN_CMD)
.addSubcmd(FMT_CMD)
Expand Down

0 comments on commit 2d3f608

Please sign in to comment.