update
This commit is contained in:
parent
221b2a82e7
commit
2ed9cd25a3
7 changed files with 126 additions and 7 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1623,6 +1623,7 @@ dependencies = [
|
||||||
"env_logger 0.11.6",
|
"env_logger 0.11.6",
|
||||||
"maud",
|
"maud",
|
||||||
"rocket",
|
"rocket",
|
||||||
|
"serde_json",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -8,4 +8,5 @@ based = { git = "https://git.hydrar.de/jmarya/based", features = ["htmx"]}
|
||||||
env_logger = "0.11.6"
|
env_logger = "0.11.6"
|
||||||
maud = "0.26.0"
|
maud = "0.26.0"
|
||||||
rocket = "0.5.1"
|
rocket = "0.5.1"
|
||||||
|
serde_json = "1.0.134"
|
||||||
sqlx = "0.8.2"
|
sqlx = "0.8.2"
|
||||||
|
|
18
Dockerfile
Normal file
18
Dockerfile
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
FROM rust:buster as builder
|
||||||
|
|
||||||
|
RUN rustup default nightly
|
||||||
|
|
||||||
|
COPY . /app
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN cargo build --release
|
||||||
|
|
||||||
|
FROM archlinux
|
||||||
|
|
||||||
|
RUN pacman -Syu --noconfirm
|
||||||
|
|
||||||
|
COPY --from=builder /app/target/release/pacco /pacco
|
||||||
|
|
||||||
|
WORKDIR /
|
||||||
|
|
||||||
|
CMD ["/pacco"]
|
10
docker-compose.yml
Normal file
10
docker-compose.yml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
services:
|
||||||
|
pacco:
|
||||||
|
build: .
|
||||||
|
ports:
|
||||||
|
- "8080:8000"
|
||||||
|
volumes:
|
||||||
|
- ./data:/data
|
||||||
|
environment:
|
||||||
|
- "RUST_LOG=info"
|
||||||
|
- "ROCKET_ADDRESS=0.0.0.0"
|
|
@ -32,5 +32,9 @@ pub async fn index_page(ctx: RequestContext) -> StringResponse {
|
||||||
#[rocket::launch]
|
#[rocket::launch]
|
||||||
async fn launch() -> _ {
|
async fn launch() -> _ {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
rocket::build().mount("/", routes![index_page, routes::pkg_route])
|
rocket::build().mount("/", routes![
|
||||||
|
index_page,
|
||||||
|
routes::pkg_route,
|
||||||
|
routes::upload_pkg
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
|
47
src/pkg.rs
47
src/pkg.rs
|
@ -37,15 +37,15 @@ impl Repository {
|
||||||
|
|
||||||
pub fn get_pkg(&self, arch: &str, pkg_name: &str) -> Option<Package> {
|
pub fn get_pkg(&self, arch: &str, pkg_name: &str) -> Option<Package> {
|
||||||
let pkg = if pkg_name.ends_with(".pkg.tar.zst") {
|
let pkg = if pkg_name.ends_with(".pkg.tar.zst") {
|
||||||
Package::new(&self.name, arch, pkg_name.trim_end_matches(".pkg.tar.zst"))
|
Package::find(&self.name, arch, pkg_name.trim_end_matches(".pkg.tar.zst"))
|
||||||
} else if pkg_name.ends_with(".pkg.tar.zst.sig") {
|
} else if pkg_name.ends_with(".pkg.tar.zst.sig") {
|
||||||
Package::new(
|
Package::find(
|
||||||
&self.name,
|
&self.name,
|
||||||
arch,
|
arch,
|
||||||
pkg_name.trim_end_matches(".pkg.tar.zst.sig"),
|
pkg_name.trim_end_matches(".pkg.tar.zst.sig"),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Package::new(&self.name, arch, pkg_name)
|
Package::find(&self.name, arch, pkg_name)
|
||||||
};
|
};
|
||||||
|
|
||||||
if pkg.exists() {
|
if pkg.exists() {
|
||||||
|
@ -65,7 +65,16 @@ pub struct Package {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Package {
|
impl Package {
|
||||||
pub fn new(repo: &str, arch: &str, pkg_name: &str) -> Self {
|
pub fn new(repo: &str, arch: &str, pkg_name: &str, version: &str) -> Self {
|
||||||
|
Package {
|
||||||
|
repo: repo.to_string(),
|
||||||
|
arch: arch.to_string(),
|
||||||
|
name: pkg_name.to_string(),
|
||||||
|
version: Some(version.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find(repo: &str, arch: &str, pkg_name: &str) -> Self {
|
||||||
Package {
|
Package {
|
||||||
repo: repo.to_string(),
|
repo: repo.to_string(),
|
||||||
arch: arch.to_string(),
|
arch: arch.to_string(),
|
||||||
|
@ -74,6 +83,27 @@ impl Package {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn save(&self, pkg: Vec<u8>, sig: Option<Vec<u8>>) {
|
||||||
|
let pkg_file = self.base_path().join(&self.file_name());
|
||||||
|
let sig_file = self.base_path().join(format!("{}.sig", self.file_name()));
|
||||||
|
|
||||||
|
std::fs::write(&pkg_file, pkg).unwrap();
|
||||||
|
if let Some(sig) = sig {
|
||||||
|
std::fs::write(sig_file, sig).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let db_file = PathBuf::from("./data")
|
||||||
|
.join(&self.repo)
|
||||||
|
.join(&self.arch)
|
||||||
|
.join(format!("{}.db.tar.gz", self.repo));
|
||||||
|
|
||||||
|
run_command(vec![
|
||||||
|
"repo-add",
|
||||||
|
db_file.to_str().unwrap(),
|
||||||
|
pkg_file.to_str().unwrap(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
fn base_path(&self) -> PathBuf {
|
fn base_path(&self) -> PathBuf {
|
||||||
Path::new("./data").join(&self.repo).join(&self.arch)
|
Path::new("./data").join(&self.repo).join(&self.arch)
|
||||||
}
|
}
|
||||||
|
@ -152,3 +182,12 @@ impl Package {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn run_command(cmd: Vec<&str>) {
|
||||||
|
std::process::Command::new(cmd.first().unwrap())
|
||||||
|
.args(cmd.into_iter().skip(1).collect::<Vec<&str>>())
|
||||||
|
.spawn()
|
||||||
|
.unwrap()
|
||||||
|
.wait()
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
|
@ -1,14 +1,60 @@
|
||||||
use based::page::{Shell, render_page};
|
use based::page::{Shell, render_page};
|
||||||
|
use based::request::api::FallibleApiResponse;
|
||||||
use based::request::{RawResponse, RequestContext, StringResponse, respond_with};
|
use based::request::{RawResponse, RequestContext, StringResponse, respond_with};
|
||||||
use maud::html;
|
use maud::html;
|
||||||
use rocket::get;
|
|
||||||
use rocket::http::{ContentType, Status};
|
use rocket::http::{ContentType, Status};
|
||||||
|
use rocket::tokio::io::AsyncReadExt;
|
||||||
|
use rocket::{FromForm, get, post};
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
use crate::pkg::Repository;
|
use crate::pkg::{Package, Repository};
|
||||||
|
|
||||||
// /pkg/<repo>/<arch>/<pkg_name>
|
// /pkg/<repo>/<arch>/<pkg_name>
|
||||||
// /pkg/<repo>/<arch>/
|
// /pkg/<repo>/<arch>/
|
||||||
|
|
||||||
|
use rocket::form::Form;
|
||||||
|
use rocket::fs::TempFile;
|
||||||
|
|
||||||
|
#[derive(FromForm)]
|
||||||
|
pub struct PkgUpload<'r> {
|
||||||
|
name: String,
|
||||||
|
arch: String,
|
||||||
|
version: String,
|
||||||
|
pkg: TempFile<'r>,
|
||||||
|
sig: Option<TempFile<'r>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn tmp_file_to_vec<'r>(tmp: &TempFile<'r>) -> Vec<u8> {
|
||||||
|
let mut buf = Vec::with_capacity(tmp.len() as usize);
|
||||||
|
tmp.open()
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.read_to_end(&mut buf)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/pkg/<repo>/upload", data = "<upload>")]
|
||||||
|
pub async fn upload_pkg(
|
||||||
|
repo: &str,
|
||||||
|
upload: Form<PkgUpload<'_>>,
|
||||||
|
user: based::auth::User,
|
||||||
|
) -> FallibleApiResponse {
|
||||||
|
let pkg = Package::new(repo, &upload.arch, &upload.name, &upload.version);
|
||||||
|
|
||||||
|
pkg.save(
|
||||||
|
tmp_file_to_vec(&upload.pkg).await,
|
||||||
|
if let Some(sig) = &upload.sig {
|
||||||
|
Some(tmp_file_to_vec(sig).await)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(json!({"ok": 1}))
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/pkg/<repo>/<arch>/<pkg_name>")]
|
#[get("/pkg/<repo>/<arch>/<pkg_name>")]
|
||||||
pub async fn pkg_route(repo: &str, arch: &str, pkg_name: &str, ctx: RequestContext) -> RawResponse {
|
pub async fn pkg_route(repo: &str, arch: &str, pkg_name: &str, ctx: RequestContext) -> RawResponse {
|
||||||
if let Some(repo) = Repository::new(repo) {
|
if let Some(repo) = Repository::new(repo) {
|
||||||
|
|
Loading…
Reference in a new issue