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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
//! Drop manifest data.

use serde::Deserialize;

mod deps;
mod meta;

#[cfg(test)]
mod tests;

#[doc(inline)]
pub use self::{
    deps::{Deps, DepInfo},
    meta::Meta,
};

/// A drop manifest.
///
/// Note the lack of `drop::Name` usage throughout this type. This is because
/// name validation is done by the backend in order for clients to be
/// forward-compatible with later backend versions.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Manifest {
    /// The drop's info.
    pub meta: Meta,

    /// The drops that this drop relies on.
    #[serde(rename = "dependencies")]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub deps: Option<Deps>,
}

impl Manifest {
    /// The name used for manifest files.
    pub const FILE_NAME: &'static str = "Ocean.toml";

    /// Parses a manifest from [TOML](https://en.wikipedia.org/wiki/TOML).
    ///
    /// ```
    /// use oceanpkg::drop::Manifest;
    ///
    /// let toml = r#"
    ///     [meta]
    ///     name = "ocean"
    ///     description = "Cross-platform package manager"
    ///     version = "0.1.0"
    ///     license = "AGPL-3.0-only"
    ///     authors = ["Nikolai Vazquez", "Alex Farra", "Nicole Zhao"]
    ///     readme = "README.md"
    ///     changelog = "CHANGELOG.md"
    ///     git = "https://github.com/oceanpkg/ocean"
    ///
    ///     [dependencies]
    ///     wget = "*"
    /// "#;
    /// let manifest = Manifest::parse_toml(toml).unwrap();
    /// ```
    #[cfg(feature = "toml")]
    pub fn parse_toml(toml: &str) -> Result<Self, toml::de::Error> {
        toml::de::from_str(toml)
    }

    /// Parses a manifest from a [TOML](https://en.wikipedia.org/wiki/TOML) file
    /// at the given path.
    #[cfg(feature = "toml")]
    pub fn read_toml_file<T>(toml: T) -> Result<Self, std::io::Error>
        where T: AsRef<std::path::Path>
    {
        use std::io::{Error, ErrorKind, Read};

        let mut buf = String::with_capacity(128);
        std::fs::File::open(toml)?.read_to_string(&mut buf)?;
        Self::parse_toml(&buf).map_err(|error| {
            Error::new(ErrorKind::InvalidData, error)
        })
    }

    /// Parses a manifest from [JSON](https://en.wikipedia.org/wiki/JSON).
    ///
    /// ```
    /// use oceanpkg::drop::Manifest;
    ///
    /// let json = r#"{
    ///     "meta": {
    ///         "name": "ocean",
    ///         "description": "Cross-platform package manager",
    ///         "version": "0.1.0",
    ///         "license": "AGPL-3.0-only",
    ///         "authors": ["Nikolai Vazquez", "Alex Farra", "Nicole Zhao"],
    ///         "readme": "README.md",
    ///         "changelog": "CHANGELOG.md",
    ///         "git": "https://github.com/oceanpkg/ocean"
    ///     },
    ///     "dependencies": {
    ///         "wget": "*"
    ///     }
    /// }"#;
    /// let manifest = Manifest::parse_json(json).unwrap();
    /// ```
    pub fn parse_json(json: &str) -> Result<Self, json::Error> {
        json::from_str(json)
    }

    /// Parses a manifest from [JSON](https://en.wikipedia.org/wiki/JSON)
    /// provided by the reader.
    pub fn read_json<J>(json: J) -> Result<Self, json::Error>
        where J: std::io::Read
    {
        json::from_reader(json)
    }

    /// Parses a manifest from a [JSON](https://en.wikipedia.org/wiki/JSON) file
    /// at the given path.
    pub fn read_json_file<J>(json: J) -> Result<Self, std::io::Error>
        where J: AsRef<std::path::Path>
    {
        let reader = std::io::BufReader::new(std::fs::File::open(json)?);
        Self::read_json(reader).map_err(Into::into)
    }

    /// Returns `self` as a TOML string.
    #[cfg(feature = "toml")]
    pub fn to_toml(&self, pretty: bool) -> Result<String, toml::ser::Error> {
        if pretty {
            toml::to_string_pretty(self)
        } else {
            toml::to_string(self)
        }
    }

    /// Returns `self` as a JSON string.
    pub fn to_json(&self, pretty: bool) -> Result<String, json::Error> {
        if pretty {
            json::to_string_pretty(self)
        } else {
            json::to_string(self)
        }
    }

    /// Returns the list of files to package.
    pub fn files(&self) -> Vec<&str> {
        let mut files = Vec::new();

        let exe_path = self.meta.exe_path();
        files.push(exe_path);

        files
    }
}