summaryrefslogtreecommitdiffstats
path: root/src/main.rs
blob: 725821cd545609b14e9bd787a373c61fb000f23a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#[macro_use] extern crate log;

use std::path::Path;
use std::path::PathBuf;
use anyhow::Result;
use anyhow::Error;
use walkdir::WalkDir;
use indicatif::*;
use tokio::stream::StreamExt;

mod cli;
mod util;
mod package;
mod phase;
mod config;
mod repository;
use crate::config::*;
use crate::repository::Repository;
use crate::package::PackageName;
use crate::package::PackageVersion;
use crate::util::executor::DummyExecutor;
use crate::package::DummyVersionParser;
use crate::package::Tree;

#[tokio::main]
async fn main() -> Result<()> {
    let cli = cli::cli();
    let cli = cli.get_matches();

    let mut config = ::config::Config::default();
    config
        .merge(::config::File::with_name("config"))?
        .merge(::config::Environment::with_prefix("YABOS"))?;
        // Add in settings from the environment (with a prefix of YABOS)
        // Eg.. `YABOS_DEBUG=1 ./target/app` would set the `debug` key
    //

    let config: Configuration = config.try_into::<NotValidatedConfiguration>()?.validate()?;
    let repo_path    = PathBuf::from(config.repository());
    let max_packages = count_pkg_files(&repo_path);
    let progressbars = setup_progressbars(max_packages);
    let repo         = Repository::load(&repo_path, &progressbars.repo_loading)?;
    progressbars.repo_loading.finish_with_message("Repository loading finished");

    let pname = cli.value_of("package_name").map(String::from).map(PackageName::from).unwrap(); // safe by clap
    let pvers = cli.value_of("package_version").map(String::from).map(PackageVersion::from);

    let packages = if let Some(pvers) = pvers {
        repo.find(&pname, &pvers)
    } else {
        repo.find_by_name(&pname)
    };
    debug!("Found {} relevant packages", packages.len());

    tokio::stream::iter(packages.into_iter().cloned())
        .map(|p| {
            let bar = progressbars.root.add(tree_building_progress_bar(max_packages));
            bar.set_message(&format!("Building Package Tree for {}", p.name()));
            let mut tree = Tree::new();
            tree.add_package(p, &repo, &DummyExecutor::new(), &DummyVersionParser::new(), &bar)?;
            Ok(tree)
        })
        .collect::<Result<Vec<_>>>()
        .await?;

    progressbars.root.join().map_err(Error::from)
}

struct ProgressBars {
    root:           MultiProgress,
    repo_loading:   ProgressBar,
}

fn setup_progressbars(max_packages: u64) -> ProgressBars {
    let repo_loading = {
        let b = ProgressBar::new(max_packages);
        b.set_style({
            ProgressStyle::default_bar().template("[{elapsed_precise}] {pos:>3}/{len:>3} ({percent:>3}%): {bar} | {msg}")
        });

        b.set_message("Loading Repository");
        b
    };

    let root         = MultiProgress::new();
    let repo_loading = root.add(repo_loading);

    ProgressBars {
        root,
        repo_loading,
    }
}

fn tree_building_progress_bar(max: u64) -> ProgressBar {
    let b = ProgressBar::new(max);
    b.set_style({
        ProgressStyle::default_bar().template("[{elapsed_precise}] {pos:>3}/{len:>3} ({percent:>3}%): {bar} | {msg}")
    });
    b
}

fn count_pkg_files(p: &Path) -> u64 {
    WalkDir::new(p)
        .follow_links(true)
        .into_iter()
        .filter_map(Result::ok)
        .filter(|d| d.file_type().is_file())
        .filter(|f| f.path().file_name().map(|name| name == "pkg.toml").unwrap_or(false))
        .count() as u64
}