Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
19 changes: 19 additions & 0 deletions include/cppship/cmd/index.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

#include <optional>
#include <string>

#include "cppship/util/fs.h"

namespace cppship::cmd {

struct IndexOptions {
std::string operation;
std::optional<std::string> name;
std::optional<std::string> path;
std::optional<std::string> git;
};

int run_index(const IndexOptions& options);

}
4 changes: 3 additions & 1 deletion include/cppship/cmd/install.h
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
#pragma once

#include "cppship/core/profile.h"
#include <optional>

namespace cppship::cmd {

struct InstallOptions {
Profile profile = Profile::debug;
std::string root;
};

int run_install(const InstallOptions& options);

}
}
15 changes: 15 additions & 0 deletions include/cppship/cmd/publish.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once

#include <optional>

#include "cppship/util/fs.h"

namespace cppship::cmd {

struct PublishOptions {
fs::path index;
};

int run_publish(const PublishOptions& options);

}
4 changes: 3 additions & 1 deletion include/cppship/cppship.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
#include "cppship/cmd/clean.h"
#include "cppship/cmd/cmake.h"
#include "cppship/cmd/fmt.h"
#include "cppship/cmd/index.h"
#include "cppship/cmd/init.h"
#include "cppship/cmd/install.h"
#include "cppship/cmd/lint.h"
#include "cppship/cmd/publish.h"
#include "cppship/cmd/run.h"
#include "cppship/cmd/test.h"
#include "cppship/cmd/test.h"
12 changes: 4 additions & 8 deletions include/cppship/util/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,9 @@ class ScopedCurrentDir {
fs::path mPrevCwd;
};

inline void create_if_not_exist(const fs::path& path)
{
if (fs::exists(path)) {
return;
}
void create_if_not_exist(const fs::path& path);

fs::create_directory(path);
}
inline constexpr std::string_view kCppShipDirName = ".cppship";
fs::path get_cppship_dir();

}
}
79 changes: 79 additions & 0 deletions lib/cmd/index.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include "cppship/cmd/index.h"
#include "cppship/core/manifest.h"
#include "cppship/exception.h"
#include "cppship/util/cmd.h"
#include "cppship/util/fs.h"
#include "cppship/util/log.h"
#include "cppship/util/string.h"
#include <filesystem>
#include <range/v3/algorithm/contains.hpp>
#include <range/v3/view.hpp>
#include <string>
#include <vector>

using namespace cppship;

int cmd::run_index(const IndexOptions& options)
{
const std::vector<std::string> supported_operations { "add", "remove", "list" };
if (!ranges::contains(supported_operations, options.operation)) {
throw Error { std::format("Unrecognized operation '{}'", options.operation) };
}
const auto cppship_dir = get_cppship_dir();
const auto index_store_dir = cppship_dir / "index_store";
create_if_not_exist(index_store_dir);

if (options.operation == "list") {
const auto out = check_output("conan remote list");
const auto lines = util::split(out, boost::is_any_of("\n"));
fmt::print("local package indexes:\n");
for (const auto& line : lines | ranges::views::filter([&index_store_dir](std::string_view line) {
return line.find(index_store_dir.string()) != std::string::npos;
;
})) {
fmt::print(" {}\n", line);
}
return EXIT_SUCCESS;
}

if (!options.name) {
throw Error { "--name option required" };
}
const auto index_dir = index_store_dir / options.name.value();
if (options.operation == "add") {
if (fs::exists(index_dir)) {
throw Error { fmt::format("index with name '{}' already exists", options.name.value()) };
}

if (!options.path && !options.git) {
throw Error { std::format("one of --path or --git must be given") };
}
const auto url = options.path.value_or(options.git.value_or(""));
const auto git_cmd = fmt::format("git clone {} {}", url, index_dir.string());
int res = run_cmd(git_cmd);
if (res != 0) {
throw Error { "git clone failed" };
}

const auto conan_cmd = fmt::format(
"conan remote add --type local-recipes-index {} {}", options.name.value(), index_dir.string());
res = run_cmd(conan_cmd);
if (res != 0) {
throw Error { fmt::format("failed adding '{}' as local index", index_dir.string()) };
}
}
if (options.operation == "remove") {
if (!fs::exists(index_dir)) {
throw Error { std::format("no index with name '{}' exists", options.name.value()) };
}
fs::remove_all(index_dir);

const auto conan_cmd = fmt::format("conan remote remove {}", options.name.value());
int res = run_cmd(conan_cmd);
if (res != 0) {
throw Error { fmt::format("failed adding '{}' as local index", index_dir.string()) };
}
}

return EXIT_SUCCESS;
}
2 changes: 1 addition & 1 deletion lib/cmd/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ int cmd::run_init(const InitOptions& options)
}

return EXIT_SUCCESS;
}
}
9 changes: 6 additions & 3 deletions lib/cmd/install.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <cstdlib>
#include <filesystem>
#include <thread>

