summaryrefslogtreecommitdiffstats
path: root/src/repository/fs/path.rs
blob: 284727ce5a30dc45f3a5e29a5c37a8e5efe44789 (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
//
// Copyright (c) 2020-2021 science+computing ag and other contributors
//
// This program and the accompanying materials are made
// available under the terms of the Eclipse Public License 2.0
// which is available at https://www.eclipse.org/legal/epl-2.0/
//
// SPDX-License-Identifier: EPL-2.0
//

use std::convert::TryFrom;
use std::path::Component;

use anyhow::anyhow;
use anyhow::Result;

/// Helper type for filtering for pathes we need or dont need
///
/// We either have a directory, which has a name, or we have a pkg.toml file, which is of interest.
/// All other files can be ignored and thus are not represented by this type.
///
/// The PathComponent::DirName(_) represents a _part_ of a Path. Something like
///
/// ```ignore
///     let p = PathBuf::from("foo/bar/baz")
///     p.components().map(PathComponent::DirName) // does not actually work because of types
/// ```
///
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum PathComponent {
    PkgToml,
    DirName(String),
}

impl TryFrom<&std::path::Component<'_>> for PathComponent {
    type Error = anyhow::Error;

    fn try_from(c: &std::path::Component) -> Result<Self> {
        match *c {
            Component::Prefix(_) => anyhow::bail!("Unexpected path component: Prefix"),
            Component::RootDir => anyhow::bail!("Unexpected path component: RootDir"),
            Component::CurDir => anyhow::bail!("Unexpected path component: CurDir"),
            Component::ParentDir => anyhow::bail!("Unexpected path component: ParentDir"),
            Component::Normal(filename) => {
                let filename = filename.to_str().ok_or_else(|| anyhow!("UTF8-error"))?;
                if filename == "pkg.toml" {
                    Ok(PathComponent::PkgToml)
                } else {
                    Ok(PathComponent::DirName(filename.to_string()))
                }
            },
        }
    }
}

impl PathComponent {
    /// Helper fn whether this PathComponent is a PathComponent::PkgToml
    pub fn is_pkg_toml(&self) -> bool {
        std::matches!(self, PathComponent::PkgToml)
    }

    /// Helper fn to get the directory name of this PathComponent if it is a PathComponent::DirName
    /// or None if it is not.
    pub fn dir_name(&self) -> Option<&str> {
        match self {
            PathComponent::PkgToml => None,
            PathComponent::DirName(dn) => Some(dn)
        }
    }
}