aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/util/sync_helper.rs
blob: c5ab88972231577903bca4a417f371971ba97e31 (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
//! ref: composer/src/Composer/Util/SyncHelper.php

use anyhow::Result;
use shirabe_external_packages::react::promise::promise_interface::PromiseInterface;
use crate::downloader::download_manager::DownloadManager;
use crate::downloader::downloader_interface::DownloaderInterface;
use crate::package::package_interface::PackageInterface;
use crate::util::r#loop::Loop;

pub enum DownloaderOrManager<'a> {
    Interface(&'a dyn DownloaderInterface),
    Manager(&'a DownloadManager),
}

impl<'a> DownloaderOrManager<'a> {
    fn download(&self, package: &dyn PackageInterface, path: &str, prev_package: Option<&dyn PackageInterface>) -> Box<dyn PromiseInterface> {
        match self {
            Self::Interface(d) => d.download(package, path, prev_package),
            Self::Manager(d) => d.download(package, path, prev_package),
        }
    }

    fn prepare(&self, r#type: &str, package: &dyn PackageInterface, path: &str, prev_package: Option<&dyn PackageInterface>) -> Box<dyn PromiseInterface> {
        match self {
            Self::Interface(d) => d.prepare(r#type, package, path, prev_package),
            Self::Manager(d) => d.prepare(r#type, package, path, prev_package),
        }
    }

    fn install(&self, package: &dyn PackageInterface, path: &str) -> Box<dyn PromiseInterface> {
        match self {
            Self::Interface(d) => d.install(package, path),
            Self::Manager(d) => d.install(package, path),
        }
    }

    fn update(&self, package: &dyn PackageInterface, prev_package: &dyn PackageInterface, path: &str) -> Box<dyn PromiseInterface> {
        match self {
            Self::Interface(d) => d.update(package, prev_package, path),
            Self::Manager(d) => d.update(package, prev_package, path),
        }
    }

    fn cleanup(&self, r#type: &str, package: &dyn PackageInterface, path: &str, prev_package: Option<&dyn PackageInterface>) -> Box<dyn PromiseInterface> {
        match self {
            Self::Interface(d) => d.cleanup(r#type, package, path, prev_package),
            Self::Manager(d) => d.cleanup(r#type, package, path, prev_package),
        }
    }
}

pub struct SyncHelper;

impl SyncHelper {
    pub fn download_and_install_package_sync(
        r#loop: &Loop,
        downloader: DownloaderOrManager<'_>,
        path: String,
        package: &dyn PackageInterface,
        prev_package: Option<&dyn PackageInterface>,
    ) -> Result<()> {
        let r#type = if prev_package.is_some() { "update" } else { "install" };

        let result: Result<()> = (|| {
            Self::r#await(r#loop, Some(downloader.download(package, &path, prev_package)))?;
            Self::r#await(r#loop, Some(downloader.prepare(r#type, package, &path, prev_package)))?;
            if r#type == "update" {
                if let Some(prev) = prev_package {
                    Self::r#await(r#loop, Some(downloader.update(package, prev, &path)))?;
                }
            } else {
                Self::r#await(r#loop, Some(downloader.install(package, &path)))?;
            }
            Ok(())
        })();

        if result.is_err() {
            Self::r#await(r#loop, Some(downloader.cleanup(r#type, package, &path, prev_package)))?;
            return result;
        }

        Self::r#await(r#loop, Some(downloader.cleanup(r#type, package, &path, prev_package)))?;
        Ok(())
    }

    pub fn r#await(r#loop: &Loop, promise: Option<Box<dyn PromiseInterface>>) -> Result<()> {
        if let Some(promise) = promise {
            r#loop.wait(vec![promise]);
        }
        Ok(())
    }
}