Skip to content
This repository has been archived by the owner on May 2, 2024. It is now read-only.

feat: persistance system #61

Open
wants to merge 19 commits into
base: oxidation
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ categories = ["caching", "config", "parsing", "os::linux-apis"]
figment = { version = "0.10.6", features = ["env", "test", "toml" ] }
num_cpus = "1.13.1"
serde = { version = "1.0.144", features = ["derive"] }
chrono = { version = "0.4.22", features = ["serde", "clock", "std"], default-features = false }
serde_derive = "1.0.144"
serde_json = "1.0.85"
error-stack = "0.2.2"

[dev-dependencies]
rstest = "0.15.0"
35 changes: 2 additions & 33 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ use figment::value::{Dict, Map};
use figment::{Error, Figment, Metadata, Profile, Provider};
use serde::{Deserialize, Serialize};

use crate::model::{default_repository, Repository};

/// Pacstall's configuration.
///
/// Gives access to the [configuration](Config) extracted, and the [Figment]
Expand Down Expand Up @@ -191,39 +193,6 @@ impl Default for Settings {
}
}

/// The extracted `repositories` array of tables.
///
/// Defaults to the official repository.
#[derive(Deserialize, Debug, Eq, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Repository {
/// The name of the repository.
pub name: String,
/// URL of the repository.
///
/// Note that the URL **isn't verified** during extraction!
pub url: String,
/// Preference of the repository.
///
/// Specifies which repository to look into first during certain operations
/// like installing a package. If the package isn't present in the first
/// preferred repository, then the second preferred repository is looked
/// into.
pub preference: u32,
}

fn default_repository() -> Vec<Repository> { vec![Repository::default()] }

impl Default for Repository {
fn default() -> Self {
Self {
name: "official".into(),
url: "https://github.com/pacstall/pacstall-programs".into(),
preference: 1,
}
}
}

#[cfg(test)]
mod tests {
use std::fs::{self, File};
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@
)]
#![allow(clippy::must_use_candidate)]
pub mod config;
pub mod model;
pub mod store;
7 changes: 7 additions & 0 deletions src/model/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//! Provides structs to handle Pacstall's data models.

mod pacbuild;
mod repository;

pub use crate::model::pacbuild::*;
pub use crate::model::repository::{default_repository, Repository};
saenai255 marked this conversation as resolved.
Show resolved Hide resolved
157 changes: 157 additions & 0 deletions src/model/pacbuild.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
//!

use chrono::NaiveDateTime as DateTime;
use serde_derive::{Deserialize, Serialize};

/// Representation of the PACBUILD file.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct PacBuild {
/// PacBuild unique name per [`Repository`](crate::model::Repository).
pub name: PackageId,

/// Last time it was changed.
pub last_updated: DateTime,

/// [`Repository`](crate::model::Repository) url.
pub repository: URL,

/// Maintainer name and possibly email.
///
/// # Example
/// `Paul Cosma <[email protected]>`
pub maintainer: String,

/// Canonical package name. Usually the `name` without the type extension.
///
/// # Example
/// - `PacBuild { name: "discord-deb", package_name: "discord" }`
pub package_name: String,

/// Short package description.
pub description: String,

/// Official homepage [URL].
pub homepage: URL,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shoud be optional


/// Latest version fetched from Repology.
pub repology_version: Version,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should we store the repology version?


/// Repology filter.
///
/// # Example
/// **TBA**
pub repology: String,
Comment on lines +43 to +47
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be a HashMap of the filters?


/// Installation state.
pub install_state: InstallState,

/// Runtime dependencies.
pub dependencies: Vec<PackageId>,

/// Optional dependencies.
pub optional_dependencies: Vec<PackageId>,

/// SPDX License.
pub license: String,

/// Download [URL].
pub url: URL,

/// [`PacBuild`] type, deduced from the name suffix.
pub kind: Kind,
}

/// Represents a `SemVer` version.
/// # Examples
saenai255 marked this conversation as resolved.
Show resolved Hide resolved
///
/// ```
/// use libpacstall::model::Version;
///
/// let ver: Version = "1.0.0".into();
/// ```
pub type Version = String;

/// Represents a [`PacBuild`] or Apt package name.
/// # Examples
///
/// ```
/// use libpacstall::model::PackageId;
///
/// let identifier: PackageId = "discord-deb".into();
/// ```
pub type PackageId = String;
/// Represents an URL
/// # Examples
///
/// ```
/// use libpacstall::model::URL;
///
/// let url: URL = "https://example.com".into();
/// ```
pub type URL = String;
/// Represents a file checksum
/// # Examples
///
/// ```
/// use libpacstall::model::Hash;
///
/// let hash: Hash = "b5c9710f33204498efb64cf8257cd9b19e9d3e6b".into();
/// ```
pub type Hash = String;

/// Represents the install state of a package.
/// # Examples
///
/// ```
/// use chrono::NaiveDate;
/// use libpacstall::model::InstallState;
///
/// let installed_directly = InstallState::Direct(
/// NaiveDate::from_ymd(2016, 7, 8).and_hms(9, 10, 11),
/// "0.9.2".into(),
/// );
/// ```
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum InstallState {
/// Package is installed directly, meaning the user wanted it.
Direct(DateTime, Version),

/// Package is installed as a dependency.
Indirect(DateTime, Version),

/// Package is not installed.
None,
}

impl InstallState {
/// Returns `true` if the package is installed otherwise `false`.
pub fn is_installed(&self) -> bool { !matches!(self, Self::None) }
}

/// Represents the type of the package. Usually deduced by the [PacBuild#name]
/// suffix.
///
/// # Examples
///
/// ```
/// use libpacstall::model::Kind;
///
/// let git_release = Kind::GitRelease;
/// ```
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum Kind {
/// [`PacBuild`] will install an `AppImage`.
AppImage(Hash),

/// [`PacBuild`] will install a prebuilt, usually `tar.gz`, package.
Binary(Hash),

/// [`PacBuild`] will install an existing `.deb` file.
DebFile(Hash),

/// [`PacBuild`] will install the source of a given Git branch.
GitBranch,

/// [`PacBuild`] will install the source of a given Git release.
GitRelease,
}
35 changes: 35 additions & 0 deletions src/model/repository.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use serde_derive::{Deserialize, Serialize};

/// Representation of a Pacstall repository.
///
/// Defaults to the official repository.
#[derive(Deserialize, Debug, Eq, PartialEq, Serialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct Repository {
/// The name of the repository.
pub name: String,
/// URL of the repository.
///
/// Note that the URL **isn't verified** during extraction!
pub url: String,
/// Preference of the repository.
///
/// Specifies which repository to look into first during certain operations
/// like installing a package. If the package isn't present in the first
/// preferred repository, then the second preferred repository is looked
/// into.
pub preference: u32,
}

#[allow(clippy::module_name_repetitions)]
pub fn default_repository() -> Vec<Repository> { vec![Repository::default()] }

impl Default for Repository {
fn default() -> Self {
Self {
name: "official".into(),
url: "https://github.com/pacstall/pacstall-programs".into(),
preference: 1,
}
}
}
Loading