implement git store sync (maybe)
This commit is contained in:
parent
72df0f0b21
commit
2663838af0
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
/target
|
/target
|
||||||
|
.cargo
|
||||||
|
2432
Cargo.lock
generated
2432
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -8,3 +8,8 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
sha2 = "0.10.6"
|
sha2 = "0.10.6"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
|
gix = { version = "0.44.1", features = [
|
||||||
|
"blocking-network-client",
|
||||||
|
"blocking-http-transport-reqwest-rust-tls",
|
||||||
|
]}
|
||||||
|
tempdir = "0.3.7"
|
||||||
|
@ -35,16 +35,16 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1683020768,
|
"lastModified": 1683103914,
|
||||||
"narHash": "sha256-ZyZl6k9NWS5QPwD3NoAVz/eSgodQDvl+y+fu8MVbrHc=",
|
"narHash": "sha256-Mbrst3sLaiL55eOlZOEL8kB+XTWffaQVfcI03YWiryg=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "44f30edf5661d86fb3a95841c35127f3d0ea8b0f",
|
"rev": "54495a4eafe99c537695a87fe04cb50bf17e651d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"ref": "nixpkgs-unstable",
|
"ref": "nixos-22.11",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
naersk.url = "github:nix-community/naersk/master";
|
naersk.url = "github:nix-community/naersk/master";
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-22.11";
|
||||||
utils.url = "github:numtide/flake-utils";
|
utils.url = "github:numtide/flake-utils";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -16,6 +16,9 @@
|
|||||||
devShell = with pkgs; mkShell {
|
devShell = with pkgs; mkShell {
|
||||||
buildInputs = [ cargo rustc rustfmt pre-commit rustPackages.clippy ];
|
buildInputs = [ cargo rustc rustfmt pre-commit rustPackages.clippy ];
|
||||||
RUST_SRC_PATH = rustPlatform.rustLibSrc;
|
RUST_SRC_PATH = rustPlatform.rustLibSrc;
|
||||||
|
shellHook = ''
|
||||||
|
export CARGO_HOME=$(pwd)/.cargo
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
1
src/lib.rs
Normal file
1
src/lib.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod origin;
|
13
src/main.rs
13
src/main.rs
@ -1,13 +0,0 @@
|
|||||||
mod origin;
|
|
||||||
|
|
||||||
use crate::origin::Descr;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
|
|
||||||
let d = Descr::Git{
|
|
||||||
url: "foo",
|
|
||||||
branch: "bar",
|
|
||||||
};
|
|
||||||
|
|
||||||
println!("{}", d.id());
|
|
||||||
}
|
|
@ -1,44 +1,10 @@
|
|||||||
use sha2::{Sha256, Digest};
|
mod descr;
|
||||||
use hex::ToHex;
|
pub use self::descr::Descr;
|
||||||
|
|
||||||
/// A unique description of an origin, from where a domain might be served.
|
pub mod store;
|
||||||
pub enum Descr<'a> {
|
|
||||||
Git{url: &'a str, branch: &'a str},
|
/// A View of an origin is used to read the files of that origin at a particular point in time. A
|
||||||
|
/// single instance of a View should remain consistent across its lifetime.
|
||||||
|
pub trait View {
|
||||||
|
fn open(&self, path: &str) -> &dyn std::io::Read;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Descr<'a> {
|
|
||||||
|
|
||||||
/// Returns a globally unique string for the Descr.
|
|
||||||
pub fn id(&'a self) -> String {
|
|
||||||
|
|
||||||
let mut h = Sha256::new();
|
|
||||||
|
|
||||||
let mut h_update = |b: &str| {
|
|
||||||
h.update(b);
|
|
||||||
h.update("\n");
|
|
||||||
};
|
|
||||||
|
|
||||||
match self {
|
|
||||||
Descr::Git{url, branch} => {
|
|
||||||
h_update("git");
|
|
||||||
h_update(url);
|
|
||||||
h_update(branch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h.finalize().encode_hex::<String>()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod descr_tests {
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn id() {
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
super::Descr::Git{url:"foo", branch:"bar"}.id(),
|
|
||||||
"424130b9e6c1675c983b4b97579877e16d8a6377e4fe10970e6d210811c3b7ac",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
//}
|
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
use sha2::{Sha256, Digest};
|
use sha2::{Sha256, Digest};
|
||||||
use hex::ToHex;
|
use hex::ToHex;
|
||||||
|
|
||||||
|
#[derive(Clone,Copy)]
|
||||||
/// A unique description of an origin, from where a domain might be served.
|
/// A unique description of an origin, from where a domain might be served.
|
||||||
pub enum Descr<'a> {
|
pub enum Descr<'a> {
|
||||||
Git{url: &'a str, branch: &'a str},
|
Git{url: &'a str, branch_name: &'a str},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Descr<'a> {
|
impl<'a> Descr<'a> {
|
||||||
@ -19,10 +20,10 @@ impl<'a> Descr<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Descr::Git{url, branch} => {
|
Descr::Git{url, branch_name} => {
|
||||||
h_update("git");
|
h_update("git");
|
||||||
h_update(url);
|
h_update(url);
|
||||||
h_update(branch);
|
h_update(branch_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +38,7 @@ mod descr_tests {
|
|||||||
fn id() {
|
fn id() {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
super::Descr::Git{url:"foo", branch:"bar"}.id(),
|
super::Descr::Git{url:"foo", branch_name:"bar"}.id(),
|
||||||
"424130b9e6c1675c983b4b97579877e16d8a6377e4fe10970e6d210811c3b7ac",
|
"424130b9e6c1675c983b4b97579877e16d8a6377e4fe10970e6d210811c3b7ac",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
138
src/origin/store.rs
Normal file
138
src/origin/store.rs
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
use super::Descr;
|
||||||
|
use super::View;
|
||||||
|
|
||||||
|
#[derive(Clone,Copy)]
|
||||||
|
pub struct Limits {}
|
||||||
|
|
||||||
|
pub enum GetViewError {
|
||||||
|
TODO,
|
||||||
|
Unexpected(Box<dyn Error>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum SyncError {
|
||||||
|
InvalidURL,
|
||||||
|
InvalidBranchName,
|
||||||
|
Unexpected(Box<dyn Error>),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Store {
|
||||||
|
fn get_view(&self, descr: Descr) -> Result<&dyn View, GetViewError>;
|
||||||
|
fn sync(&self, descr: Descr, limits: Limits) -> Result<(), SyncError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod git {
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
use super::{Store as originStore, *};
|
||||||
|
|
||||||
|
use gix::clone::Error as gixCloneErr;
|
||||||
|
use gix::progress::Discard;
|
||||||
|
|
||||||
|
// Catching error from gix::prepare_clone_bare
|
||||||
|
impl From<gixCloneErr> for SyncError {
|
||||||
|
fn from(e: gixCloneErr) -> SyncError {
|
||||||
|
match e {
|
||||||
|
gixCloneErr::Init(gix::init::Error::InvalidBranchName{..}) =>
|
||||||
|
SyncError::InvalidBranchName,
|
||||||
|
gixCloneErr::UrlParse(_) |
|
||||||
|
gixCloneErr::CanonicalizeUrl{..} =>
|
||||||
|
SyncError::InvalidURL,
|
||||||
|
_ =>
|
||||||
|
SyncError::Unexpected(Box::from(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Store<'a> {
|
||||||
|
dir_path: &'a Path,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Store<'a> {
|
||||||
|
|
||||||
|
pub fn new(dir_path: &Path) -> std::io::Result<Store> {
|
||||||
|
std::fs::create_dir_all(dir_path)?;
|
||||||
|
println!("{}", &dir_path.display());
|
||||||
|
Ok(Store{dir_path})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> originStore for Store<'a> {
|
||||||
|
|
||||||
|
fn sync(&self, descr: Descr, _limits: Limits) -> Result<(), SyncError> {
|
||||||
|
|
||||||
|
let should_interrupt = &core::sync::atomic::AtomicBool::new(false);
|
||||||
|
|
||||||
|
let Descr::Git{url, ..} = descr;
|
||||||
|
|
||||||
|
let path = &self.dir_path.clone().join(descr.id());
|
||||||
|
|
||||||
|
// if the path doesn't exist then use the gix clone feature to clone it into the
|
||||||
|
// directory.
|
||||||
|
if std::fs::read_dir(path).is_err() {
|
||||||
|
|
||||||
|
std::fs::create_dir_all(path)
|
||||||
|
.map_err(|e| SyncError::Unexpected(Box::from(e)))?;
|
||||||
|
|
||||||
|
gix::prepare_clone_bare(url, path)?
|
||||||
|
.fetch_only(Discard, should_interrupt)
|
||||||
|
.map_err(|_| SyncError::InvalidURL)?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let direction = gix::remote::Direction::Fetch;
|
||||||
|
|
||||||
|
let repo = gix::open(path)
|
||||||
|
.map_err(|e| SyncError::Unexpected(Box::from(e)))?;
|
||||||
|
|
||||||
|
let remote = repo.find_default_remote(direction)
|
||||||
|
.ok_or(SyncError::Unexpected(Box::from("no default configured")))?
|
||||||
|
.map_err(|e| SyncError::Unexpected(Box::from(e)))?;
|
||||||
|
|
||||||
|
remote
|
||||||
|
.connect(direction)
|
||||||
|
.map_err(|e| SyncError::Unexpected(Box::from(e)))?
|
||||||
|
.prepare_fetch(Discard, Default::default())
|
||||||
|
.map_err(|e| SyncError::Unexpected(Box::from(e)))?
|
||||||
|
.receive(Discard, should_interrupt)
|
||||||
|
.map_err(|e| SyncError::Unexpected(Box::from(e)))?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_view(&self, _descr: Descr) -> Result<&dyn View, GetViewError> {
|
||||||
|
Err(GetViewError::TODO)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use super::Descr;
|
||||||
|
use super::super::Store;
|
||||||
|
|
||||||
|
use tempdir::TempDir;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sync() {
|
||||||
|
|
||||||
|
let tmp_dir = TempDir::new("origin_store_git").unwrap();
|
||||||
|
|
||||||
|
let descr = Descr::Git{
|
||||||
|
url: "https://github.com/mediocregopher/priority-finder.git",
|
||||||
|
branch_name: "master",
|
||||||
|
};
|
||||||
|
|
||||||
|
let limits = super::Limits{};
|
||||||
|
|
||||||
|
let store = super::Store::new(tmp_dir.path()).expect("store created");
|
||||||
|
|
||||||
|
store.sync(descr, limits).expect("sync should succeed");
|
||||||
|
store.sync(descr, limits).expect("second sync should succeed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user