diff --git a/Makefile b/Makefile index 0c946f087..fd4715e22 100644 --- a/Makefile +++ b/Makefile @@ -100,7 +100,7 @@ $(O)/tests/test_BuildConfig: $(O)/tests/test_BuildConfig.o $(O)/Algos.o \ $(O)/TermColor.o $(O)/Manifest.o $(O)/Parallelism.o $(O)/Semver.o \ $(O)/VersionReq.o $(O)/Git2/Repository.o $(O)/Git2/Object.o $(O)/Git2/Oid.o \ $(O)/Git2/Global.o $(O)/Git2/Config.o $(O)/Git2/Exception.o $(O)/Git2/Time.o \ - $(O)/Git2/Commit.o $(O)/Command.o + $(O)/Git2/Commit.o $(O)/Command.o $(O)/Dependency.o $(CXX) $(CXXFLAGS) $^ $(LIBS) $(LDFLAGS) -o $@ $(O)/tests/test_Algos: $(O)/tests/test_Algos.o $(O)/TermColor.o $(O)/Command.o @@ -116,7 +116,7 @@ $(O)/tests/test_VersionReq: $(O)/tests/test_VersionReq.o $(O)/TermColor.o \ $(O)/tests/test_Manifest: $(O)/tests/test_Manifest.o $(O)/TermColor.o \ $(O)/Semver.o $(O)/VersionReq.o $(O)/Algos.o $(O)/Git2/Repository.o \ $(O)/Git2/Global.o $(O)/Git2/Oid.o $(O)/Git2/Config.o $(O)/Git2/Exception.o \ - $(O)/Git2/Object.o $(O)/Command.o + $(O)/Git2/Object.o $(O)/Command.o $(O)/Dependency.o $(CXX) $(CXXFLAGS) $^ $(LIBS) $(LDFLAGS) -o $@ $(O)/tests/test_Cli: $(O)/tests/test_Cli.o $(O)/Algos.o $(O)/TermColor.o \ diff --git a/src/Dependency.cc b/src/Dependency.cc new file mode 100644 index 000000000..0039028cc --- /dev/null +++ b/src/Dependency.cc @@ -0,0 +1,108 @@ +#include "Dependency.hpp" + +#include "Algos.hpp" +#include "Command.hpp" +#include "Git2.hpp" +#include "Logger.hpp" + +#include +#include +#include + +namespace cabin { + +namespace fs = std::filesystem; + +static fs::path +getXdgCacheHome() noexcept { + if (const char* envP = std::getenv("XDG_CACHE_HOME")) { + return envP; + } + const fs::path userDir = std::getenv("HOME"); + return userDir / ".cache"; +} + +static const fs::path CACHE_DIR(getXdgCacheHome() / "cabin"); +static const fs::path GIT_DIR(CACHE_DIR / "git"); +static const fs::path GIT_SRC_DIR(GIT_DIR / "src"); + +Result +GitDependency::install() const { + fs::path installDir = GIT_SRC_DIR / name; + if (target.has_value()) { + installDir += '-' + target.value(); + } + + if (fs::exists(installDir) && !fs::is_empty(installDir)) { + logger::debug("{} is already installed", name); + } else { + git2::Repository repo; + repo.clone(url, installDir.string()); + + if (target.has_value()) { + // Checkout to target. + const std::string target = this->target.value(); + const git2::Object obj = repo.revparseSingle(target); + repo.setHeadDetached(obj.id()); + repo.checkoutHead(true); + } + + logger::info( + "Downloaded", "{} {}", name, target.has_value() ? target.value() : url + ); + } + + const fs::path includeDir = installDir / "include"; + std::string includes = "-isystem"; + + if (fs::exists(includeDir) && fs::is_directory(includeDir) + && !fs::is_empty(includeDir)) { + includes += includeDir.string(); + } else { + includes += installDir.string(); + } + + // Currently, no libs are supported. + return Ok(DepMetadata{ .includes = includes, .libs = "" }); +} + +Result +PathDependency::install() const { + const fs::path installDir = fs::weakly_canonical(path); + if (fs::exists(installDir) && !fs::is_empty(installDir)) { + logger::debug("{} is already installed", name); + } else { + Bail("{} can't be accessible as directory", installDir.string()); + } + + const fs::path includeDir = installDir / "include"; + std::string includes = "-isystem"; + + if (fs::exists(includeDir) && fs::is_directory(includeDir) + && !fs::is_empty(includeDir)) { + includes += includeDir.string(); + } else { + includes += installDir.string(); + } + + // Currently, no libs are supported. + return Ok(DepMetadata{ .includes = includes, .libs = "" }); +} + +Result +SystemDependency::install() const { + const std::string pkgConfigVer = versionReq.toPkgConfigString(name); + const Command cflagsCmd = + Command("pkg-config").addArg("--cflags").addArg(pkgConfigVer); + const Command libsCmd = + Command("pkg-config").addArg("--libs").addArg(pkgConfigVer); + + std::string cflags = Try(getCmdOutput(cflagsCmd)); + cflags.pop_back(); // remove '\n' + std::string libs = Try(getCmdOutput(libsCmd)); + libs.pop_back(); // remove '\n' + + return Ok(DepMetadata{ .includes = cflags, .libs = libs }); +} + +} // namespace cabin diff --git a/src/Dependency.hpp b/src/Dependency.hpp new file mode 100644 index 000000000..a356cdacf --- /dev/null +++ b/src/Dependency.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include "Rustify/Result.hpp" +#include "VersionReq.hpp" + +#include +#include +#include +#include + +namespace cabin { + +struct DepMetadata { + const std::string includes; // -Isomething + const std::string libs; // -Lsomething -lsomething +}; + +struct GitDependency { + const std::string name; + const std::string url; + const std::optional target; + + Result install() const; + + GitDependency( + std::string name, std::string url, std::optional target + ) + : name(std::move(name)), url(std::move(url)), target(std::move(target)) {} +}; + +struct PathDependency { + const std::string name; + const std::string path; + + Result install() const; + + PathDependency(std::string name, std::string path) + : name(std::move(name)), path(std::move(path)) {} +}; + +struct SystemDependency { + const std::string name; + const VersionReq versionReq; + + Result install() const; + + SystemDependency(std::string name, VersionReq versionReq) + : name(std::move(name)), versionReq(std::move(versionReq)) {}; +}; + +using Dependency = + std::variant; + +} // namespace cabin diff --git a/src/Manifest.cc b/src/Manifest.cc index 8d6653eda..ed18ce355 100644 --- a/src/Manifest.cc +++ b/src/Manifest.cc @@ -1,8 +1,5 @@ #include "Manifest.hpp" -#include "Algos.hpp" -#include "Command.hpp" -#include "Git2.hpp" #include "Logger.hpp" #include "Rustify/Result.hpp" #include "Semver.hpp" @@ -24,19 +21,6 @@ namespace cabin { -static fs::path -getXdgCacheHome() noexcept { - if (const char* envP = std::getenv("XDG_CACHE_HOME")) { - return envP; - } - const fs::path userDir = std::getenv("HOME"); - return userDir / ".cache"; -} - -static const fs::path CACHE_DIR(getXdgCacheHome() / "cabin"); -static const fs::path GIT_DIR(CACHE_DIR / "git"); -static const fs::path GIT_SRC_DIR(GIT_DIR / "src"); - static const std::unordered_set ALLOWED_CHARS = { '-', '_', '/', '.', '+' // allowed in the dependency name }; @@ -383,85 +367,6 @@ parseDependencies(const toml::value& val, const char* key) noexcept { return Ok(deps); } -Result -GitDependency::install() const { - fs::path installDir = GIT_SRC_DIR / name; - if (target.has_value()) { - installDir += '-' + target.value(); - } - - if (fs::exists(installDir) && !fs::is_empty(installDir)) { - logger::debug("{} is already installed", name); - } else { - git2::Repository repo; - repo.clone(url, installDir.string()); - - if (target.has_value()) { - // Checkout to target. - const std::string target = this->target.value(); - const git2::Object obj = repo.revparseSingle(target); - repo.setHeadDetached(obj.id()); - repo.checkoutHead(true); - } - - logger::info( - "Downloaded", "{} {}", name, target.has_value() ? target.value() : url - ); - } - - const fs::path includeDir = installDir / "include"; - std::string includes = "-isystem"; - - if (fs::exists(includeDir) && fs::is_directory(includeDir) - && !fs::is_empty(includeDir)) { - includes += includeDir.string(); - } else { - includes += installDir.string(); - } - - // Currently, no libs are supported. - return Ok(DepMetadata{ .includes = includes, .libs = "" }); -} - -Result -PathDependency::install() const { - const fs::path installDir = fs::weakly_canonical(path); - if (fs::exists(installDir) && !fs::is_empty(installDir)) { - logger::debug("{} is already installed", name); - } else { - Bail("{} can't be accessible as directory", installDir.string()); - } - - const fs::path includeDir = installDir / "include"; - std::string includes = "-isystem"; - - if (fs::exists(includeDir) && fs::is_directory(includeDir) - && !fs::is_empty(includeDir)) { - includes += includeDir.string(); - } else { - includes += installDir.string(); - } - - // Currently, no libs are supported. - return Ok(DepMetadata{ .includes = includes, .libs = "" }); -} - -Result -SystemDependency::install() const { - const std::string pkgConfigVer = versionReq.toPkgConfigString(name); - const Command cflagsCmd = - Command("pkg-config").addArg("--cflags").addArg(pkgConfigVer); - const Command libsCmd = - Command("pkg-config").addArg("--libs").addArg(pkgConfigVer); - - std::string cflags = Try(getCmdOutput(cflagsCmd)); - cflags.pop_back(); // remove '\n' - std::string libs = Try(getCmdOutput(libsCmd)); - libs.pop_back(); // remove '\n' - - return Ok(DepMetadata{ .includes = cflags, .libs = libs }); -} - Result Manifest::tryParse(fs::path path, const bool findParents) noexcept { if (findParents) { diff --git a/src/Manifest.hpp b/src/Manifest.hpp index 1bd64800d..1d945613b 100644 --- a/src/Manifest.hpp +++ b/src/Manifest.hpp @@ -1,21 +1,19 @@ #pragma once +#include "Dependency.hpp" #include "Rustify/Result.hpp" #include "Semver.hpp" -#include "VersionReq.hpp" #include #include #include #include #include -#include #include #include #include #include #include -#include #include namespace cabin { @@ -146,47 +144,6 @@ struct Lint { explicit Lint(Cpplint cpplint) noexcept : cpplint(std::move(cpplint)) {} }; -struct DepMetadata { - const std::string includes; // -Isomething - const std::string libs; // -Lsomething -lsomething -}; - -struct GitDependency { - const std::string name; - const std::string url; - const std::optional target; - - Result install() const; - - GitDependency( - std::string name, std::string url, std::optional target - ) - : name(std::move(name)), url(std::move(url)), target(std::move(target)) {} -}; - -struct PathDependency { - const std::string name; - const std::string path; - - Result install() const; - - PathDependency(std::string name, std::string path) - : name(std::move(name)), path(std::move(path)) {} -}; - -struct SystemDependency { - const std::string name; - const VersionReq versionReq; - - Result install() const; - - SystemDependency(std::string name, VersionReq versionReq) - : name(std::move(name)), versionReq(std::move(versionReq)) {}; -}; - -using Dependency = - std::variant; - class Manifest { public: static constexpr const char* FILE_NAME = "cabin.toml";