FS2NWBVN2SZB2FFPB3JSYT5URTVZEAZWMQ7QW4JUYPNJVDVAJTTQC
BAWJ3BJ5X7JY7BFSEO2PLC4ZYIQ7WLAWKCVHIW4EP2DZLBDA2K2AC
ESKQM7MASZKH333Z53IVRDG5XSMXPMLWLRI5GQS2TIBESL644YHAC
TWIZ7QV4GCTQK743IKZSOJCIAEX62GZHFIYGOIFCFGIBOGPSY2WAC
W3M3C7CCWHJWRWHULDWO45D3OFD4NL3V4OTJVIJCYRQG57Z2JTWQC
5UNA2DEALCSRBINR27KSA6OMD6GQAXHYZ35ICQ7NB62G2XP4FT5QC
T7TT5B4G3RBWVEG3BK6TPZQJJ3PSBBUZZCNBUM5KWYPVVPJ2VKAAC
K4JNAJOFEJLHHWP6YSCC2U3CNK3ZPPX6EMBAVQG4VRPZWZRXMPCQC
KFVJ3KMWXEGILN4NWIWPPX7AU65M4H4UEAUIAQL2QSXOW3B5RFGQC
EIIUUAKGFBWJJ67QKWXX3X7TC2ASQIAUZV4734C5KQKWNHOVYJGAC
IWM4EE63YXP2B6KHE2UL3CORFZGXMUKLWB43TXYCYABKAFSTA6FQC
use std::path::PathBuf;
pub struct RepoMan {
pub storage_root: PathBuf,
}
pub fn new(root: String) -> RepoMan {
RepoMan {
storage_root: PathBuf::from(root),
}
}
use crate::database::Database;
use crate::models::projects;
use crate::repoman::RepoMan;
use rocket::{Route, State};
#[derive(FromForm)]
struct ChangelistReq {
channel: String, // TODO check if this breaks non-UTF-8 channels
id: Option<String>,
}
// TODO is this for push and/or pull???
#[get("/<org_path>/<proj_path>/.pijul?<cl_req..>")]
async fn changelist(
db: &State<Database>,
repoman: &State<RepoMan>,
org_path: String,
proj_path: String,
cl_req: ChangelistReq,
) -> Option<String> {
let p = match projects::find(db, org_path, proj_path).await {
Some(p) => p,
None => return None,
};
match p.repository(&repoman.storage_root) {
Ok(r) => r.channel_remote_id(cl_req.channel),
Err(e) => {
println!("{}", e);
None
}
}
// - Reverse engineer the rest of Push
}
pub fn routes() -> Vec<Route> {
routes![changelist]
}
pub async fn find(db: &State<Database>, org_path: String, proj_path: String) -> Option<Project> {
let result = sqlx::query_as!(Project,
"SELECT * FROM projects WHERE name = $1 AND owner_id = (SELECT id FROM users WHERE name = $2)",
proj_path, org_path).fetch_optional(&**db)
.await.ok()?;
result
}
pub async fn create(
db: &State<Database>,
owner_id: i32,
name: String,
) -> Result<Project, sqlx::Error> {
let result = query_as!(
Project,
"INSERT INTO projects (owner_id, name) VALUES ($1, $2) RETURNING *",
owner_id,
name.to_lowercase(),
)
.fetch_one(&**db)
.await?;
pub async fn create(&self, db: &State<Database>) -> Result<i32, sqlx::Error> {
let result = query!(
"INSERT INTO projects (owner_id, name) VALUES ($1, $2) RETURNING id",
&self.owner_id,
&self.name.to_lowercase(),
)
.fetch_one(&**db)
.await?;
pub fn repository(&self, root: &PathBuf) -> Result<Repository> {
Ok(Repository::init_or_open(root, self.repo_path())?)
}
use std::path::PathBuf;
use libpijul::pristine::sanakirja::Pristine;
use libpijul::MutTxnT;
use libpijul::TxnT;
use anyhow::bail;
pub struct Repository {
/// full_path is the fully qualified path on disk
full_path: PathBuf,
}
const DEFAULT_CHANNEL: &str = "main";
const PRISTINE_DIR: &str = "pristine";
impl Repository {
fn pristine_dir(&self) -> PathBuf {
self.full_path.join(PRISTINE_DIR)
}
fn pristine(&self) -> Result<Pristine, anyhow::Error> {
// TODO error should be logged, or handled somehow, not like this
match Pristine::new(self.pristine_dir().join("db")) {
Ok(p) => Ok(p),
Err(e) => bail!("Failed to open pristine: {}", e),
}
}
fn new(full_path: PathBuf) -> Repository {
Repository {
full_path: full_path,
}
}
// init returns an error if there's already something on disk
fn init(&self) -> Result<(), anyhow::Error> {
if std::fs::metadata(self.pristine_dir()).is_err() {
std::fs::create_dir_all(self.pristine_dir())?;
} else {
bail!("Already a repository on disk")
}
// TODO why the f does libpijul do this? It's properly weird even small
// actions can just create their own txn
let mut txn = self.pristine()?.mut_txn_begin()?;
txn.open_or_create_channel(DEFAULT_CHANNEL)?;
txn.set_current_channel(DEFAULT_CHANNEL)?;
txn.commit()?;
Ok(())
}
pub fn init_or_open(root: &PathBuf, repo_path: PathBuf) -> Result<Self, anyhow::Error> {
let repo = Self::new(root.join(repo_path));
// If the pristine can't be construsted, assume nothing is on disk
// TODO make a proper is_valid();
match repo.pristine() {
Ok(_) => Ok(repo),
Err(e) => {
println!("{}", e);
repo.init()?;
Ok(repo)
}
}
}
pub fn channel_remote_id(&self, channel: String) -> Option<String> {
let txn = match self.pristine().ok()?.mut_txn_begin() {
Err(_) => return None,
Ok(txn) => txn,
};
// TODO validate the txn needs closing?
//
// Or does the drop function do that?
//
let chan = match txn.load_channel(&channel) {
Ok(c) => c,
Err(_) => None,
};
match chan {
Some(c) => Some(c.read().id.to_string()),
None => {
println!("No chan found");
None
}
}
}
}
pub mod repositories;
pub mod pijul;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
ALTER TABLE projects ADD repository_uuid uuid NOT NULL DEFAULT uuid_generate_v4();
ALTER TABLE projects DROP COLUMN repository_uuid;
DROP EXTENSION IF EXISTS "uuid-ossp";
"cipher",
"cipher 0.2.5",
]
[[package]]
name = "aes"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
dependencies = [
"cfg-if 1.0.0",
"cipher 0.3.0",
"cpufeatures 0.2.1",
"ctr 0.8.0",
"opaque-debug 0.3.0",
name = "anyhow"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28ae2b3dec75a406790005a200b1bd89785afc02517a00ca99ecfe093ee9e6cf"
[[package]]
name = "arrayref"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
[[package]]
]
[[package]]
name = "blake3"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcd555c66291d5f836dbb6883b48660ece810fe25a31f3bdfb911945dff2691f"
dependencies = [
"arrayref",
"arrayvec 0.7.1",
"cc",
"cfg-if 1.0.0",
"constant_time_eq",
"digest 0.9.0",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-utils",
"lazy_static",
"memoffset",
"scopeguard",
name = "curve25519-dalek"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61"
dependencies = [
"byteorder",
"digest 0.9.0",
"rand_core 0.5.1",
"serde",
"subtle",
"zeroize",
]
[[package]]
name = "data-encoding"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57"
[[package]]
name = "ed25519"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4620d40f6d2601794401d6dd95a5cf69b6c157852539470eeda433a99b3c0efc"
dependencies = [
"serde",
"signature",
]
[[package]]
name = "ed25519-dalek"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d"
dependencies = [
"curve25519-dalek",
"ed25519",
"rand 0.7.3",
"serde",
"serde_bytes",
"sha2",
"zeroize",
]
[[package]]
"crypto-mac",
"crypto-mac 0.10.0",
"digest 0.9.0",
]
[[package]]
name = "hmac"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"
dependencies = [
"crypto-mac 0.11.1",
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
checksum = "ffbd6c9d230f5db81cadc7cbfd824bdd594a864df8fb173487717dc4a6d0c6cb"
dependencies = [
"adler32",
"aes 0.7.5",
"bincode",
"bitflags",
"blake3",
"bs58",
"byteorder",
"canonical-path",
"cfg-if 1.0.0",
"chrono",
"crossbeam-deque",
"crossbeam-utils",
"curve25519-dalek",
"data-encoding",
"diffs",
"ed25519-dalek",
"encoding_rs",
"generic-array 0.14.4",
"hmac 0.11.0",
"ignore",
"lazy_static",
"log",
"lru-cache",
"memchr",
"parking_lot",
"path-slash",
"pbkdf2",
"pijul-macros",
"rand 0.7.3",
"rand_core 0.6.3",
"regex",
"sanakirja",
"serde",
"serde_derive",
"serde_json",
"sha2",
"tempfile",
"thiserror",
"tokio",
"toml",
"twox-hash",
"zstd-seekable",
]
[[package]]
name = "linked-hash-map"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
name = "memmap"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
dependencies = [
"libc",
"winapi 0.3.9",
]
[[package]]
name = "memoffset"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
dependencies = [
"autocfg",
]
[[package]]
name = "path-slash"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cacbb3c4ff353b534a67fb8d7524d00229da4cb1dc8c79f4db96e375ab5b619"
[[package]]
name = "pbkdf2"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa"
dependencies = [
"crypto-mac 0.11.1",
]
[[package]]
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
dependencies = [
"getrandom 0.1.16",
"libc",
"rand_chacha 0.2.2",
"rand_core 0.5.1",
"rand_hc 0.2.0",
]
[[package]]
name = "rand"
"rand_chacha",
"rand_core",
"rand_hc",
"rand_chacha 0.3.1",
"rand_core 0.6.3",
"rand_hc 0.3.1",
]
[[package]]
name = "rand_chacha"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
dependencies = [
"ppv-lite86",
"rand_core 0.5.1",
"rand_core",
"rand_core 0.6.3",
]
[[package]]
name = "rand_core"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
dependencies = [
"getrandom 0.1.16",
"getrandom",
"getrandom 0.2.3",
]
[[package]]
name = "rand_hc"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
dependencies = [
"rand_core 0.5.1",
]
[[package]]
name = "sanakirja"
version = "1.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be030ebfecb0589e7c83817620ee833b98c3de089b1a9393b195dfc04b7fc9fe"
dependencies = [
"crc32fast",
"fs2",
"lazy_static",
"log",
"memmap",
"parking_lot",
"sanakirja-core",
"thiserror",
]
[[package]]
name = "sanakirja-core"
version = "1.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9828a6c9219969d6b19cfb0b53a8aed96e29983d0944a67db0a8c44db20ebe00"
dependencies = [
"crc32fast",
[[package]]
name = "zeroize"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "377db0846015f7ae377174787dd452e1c5f5a9050bc6f954911d01f116daa0cd"
dependencies = [
"zeroize_derive",
]
[[package]]
name = "zeroize_derive"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2c1e130bebaeab2f23886bf9acbaca14b092408c452543c857f66399cd6dab1"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]
[[package]]
name = "zstd-seekable"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e3b99cee88f0309ca765c6aa8c284a00394c35ef8ca012e2409485fc369bf2f"
dependencies = [
"cc",
"libc",
"pkg-config",
"thiserror",
"threadpool",
]