Manifest {
@@ -50,7 +50,7 @@ impl Default for Manifest {
fs: fs::FS::default(),
bin: None,
build: None,
- pkgr: None,
+ ext: None,
}
}
}
diff --git a/package.example.toml b/package.example.toml
index c99108d..c20aabb 100644
--- a/package.example.toml
+++ b/package.example.toml
@@ -84,16 +84,16 @@ install_script = "scripts/install" # relative to pkg
[build.dependencies]
base = "latest,stable" # selected by default
-## 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]
+# other clients may offer extra functionality this must be put under "ext.*"
+[ext]
-## 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]
+[ext.bootstrap]
## any non-zero = installed
check_installed_commands = [
"sh scripts/check_installed"
diff --git a/pkgr/Cargo.toml b/pkgr/Cargo.toml
index d6b098f..e43b436 100644
--- a/pkgr/Cargo.toml
+++ b/pkgr/Cargo.toml
@@ -25,3 +25,5 @@ reqwest = { version = "0.11.18", features = ["blocking"] }
tar = "0.4.39"
humantime = "2.1.0"
expanduser = "1.2.2"
+url = { version = "2.4.0", features = ["serde"] }
+dns-lookup = "2.0.3"
diff --git a/pkgr/package.toml b/pkgr/package.toml
index 723ebed..fa95cd9 100644
--- a/pkgr/package.toml
+++ b/pkgr/package.toml
@@ -1,66 +1,32 @@
[package]
-name = "packager" #*
-description = "A package installation tool" #*
-version = 1 # this can automatically be incremented when publishing by running `pkgr publish -i ...`
+name = "packager"
+description = "A package installation tool"
+version = 1
tags = [ "prod", "pkgr-spec-1" ]
type = "application"
+arch = "x86_64"
-arch = "x86_64" # this is automatically filled by `pkgr publish ...`
-
-## dependencies
-# you may use the following syntax
-# "" or ",,..."
[dependencies]
-## bin
-# Used for systems that don't want to build pkgs.
-[bin] # binary files root
+[bin]
+root = "/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]
"/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_script = "scripts/build" # relative to pkg
-install_script = "scripts/install" # relative to pkg
+build_script = "scripts/build"
+install_script = "scripts/install"
[build.dependencies]
-## pkgr.*
-# 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]
+[ext]
-## pkgr.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
+[ext.bootstrap]
check_installed_commands = [
"file /usr/bin/pkgr"
]
-# any non-zero = fail
commands = [
"cp root/usr/bin/pkgr /usr/bin/pkgr"
]
diff --git a/pkgr/skel/etc/pkgr.d/repos.toml b/pkgr/skel/etc/pkgr.d/repos.toml
new file mode 100644
index 0000000..2723e7b
--- /dev/null
+++ b/pkgr/skel/etc/pkgr.d/repos.toml
@@ -0,0 +1,4 @@
+[repo.main]
+name = "Main"
+url = "tcp://pkgs.ixvd.net:1050"
+
diff --git a/pkgr/skel/etc/pkgr.toml b/pkgr/skel/etc/pkgr.toml
new file mode 100644
index 0000000..2ee5004
--- /dev/null
+++ b/pkgr/skel/etc/pkgr.toml
@@ -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"
\ No newline at end of file
diff --git a/pkgr/skel/var/lib/pkgr/indexes/repo.toml b/pkgr/skel/var/lib/pkgr/indexes/repo.toml
new file mode 100644
index 0000000..47fa234
--- /dev/null
+++ b/pkgr/skel/var/lib/pkgr/indexes/repo.toml
@@ -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
\ No newline at end of file
diff --git a/pkgr/src/api/client.rs b/pkgr/src/api/client.rs
new file mode 100644
index 0000000..e69de29
diff --git a/pkgr/src/api/mod.rs b/pkgr/src/api/mod.rs
index 3cec172..1ed3d70 100644
--- a/pkgr/src/api/mod.rs
+++ b/pkgr/src/api/mod.rs
@@ -1,27 +1,63 @@
-use reqwest::blocking::Response;
+use std::collections::HashMap;
+use serde;
+use serde::{Deserialize, Serialize};
-pub struct APITransaction {
- /// Query made to API.
- query: String, //TODO: enum
- /// Response struct from abstracted library
- _response: Option
-}
+pub mod client;
-impl APITransaction {
- pub fn new(_response: Option) -> Self {
- APITransaction {
- query: String::default(),
- _response
- }
+#[derive(Serialize, Deserialize)]
+pub enum Query {
+ #[serde(rename = "pull")]
+ Pull {
+ name: String,
+ version: Option,
+ tags: Vec
+ },
+ #[serde(rename = "push")]
+ Push {
+ // todo: review me pls
+ _data: Vec
+ },
+ #[serde(rename = "index")]
+ Index {
+ request_update: bool,
+ fetch: bool
}
}
-pub struct API {
- base_url: String,
+#[derive(Serialize, Deserialize)]
+pub struct Request {
+ version: u32,
+ id: String,
token: Option,
- history: Vec
+ query: HashMap
}
-impl API {
+#[derive(Serialize, Deserialize)]
+pub struct DataErrorDetails {
+ actor: String,
+ detailed_cause: String,
+ recovery_options: Vec,
+}
+#[derive(Serialize, Deserialize)]
+pub struct DataError {
+ name: String,
+ cause: Option,
+ details: Option
+}
+
+#[derive(Serialize, Deserialize)]
+pub enum Data {
+ Pull {
+ _data: Option>,
+ }
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct Response {
+ version: u32,
+ id: String,
+ reply_to: String,
+ errors: HashMap,
+ data: HashMap
}
\ No newline at end of file
diff --git a/pkgr/src/commands.rs b/pkgr/src/commands.rs
index 869e961..80e9448 100644
--- a/pkgr/src/commands.rs
+++ b/pkgr/src/commands.rs
@@ -1,16 +1,17 @@
use std::process::exit;
use clap::{Parser, Subcommand};
+use colored::Colorize;
use log::{debug, error, info, trace, warn};
-use colored::Colorize;
use manifest::package::PackageType;
-use crate::CONFIG;
+
use crate::package::identifier::PackageIdentifier;
use crate::package::Package;
use crate::package::queue::PackageQueue;
use crate::process::Process;
use crate::types::fetch::TryFetch;
+use crate::util::prompts::prompt_bool;
#[derive(Parser, Debug)]
#[clap(name = "pkgr", version)]
@@ -25,6 +26,8 @@ pub enum Command {
Install {
#[arg(short, long, default_value_t = false)]
build: bool,
+ #[arg(short, long, default_value_t = false)]
+ ask: bool,
package_identifier: PackageIdentifier,
},
/// Remove a package from the system
@@ -57,6 +60,7 @@ impl Command {
match self {
Command::Install {
build,
+ ask,
package_identifier,
} => {
warn!("Installer does not run in isolation.");
@@ -80,6 +84,15 @@ impl Command {
let mut queue = PackageQueue::new();
queue.add_package(pkg, *build);
trace!("Installing queue...");
+ {
+ if *ask {
+ info!("Install following packages?");
+ info!(target: "item", "{}", queue);
+ if !prompt_bool("Continue?", false) {
+ return;
+ }
+ }
+ }
queue.install(*build);
let end = std::time::Instant::now();
diff --git a/pkgr/src/config.rs b/pkgr/src/config/mod.rs
similarity index 78%
rename from pkgr/src/config.rs
rename to pkgr/src/config/mod.rs
index 9a932d2..4c6876e 100644
--- a/pkgr/src/config.rs
+++ b/pkgr/src/config/mod.rs
@@ -1,4 +1,8 @@
use serde::{Deserialize, Serialize};
+use storage::Storage;
+
+mod storage;
+pub mod repos;
#[derive(Debug, Serialize, Deserialize)]
pub struct Config {
@@ -6,13 +10,16 @@ pub struct Config {
pub build_by_default: bool,
#[serde(default)]
pub tmp_dir: Option,
+ #[serde(default)]
+ pub storage: Storage
}
impl Default for Config {
fn default() -> Config {
Config {
build_by_default: false,
- tmp_dir: Some(String::from("/tmp/pkgr"))
+ tmp_dir: Some(String::from("/tmp/pkgr")),
+ storage: Storage::default()
}
}
}
diff --git a/pkgr/src/config/repos.rs b/pkgr/src/config/repos.rs
new file mode 100644
index 0000000..8594a25
--- /dev/null
+++ b/pkgr/src/config/repos.rs
@@ -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
+}
+
+impl RepoFile {
+ pub fn from_path(path: &str) -> Result {
+ 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)),
+ }
+ }
+}
\ No newline at end of file
diff --git a/pkgr/src/config/storage.rs b/pkgr/src/config/storage.rs
new file mode 100644
index 0000000..5fa8fa1
--- /dev/null
+++ b/pkgr/src/config/storage.rs
@@ -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"),
+ }
+ }
+}
diff --git a/pkgr/src/main.rs b/pkgr/src/main.rs
index 798eb1d..3aff896 100644
--- a/pkgr/src/main.rs
+++ b/pkgr/src/main.rs
@@ -9,6 +9,8 @@ mod commands;
mod logging;
/// Package and helpers.
mod package;
+/// Repo and helpers
+mod repo;
/// Process wrapper with logging wrapper.
mod process;
/// tmpfs wrapper.
diff --git a/pkgr/src/package/installer/mod.rs b/pkgr/src/package/installer/mod.rs
index da37f1b..4dbeab0 100644
--- a/pkgr/src/package/installer/mod.rs
+++ b/pkgr/src/package/installer/mod.rs
@@ -1,22 +1,17 @@
+use std::io;
use std::fs::remove_dir_all;
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 manifest::Manifest;
use pkgfile::PKGFile;
-
use crate::CONFIG;
-use crate::package::identifier::{PackageIdentifier, PackageLocator};
-use crate::package::Package;
+
use crate::tmpfs::TempDir;
use crate::types::fetch::TryFetch;
-use crate::util::fs::{copy_recursively, visit_dirs};
-use crate::util::prompts::{is_noninteractive, prompt_bool};
+use crate::util::fs::copy_recursively;
pub mod errors;
@@ -114,11 +109,17 @@ impl PackageInstaller {
}
}
- match self.install_type {
+ let r = match self.install_type {
InstallType::Bin => self.bin()
.map_err(|e| InstallError::BinError(e)),
InstallType::Build => self.build()
.map_err(|e| InstallError::BuildError(e)),
+ };
+
+ if let Err(e) = r {
+ return Err(e);
}
+
+ Ok(())
}
}
diff --git a/pkgr/src/package/queue.rs b/pkgr/src/package/queue.rs
index 16a7b95..601d8da 100644
--- a/pkgr/src/package/queue.rs
+++ b/pkgr/src/package/queue.rs
@@ -1,8 +1,11 @@
+use std::fmt::{Display, Formatter};
+
use log::trace;
+
use crate::package::Package;
pub struct PackageQueue {
- packages: Vec
+ packages: Vec,
}
impl PackageQueue {
@@ -17,7 +20,7 @@ impl PackageQueue {
for dependency in dependencies {
trace!("Checking package: {}", &dependency.identifier);
if self.packages.contains(&dependency) {
- continue
+ continue;
}
trace!("Adding package: {}", &dependency.identifier);
self.packages.push(dependency);
@@ -31,7 +34,18 @@ impl PackageQueue {
self.packages
.iter_mut()
.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, "")
+ }
+}
\ No newline at end of file
diff --git a/pkgr/src/repo/index/index_package.rs b/pkgr/src/repo/index/index_package.rs
new file mode 100644
index 0000000..ca60160
--- /dev/null
+++ b/pkgr/src/repo/index/index_package.rs
@@ -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,
+ tags: Vec,
+ uri: Url
+}
\ No newline at end of file
diff --git a/pkgr/src/repo/index/mod.rs b/pkgr/src/repo/index/mod.rs
new file mode 100644
index 0000000..fc516b6
--- /dev/null
+++ b/pkgr/src/repo/index/mod.rs
@@ -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
+}
+
+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 {
+ Ok(Repo::from_name(&self.origin_repo)?)
+ }
+
+ pub fn from_path(path: &str) -> Result {
+ 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 for RepoIndex {
+ type Error = ();
+ /// Fetch
+ fn try_fetch(query: Repo) -> Result {
+ 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(())
+ }
+ }
+}
\ No newline at end of file
diff --git a/pkgr/src/repo/mod.rs b/pkgr/src/repo/mod.rs
new file mode 100644
index 0000000..d0c3e88
--- /dev/null
+++ b/pkgr/src/repo/mod.rs
@@ -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 {
+ 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) {
+
+ }
+}
\ No newline at end of file
diff --git a/pkgr/src/tmpfs.rs b/pkgr/src/tmpfs.rs
index e83b860..7d68892 100644
--- a/pkgr/src/tmpfs.rs
+++ b/pkgr/src/tmpfs.rs
@@ -1,4 +1,4 @@
-use std::path::{Path, PathBuf};
+use std::path::PathBuf;
use crate::CONFIG;
diff --git a/pkgr/src/util/fs.rs b/pkgr/src/util/fs.rs
index 03b5cb2..815b950 100644
--- a/pkgr/src/util/fs.rs
+++ b/pkgr/src/util/fs.rs
@@ -1,6 +1,7 @@
-use std::path::Path;
-use std::fs::DirEntry;
use std::{fs, io};
+use std::fs::DirEntry;
+use std::path::Path;
+
use log::trace;
pub fn visit_dirs(dir: &Path, cb: &dyn Fn(&DirEntry)) -> std::io::Result<()> {
diff --git a/pkgr/src/util/mod.rs b/pkgr/src/util/mod.rs
index c239775..25c313c 100644
--- a/pkgr/src/util/mod.rs
+++ b/pkgr/src/util/mod.rs
@@ -1,2 +1,9 @@
pub mod prompts;
-pub mod fs;
\ No newline at end of file
+/// Helpers for fs
+pub mod fs;
+
+/// Create a UUID
+pub fn create_uuid() -> String {
+ // TODO
+ String::from("rand")
+}
\ No newline at end of file
diff --git a/pkgr/src/util/prompts.rs b/pkgr/src/util/prompts.rs
index 6c3e11a..9dcae5d 100644
--- a/pkgr/src/util/prompts.rs
+++ b/pkgr/src/util/prompts.rs
@@ -1,4 +1,5 @@
use std::io::Write;
+
use log::trace;
pub fn is_noninteractive() -> bool {