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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
//! # About
//!
//! Welcome to the documentation for the Please Package Manager client! This
//! documentation will provide all of the nessecary information to install, run
//! and prehaps contribute to this project (named `please-pm-client` from here
//! on).
//! # Examples
//!
//! ## As a library
//!
//! Install the official, dummy `test-package` and view the infomation for it:
//!
//! ```rust
//! use please_pm_client::{get_package_info, install_package};
//!
//! fn main() {
//!     println!(
//!         "NEW PACKAGE INSTALLED:\n\n{:?}",
//!         install_package("test-package".to_string(), false, false)
//!     );
//!     println!(
//!         "INFO:\n\n{:?}",
//!         get_package_info("test-package".to_string(), false)
//!     );
//! }
//! ```
//!
//! This will install a new package named "test-package" with only the required
//! dependencies and will print a fancy output (set `is_verbose` to `false` in
//! [install_package] if you want a more verbose output).
//!
//! This is a basic example and such, it does not implamented the proper
//! package checking (only debug prints `{:?}`).
//!
//! ## Config examples
//!
//! #### Basic `please.toml`:
//!
//! ```toml
//! [package] # Basic package metadata
//! name = "my-test-package" # Name of package (Not optional)
//! description = "This is a small test package. The name of this should be like-this" # Package description
//! icon = "logo.png" # The icon file
//! readme = "README.md" # The readme file
//!
//! [dependencies]
//!     [dependencies.required] # Required dependencies
//!     node = "4.6.3"
//!     flask = "2.0.4"
//!
//!     [dependencies.optional] # Optional dependencies that user can choose to install
//!     python3 = "9.4.2"
//!
//!     [dependencies.build] # Build dependencies. This will not be uploaded to the api but is a shortcut for a build script
//!     git = "1.0.2"
//!     docker = "5.7.2"
//!
//! [build]
//! build_script = "build.sh" # The bash build script (Not optional)
//! launch_script = "launch.sh" # The launch script that determines how it will run after building
//! binary_dir = "build/" # The directory where binaries are produced from build_script
//! binary_pattern = "a.out|my_build" # Regex parsing to get the proper files.
//! ```
//!
//! ##### `please.toml` notes
//!
//! - For `binary_pattern`, please see [here](#binary-pattern) for more
//! information for more complicated binary outputs.
//! - The only required parts of `please.toml` are the `name` in `[package]`
//! and the full `[build]` for your package.
//!
//! #### Basic `please.json`
//!
//! ```json
//! {
//!     "package": {
//!         "name": "my-test-package",
//!         "description": "This is a small test package. The name of this should be like-this",
//!         "icon": "logo.png",
//!         "readme": "README.md"
//!     },
//!     "dependencies": {
//!         "optional": {
//!             "python3": "9.4.2"
//!         },
//!         "build": {
//!             "git": "1.0.2",
//!             "docker": "5.7.2"
//!         },
//!         "required": {
//!             "node": "4.6.3",
//!             "flask": "2.0.4"
//!         }
//!     },
//!     "build": {
//!         "build_script": "build.sh",
//!         "launch_script": "launch.sh",
//!         "binary_dir": "build/",
//!         "binary_pattern": "a.out|my_build"
//!     }
//! }
//! ```
//!
//! ## Basic usage
//! ### Installing the Client
//!
//! #### From source
//!
//! 1. Clone the repository: `git clone https://gitlab.com/owez/please-pm-client`
//! 2. Build the package manager with `cargo build --release`
//! 3. Head to `please-pm-client/target/release/` and copy the executable named `client-backend`
//!
//! #### From [crates.io](https://crates.io/)
//!
//! As this repository is under heavy development, there is currently not a
//! stable *[crates.io]((https://crates.io/))* release. For now, please build
//! it from source using **[this](#from-source)** guide.
//!

use std::path::PathBuf;

/// A simple trait for allowing the use of representing something as a string
/// in an easy and extendible way.
pub trait StringRep {
    /// Basic `&str` representation of the generic implamented trait.
    fn str_rep(&self) -> &'static str;

    /// Customised representation addressing the individual part of the
    /// implamented trait. If there is none, it is allowed to fall back to
    /// [StringRep::str_rep].
    fn string_rep(&self) -> String;
}

/// Main error enum for Please Package Manager. For more infomation on each
/// type of Error, please view each of their individual docs.
///
/// To easily get a description of each error, please refer to the implament
/// method that's *coming soon*.
#[derive(Debug)]
pub enum ErrorKind {
    /// When the [publish_package] function didn't get a package path and could
    /// not determine the current running path. This commonly happens when it
    /// is being ran directly from functions instead of the API.
    NoUploadPath,

    /// When the `please.toml`/`please.json` file could not be decoded properly.
    /// This error should be raised if the toml/json file has incorrect syntax.
    MetadataDecodeError,
}

#[allow(non_snake_case, unreachable_patterns)]
impl StringRep for ErrorKind {
    /// Represent an error generically, allowing the use of a [str].
    fn str_rep(&self) -> &'static str {
        match self {
            NoUploadPath => "Could not determine what directory to upload!",
            MetadataDecodeError => "Could not decode the metadata (please.x)!",
        }
    }

    /// Represent the [ErrorKind] as a customised error, allowing more
    /// detailed responses at the cost of using a heap-allocated [String].
    fn string_rep(&self) -> String {
        match self {
            // Add more in this as more with names come
            _ => String::from(self.str_rep()), // No metadata, this is shortcut
        }
    }
}

/// Gets correctly-formatted infomation on a selected package by.
///
/// *NOTE: This function is a frontend and will therefore display a formatted
/// answer; no matter what*.
pub fn get_package_info(package_name: String, is_verbose: bool) -> Result<String, ErrorKind> {
    unimplemented!();
}

/// Installs a package with the given name (`package_name`).
///
/// *NOTE: This function is a frontend and will therefore display a formatted
/// answer; no matter what*.
///
/// # Arguments
///
/// - `package_name`: The unique package name.
/// - `is_verbose`: Should give a verbose/detailed output when installing.
/// - `install_optional`: If it should install requested optional packages.
pub fn install_package(
    package_name: String,
    is_verbose: bool,
    install_optional: bool,
) -> Result<String, ErrorKind> {
    unimplemented!();
}

/// Removes a given `package_name`. This function will not succeed if the
/// package is not installed or is a dependancy (optional or otherwise) to
/// another package.
///
/// `force_remove` foces the removal of a package. This should **not** be used
/// unless it is an emergency.
///
/// *NOTE: This function is a frontend and will therefore display a formatted
/// answer; no matter what*.
pub fn remove_package(package_name: String, force_remove: bool) -> Result<String, ErrorKind> {
    unimplemented!();
}

/// Publishes a given package path (must be package root & a valid package tree)
/// to the Please Package Manager API.
///
/// If a `path` [PathBuf] is not provided in [Option]<[PathBuf]> is not
/// provided, it will try to validate the directory the program is running from.
/// If it cannot find this file, it will return a special error message.
///
/// *NOTE: This function is a frontend and will therefore display a formatted
/// answer; no matter what*.
pub fn publish_package(path: Option<PathBuf>) -> Result<String, ErrorKind> {
    unimplemented!();
}