Compare commits
No commits in common. "v0.1.0-alpha4" and "main" have entirely different histories.
v0.1.0-alp
...
main
30 changed files with 424 additions and 100 deletions
25
.idea/jsonSchemas.xml
Normal file
25
.idea/jsonSchemas.xml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="JsonSchemaMappingsProjectConfiguration">
|
||||||
|
<state>
|
||||||
|
<map>
|
||||||
|
<entry key="Woodpecker pipeline config">
|
||||||
|
<value>
|
||||||
|
<SchemaInfo>
|
||||||
|
<option name="name" value="Woodpecker pipeline config" />
|
||||||
|
<option name="relativePathToSchema" value="https://raw.githubusercontent.com/woodpecker-ci/woodpecker/master/pipeline/schema/schema.json" />
|
||||||
|
<option name="applicationDefined" value="true" />
|
||||||
|
<option name="patterns">
|
||||||
|
<list>
|
||||||
|
<Item>
|
||||||
|
<option name="path" value=".woodpecker.yml" />
|
||||||
|
</Item>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</SchemaInfo>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</state>
|
||||||
|
</component>
|
||||||
|
</project>
|
39
README.md
39
README.md
|
@ -5,6 +5,43 @@
|
||||||
> "A package manager and builder but like rust."
|
> "A package manager and builder but like rust."
|
||||||
> -- Gandhi (2050)
|
> -- Gandhi (2050)
|
||||||
|
|
||||||
> ***not even close to done*** :)
|
> ***Almost to a point you can use it*** :)
|
||||||
|
|
||||||
Packager is a simple yet powerful package manager
|
Packager is a simple yet powerful package manager
|
||||||
|
|
||||||
|
## Install a package
|
||||||
|
pkgr supports fetching packages with a:
|
||||||
|
- path
|
||||||
|
- url (http/https)
|
||||||
|
- package locator
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# example with path
|
||||||
|
pkgr install ./foxy/snek.pkg
|
||||||
|
# example with url
|
||||||
|
pkgr install https://example.com/doggo.pkg
|
||||||
|
# example with package locator
|
||||||
|
pkgr install foo:stable,bar
|
||||||
|
```
|
||||||
|
|
||||||
|
## Composing a package
|
||||||
|
Right now, pkgr does not have a compose/package command. (it's in the works dw!)
|
||||||
|
You can create a package with `pkg.py`!
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# Usage: pkg.py <package_toml_path> <output_path> [<directories_to_include> ...]
|
||||||
|
# example:
|
||||||
|
python pkg.py manifest.toml example.pkg root/ source/ scripts/
|
||||||
|
# this will create a package with an archive that look like this:
|
||||||
|
# [header+manifest]
|
||||||
|
# ...
|
||||||
|
# [archive:
|
||||||
|
# root/
|
||||||
|
# source/
|
||||||
|
# scripts/
|
||||||
|
# ]
|
||||||
|
```
|
||||||
|
|
||||||
|
It's not perfect, but it'll get the job done :)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,12 +30,12 @@ pub fn mani_from_str(s: &str) -> Manifest<Option<PKGR>> {
|
||||||
fs: mani.fs,
|
fs: mani.fs,
|
||||||
bin: mani.bin,
|
bin: mani.bin,
|
||||||
build: mani.build,
|
build: mani.build,
|
||||||
pkgr: bmani.pkgr,
|
ext: bmani.pkgr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_bootstrap(mani: Manifest<Option<PKGR>>) -> bool {
|
pub fn run_bootstrap(mani: Manifest<Option<PKGR>>) -> bool {
|
||||||
if let Some(pkgr) = mani.pkgr {
|
if let Some(pkgr) = mani.ext {
|
||||||
if let Some(bootstrap) = pkgr.bootstrap {
|
if let Some(bootstrap) = pkgr.bootstrap {
|
||||||
fn run_command<S: Into<String>>(s: S) -> i32 {
|
fn run_command<S: Into<String>>(s: S) -> i32 {
|
||||||
std::process::Command::new("sh")
|
std::process::Command::new("sh")
|
||||||
|
|
2
build
2
build
|
@ -3,7 +3,7 @@
|
||||||
build_pkgr() {
|
build_pkgr() {
|
||||||
cd pkgr
|
cd pkgr
|
||||||
mkdir -p dist/root/{usr/bin,etc/pkgr}
|
mkdir -p dist/root/{usr/bin,etc/pkgr}
|
||||||
echo -e "You can't use pkgr to update pkgr because the file will be in use while updating.\nuse bootpkg" > dist/root/etc/pkgr/YOU-CAN-NOT-USE-PKGR-TO-UPDATE-PKGR.txt
|
echo -e "You can't use pkgr to update pkgr because the file will be in use while updating.\nuse bootpkg" > dist/root/etc/pkgr.d/YOU-CAN-NOT-USE-PKGR-TO-UPDATE-PKGR.txt
|
||||||
|
|
||||||
# for bin
|
# for bin
|
||||||
cargo build -r
|
cargo build -r
|
||||||
|
|
|
@ -9,7 +9,9 @@ pkgr is the main tool for the packager.
|
||||||
Because this tool is so feature rich, it has its own [README](./pkgr/README.md).
|
Because this tool is so feature rich, it has its own [README](./pkgr/README.md).
|
||||||
|
|
||||||
## bootpkg
|
## bootpkg
|
||||||
bootpkg is a tool primariliy used to bootstrap the packager.
|
`bootpkg` is a simple pkgr variant.
|
||||||
|
It doesn't contain anything fancy and is only used to install and update pkgr.
|
||||||
|
Using it for anything other than pkgr is not recommended.
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ PKGFiles are an all-in-one solution to install a package.
|
||||||
|
|
||||||
## Overhead
|
## Overhead
|
||||||
|
|
||||||
Because pkgfiles include everything, many times you can download more than what is needed.
|
Because pkgfiles include everything, many times you're downloading more than what is needed.
|
||||||
This may seem stupid but pkgfiles are *not* meant to stay on your system.
|
This may seem stupid but pkgfiles are *not* meant to stay on your system.
|
||||||
|
|
||||||
## Format
|
## Format
|
||||||
|
|
|
@ -2,9 +2,9 @@ use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct PKGR {}
|
pub struct Extension {}
|
||||||
|
|
||||||
impl Display for PKGR {
|
impl Display for Extension {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "")
|
write!(f, "")
|
||||||
}
|
}
|
|
@ -6,17 +6,17 @@ pub mod bin;
|
||||||
pub mod build;
|
pub mod build;
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
pub mod package;
|
pub mod package;
|
||||||
pub mod pkgr;
|
pub mod ext;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct Manifest<P: Clone = Option<pkgr::PKGR>> {
|
pub struct Manifest<E: Clone = Option<ext::Extension>> {
|
||||||
pub package: package::Package,
|
pub package: package::Package,
|
||||||
pub dependencies: HashMap<String, String>,
|
pub dependencies: HashMap<String, String>,
|
||||||
pub fs: fs::FS,
|
pub fs: fs::FS,
|
||||||
pub bin: Option<bin::Bin>,
|
pub bin: Option<bin::Bin>,
|
||||||
pub build: Option<build::Build>,
|
pub build: Option<build::Build>,
|
||||||
pub pkgr: P,
|
pub ext: E,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: Clone> Manifest<P> {
|
impl<P: Clone> Manifest<P> {
|
||||||
|
@ -50,7 +50,7 @@ impl Default for Manifest {
|
||||||
fs: fs::FS::default(),
|
fs: fs::FS::default(),
|
||||||
bin: None,
|
bin: None,
|
||||||
build: None,
|
build: None,
|
||||||
pkgr: None,
|
ext: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,16 +84,16 @@ install_script = "scripts/install" # relative to pkg
|
||||||
[build.dependencies]
|
[build.dependencies]
|
||||||
base = "latest,stable" # selected by default
|
base = "latest,stable" # selected by default
|
||||||
|
|
||||||
## pkgr.*
|
## ext.*
|
||||||
# packager is the official client but you may use other clients supporting the "pkgr v1 spec".
|
# packager is the official client but you may use other clients supporting the "pkgr v1 spec".
|
||||||
# other clients may offer extra functionality this must be put under "pkgr.*"
|
# other clients may offer extra functionality this must be put under "ext.*"
|
||||||
[pkgr]
|
[ext]
|
||||||
|
|
||||||
## pkgr.bootstrap
|
## ext.bootstrap
|
||||||
# This section is used for bootpkg. An edition of packager that bootstraps the full version.
|
# This section is used for bootpkg. An edition of packager that bootstraps the full version.
|
||||||
# This exists so that packager is easy to install on anything!
|
# This exists so that packager is easy to install on anything!
|
||||||
# and only 1 release channel for pkgr
|
# and only 1 release channel for pkgr
|
||||||
[pkgr.bootstrap]
|
[ext.bootstrap]
|
||||||
## any non-zero = installed
|
## any non-zero = installed
|
||||||
check_installed_commands = [
|
check_installed_commands = [
|
||||||
"sh scripts/check_installed"
|
"sh scripts/check_installed"
|
||||||
|
|
|
@ -25,3 +25,5 @@ reqwest = { version = "0.11.18", features = ["blocking"] }
|
||||||
tar = "0.4.39"
|
tar = "0.4.39"
|
||||||
humantime = "2.1.0"
|
humantime = "2.1.0"
|
||||||
expanduser = "1.2.2"
|
expanduser = "1.2.2"
|
||||||
|
url = { version = "2.4.0", features = ["serde"] }
|
||||||
|
dns-lookup = "2.0.3"
|
||||||
|
|
|
@ -1,66 +1,32 @@
|
||||||
[package]
|
[package]
|
||||||
name = "packager" #*
|
name = "packager"
|
||||||
description = "A package installation tool" #*
|
description = "A package installation tool"
|
||||||
version = 1 # this can automatically be incremented when publishing by running `pkgr publish -i ...`
|
version = 1
|
||||||
tags = [ "prod", "pkgr-spec-1" ]
|
tags = [ "prod", "pkgr-spec-1" ]
|
||||||
type = "application"
|
type = "application"
|
||||||
|
arch = "x86_64"
|
||||||
|
|
||||||
arch = "x86_64" # this is automatically filled by `pkgr publish ...`
|
|
||||||
|
|
||||||
## dependencies
|
|
||||||
# you may use the following syntax
|
|
||||||
# "<version/tag>" or "<version/tag>,<version/tag>,..."
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
||||||
## bin
|
[bin]
|
||||||
# Used for systems that don't want to build pkgs.
|
root = "/root"
|
||||||
[bin] # binary files root
|
|
||||||
|
|
||||||
## bin.root
|
|
||||||
# ** RELATIVE TO PACKAGE ROOT **
|
|
||||||
# bin.root specifies the root of the installed tree.
|
|
||||||
# anything in here will be overlayed on top of the system.
|
|
||||||
root = "/root" #*
|
|
||||||
|
|
||||||
## bin.checksums
|
|
||||||
# ** KEYS are relative to BIN.ROOT **
|
|
||||||
# ** VALUES are relative to PKG ROOT **
|
|
||||||
# checksums is used to perform checksums before install
|
|
||||||
# values may be paths or a uri. You may include variables.
|
|
||||||
# supported variables:
|
|
||||||
# - @name
|
|
||||||
# - @version
|
|
||||||
# - @display_version
|
|
||||||
[bin.checksums]
|
[bin.checksums]
|
||||||
"/usr/bin/pkgr" = "https://ixvd.net/checksums/packager/@version"
|
"/usr/bin/pkgr" = "https://ixvd.net/checksums/packager/@version"
|
||||||
|
|
||||||
## build
|
|
||||||
# Scripts will be copied to a custom root.
|
|
||||||
# After the pacakge is built, the install script is ran.
|
|
||||||
# After the install script the build directory will be deleted and an CTREE (changed tree) will be generated.
|
|
||||||
# Then the CTREE will be used to copy the files over.
|
|
||||||
[build]
|
[build]
|
||||||
build_script = "scripts/build" # relative to pkg
|
build_script = "scripts/build"
|
||||||
install_script = "scripts/install" # relative to pkg
|
install_script = "scripts/install"
|
||||||
|
|
||||||
[build.dependencies]
|
[build.dependencies]
|
||||||
|
|
||||||
## pkgr.*
|
[ext]
|
||||||
# packager is the official client but you may use other clients supporting the "pkgr v1 spec".
|
|
||||||
# other clients may offer extra functionality this must be put under "pkgr.*"
|
|
||||||
[pkgr]
|
|
||||||
|
|
||||||
## pkgr.bootstrap
|
[ext.bootstrap]
|
||||||
# This section is used for bootpkg. An edition of packager that bootstraps the full version.
|
|
||||||
# This exists so that packager is easy to install on anything!
|
|
||||||
# and only 1 release channel for pkgr
|
|
||||||
[pkgr.bootstrap]
|
|
||||||
## any non-zero = installed
|
|
||||||
check_installed_commands = [
|
check_installed_commands = [
|
||||||
"file /usr/bin/pkgr"
|
"file /usr/bin/pkgr"
|
||||||
]
|
]
|
||||||
|
|
||||||
# any non-zero = fail
|
|
||||||
commands = [
|
commands = [
|
||||||
"cp root/usr/bin/pkgr /usr/bin/pkgr"
|
"cp root/usr/bin/pkgr /usr/bin/pkgr"
|
||||||
]
|
]
|
||||||
|
|
4
pkgr/skel/etc/pkgr.d/repos.toml
Normal file
4
pkgr/skel/etc/pkgr.d/repos.toml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
[repo.main]
|
||||||
|
name = "Main"
|
||||||
|
url = "tcp://pkgs.ixvd.net:1050"
|
||||||
|
|
7
pkgr/skel/etc/pkgr.toml
Normal file
7
pkgr/skel/etc/pkgr.toml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
build_by_default = false
|
||||||
|
tmp_dir = "/tmp/pkgr"
|
||||||
|
|
||||||
|
[storage]
|
||||||
|
repo_file = "/etc/pkgr.d/repos.toml"
|
||||||
|
data_dir = "/var/lib/pkgr/packages"
|
||||||
|
index_dir = "/var/lib/pkgr/indexes"
|
20
pkgr/skel/var/lib/pkgr/indexes/repo.toml
Normal file
20
pkgr/skel/var/lib/pkgr/indexes/repo.toml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
[index.main]
|
||||||
|
last_update = "1610219288"
|
||||||
|
[index.main.packager]
|
||||||
|
versions = [1, 2, 3]
|
||||||
|
tags = ["tag"]
|
||||||
|
|
||||||
|
## rust
|
||||||
|
# IndexedPackage
|
||||||
|
# - name -> packager
|
||||||
|
# - origin_repo -> main
|
||||||
|
# - versions -> [1,2,3]
|
||||||
|
# - tags -> ["tag"]
|
||||||
|
# - get_package() -> Package
|
||||||
|
|
||||||
|
## rust
|
||||||
|
# Repo
|
||||||
|
# - name -> main
|
||||||
|
# - last_update -> 1610219288
|
||||||
|
# - update_repo() -> io::Result<()>
|
||||||
|
# - searchIndex(p: PackageIdentifier) -> IndexedPackage
|
0
pkgr/src/api/client.rs
Normal file
0
pkgr/src/api/client.rs
Normal file
|
@ -1,27 +1,63 @@
|
||||||
use reqwest::blocking::Response;
|
use std::collections::HashMap;
|
||||||
|
use serde;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub struct APITransaction<R = Response> {
|
pub mod client;
|
||||||
/// Query made to API.
|
|
||||||
query: String, //TODO: enum
|
|
||||||
/// Response struct from abstracted library
|
|
||||||
_response: Option<R>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<R> APITransaction<R> {
|
#[derive(Serialize, Deserialize)]
|
||||||
pub fn new(_response: Option<R>) -> Self {
|
pub enum Query {
|
||||||
APITransaction {
|
#[serde(rename = "pull")]
|
||||||
query: String::default(),
|
Pull {
|
||||||
_response
|
name: String,
|
||||||
}
|
version: Option<u128>,
|
||||||
|
tags: Vec<String>
|
||||||
|
},
|
||||||
|
#[serde(rename = "push")]
|
||||||
|
Push {
|
||||||
|
// todo: review me pls
|
||||||
|
_data: Vec<u8>
|
||||||
|
},
|
||||||
|
#[serde(rename = "index")]
|
||||||
|
Index {
|
||||||
|
request_update: bool,
|
||||||
|
fetch: bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct API {
|
#[derive(Serialize, Deserialize)]
|
||||||
base_url: String,
|
pub struct Request {
|
||||||
|
version: u32,
|
||||||
|
id: String,
|
||||||
token: Option<String>,
|
token: Option<String>,
|
||||||
history: Vec<APITransaction>
|
query: HashMap<String, Query>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl API {
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct DataErrorDetails {
|
||||||
|
actor: String,
|
||||||
|
detailed_cause: String,
|
||||||
|
recovery_options: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct DataError {
|
||||||
|
name: String,
|
||||||
|
cause: Option<String>,
|
||||||
|
details: Option<DataErrorDetails>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub enum Data {
|
||||||
|
Pull {
|
||||||
|
_data: Option<Vec<u8>>,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct Response {
|
||||||
|
version: u32,
|
||||||
|
id: String,
|
||||||
|
reply_to: String,
|
||||||
|
errors: HashMap<String, DataError>,
|
||||||
|
data: HashMap<String, Data>
|
||||||
}
|
}
|
|
@ -1,16 +1,17 @@
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
|
use colored::Colorize;
|
||||||
use log::{debug, error, info, trace, warn};
|
use log::{debug, error, info, trace, warn};
|
||||||
|
|
||||||
use colored::Colorize;
|
|
||||||
use manifest::package::PackageType;
|
use manifest::package::PackageType;
|
||||||
use crate::CONFIG;
|
|
||||||
use crate::package::identifier::PackageIdentifier;
|
use crate::package::identifier::PackageIdentifier;
|
||||||
use crate::package::Package;
|
use crate::package::Package;
|
||||||
use crate::package::queue::PackageQueue;
|
use crate::package::queue::PackageQueue;
|
||||||
use crate::process::Process;
|
use crate::process::Process;
|
||||||
use crate::types::fetch::TryFetch;
|
use crate::types::fetch::TryFetch;
|
||||||
|
use crate::util::prompts::prompt_bool;
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[clap(name = "pkgr", version)]
|
#[clap(name = "pkgr", version)]
|
||||||
|
@ -25,6 +26,8 @@ pub enum Command {
|
||||||
Install {
|
Install {
|
||||||
#[arg(short, long, default_value_t = false)]
|
#[arg(short, long, default_value_t = false)]
|
||||||
build: bool,
|
build: bool,
|
||||||
|
#[arg(short, long, default_value_t = false)]
|
||||||
|
ask: bool,
|
||||||
package_identifier: PackageIdentifier,
|
package_identifier: PackageIdentifier,
|
||||||
},
|
},
|
||||||
/// Remove a package from the system
|
/// Remove a package from the system
|
||||||
|
@ -57,6 +60,7 @@ impl Command {
|
||||||
match self {
|
match self {
|
||||||
Command::Install {
|
Command::Install {
|
||||||
build,
|
build,
|
||||||
|
ask,
|
||||||
package_identifier,
|
package_identifier,
|
||||||
} => {
|
} => {
|
||||||
warn!("Installer does not run in isolation.");
|
warn!("Installer does not run in isolation.");
|
||||||
|
@ -80,6 +84,15 @@ impl Command {
|
||||||
let mut queue = PackageQueue::new();
|
let mut queue = PackageQueue::new();
|
||||||
queue.add_package(pkg, *build);
|
queue.add_package(pkg, *build);
|
||||||
trace!("Installing queue...");
|
trace!("Installing queue...");
|
||||||
|
{
|
||||||
|
if *ask {
|
||||||
|
info!("Install following packages?");
|
||||||
|
info!(target: "item", "{}", queue);
|
||||||
|
if !prompt_bool("Continue?", false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
queue.install(*build);
|
queue.install(*build);
|
||||||
|
|
||||||
let end = std::time::Instant::now();
|
let end = std::time::Instant::now();
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use storage::Storage;
|
||||||
|
|
||||||
|
mod storage;
|
||||||
|
pub mod repos;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
@ -6,13 +10,16 @@ pub struct Config {
|
||||||
pub build_by_default: bool,
|
pub build_by_default: bool,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub tmp_dir: Option<String>,
|
pub tmp_dir: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub storage: Storage
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
fn default() -> Config {
|
fn default() -> Config {
|
||||||
Config {
|
Config {
|
||||||
build_by_default: false,
|
build_by_default: false,
|
||||||
tmp_dir: Some(String::from("/tmp/pkgr"))
|
tmp_dir: Some(String::from("/tmp/pkgr")),
|
||||||
|
storage: Storage::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
37
pkgr/src/config/repos.rs
Normal file
37
pkgr/src/config/repos.rs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Repo {
|
||||||
|
#[serde(default)]
|
||||||
|
pub name: String,
|
||||||
|
pub uri: Url
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Repo {
|
||||||
|
fn default() -> Self {
|
||||||
|
Repo {
|
||||||
|
name: String::from("Repo"),
|
||||||
|
uri: Url::parse("tcp://0.0.0.0:0000").unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
pub struct RepoFile {
|
||||||
|
pub repos: HashMap<String, Repo>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RepoFile {
|
||||||
|
pub fn from_path(path: &str) -> Result<RepoFile, String> {
|
||||||
|
match std::fs::read_to_string(path) {
|
||||||
|
Ok(s) => match toml::from_str(&s) {
|
||||||
|
Ok(c) => Ok(c),
|
||||||
|
Err(e) => Err(format!("failed to parse config: {}", e)),
|
||||||
|
},
|
||||||
|
Err(e) => Err(format!("failed to read config: {}", e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
pkgr/src/config/storage.rs
Normal file
24
pkgr/src/config/storage.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Storage {
|
||||||
|
/// Where the repositories are defined.
|
||||||
|
#[serde(default)]
|
||||||
|
pub repo_file: String,
|
||||||
|
/// Where to store pkgs data
|
||||||
|
#[serde(default)]
|
||||||
|
pub data_dir: String,
|
||||||
|
/// Where to store repo indexes
|
||||||
|
#[serde(default)]
|
||||||
|
pub index_dir: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Storage {
|
||||||
|
fn default() -> Self {
|
||||||
|
Storage {
|
||||||
|
repo_file: String::from("/etc/pkgr.d/repos.toml"),
|
||||||
|
data_dir: String::from("/var/lib/pkgr/packages"),
|
||||||
|
index_dir: String::from("/var/lib/pkgr/indexes"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,6 +9,8 @@ mod commands;
|
||||||
mod logging;
|
mod logging;
|
||||||
/// Package and helpers.
|
/// Package and helpers.
|
||||||
mod package;
|
mod package;
|
||||||
|
/// Repo and helpers
|
||||||
|
mod repo;
|
||||||
/// Process wrapper with logging wrapper.
|
/// Process wrapper with logging wrapper.
|
||||||
mod process;
|
mod process;
|
||||||
/// tmpfs wrapper.
|
/// tmpfs wrapper.
|
||||||
|
|
|
@ -1,22 +1,17 @@
|
||||||
|
use std::io;
|
||||||
use std::fs::remove_dir_all;
|
use std::fs::remove_dir_all;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::exit;
|
|
||||||
use std::{io, thread};
|
|
||||||
use libc::SIGINT;
|
|
||||||
|
|
||||||
use log::{debug, error, info, trace};
|
use log::{debug, trace};
|
||||||
|
|
||||||
use errors::{BinError, BuildError, InstallError};
|
use errors::{BinError, BuildError, InstallError};
|
||||||
use manifest::Manifest;
|
use manifest::Manifest;
|
||||||
use pkgfile::PKGFile;
|
use pkgfile::PKGFile;
|
||||||
|
|
||||||
use crate::CONFIG;
|
use crate::CONFIG;
|
||||||
use crate::package::identifier::{PackageIdentifier, PackageLocator};
|
|
||||||
use crate::package::Package;
|
|
||||||
use crate::tmpfs::TempDir;
|
use crate::tmpfs::TempDir;
|
||||||
use crate::types::fetch::TryFetch;
|
use crate::types::fetch::TryFetch;
|
||||||
use crate::util::fs::{copy_recursively, visit_dirs};
|
use crate::util::fs::copy_recursively;
|
||||||
use crate::util::prompts::{is_noninteractive, prompt_bool};
|
|
||||||
|
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
|
|
||||||
|
@ -114,11 +109,17 @@ impl PackageInstaller {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.install_type {
|
let r = match self.install_type {
|
||||||
InstallType::Bin => self.bin()
|
InstallType::Bin => self.bin()
|
||||||
.map_err(|e| InstallError::BinError(e)),
|
.map_err(|e| InstallError::BinError(e)),
|
||||||
InstallType::Build => self.build()
|
InstallType::Build => self.build()
|
||||||
.map_err(|e| InstallError::BuildError(e)),
|
.map_err(|e| InstallError::BuildError(e)),
|
||||||
}
|
};
|
||||||
|
|
||||||
|
if let Err(e) = r {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
use crate::package::Package;
|
use crate::package::Package;
|
||||||
|
|
||||||
pub struct PackageQueue {
|
pub struct PackageQueue {
|
||||||
packages: Vec<Package>
|
packages: Vec<Package>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PackageQueue {
|
impl PackageQueue {
|
||||||
|
@ -17,7 +20,7 @@ impl PackageQueue {
|
||||||
for dependency in dependencies {
|
for dependency in dependencies {
|
||||||
trace!("Checking package: {}", &dependency.identifier);
|
trace!("Checking package: {}", &dependency.identifier);
|
||||||
if self.packages.contains(&dependency) {
|
if self.packages.contains(&dependency) {
|
||||||
continue
|
continue;
|
||||||
}
|
}
|
||||||
trace!("Adding package: {}", &dependency.identifier);
|
trace!("Adding package: {}", &dependency.identifier);
|
||||||
self.packages.push(dependency);
|
self.packages.push(dependency);
|
||||||
|
@ -31,7 +34,18 @@ impl PackageQueue {
|
||||||
self.packages
|
self.packages
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.for_each(|pkg| {
|
.for_each(|pkg| {
|
||||||
pkg.install(build);
|
pkg.install(build).expect("TODO: panic message");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for PackageQueue {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
for pkg in &self.packages {
|
||||||
|
if let Err(e) = write!(f, "{}", pkg.identifier) {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write!(f, "")
|
||||||
|
}
|
||||||
|
}
|
18
pkgr/src/repo/index/index_package.rs
Normal file
18
pkgr/src/repo/index/index_package.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
use std::io;
|
||||||
|
use std::path::Path;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use url::Url;
|
||||||
|
use pkgfile::PKGFile;
|
||||||
|
use crate::api::Query;
|
||||||
|
use crate::CONFIG;
|
||||||
|
use crate::package::Package;
|
||||||
|
use crate::repo::index::RepoIndex;
|
||||||
|
|
||||||
|
/// This struct solely exists for indexing and has no real functionality.
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct IndexPackage {
|
||||||
|
name: String,
|
||||||
|
versions: Vec<u32>,
|
||||||
|
tags: Vec<String>,
|
||||||
|
uri: Url
|
||||||
|
}
|
58
pkgr/src/repo/index/mod.rs
Normal file
58
pkgr/src/repo/index/mod.rs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::io;
|
||||||
|
use std::path::Path;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use crate::api::Request;
|
||||||
|
use crate::CONFIG;
|
||||||
|
use crate::repo::index::index_package::IndexPackage;
|
||||||
|
use crate::repo::Repo;
|
||||||
|
use crate::types::fetch::{Fetch, TryFetch};
|
||||||
|
use crate::util::create_uuid;
|
||||||
|
|
||||||
|
pub mod index_package;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct RepoIndex {
|
||||||
|
origin_repo: String,
|
||||||
|
packages: HashMap<String, IndexPackage>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RepoIndex {
|
||||||
|
// /// Fetch existing index or create a new one.
|
||||||
|
// pub fn from_repo(repo: Repo) -> Self {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /// Create new index.
|
||||||
|
// pub fn create_with_repo(repo: Repo) -> Self {
|
||||||
|
// }
|
||||||
|
|
||||||
|
/// Get repo
|
||||||
|
pub fn get_repo(&self) -> io::Result<Repo> {
|
||||||
|
Ok(Repo::from_name(&self.origin_repo)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_path(path: &str) -> Result<RepoIndex, String> {
|
||||||
|
match std::fs::read_to_string(path) {
|
||||||
|
Ok(s) => match toml::from_str(&s) {
|
||||||
|
Ok(c) => Ok(c),
|
||||||
|
Err(e) => Err(format!("failed to parse config: {}", e)),
|
||||||
|
},
|
||||||
|
Err(e) => Err(format!("failed to read config: {}", e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFetch<Repo> for RepoIndex {
|
||||||
|
type Error = ();
|
||||||
|
/// Fetch
|
||||||
|
fn try_fetch(query: Repo) -> Result<Self, Self::Error> {
|
||||||
|
let path = CONFIG.with(|c| c.storage.index_dir.clone()) + query.uri.as_str() + ".toml";
|
||||||
|
if Path::new(path.as_str()).exists() {
|
||||||
|
RepoIndex::from_path(path.as_str())
|
||||||
|
.map_err(|_| ())
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
42
pkgr/src/repo/mod.rs
Normal file
42
pkgr/src/repo/mod.rs
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
use std::io;
|
||||||
|
use std::io::{Error, ErrorKind};
|
||||||
|
use std::path::Path;
|
||||||
|
use url::Url;
|
||||||
|
use crate::CONFIG;
|
||||||
|
use crate::config::repos::RepoFile;
|
||||||
|
|
||||||
|
/// Indexed repos
|
||||||
|
pub mod index;
|
||||||
|
|
||||||
|
pub struct Repo {
|
||||||
|
name: String,
|
||||||
|
uri: Url,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Repo {
|
||||||
|
pub fn from_name(name: &String) -> io::Result<Repo> {
|
||||||
|
let r = RepoFile::from_path(CONFIG.with(|c| c.storage.repo_file.clone()).as_str())
|
||||||
|
.map_err(|e| Error::new(ErrorKind::Other, e))?;
|
||||||
|
let r = r
|
||||||
|
.repos
|
||||||
|
.get(name)
|
||||||
|
.ok_or(Error::new(ErrorKind::InvalidData, "Could not get repo"))?;
|
||||||
|
Ok(Repo {
|
||||||
|
name: r.name.clone(),
|
||||||
|
uri: r.uri.clone()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_name(&self) -> String {
|
||||||
|
self.name.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_uri(&self) -> Url {
|
||||||
|
self.uri.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch indexed repo
|
||||||
|
pub fn get_index(&self) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::CONFIG;
|
use crate::CONFIG;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::path::Path;
|
|
||||||
use std::fs::DirEntry;
|
|
||||||
use std::{fs, io};
|
use std::{fs, io};
|
||||||
|
use std::fs::DirEntry;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
pub fn visit_dirs(dir: &Path, cb: &dyn Fn(&DirEntry)) -> std::io::Result<()> {
|
pub fn visit_dirs(dir: &Path, cb: &dyn Fn(&DirEntry)) -> std::io::Result<()> {
|
||||||
|
|
|
@ -1,2 +1,9 @@
|
||||||
pub mod prompts;
|
pub mod prompts;
|
||||||
|
/// Helpers for fs
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
|
|
||||||
|
/// Create a UUID
|
||||||
|
pub fn create_uuid() -> String {
|
||||||
|
// TODO
|
||||||
|
String::from("rand")
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
pub fn is_noninteractive() -> bool {
|
pub fn is_noninteractive() -> bool {
|
||||||
|
|
Loading…
Reference in a new issue