#include <gsl/narrow>
Expand Down Expand Up @@ -32,9 +33,11 @@ int cmd::run_install([[maybe_unused]] const InstallOptions& options)
return EXIT_SUCCESS;
}

const auto dst = fmt::format("/usr/local/bin/{}", manifest.name());
status("install", "{} to {}", bin_file.string(), dst);
const auto root = fs::path(options.root);
const auto dst = root / "bin" / manifest.name();
cppship::create_if_not_exist(dst.parent_path());
status("install", "{} to {}", bin_file.string(), dst.string());
fs::copy_file(bin_file, dst, fs::copy_options::overwrite_existing);
return EXIT_SUCCESS;
#endif
}
}
9 changes: 9 additions & 0 deletions lib/cmd/publish.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "cppship/cmd/publish.h"
#include "cppship/core/manifest.h"
#include "cppship/exception.h"
#include "cppship/util/fs.h"
#include "cppship/util/log.h"

using namespace cppship;

int cmd::run_publish(const PublishOptions& options) { return EXIT_SUCCESS; }
17 changes: 17 additions & 0 deletions lib/util/fs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include "cppship/util/fs.h"
#include <cstdlib>

void cppship::create_if_not_exist(const fs::path& path)
{
if (fs::exists(path)) {
return;
}

if (path.has_parent_path()) {
create_if_not_exist(path.parent_path());
}

fs::create_directory(path);
}

fs::path cppship::get_cppship_dir() { return fs::path(std::getenv("HOME")) / kCppShipDirName; }
27 changes: 23 additions & 4 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "cppship/cppship.h"
#include "cppship/exception.h"
#include "cppship/util/fs.h"
#include "cppship/util/log.h"

#ifndef CPPSHIP_VERSION
Expand Down Expand Up @@ -159,16 +160,18 @@ std::list<SubCommand> build_commands(const ArgumentParser& common)

// install
auto& install = commands.emplace_back("install", common, [](const ArgumentParser& cmd) {
return cmd::run_install({
.profile = parse_profile(cmd.get("--profile")),
});
return cmd::run_install({ .profile = parse_profile(cmd.get("--profile")), .root = cmd.get("--root") });
});

install.parser.add_description("install binary if exists");
install.parser.add_argument("--profile")
.help("build with specific profile")
.metavar("profile")
.default_value(std::string { kProfileRelease });
install.parser.add_argument("--root")
.help("specify the installation root")
.metavar("root")
.default_value(get_cppship_dir().string());

// run
auto& run = commands.emplace_back("run", common, [](const ArgumentParser& cmd) {
Expand Down Expand Up @@ -271,6 +274,22 @@ std::list<SubCommand> build_commands(const ArgumentParser& common)

cmake.parser.add_description("generate cmake CMakeFiles.txt");

// index
auto& index = commands.emplace_back("index", common, [](const ArgumentParser& cmd) {
return run_index(cmd::IndexOptions {
.operation = cmd.get("operation"),
.name = cmd.present("name"),
.path = cmd.present("--path"),
.git = cmd.present("git"),
});
});

index.parser.add_description("manage package indexes");
index.parser.add_argument("operation").help("operation [add, remove, list]");
index.parser.add_argument("--name").help("name of index");
index.parser.add_argument("--path").help("filesystem path to local index to add");
index.parser.add_argument("--git").help("git URL to index to add");

return commands;
}

Expand Down Expand Up @@ -322,4 +341,4 @@ try {
} catch (const std::exception& e) {
error("unknown error {}", e.what());
return EXIT_FAILURE;
}
}
39 changes: 38 additions & 1 deletion tests/util/fs.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#include <filesystem>
#include <gtest/gtest.h>
#include <iostream>

#include "cppship/util/fs.h"

Expand All @@ -16,4 +18,39 @@ TEST(fs, ScopedCurrentDir)
}

EXPECT_EQ(fs::current_path(), cwd);
}
}

TEST(fs, CreateIfNotExist)
{
const auto tmpdir = fs::temp_directory_path();
const auto testdir = fs::path("cppship-unitests");

ScopedCurrentDir guard(tmpdir);

if (fs::exists(testdir)) {
fs::remove_all(testdir);
}
fs::create_directory(testdir);

{
ScopedCurrentDir guard2(testdir);
const auto newdir = fs::path("subdir1");
EXPECT_FALSE(fs::exists(newdir));
cppship::create_if_not_exist(newdir);
EXPECT_TRUE(fs::exists(newdir));
}
{
ScopedCurrentDir guard2(testdir);
const auto newdir = fs::path("./subdir2/subsubdir1");
EXPECT_FALSE(fs::exists(newdir));
cppship::create_if_not_exist(newdir);
EXPECT_TRUE(fs::exists(newdir));
}
{
ScopedCurrentDir guard2(testdir);
const auto newdir = fs::path("subdir3/subsubdir1/subsubsubdir1");
EXPECT_FALSE(fs::exists(newdir));
cppship::create_if_not_exist(newdir);
EXPECT_TRUE(fs::exists(newdir));
}
}