about summary refs log tree commit diff
diff options
context:
space:
mode:
authorProfpatsch <mail@profpatsch.de>2021-04-19T20·49+0200
committerProfpatsch <mail@profpatsch.de>2021-12-26T16·34+0000
commitc1d7714a212e80756e8f1b83cbc7f077dedb7abd (patch)
treef1d9c25ba9734f06be29fbe2265756180f43f879
parent38b3cdebef59f3eebf9ded815631db8cb6ee5b98 (diff)
feat(users/Profpatsch): add git-db r/3423
WIP: currently just a simple setup that creates an empty git repo if
it doesn’t exist yet, and writes a commit to it.

A simple database backed by a bare git repository.

WIP: Will speak a simple interactive protocol to query files and
update them atomically.

It could be made atomic on the git repo level, if a lock is taken
between reading the current commit ref and creating the commit.

Change-Id: I1fd30a046ac977063c3e08c36d96e835b35ff07d
Reviewed-on: https://cl.tvl.fyi/c/depot/+/3046
Tested-by: BuildkiteCI
Reviewed-by: Profpatsch <mail@profpatsch.de>
-rw-r--r--users/Profpatsch/git-db/default.nix8
-rw-r--r--users/Profpatsch/git-db/git-db.rs85
2 files changed, 93 insertions, 0 deletions
diff --git a/users/Profpatsch/git-db/default.nix b/users/Profpatsch/git-db/default.nix
new file mode 100644
index 000000000000..7c6f1aee7c5c
--- /dev/null
+++ b/users/Profpatsch/git-db/default.nix
@@ -0,0 +1,8 @@
+{ depot, pkgs, lib, ... }:
+
+depot.nix.writers.rustSimple {
+  name = "git-db";
+  dependencies = [
+    depot.third_party.rust-crates.git2
+  ];
+} (builtins.readFile ./git-db.rs)
diff --git a/users/Profpatsch/git-db/git-db.rs b/users/Profpatsch/git-db/git-db.rs
new file mode 100644
index 000000000000..5c6bb1f85646
--- /dev/null
+++ b/users/Profpatsch/git-db/git-db.rs
@@ -0,0 +1,85 @@
+extern crate git2;
+use std::os::unix::ffi::OsStrExt;
+use std::path::PathBuf;
+
+const DEFAULT_BRANCH : &str = "refs/heads/main";
+
+fn main() {
+    let git_db_dir = std::env::var_os("GIT_DB_DIR").expect("set GIT_DB_DIR");
+    let git_db = PathBuf::from(git_db_dir).join("git");
+
+    std::fs::create_dir_all(&git_db).unwrap();
+
+    let repo = git2::Repository::init_opts(
+        &git_db,
+        git2::RepositoryInitOptions::new()
+            .bare(true)
+            .mkpath(true)
+            .description("git-db database")
+            .initial_head(DEFAULT_BRANCH)
+    ).expect(&format!("unable to create or open bare git repo at {}", &git_db.display()));
+
+    let mut index = repo.index().expect("cannot get the git index file");
+    eprintln!("{:#?}", index.version());
+    index.clear().expect("could not clean the index");
+
+    let now = std::time::SystemTime::now()
+        .duration_since(std::time::SystemTime::UNIX_EPOCH)
+        .expect("unable to get system time");
+
+    let now_git_time = git2::IndexTime::new(
+        now.as_secs() as i32, // lol
+        u32::from(now.subsec_nanos()),
+    );
+
+    let data = "hi, it’s me".as_bytes();
+
+    index.add_frombuffer(
+        &git2::IndexEntry {
+            mtime: now_git_time,
+            ctime: now_git_time,
+            // don’t make sense
+            dev: 0,
+            ino: 0,
+            mode: /*libc::S_ISREG*/ 0b1000 << (3+9) | /* read write for owner */ 0o644,
+            uid: 0,
+            gid: 0,
+            file_size: data.len() as u32, // lol again
+            id: git2::Oid::zero(),
+            flags: 0,
+            flags_extended: 0,
+            path: "hi.txt".as_bytes().to_owned(),
+        },
+        data
+    ).expect("could not add data to index");
+
+    let oid = index.write_tree().expect("could not write index tree");
+
+    let to_add_tree = repo.find_tree(oid)
+        .expect("we just created this tree, where did it go?");
+
+    let parent_commits = match repo.find_reference(DEFAULT_BRANCH) {
+        Ok(ref_) => vec![
+            ref_
+            .peel_to_commit()
+            .expect(&format!("reference {} does not point to a commit", DEFAULT_BRANCH))
+        ],
+        Err(err) => match err.code() {
+            // no commit exists yet
+            git2::ErrorCode::NotFound => vec![],
+            _ => panic!("could not read latest commit from {}", DEFAULT_BRANCH),
+        }
+    };
+    repo.commit(
+        Some(DEFAULT_BRANCH),
+        &git2::Signature::now("Mr. Authorboy", "author@example.com").unwrap(),
+        &git2::Signature::now("Mr. Commiterboy", "committer@example.com").unwrap(),
+        "This is my first commit!\n\
+         \n\
+         I wonder if it supports extended commit descriptions?\n",
+        &to_add_tree,
+        &parent_commits.iter().collect::<Vec<_>>()[..],
+    ).expect("could not commit the index we just wrote");
+
+
+}