startgitStatic page generator for git repositories |
git clone git://git.dimitrijedobrota.com/startgit.git |
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING |
commit | f074f5020be313c89cf9ee22e6ae8861799f7492 |
parent | 70650857edfdc7ca0e5a658944ec51dddddc65af |
author | Dimitrije Dobrota < mail@dimitrijedobrota.com > |
date | Sat, 7 Jun 2025 18:36:13 +0200 |
Use the latest version of poafloc
M | CMakeLists.txt | | | + - |
M | source/arguments.hpp | | | ++++++++++++++++++++++++ |
M | source/startgit-index.cpp | | | ++++++++++++++++++++++++++++++++++ ------------------------------------------------ |
M | source/startgit.cpp | | | ++++++++++++++++++++++++++++++++ -------------------------------------------------- |
A | vcpkg-configuration.json | | | +++++++++++++++ |
A | vcpkg.json | | | +++++++++++++++++++++++++++++++++++++++ |
6 files changed, 207 insertions(+), 194 deletions(-)
diff --git a/ CMakeLists.txt b/ CMakeLists.txt
@@ -19,7 +19,7 @@
find_package(based 0.2.0 CONFIG REQUIRED)
find_package(git2wrap 0.3.0 CONFIG REQUIRED)
find_package(hemplate 0.4 CONFIG REQUIRED)
find_package(md4c CONFIG REQUIRED)
find_package(poafloc 1.2 CONFIG REQUIRED)
find_package(poafloc 2.0 CONFIG REQUIRED)
# ---- Declare library ----
diff --git a/ source/arguments.hpp b/ source/arguments.hpp
@@ -2,6 +2,7 @@
#include <filesystem>
#include <string>
#include <string_view>
#include <unordered_set>
#include <vector>
@@ -10,6 +11,29 @@
namespace startgit
struct arguments_t
{
void add_special(std::string_view value) { special.insert(value); }
void set_repository(std::string_view value)
{
repos.emplace_back(std::filesystem::canonical(value));
}
void set_resource(std::string_view value)
{
resource_url = value;
if (resource_url.back() == '/') {
resource_url.pop_back();
}
}
void set_base(std::string_view value)
{
base_url = value;
if (base_url.back() == '/') {
base_url.pop_back();
}
}
std::filesystem::path output_dir = ".";
std::vector<std::filesystem::path> repos;
std::string resource_url = "https://dimitrijedobrota.com";
diff --git a/ source/startgit-index.cpp b/ source/startgit-index.cpp
@@ -5,6 +5,7 @@
#include <git2wrap/error.hpp>
#include <git2wrap/libgit2.hpp>
#include <hemplate/html.hpp>
#include <poafloc/error.hpp>
#include <poafloc/poafloc.hpp>
#include "arguments.hpp"
@@ -72,97 +73,68 @@
hemplate::element write_table()
} // namespace startgit
namespace
{
int parse_opt(int key, const char* arg, poafloc::Parser* parser)
{
auto* l_args = static_cast<startgit::arguments_t*>(parser->input());
switch (key) {
case 'o':
l_args->output_dir = arg;
break;
case 'b':
l_args->base_url = arg;
if (l_args->base_url.back() == '/') {
l_args->base_url.pop_back();
}
break;
case 'r':
l_args->resource_url = arg;
if (l_args->resource_url.back() == '/') {
l_args->resource_url.pop_back();
}
break;
case 'a':
l_args->author = arg;
break;
case 'd':
l_args->description = arg;
break;
case 'f':
l_args->force = true;
break;
case poafloc::ARG:
try {
l_args->repos.emplace_back(std::filesystem::canonical(arg));
} catch (const std::filesystem::filesystem_error& arr) {
std::cerr << std::format("Warning: {} doesn't exist\n", arg);
}
break;
case poafloc::END:
if (l_args->repos.empty()) {
std::cerr << std::format("Error: no repositories provided\n");
return -1;
}
break;
case poafloc::ERROR:
poafloc::help(parser, stderr, poafloc::STD_ERR);
break;
default:
break;
}
return 0;
}
// NOLINTBEGIN
// clang-format off
static const poafloc::option_t options[] = {
{0, 0, 0, 0, "Output mode", 1},
{"output", 'o', "DIR", 0, "Output directory"},
{"force", 'f', 0, 0, "Force write even if file exists"},
{0, 0, 0, 0, "General information", 2},
{"base", 'b', "URL", 0, "Absolute destination URL"},
{"resource", 'r', "URL", 0, "URL that houses styles and scripts"},
{"author", 'a', "NAME", 0, "Owner of the repository"},
{"title", 't', "TITLE", 0, "Title for the index page"},
{"description", 'd', "DESC", 0, "Description for the index page"},
{0, 0, 0, 0, "Informational Options", -1},
{0},
};
// clang-format on
static const poafloc::arg_t arg {
options,
parse_opt,
"repositories...",
"",
};
// NOLINTEND
} // namespace
int main(int argc, char* argv[])
int main(int argc, const char* argv[])
{
using namespace hemplate::html; // NOLINT
using namespace startgit; // NOLINT
using namespace poafloc; // NOLINT
if (poafloc::parse(&arg, argc, argv, 0, &args) != 0) {
std::cerr << "There was an error while parsing arguments\n";
return 1;
}
auto program = parser<arguments_t> {
positional {
argument_list {
"repositories",
&arguments_t::set_repository,
},
},
group {
"Output mode",
direct {
"o output",
&arguments_t::output_dir,
"DIR Output directory",
},
boolean {
"f force",
&arguments_t::force,
"Force write even if file exists",
},
},
group {
"General Information",
direct {
"b base",
&arguments_t::set_base,
"URL Absolute destination",
},
direct {
"r resources",
&arguments_t::set_resource,
"URL Location of styles and scripts",
},
direct {
"a author",
&arguments_t::author,
"NAME Owner of the repository",
},
direct {
"t title",
&arguments_t::title,
"TITLE Title for the index page",
},
direct {
"d description",
&arguments_t::description,
"DESC Description for the index page",
},
},
};
try {
program(args, argc, argv);
if (args.repos.empty()) {
return -1;
}
const git2wrap::libgit2 libgit;
auto& output_dir = args.output_dir;
@@ -174,7 +146,8 @@
int main(int argc, char* argv[])
args.title, args.description, args.author, "./", /* has_feed = */ false
};
doc.render(ofs, write_table);
} catch (const poafloc::runtime_error& err) {
std::cerr << std::format("Error (poafloc): {}\n", err.what());
} catch (const git2wrap::runtime_error& err) {
std::cerr << std::format("Error (git2wrap): {}\n", err.what());
} catch (const std::runtime_error& err) {
diff --git a/ source/startgit.cpp b/ source/startgit.cpp
@@ -1,5 +1,4 @@
#include <cmath>
#include <cstring>
#include <filesystem>
#include <format>
#include <fstream>
@@ -11,6 +10,7 @@
#include <hemplate/atom.hpp>
#include <hemplate/html.hpp>
#include <hemplate/rss.hpp>
#include <poafloc/error.hpp>
#include <poafloc/poafloc.hpp>
#include "arguments.hpp"
@@ -676,122 +676,81 @@
void write_rss(
} // namespace startgit
namespace
{
int parse_opt(int key, const char* arg, poafloc::Parser* parser)
{
auto* l_args = static_cast<startgit::arguments_t*>(parser->input());
switch (key) {
case 'o':
l_args->output_dir = arg;
break;
case 'b':
l_args->base_url = arg;
if (l_args->base_url.back() == '/') {
l_args->base_url.pop_back();
}
break;
case 'r':
l_args->resource_url = arg;
if (l_args->resource_url.back() == '/') {
l_args->resource_url.pop_back();
}
break;
case 'a':
l_args->author = arg;
break;
case 'd':
l_args->description = arg;
break;
case 'g':
l_args->github = arg;
break;
case 'f':
l_args->force = true;
break;
case 's': {
std::stringstream str(arg);
std::string crnt;
l_args->special.clear();
while (std::getline(str, crnt, ',')) {
l_args->special.emplace(crnt);
}
break;
}
case poafloc::ARG:
if (!l_args->repos.empty()) {
std::cerr << std::format("Error: only one repository required\n");
return -1;
}
try {
l_args->repos.emplace_back(std::filesystem::canonical(arg));
} catch (const std::filesystem::filesystem_error& arr) {
std::cerr << std::format("Error: {} doesn't exist\n", arg);
return -1;
}
break;
case poafloc::END:
if (l_args->repos.empty()) {
std::cerr << std::format("Error: no repository provided\n");
return -1;
}
break;
default:
break;
}
return 0;
}
// NOLINTBEGIN
// clang-format off
static const poafloc::option_t options[] = {
{0, 0, 0, 0, "Output mode", 1},
{"output", 'o', "DIR", 0, "Output directory"},
{"force", 'f', 0, 0, "Force write even if file exists"},
{"special", 's', "NAME", 0, "Comma separated files to be rendered to html"},
{"github", 'g', "USERNAME", 0, "Github username for url translation"},
{0, 0, 0, 0, "General information", 2},
{"base", 'b', "URL", 0, "Absolute destination URL"},
{"resource", 'r', "URL", 0, "URL that houses styles and scripts"},
{"author", 'a', "NAME", 0, "Owner of the repository"},
{"title", 't', "TITLE", 0, "Title for the index page"},
{"description", 'd', "DESC", 0, "Description for the index page"},
{0, 0, 0, 0, "Informational Options", -1},
{0},
};
// clang-format on
static const poafloc::arg_t arg {
options,
parse_opt,
"repository",
"",
};
// NOLINTEND
} // namespace
int main(int argc, char* argv[])
int main(int argc, const char* argv[])
{
using namespace startgit; // NOLINT
using namespace poafloc; // NOLINT
if (poafloc::parse(&arg, argc, argv, 0, &args) != 0) {
std::cerr << "There was an error while parsing arguments\n";
return 1;
}
auto program = parser<arguments_t> {
positional {
argument {"repository", &arguments_t::set_repository},
},
group {
"Output mode",
direct {
"o output",
&arguments_t::output_dir,
"DIR Output directory",
},
boolean {
"f force",
&arguments_t::force,
"Force write even if file exists",
},
list {
"s special",
&arguments_t::add_special,
"FILE Files to be rendered to html",
},
direct {
"g github",
&arguments_t::github,
"USERNAME Github username for url translation",
},
},
group {
"General Information",
direct {
"b base",
&arguments_t::set_base,
"URL Absolute destination",
},
direct {
"r resources",
&arguments_t::set_resource,
"URL Location of styles and scripts",
},
direct {
"a author",
&arguments_t::author,
"NAME Owner of the repository",
},
direct {
"t title",
&arguments_t::title,
"TITLE Title for the index page",
},
direct {
"d description",
&arguments_t::description,
"DESC Description for the index page",
},
},
};
try {
program(args, argc, argv);
if (args.repos.empty()) {
return -1;
}
const git2wrap::libgit2 libgit;
auto& output_dir = args.output_dir;
std::filesystem::create_directories(output_dir);
output_dir = std::filesystem::canonical(output_dir);
const repository repo(args.repos[0]);
const repository repo(args.repos.front());
const std::filesystem::path base = args.output_dir / repo.get_name();
std::filesystem::create_directory(base);
@@ -831,8 +790,11 @@
int main(int argc, char* argv[])
}
} catch (const git2wrap::error<git2wrap::error_code_t::enotfound>& err) {
std::cerr << std::format(
"Warning: {} is not a repository\n", args.repos[0].string()
"Warning: {} is not a repository\n", args.repos.front().string()
);
} catch (const poafloc::runtime_error& err) {
std::cerr << std::format("Error (poafloc): {}\n", err.what());
return 1;
} catch (const git2wrap::runtime_error& err) {
std::cerr << std::format("Error (git2wrap): {}\n", err.what());
} catch (const std::runtime_error& err) {
diff --git a/ vcpkg-configuration.json b/ vcpkg-configuration.json
@@ -0,0 +1,15 @@
{
"default-registry": {
"kind": "git",
"baseline": "566f9496b7e00ee0cc00aca0ab90493d122d148a",
"repository": "https://github.com/microsoft/vcpkg"
},
"registries": [
{
"kind": "git",
"repository": "git://git.dimitrijedobrota.com/vcpkg-registry.git",
"baseline": "cc7113e63d7bb988a70e6b6dd91c5cd1af04bdfb",
"packages": [ "based", "hemplate", "git2wrap", "md4c" ]
}
]
}
diff --git a/ vcpkg.json b/ vcpkg.json
@@ -0,0 +1,39 @@
{
"name": "hemplate",
"version-semver": "0.3.0",
"dependencies": [
{
"name": "based",
"version>=": "0.2.0"
},
{
"name": "hemplate",
"version>=": "0.4.1"
},
{
"name": "git2wrap",
"version>=": "0.3.0"
},
{
"name": "md4c",
"version>=": "0.5.2"
},
{
"name": "poafloc",
"version>=": "2.0.0"
}
],
"default-features": [],
"features": {
"test": {
"description": "Dependencies for testing",
"dependencies": [
{
"name": "catch2",
"version>=": "3.7.1"
}
]
}
},
"builtin-baseline": "eba7c6a894fce24146af4fdf161fef8e90dd6be3"
}