This commit is contained in:
parent
fcd3d6ffca
commit
ac07105bf7
6 changed files with 87 additions and 29 deletions
14
Cargo.lock
generated
14
Cargo.lock
generated
|
@ -207,7 +207,7 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "based"
|
name = "based"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://git.hydrar.de/jmarya/based#cd10c64a1f96703894de9e40a95fd81cc50d244a"
|
source = "git+https://git.hydrar.de/jmarya/based#04852f2fbcc301d0c2b4098f613b9450b4474363"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bcrypt",
|
"bcrypt",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
@ -1801,9 +1801,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.37"
|
version = "1.0.38"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
@ -2135,9 +2135,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.18"
|
version = "1.0.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
|
checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
|
@ -2616,9 +2616,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.91"
|
version = "2.0.92"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d53cbcb5a243bd33b7858b1d7f4aca2153490815872d86d955d6ea29f743c035"
|
checksum = "70ae51629bf965c5c098cc9e87908a3df5301051a9e087d6f9bef5c9771ed126"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
32
README.md
32
README.md
|
@ -7,3 +7,35 @@ Pacco is an application for managing and hosting pacman repositories.
|
||||||
- Web UI for packages
|
- Web UI for packages
|
||||||
- API for pushing new packages
|
- API for pushing new packages
|
||||||
- Smart mirroring
|
- Smart mirroring
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
### Package Repo
|
||||||
|
To use the packages pacco provides, add the following to `pacman.conf`:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
# /etc/pacman.conf
|
||||||
|
|
||||||
|
[repo]
|
||||||
|
Include = /etc/pacman.d/mirrorlist_pacco
|
||||||
|
```
|
||||||
|
|
||||||
|
Add `/etc/pacman.d/mirrorlist_pacco`:
|
||||||
|
|
||||||
|
```
|
||||||
|
# /etc/pacman.d/mirrorlist_pacco
|
||||||
|
|
||||||
|
Server = https://example.com/pkg/$repo/$arch
|
||||||
|
```
|
||||||
|
|
||||||
|
### Add a new package
|
||||||
|
To upload a package you created with `makepkg` to a repo use curl:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl -X POST \
|
||||||
|
-F "pkg=@./<pkg_name>-<version>-<rel>-<arch>.pkg.tar.zst" \
|
||||||
|
-F "sig=@./<pkg_name>-<version>-<rel>-<arch>.pkg.tar.zst.sig" \
|
||||||
|
-F "name=<pkg_name>" \
|
||||||
|
-F "arch=<arch>" \
|
||||||
|
-F "version=<version>" \
|
||||||
|
"https://<domain>/pkg/<repo>/upload"
|
||||||
|
```
|
||||||
|
|
|
@ -8,3 +8,16 @@ services:
|
||||||
environment:
|
environment:
|
||||||
- "RUST_LOG=info"
|
- "RUST_LOG=info"
|
||||||
- "ROCKET_ADDRESS=0.0.0.0"
|
- "ROCKET_ADDRESS=0.0.0.0"
|
||||||
|
- "DATABASE_URL=postgres://user:pass@postgres/watchdogs"
|
||||||
|
|
||||||
|
postgres:
|
||||||
|
image: timescale/timescaledb:latest-pg16
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
|
volumes:
|
||||||
|
- ./db:/var/lib/postgresql/data/
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=user
|
||||||
|
- POSTGRES_PASSWORD=pass
|
||||||
|
- POSTGRES_DB=pacco
|
10
src/main.rs
10
src/main.rs
|
@ -8,6 +8,7 @@
|
||||||
use based::page::{Shell, render_page};
|
use based::page::{Shell, render_page};
|
||||||
use based::request::{RequestContext, StringResponse};
|
use based::request::{RequestContext, StringResponse};
|
||||||
use maud::html;
|
use maud::html;
|
||||||
|
use pkg::Repository;
|
||||||
use rocket::get;
|
use rocket::get;
|
||||||
use rocket::routes;
|
use rocket::routes;
|
||||||
|
|
||||||
|
@ -16,13 +17,18 @@ pub mod routes;
|
||||||
|
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
pub async fn index_page(ctx: RequestContext) -> StringResponse {
|
pub async fn index_page(ctx: RequestContext) -> StringResponse {
|
||||||
|
let repos: Vec<String> = Repository::list();
|
||||||
|
|
||||||
let content = html!(
|
let content = html!(
|
||||||
h1 { "Hello World!" };
|
h1 { "Repositories" };
|
||||||
|
@for repo in repos {
|
||||||
|
p { (repo) };
|
||||||
|
};
|
||||||
);
|
);
|
||||||
|
|
||||||
render_page(
|
render_page(
|
||||||
content,
|
content,
|
||||||
"Hello World",
|
"Repositories",
|
||||||
ctx,
|
ctx,
|
||||||
&Shell::new(html! {}, html! {}, Some(String::new())),
|
&Shell::new(html! {}, html! {}, Some(String::new())),
|
||||||
)
|
)
|
||||||
|
|
20
src/pkg.rs
20
src/pkg.rs
|
@ -4,6 +4,26 @@ pub struct Repository {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Repository {
|
||||||
|
pub fn list() -> Vec<String> {
|
||||||
|
let mut repos = vec![];
|
||||||
|
|
||||||
|
for entry in std::fs::read_dir("./data").unwrap() {
|
||||||
|
let path = entry.unwrap().path();
|
||||||
|
let file_name = path.file_name().unwrap().to_str().unwrap().to_string();
|
||||||
|
repos.push(file_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
repos
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create(name: &str) -> Repository {
|
||||||
|
let path = PathBuf::from("./data").join(name);
|
||||||
|
std::fs::create_dir_all(path).unwrap();
|
||||||
|
Repository::new(name).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Repository {
|
impl Repository {
|
||||||
pub fn new(name: &str) -> Option<Self> {
|
pub fn new(name: &str) -> Option<Self> {
|
||||||
if PathBuf::from("./data").join(name).exists() {
|
if PathBuf::from("./data").join(name).exists() {
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
use based::page::{Shell, render_page};
|
use based::request::api::{FallibleApiResponse, api_error};
|
||||||
use based::request::api::FallibleApiResponse;
|
use based::request::{RawResponse, RequestContext, respond_with};
|
||||||
use based::request::{RawResponse, RequestContext, StringResponse, respond_with};
|
|
||||||
use maud::html;
|
|
||||||
use rocket::http::{ContentType, Status};
|
use rocket::http::{ContentType, Status};
|
||||||
use rocket::tokio::io::AsyncReadExt;
|
use rocket::tokio::io::AsyncReadExt;
|
||||||
use rocket::{FromForm, get, post};
|
use rocket::{FromForm, get, post};
|
||||||
|
@ -39,8 +37,12 @@ pub async fn tmp_file_to_vec<'r>(tmp: &TempFile<'r>) -> Vec<u8> {
|
||||||
pub async fn upload_pkg(
|
pub async fn upload_pkg(
|
||||||
repo: &str,
|
repo: &str,
|
||||||
upload: Form<PkgUpload<'_>>,
|
upload: Form<PkgUpload<'_>>,
|
||||||
user: based::auth::User,
|
user: based::auth::APIUser,
|
||||||
) -> FallibleApiResponse {
|
) -> FallibleApiResponse {
|
||||||
|
if !user.0.is_admin() {
|
||||||
|
return Err(api_error("Forbidden"));
|
||||||
|
}
|
||||||
|
|
||||||
let pkg = Package::new(repo, &upload.arch, &upload.name, &upload.version);
|
let pkg = Package::new(repo, &upload.arch, &upload.name, &upload.version);
|
||||||
|
|
||||||
pkg.save(
|
pkg.save(
|
||||||
|
@ -101,18 +103,3 @@ pub async fn pkg_route(repo: &str, arch: &str, pkg_name: &str, ctx: RequestConte
|
||||||
"Not found".as_bytes().to_vec(),
|
"Not found".as_bytes().to_vec(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/")]
|
|
||||||
pub async fn index_page(ctx: RequestContext) -> StringResponse {
|
|
||||||
let content = html!(
|
|
||||||
h1 { "Hello World!" };
|
|
||||||
);
|
|
||||||
|
|
||||||
render_page(
|
|
||||||
content,
|
|
||||||
"Hello World",
|
|
||||||
ctx,
|
|
||||||
&Shell::new(html! {}, html! {}, Some(String::new())),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue