diff options
author | Kim Altintop <kim@eagain.io> | 2023-01-09 13:18:33 +0100 |
---|---|---|
committer | Kim Altintop <kim@eagain.io> | 2023-01-09 13:18:33 +0100 |
commit | d2f423521ec76406944ad83098ec33afe20c692b (patch) | |
tree | afd86bcb088eebdd61ba4e52fa666ff0f41c42a2 /src/git/repo.rs |
This is it
Squashed commit of all the exploration history. Development starts here.
Signed-off-by: Kim Altintop <kim@eagain.io>
Diffstat (limited to 'src/git/repo.rs')
-rw-r--r-- | src/git/repo.rs | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/src/git/repo.rs b/src/git/repo.rs new file mode 100644 index 0000000..3fb8a16 --- /dev/null +++ b/src/git/repo.rs @@ -0,0 +1,93 @@ +// Copyright © 2022 Kim Altintop <kim@eagain.io> +// SPDX-License-Identifier: GPL-2.0-only WITH openvpn-openssl-exception + +use std::{ + collections::HashSet, + ffi::OsString, + io::{ + BufReader, + Seek, + Write, + }, + iter, + path::Path, + result::Result as StdResult, +}; + +use super::{ + if_not_found_then, + Result, +}; +use crate::{ + fs::LockedFile, + io::Lines, +}; + +pub fn open<P: AsRef<Path>>(path: P) -> Result<git2::Repository> { + git2::Repository::open_ext( + path, + git2::RepositoryOpenFlags::FROM_ENV, + iter::empty::<OsString>(), + ) +} + +pub fn open_bare<P: AsRef<Path>>(path: P) -> Result<git2::Repository> { + git2::Repository::open_ext( + path, + git2::RepositoryOpenFlags::FROM_ENV | git2::RepositoryOpenFlags::BARE, + iter::empty::<OsString>(), + ) +} + +pub fn open_or_init<P: AsRef<Path>>(path: P, opts: InitOpts) -> Result<git2::Repository> { + if_not_found_then(open(path.as_ref()), || init(path, opts)) +} + +pub struct InitOpts<'a> { + pub bare: bool, + pub description: &'a str, + pub initial_head: &'a str, +} + +pub fn init<P: AsRef<Path>>(path: P, opts: InitOpts) -> Result<git2::Repository> { + git2::Repository::init_opts( + path, + git2::RepositoryInitOptions::new() + .no_reinit(true) + .mkdir(true) + .mkpath(true) + .bare(opts.bare) + .description(opts.description) + .initial_head(opts.initial_head), + ) +} + +pub fn add_alternates<'a, I>(repo: &git2::Repository, alt: I) -> crate::Result<()> +where + I: IntoIterator<Item = &'a git2::Repository>, +{ + let (mut persistent, known) = { + let mut lock = LockedFile::atomic( + repo.path().join("objects").join("info").join("alternates"), + false, + LockedFile::DEFAULT_PERMISSIONS, + )?; + lock.seek(std::io::SeekFrom::Start(0))?; + let mut bufread = BufReader::new(lock); + let known = Lines::new(&mut bufread).collect::<StdResult<HashSet<String>, _>>()?; + (bufread.into_inner(), known) + }; + { + let odb = repo.odb()?; + for alternate in alt { + let path = format!("{}", alternate.path().join("objects").display()); + odb.add_disk_alternate(&path)?; + if !known.contains(&path) { + writeln!(&mut persistent, "{}", path)? + } + } + } + persistent.persist()?; + + Ok(()) +} |