Skip to content

Commit

Permalink
docs & some improvements
Browse files Browse the repository at this point in the history
Signed-off-by: Adam Perkowski <[email protected]>
  • Loading branch information
adamperkowski committed Nov 24, 2024
1 parent 07de93a commit 2f6d745
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 66 deletions.
35 changes: 18 additions & 17 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
//! this module handles management & communication with sources, also knows as APIs
#[cfg(feature = "aur")]
mod aur;
#[cfg(feature = "github")]
mod github;
#[cfg(feature = "gitlab")]
mod gitlab;

// this is what `get_latest`s return
#[derive(Debug)]
pub struct Release {
pub name: String,
pub tag: Option<String>,
pub url: String,
/// struct containing the API name & a pointer to API's `get_latest` function
pub struct Api {
pub name: &'static str,
pub func: fn(ApiArgs) -> ReleaseFuture,
}

/// arguments passed to a source
pub struct ApiArgs {
pub request_client: reqwest::Client,
pub package: String,
//pub target: String, // equivalent to ex. `github = "adamperkowski/nvrs"` in the config
//pub host: Option<String>,
pub args: Vec<String>,
pub api_key: Option<String>,
}

/// this is what `get_latest`s return
#[derive(Debug)]
pub struct Release {
pub name: String,
pub tag: Option<String>,
pub url: String,
}

// this is necessary because we need to store a reference to an async function in `Api`
type ReleaseFuture =
std::pin::Pin<Box<dyn std::future::Future<Output = crate::error::Result<Release>> + Send>>;

pub struct Api {
pub name: &'static str,
pub func: fn(ApiArgs) -> ReleaseFuture,
}

// TODO: consider not using ReleaseFuture & Source. just calling by name

#[cfg(feature = "http")]
pub fn setup_headers() -> reqwest::header::HeaderMap {
fn setup_headers() -> reqwest::header::HeaderMap {
use reqwest::header::{HeaderMap, HeaderValue, USER_AGENT};

let mut headers = HeaderMap::new();
Expand All @@ -44,7 +44,7 @@ pub fn setup_headers() -> reqwest::header::HeaderMap {
}

#[cfg(feature = "http")]
pub fn match_statuscode(req: &reqwest::Response) -> crate::error::Result<()> {
fn match_statuscode(req: &reqwest::Response) -> crate::error::Result<()> {
use crate::error;
use reqwest::StatusCode;

Expand All @@ -58,6 +58,7 @@ pub fn match_statuscode(req: &reqwest::Response) -> crate::error::Result<()> {
}
}

/// public list of available sources
pub const API_LIST: &[Api] = &[
#[cfg(feature = "aur")]
Api {
Expand Down
33 changes: 22 additions & 11 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
//! operations on configuration files
///
/// see the [example `nvrs.toml`](https://github.com/adamperkowski/nvrs/blob/main/nvrs.toml)
use crate::error;
use serde::{Deserialize, Serialize};
use std::{
Expand All @@ -24,16 +28,29 @@ struct Keyfile {
keys: KeysTable,
}*/

// main config file
// __config__ structure
/// main configuration file structure
///
/// see the [example `nvrs.toml`](https://github.com/adamperkowski/nvrs/blob/main/nvrs.toml)
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Config {
pub __config__: Option<ConfigTable>,
#[serde(flatten)]
pub packages: BTreeMap<String, Package>,
}

/// `__config__` structure
///
/// see the [example `nvrs.toml`](https://github.com/adamperkowski/nvrs/blob/main/nvrs.toml)
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ConfigTable {
pub oldver: Option<String>, // TODO: exceptions for empty oldver & newver entries
pub newver: Option<String>,
keyfile: Option<String>,
}

// package entry structure
/// package entry structure
///
/// see the [example `nvrs.toml`](https://github.com/adamperkowski/nvrs/blob/main/nvrs.toml)
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Package {
source: String, // ex. "github", "aur"
Expand All @@ -60,15 +77,8 @@ pub struct Package {
pub prefix: String,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Config {
pub __config__: Option<ConfigTable>,
#[serde(flatten)]
pub packages: BTreeMap<String, Package>,
}

impl Package {
// global function to pass API agrs
/// global function to get various API-specific agrs for a package
pub fn get_api(&self) -> (String, Vec<String>) {
let args = match self.source.as_str() {
#[cfg(feature = "aur")]
Expand All @@ -84,6 +94,7 @@ impl Package {
}
}

/// global asynchronous function to load all config files
pub async fn load(
custom_path: Option<String>,
) -> error::Result<(Config, PathBuf /*, Option<Keyfile>*/)> {
Expand Down
5 changes: 4 additions & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! [thiserror] implementation
use colored::Colorize;
use thiserror::Error as ThisError;

Expand Down Expand Up @@ -63,14 +65,15 @@ pub enum Error {

pub type Result<T> = std::result::Result<T, Error>;

// TODO: force
/*
pub fn custom_error(title: &'static str, message: String, exit: bool /*, force: bool*/) {
println!("! {}{}", title.red(), message.replace("\n", "\n "));
if exit {
std::process::exit(1);
}
}
*/

#[cfg(test)]
mod tests {
Expand Down
30 changes: 15 additions & 15 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
// nvrs - fast new version checker for software releases 🦀
//! nvrs - fast new version checker for software releases 🚦🦀
//!
//! nvrs is still a WIP<br>
//! new features & bugfixes are being pushed every day<br>
//! you may encounter some issues. please consider [submitting feedback](https://github.com/adamperkowski/nvrs/issues/new/choose) if you do.
// thiserror implementation
pub mod error;

// communication with sources
pub mod api;

// command-line arguments
pub mod cli;

// operations on configuration files
pub mod config;

// operations on version files
pub mod error;
pub mod verfiles;

// example "core" vars structure
/// example "core" vars structure
pub struct Core {
pub cli: cli::Cli,
pub config: config::Config,
pub verfiles: (verfiles::Verfile, verfiles::Verfile),
pub client: reqwest::Client,
}

/// an asynchronous function that package's source and gets the latest release
/// # example usage
/// ```rust
/// let package = "nvrs";
/// let client = reqwest::Client::new();
/// run_source(package, client).await;
/// ```
pub async fn run_source(
package: (String, config::Package),
client: reqwest::Client,
Expand All @@ -41,4 +41,4 @@ pub async fn run_source(
} else {
Err(error::Error::SourceNotFound)
}
}
}
23 changes: 12 additions & 11 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,35 @@
use colored::Colorize;
use nvrs::*;

mod cli;

#[tokio::main]
async fn main() -> error::Result<()> {
let core = init().await?;

if core.cli.cmp {
compare(core).await;
} else if core.cli.take.is_some() {
take(core).await?;
if core.1.cmp {
compare(core.0).await;
} else if core.1.take.is_some() {
take(core.0, core.1.take).await?;
} else {
sync(core).await?;
sync(core.0).await?;
}

Ok(())
}

async fn init() -> error::Result<Core> {
async fn init() -> error::Result<(Core, cli::Cli)> {
let cli = cli::get_args();
let config = config::load(cli.clone().custom_config).await?;

// TODO: this could be handled entirely within lib
let verfiles = verfiles::load(config.0.__config__.clone()).await?;

Ok(Core {
cli,
Ok((Core {
config: config.0,
verfiles,
client: reqwest::Client::new(),
})
}, cli))
}

async fn compare(core: Core) {
Expand All @@ -55,8 +56,8 @@ async fn compare(core: Core) {
}
}

async fn take(core: Core) -> error::Result<()> {
let names = core.cli.take.unwrap();
async fn take(core: Core, take_names: Option<Vec<String>>) -> error::Result<()> {
let names = take_names.unwrap();
let config = core.config;
let (mut oldver, newver) = core.verfiles;

Expand Down
25 changes: 14 additions & 11 deletions src/verfiles.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
//! operations on version files
//!
//! see `newver` & `oldver` in [crate::config::ConfigTable]
use serde::{Deserialize, Serialize};
use std::{collections::BTreeMap, path::Path};
use tokio::{fs, io::AsyncWriteExt};

use crate::{config, error};

// this module handles operations on verfiles.
// see `newver` & `oldver` in `config.rs`

// verfiles get created from this
const TEMPLATE: &str = r#"{
"version": 2,
"data": {}
}
"#;

// package entry structure
/// main data structure
#[derive(Serialize, Deserialize)]
pub struct VerData {
pub data: BTreeMap<String, VerPackage>,
}

/// package entry structure
#[derive(Clone, Serialize, Deserialize)]
pub struct VerPackage {
pub version: String,
Expand All @@ -24,13 +31,7 @@ pub struct VerPackage {
pub url: String,
}

// main data structure
#[derive(Serialize, Deserialize)]
pub struct VerData {
pub data: BTreeMap<String, VerPackage>,
}

// file structure
/// file structure
#[derive(Serialize, Deserialize)]
pub struct Verfile {
version: u8,
Expand All @@ -39,6 +40,7 @@ pub struct Verfile {
}

// TODO: move `load` & `save` logic into `config.rs` maybe
/// asynchronous function for loading the verfiles
pub async fn load(config_table: Option<config::ConfigTable>) -> error::Result<(Verfile, Verfile)> {
if config_table.is_none() {
return Err(error::Error::NoConfigTable);
Expand All @@ -59,6 +61,7 @@ pub async fn load(config_table: Option<config::ConfigTable>) -> error::Result<(V
}
}

/// asynchronous function for saving changes to the verfiles
pub async fn save(
verfile: Verfile,
is_oldver: bool,
Expand Down

0 comments on commit 2f6d745

Please sign in to comment.