S6TFYMRGWC4PSRLQ4OAKE2Z3JFEVGF3RZ5Z3MEN5XSA4INPQILOAC
HOAKL56VHB543H2MWVHLBI3R7NPW3LLVJ5X5LZ4DVXIYGIMFOXJQC
3E77DEMDLYBFJEGS2SLQKLQJQIXG2Y4TBDHAG3UKFLMKQ53CFOKQC
W3M3C7CCWHJWRWHULDWO45D3OFD4NL3V4OTJVIJCYRQG57Z2JTWQC
FS2NWBVN2SZB2FFPB3JSYT5URTVZEAZWMQ7QW4JUYPNJVDVAJTTQC
DSWQKJRHGLKXUDXKMRXCIQZKEGXYV3H5LPUMGSV4HQ4HYPTI47GQC
WSHUT37CPBBR5JHWAHR27BKOADUWPUHYBWBJPNI6TEQ47TDWTL7QC
W2ZEVC64ORZWKRPSQ3JFLIV54FYOTHIK2VW7H7HASO3Z6RC66LSQC
5UNA2DEALCSRBINR27KSA6OMD6GQAXHYZ35ICQ7NB62G2XP4FT5QC
TWIZ7QV4GCTQK743IKZSOJCIAEX62GZHFIYGOIFCFGIBOGPSY2WAC
KULVODXDL6KFQDLXYAAM3YPYNUMTRWV3LP6NRTYUHU7XBM2OKYZAC
use crate::database::Database;
use crate::models::projects;
use crate::repoman::RepoMan;
use rocket::{Route, State};
channel: String, // TODO check if this breaks non-UTF-8 channels
id: Option<String>,
) -> 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(channel, id),
Err(e) => {
println!("{}", e);
None
}
}
}
async fn changelist(
db: &State<Database>,
repoman: &State<RepoMan>,
org_path: String,
proj_path: String,
) -> Option<String> {
Err(e) => {
None
}
}
}
pub fn routes() -> Vec<Route> {
}
routes![remote_id, changelist, apply, identities, change]
// TODO pijul: When this endpoint returns a 4XX or 5XX status code, it thinks the push still
// succeeded.
#[post("/<org_path>/<proj_path>/.pijul?<apply>", data = "<patch>")]
async fn apply(
db: &State<Database>,
repoman: &State<RepoMan>,
org_path: String,
proj_path: String,
apply: String,
mut patch: TempFile<'_>,
) -> rocket::http::Status {
let p = if let Some(p) = projects::find(db, org_path, proj_path).await {
p
} else {
return rocket::http::Status::NotFound;
};
}
}
#[derive(FromForm)]
identities: Vec<String>,
}
use rocket::serde::{json::Json, Serialize};
id: Vec<String>,
rev: u64,
}
// TODO figure out what I'm supposed to send here?
}
let hash = crate::models::pijul::changestores::Changestore::hash_from_string(change)?;
let repo = p.repository(&repoman.storage_root).ok()?;
let path = repo.changestore().change_file(hash);
NamedFile::open(path).await.ok()
#[get("/<org_path>/<proj_path>/.pijul?<identities>", rank = 4)]
fn identities(org_path: String, proj_path: String, identities: Identities) -> Json<IdentitieRes> {
Json(IdentitieRes { id: vec![], rev: 0 })
}
#[get("/<org_path>/<proj_path>/.pijul?<change>", rank = 3)]
async fn change(
db: &State<Database>,
repoman: &State<RepoMan>,
org_path: String,
proj_path: String,
change: String,
) -> Option<NamedFile> {
let p = projects::find(db, org_path, proj_path).await?;
#[derive(Serialize, FromForm)]
struct IdentitieRes {
struct Identities {
if !repo.valid_change(hash) {
// TODO clean up
println!("Not valid as object");
return rocket::http::Status::InternalServerError;
}
if repo.apply_change_to_channel("main", hash).is_ok() {
return rocket::http::Status::Accepted;
};
rocket::http::Status::InternalServerError
if patch.persist_to(&patch_path).await.is_err() {
return rocket::http::Status::InternalServerError;
let repo = p.repository(&repoman.storage_root).unwrap();
let hash =
if let Some(h) = crate::models::pijul::changestores::Changestore::hash_from_string(apply) {
h
} else {
return rocket::http::Status::InternalServerError;
};
let patch_path = repo.changestore().change_file(hash);
repo.changestore().ensure_parent_dirs(hash);
use rocket::fs::TempFile;
println!("error getting changelist: {}", e);
match p
.repository(&repoman.storage_root)
.unwrap()
.changelist(channel, changelist)
{
Ok(out) => Some(out),
let p = projects::find(db, org_path, proj_path).await?;
channel: String, // TODO check if this breaks non-UTF-8 channels
changelist: u64,
#[get("/<org_path>/<proj_path>/.pijul?<changelist>&<channel>")]
/// Because of the overlap with other routes in parameters, this route has
/// rank 2. This way the changelist matches first, and if it doesn't, this route
/// will respond. Note that in the push flow this order is reversed.
#[get("/<org_path>/<proj_path>/.pijul?<channel>&<id>", rank = 2)]
async fn remote_id(
db: &State<Database>,
repoman: &State<RepoMan>,
org_path: String,
proj_path: String,
use rocket::fs::NamedFile;
use crate::database::Database;
use crate::models::projects;
use crate::repoman::RepoMan;
use rocket::fs::NamedFile;
use rocket::{Route, State};
/// Because of the overlap with other routes in parameters, this route has
/// rank 2. This way the changelist matches first, and if it doesn't, this route
/// will respond. Note that in the push flow this order is reversed.
#[get("/<org_path>/<proj_path>/.pijul?<channel>&<id>", rank = 2)]
async fn remote_id(
db: &State<Database>,
repoman: &State<RepoMan>,
org_path: String,
proj_path: String,
channel: String, // TODO check if this breaks non-UTF-8 channels
id: Option<String>,
) -> 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(channel, id),
Err(e) => {
println!("{}", e);
None
}
}
}
#[get("/<org_path>/<proj_path>/.pijul?<changelist>&<channel>")]
async fn changelist(
db: &State<Database>,
repoman: &State<RepoMan>,
org_path: String,
proj_path: String,
channel: String, // TODO check if this breaks non-UTF-8 channels
changelist: u64,
) -> Option<String> {
let p = projects::find(db, org_path, proj_path).await?;
match p
.repository(&repoman.storage_root)
.unwrap()
.changelist(channel, changelist)
{
Ok(out) => Some(out),
Err(e) => {
println!("error getting changelist: {}", e);
None
}
}
}
use rocket::fs::TempFile;
// TODO pijul: When this endpoint returns a 4XX or 5XX status code, it thinks the push still
// succeeded.
#[post("/<org_path>/<proj_path>/.pijul?<apply>", data = "<patch>")]
async fn apply(
db: &State<Database>,
repoman: &State<RepoMan>,
org_path: String,
proj_path: String,
apply: String,
mut patch: TempFile<'_>,
) -> rocket::http::Status {
let p = if let Some(p) = projects::find(db, org_path, proj_path).await {
p
} else {
return rocket::http::Status::NotFound;
};
let repo = p.repository(&repoman.storage_root).unwrap();
let hash =
if let Some(h) = crate::models::pijul::changestores::Changestore::hash_from_string(apply) {
h
} else {
return rocket::http::Status::InternalServerError;
};
let patch_path = repo.changestore().change_file(hash);
repo.changestore().ensure_parent_dirs(hash);
if patch.persist_to(&patch_path).await.is_err() {
return rocket::http::Status::InternalServerError;
}
if !repo.valid_change(hash) {
// TODO clean up
println!("Not valid as object");
return rocket::http::Status::InternalServerError;
}
if repo.apply_change_to_channel("main", hash).is_ok() {
return rocket::http::Status::Accepted;
};
rocket::http::Status::InternalServerError
}
#[derive(FromForm)]
struct Identities {
identities: Vec<String>,
}
use rocket::serde::{json::Json, Serialize};
#[derive(Serialize, FromForm)]
struct IdentitieRes {
id: Vec<String>,
rev: u64,
}
// TODO figure out what I'm supposed to send here?
#[get("/<org_path>/<proj_path>/.pijul?<identities>", rank = 4)]
fn identities(org_path: String, proj_path: String, identities: Identities) -> Json<IdentitieRes> {
Json(IdentitieRes { id: vec![], rev: 0 })
}
#[get("/<org_path>/<proj_path>/.pijul?<change>", rank = 3)]
async fn change(
db: &State<Database>,
repoman: &State<RepoMan>,
org_path: String,
proj_path: String,
change: String,
) -> Option<NamedFile> {
let p = projects::find(db, org_path, proj_path).await?;
let hash = crate::models::pijul::changestores::Changestore::hash_from_string(change)?;
let repo = p.repository(&repoman.storage_root).ok()?;
let path = repo.changestore().change_file(hash);
NamedFile::open(path).await.ok()
}
pub fn routes() -> Vec<Route> {
routes![remote_id, changelist, apply, identities, change]
}