summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudius "keldu" Holeksa <mail@keldu.de>2025-11-07 15:15:16 +0100
committerClaudius "keldu" Holeksa <mail@keldu.de>2025-11-07 15:15:16 +0100
commit136966aeac7ac000d5b0aadc689e40a61aa5efd5 (patch)
tree4ba20593d500cf1e405db7d1340c0849123f7e0a
parentf32687ccab6158e9611007e6fc2d66bf4751e111 (diff)
downloadapps-science_tools-136966aeac7ac000d5b0aadc689e40a61aa5efd5.tar.gz
Adding git features
-rw-r--r--run_and_record/.nix/derivation.nix2
-rw-r--r--run_and_record/SConstruct3
-rw-r--r--run_and_record/c++/git.hpp88
-rw-r--r--run_and_record/c++/main.cpp89
-rw-r--r--run_and_record/c++/schema.hpp58
5 files changed, 178 insertions, 62 deletions
diff --git a/run_and_record/.nix/derivation.nix b/run_and_record/.nix/derivation.nix
index 089c7cb..ed20cbe 100644
--- a/run_and_record/.nix/derivation.nix
+++ b/run_and_record/.nix/derivation.nix
@@ -1,6 +1,7 @@
{ stdenv
, scons
, forstio
+, libgit2
}:
stdenv.mkDerivation {
@@ -18,6 +19,7 @@ stdenv.mkDerivation {
forstio.codec-json
forstio.remote
forstio.remote-filesystem
+ libgit2
];
src = ./..;
diff --git a/run_and_record/SConstruct b/run_and_record/SConstruct
index 9dbf18f..8dcd782 100644
--- a/run_and_record/SConstruct
+++ b/run_and_record/SConstruct
@@ -49,7 +49,8 @@ env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[],
CXXFLAGS=['-std=c++20','-g','-Wall','-Wextra'],
LIBS=[
'forstio-core',
- 'forstio-async'
+ 'forstio-async',
+ 'git2'
]
)
env.__class__.add_source_files = add_kel_source_files
diff --git a/run_and_record/c++/git.hpp b/run_and_record/c++/git.hpp
new file mode 100644
index 0000000..c145e01
--- /dev/null
+++ b/run_and_record/c++/git.hpp
@@ -0,0 +1,88 @@
+#pragma once
+
+#include <forstio/error.hpp>
+
+#include <git2.h>
+
+#include "schema.hpp"
+
+namespace kel {
+saw::error_or<saw::data<sch::RarGit>> is_clean_git_repo(){
+ saw::data<sch::RarGit> git_data;
+
+ git_repository *repo = nullptr;
+ {
+ int error = git_repository_open_ext(&repo, ".", 0, nullptr);
+ if (error < 0) {
+ // const git_error *e = git_error_last();
+ git_libgit2_shutdown();
+ return saw::make_error<saw::err::critical>("Not a git repository");
+ }
+ }
+
+ {
+ git_status_options status_opts = GIT_STATUS_OPTIONS_INIT;
+ status_opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
+ status_opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX;
+
+ git_status_list* status_list = nullptr;
+ int error = git_status_list_new(&status_list, repo, &status_opts);
+ if (error < 0) {
+ git_repository_free(repo);
+ git_libgit2_shutdown();
+ return saw::make_error<saw::err::critical>("Failed to get git status");
+ }
+
+ size_t count = git_status_list_entrycount(status_list);
+ if(count > 0){
+ git_status_list_free(status_list);
+ git_repository_free(repo);
+ git_libgit2_shutdown();
+ return saw::make_error<saw::err::critical>("Git repo is not clean");
+ }
+ git_status_list_free(status_list);
+ }
+
+ git_oid oid;
+ {
+ if(git_reference_name_to_id(&oid, repo, "HEAD") < 0){
+ git_repository_free(repo);
+ git_libgit2_shutdown();
+ return saw::make_error<saw::err::critical>("Failed to read HEAD");
+ }
+ }
+
+ std::array<char, (GIT_OID_HEXSZ) + 1u> hash_chars;
+ hash_chars[GIT_OID_HEXSZ] = 0;
+ git_oid_tostr(&hash_chars[0], hash_chars.size(), &oid);
+ hash_chars[GIT_OID_HEXSZ] = 0;
+
+ auto& commit = git_data.template get<"commit">();
+ commit.set(std::string{hash_chars.data()});
+
+ git_remote* remote = nullptr;
+ auto& origin = git_data.template get<"origin">();
+ {
+ int error = git_remote_lookup(&remote, repo, "origin");
+ if (error < 0) {
+ git_repository_free(repo);
+ git_libgit2_shutdown();
+ return saw::make_error<saw::err::critical>("Failed to find origin remote");
+ }
+ const char* url = git_remote_url(remote);
+ if(not url) {
+ git_remote_free(remote);
+ git_repository_free(repo);
+ git_libgit2_shutdown();
+ return saw::make_error<saw::err::critical>("Failed to get origin remote url");
+ }
+
+ origin.set(std::string{url});
+ }
+
+ git_remote_free(remote);
+ git_repository_free(repo);
+ git_libgit2_shutdown();
+ return git_data;
+}
+}
diff --git a/run_and_record/c++/main.cpp b/run_and_record/c++/main.cpp
index 8440d67..d28629f 100644
--- a/run_and_record/c++/main.cpp
+++ b/run_and_record/c++/main.cpp
@@ -10,56 +10,12 @@
#include <random>
#include <string_view>
+#include "git.hpp"
+#include "schema.hpp"
+
+extern char** environ;
+
namespace kel {
-namespace sch {
-using namespace saw::schema;
-
-using RarConfig = Struct<
->;
-
-// Additionally record the files which are needed to run the simulation
-using RarArgsTuple = Tuple<
- Array<String>
->;
-
-using RarArgs = Args<
- RarConfig,
- RarArgsTuple
->;
-
-using RarFileData = Struct<
- Member<
- Member<
- Array<
- Struct<
- Member<String, "program">,
- Member<Array<String>, "arguments">
- >
- >,
- >, "commands">,
- Member<
- Array<
- Struct<
- Member<String, "key">,
- Member<String, "value">
- >
- >, "env">,
- Member<
- Struct<
- Member<String, "commit">,
- Member<String, "origin">
- >,
- "git">,
- Member<
- Array<
- Struct<
- Member<Array<String>, "command">,
- Member<String, "stdout">,
- Member<String, "stderr">
- >
- >, "meta">
->;
-}
/**
* Check if HOME env variable is set and where it points to.
@@ -135,7 +91,7 @@ saw::error_or<std::string> generate_data_dir_name(const std::string_view& bin_na
thread_local std::mt19937 generator{std::random_device{}()};
std::uniform_int_distribution<size_t> distribution(0, chars.size() - 1);
- for (size_t i = 0; i < length; ++i){
+ for (size_t i = 0; i < 8; ++i){
oss << chars[distribution(generator)];
}
}
@@ -143,25 +99,21 @@ saw::error_or<std::string> generate_data_dir_name(const std::string_view& bin_na
return oss.str();
}
-extern char** environ;
-
/**
* Record the environment
*/
-saw::error_or<void> record_environment(saw::data<sch::RarFileData>& df){
+saw::error_or<void> record_environment(saw::data<sch::RarEnv>& df_env){
saw::data<sch::UInt64> env_size{0u};
for(char** env = environ; *env != nullptr; ++env){
++env_size;
}
- auto& df_env = df.template get<"env">();
-
- df_env = {env_size};
+ df_env = {saw::data<sch::FixedArray<sch::UInt64,1u>>{{env_size}}};
saw::data<sch::UInt64> i{0u};
for(char** env = environ; *env != nullptr; ++env){
- df_env.at(i).set(std::to_string(env));
+ df_env.at(i).set(std::string(*env));
++i;
}
@@ -202,9 +154,9 @@ saw::error_or<void> kel_main(int argc, char** argv){
saw::data<sch::RarArgs> args;
auto eo_home = get_home_env();
if(eo_home.is_error()){
- return std::move(eov.get_error());
+ return std::move(eo_home.get_error());
}
- auto& home = eov.get_value();
+ auto& home = eo_home.get_value();
auto data_dir = home / ".local" / "kel" / "run_and_record";
//
@@ -221,7 +173,7 @@ saw::error_or<void> kel_main(int argc, char** argv){
// Read the user config file for recording
{
auto conf_file = home / ".config" / "kel" / "run_and_record.json";
- auto eo_file = simple_read_file<sch::RarConfig,saw::encode::Json>(conf_file);
+ auto eo_file = saw::easy::read_and_decode_file<sch::RarConfig,saw::encode::Json>(conf_file);
if(eo_file.is_error()){
return std::move(eo_file.get_error());
@@ -247,6 +199,16 @@ saw::error_or<void> kel_main(int argc, char** argv){
return eov;
}
}
+
+ {
+ auto eo_git = is_clean_git_repo();
+ if(eo_git.is_error()){
+ return std::move(eo_git.get_error());
+ }
+ auto& v_git = eo_git.get_value();
+ data_for_file.template get<"git">() = v_git;
+ }
+
// sep_pos+1 til end
int argc_prog = argc - (sep_pos+1);
{
@@ -255,8 +217,13 @@ saw::error_or<void> kel_main(int argc, char** argv){
return eov;
}
}
+
+ if(not std::filesystem::create_directory(data_full_dir)){
+ return saw::make_error<saw::err::critical>("Couldn't create directory for file");
+ }
+
{
- auto eov = easy::write_file<sch::RarFileData, saw::encode::Json>(data_full_dir, data_for_file);
+ auto eov = saw::easy::encode_and_write_file<sch::RarFileData, saw::encode::Json>(data_full_dir / "data.json", data_for_file);
if(eov.is_error()){
return eov;
}
diff --git a/run_and_record/c++/schema.hpp b/run_and_record/c++/schema.hpp
new file mode 100644
index 0000000..140e81b
--- /dev/null
+++ b/run_and_record/c++/schema.hpp
@@ -0,0 +1,58 @@
+#pragma once
+
+#include <forstio/codec/schema.hpp>
+
+namespace kel {
+namespace sch {
+using namespace saw::schema;
+
+using RarConfig = Struct<
+>;
+
+// Additionally record the files which are needed to run the simulation
+using RarArgsTuple = Tuple<
+>;
+
+using RarGit = Struct<
+ Member<String, "commit">,
+ Member<String, "origin">
+>;
+
+using RarArgs = Args<
+ RarConfig,
+ RarArgsTuple
+>;
+
+using RarEnv = Array<String>;
+
+using RarFileData = Struct<
+ Member<
+ Array<
+ Struct<
+ Member<String, "program">,
+ Member<Array<String>, "arguments">
+ >
+ >,
+ "commands"
+ >,
+ Member<
+ RarEnv,
+ "env"
+ >,
+ Member<
+ RarGit,
+ "git"
+ >,
+ Member<
+ Array<
+ Struct<
+ Member<Array<String>, "command">,
+ Member<String, "stdout">,
+ Member<String, "stderr">
+ >
+ >,
+ "meta"
+ >
+>;
+}
+}