feat: Add pulumi module (#3055)
This commit is contained in:
parent
190743e4e0
commit
dfb1208787
|
@ -160,7 +160,16 @@ dependencies = [
|
|||
"block-padding",
|
||||
"byte-tools",
|
||||
"byteorder",
|
||||
"generic-array",
|
||||
"generic-array 0.12.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
|
||||
dependencies = [
|
||||
"generic-array 0.14.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -301,6 +310,15 @@ version = "0.8.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.1"
|
||||
|
@ -368,7 +386,16 @@ version = "0.8.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"generic-array 0.12.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
|
||||
dependencies = [
|
||||
"generic-array 0.14.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -630,6 +657,16 @@ dependencies = [
|
|||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gethostname"
|
||||
version = "0.2.1"
|
||||
|
@ -1079,6 +1116,12 @@ version = "0.2.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||
|
||||
[[package]]
|
||||
name = "open"
|
||||
version = "2.0.1"
|
||||
|
@ -1217,7 +1260,7 @@ checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
|
|||
dependencies = [
|
||||
"maplit",
|
||||
"pest",
|
||||
"sha-1",
|
||||
"sha-1 0.8.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1627,10 +1670,23 @@ version = "0.8.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"digest",
|
||||
"block-buffer 0.7.3",
|
||||
"digest 0.8.1",
|
||||
"fake-simd",
|
||||
"opaque-debug",
|
||||
"opaque-debug 0.2.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha-1"
|
||||
version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6"
|
||||
dependencies = [
|
||||
"block-buffer 0.9.0",
|
||||
"cfg-if 1.0.0",
|
||||
"cpufeatures",
|
||||
"digest 0.9.0",
|
||||
"opaque-debug 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1699,6 +1755,7 @@ dependencies = [
|
|||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha-1 0.9.8",
|
||||
"shadow-rs",
|
||||
"shell-words",
|
||||
"starship_module_config_derive",
|
||||
|
|
|
@ -69,6 +69,7 @@ which = "4.2.2"
|
|||
shadow-rs = "0.7.1"
|
||||
versions = "3.0.3"
|
||||
strsim = "0.10.0"
|
||||
sha-1 = "0.9.8"
|
||||
|
||||
process_control = { version = "3.1.0", features = ["crossbeam-channel"] }
|
||||
|
||||
|
|
|
@ -221,6 +221,7 @@ $nodejs\
|
|||
$ocaml\
|
||||
$perl\
|
||||
$php\
|
||||
$pulumi\
|
||||
$purescript\
|
||||
$python\
|
||||
$rlang\
|
||||
|
@ -2349,6 +2350,64 @@ By default the module will be shown if any of the following conditions are met:
|
|||
format = "via [🔹 $version](147 bold) "
|
||||
```
|
||||
|
||||
## Pulumi
|
||||
|
||||
The `pulumi` module shows the currently selected [Pulumi Stack](https://www.pulumi.com/docs/intro/concepts/stack/) and version.
|
||||
|
||||
::: tip
|
||||
|
||||
By default the Pulumi version is not shown, since it takes an order of magnitude longer to load then most plugins (~70ms).
|
||||
If you still want to enable it, [follow the example shown below](#with-pulumi-version).
|
||||
|
||||
:::
|
||||
|
||||
By default the module will be shown if any of the following conditions are met:
|
||||
|
||||
- The current directory contains either `Pulumi.yaml` or `Pulumi.yml`
|
||||
- A parent directory contains either `Pulumi.yaml` or `Pulumi.yml`
|
||||
|
||||
### Options
|
||||
|
||||
| Option | Default | Description |
|
||||
| ------------------- | ------------------------------------ | ------------------------------------------------------------------------- |
|
||||
| `format` | `"via [$symbol$stack]($style) "` | The format string for the module. |
|
||||
| `version_format` | `"v${raw}"` | The version format. Available vars are `raw`, `major`, `minor`, & `patch` |
|
||||
| `symbol` | `" "` | A format string shown before the Pulumi stack. |
|
||||
| `style` | `"bold 5"` | The style for the module. |
|
||||
| `disabled` | `false` | Disables the `pulumi` module. |
|
||||
|
||||
### Variables
|
||||
|
||||
| Variable | Example | Description |
|
||||
| -------- | ---------- | ------------------------------------ |
|
||||
| version | `v0.12.24` | The version of `pulumi` |
|
||||
| stack | `dev` | The current Pulumi stack |
|
||||
| symbol | | Mirrors the value of option `symbol` |
|
||||
| style\* | | Mirrors the value of option `style` |
|
||||
|
||||
\*: This variable can only be used as a part of a style string
|
||||
|
||||
### Example
|
||||
|
||||
#### With Pulumi Version
|
||||
|
||||
```toml
|
||||
# ~/.config/starship.toml
|
||||
|
||||
[pulumi]
|
||||
format = "[🛥 ($version )$stack]($style) "
|
||||
```
|
||||
|
||||
#### Without Pulumi version
|
||||
|
||||
```toml
|
||||
# ~/.config/starship.toml
|
||||
[pulumi]
|
||||
symbol = "🛥 "
|
||||
format = "[$symbol$stack]($style) "
|
||||
|
||||
```
|
||||
|
||||
## PureScript
|
||||
|
||||
The `purescript` module shows the currently installed version of [PureScript](https://www.purescript.org/) version.
|
||||
|
|
|
@ -205,6 +205,9 @@ format = '\[[$symbol($version)]($style)\]'
|
|||
[php]
|
||||
format = '\[[$symbol($version)]($style)\]'
|
||||
|
||||
[pulumi]
|
||||
format = '\[[$symbol$stack]($style)\]'
|
||||
|
||||
[purescript]
|
||||
format = '\[[$symbol($version)]($style)\]'
|
||||
|
||||
|
@ -354,6 +357,9 @@ symbol = "pl "
|
|||
[php]
|
||||
symbol = "php "
|
||||
|
||||
[pulumi]
|
||||
symbol = "pulumi "
|
||||
|
||||
[purescript]
|
||||
symbol = "purs "
|
||||
|
||||
|
@ -439,6 +445,9 @@ format = 'via [$symbol]($style)'
|
|||
[php]
|
||||
format = 'via [$symbol]($style)'
|
||||
|
||||
[pulumi]
|
||||
format = 'via [$symbol$stack]($style)'
|
||||
|
||||
[purescript]
|
||||
format = 'via [$symbol]($style)'
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ pub mod openstack;
|
|||
pub mod package;
|
||||
pub mod perl;
|
||||
pub mod php;
|
||||
pub mod pulumi;
|
||||
pub mod purescript;
|
||||
pub mod python;
|
||||
pub mod red;
|
||||
|
@ -125,6 +126,7 @@ pub struct FullConfig<'a> {
|
|||
package: package::PackageConfig<'a>,
|
||||
perl: perl::PerlConfig<'a>,
|
||||
php: php::PhpConfig<'a>,
|
||||
pulumi: pulumi::PulumiConfig<'a>,
|
||||
purescript: purescript::PureScriptConfig<'a>,
|
||||
python: python::PythonConfig<'a>,
|
||||
red: red::RedConfig<'a>,
|
||||
|
@ -200,6 +202,7 @@ impl<'a> Default for FullConfig<'a> {
|
|||
package: Default::default(),
|
||||
perl: Default::default(),
|
||||
php: Default::default(),
|
||||
pulumi: Default::default(),
|
||||
purescript: Default::default(),
|
||||
python: Default::default(),
|
||||
red: Default::default(),
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
use crate::config::ModuleConfig;
|
||||
|
||||
use serde::Serialize;
|
||||
use starship_module_config_derive::ModuleConfig;
|
||||
|
||||
#[derive(Clone, ModuleConfig, Serialize)]
|
||||
pub struct PulumiConfig<'a> {
|
||||
pub format: &'a str,
|
||||
pub version_format: &'a str,
|
||||
pub symbol: &'a str,
|
||||
pub style: &'a str,
|
||||
pub disabled: bool,
|
||||
}
|
||||
|
||||
impl<'a> Default for PulumiConfig<'a> {
|
||||
fn default() -> Self {
|
||||
PulumiConfig {
|
||||
format: "via [$symbol$stack]($style) ",
|
||||
version_format: "v${raw}",
|
||||
symbol: " ",
|
||||
style: "bold 5",
|
||||
disabled: false,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -53,6 +53,7 @@ pub const PROMPT_ORDER: &[&str] = &[
|
|||
"ocaml",
|
||||
"perl",
|
||||
"php",
|
||||
"pulumi",
|
||||
"purescript",
|
||||
"python",
|
||||
"rlang",
|
||||
|
|
|
@ -53,6 +53,7 @@ pub const ALL_MODULES: &[&str] = &[
|
|||
"package",
|
||||
"perl",
|
||||
"php",
|
||||
"pulumi",
|
||||
"purescript",
|
||||
"python",
|
||||
"red",
|
||||
|
|
|
@ -43,6 +43,7 @@ mod openstack;
|
|||
mod package;
|
||||
mod perl;
|
||||
mod php;
|
||||
mod pulumi;
|
||||
mod purescript;
|
||||
mod python;
|
||||
mod red;
|
||||
|
@ -125,6 +126,7 @@ pub fn handle<'a>(module: &str, context: &'a Context) -> Option<Module<'a>> {
|
|||
"package" => package::module(context),
|
||||
"perl" => perl::module(context),
|
||||
"php" => php::module(context),
|
||||
"pulumi" => pulumi::module(context),
|
||||
"purescript" => purescript::module(context),
|
||||
"python" => python::module(context),
|
||||
"rlang" => rlang::module(context),
|
||||
|
@ -212,6 +214,7 @@ pub fn description(module: &str) -> &'static str {
|
|||
"package" => "The package version of the current directory's project",
|
||||
"perl" => "The currently installed version of Perl",
|
||||
"php" => "The currently installed version of PHP",
|
||||
"pulumi" => "The current stack and installed version of Pulumi",
|
||||
"purescript" => "The currently installed version of PureScript",
|
||||
"python" => "The currently installed version of Python",
|
||||
"red" => "The currently installed version of Red",
|
||||
|
|
|
@ -0,0 +1,296 @@
|
|||
#![warn(missing_docs)]
|
||||
use sha1::{Digest, Sha1};
|
||||
use std::ffi::OsStr;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
use yaml_rust::{Yaml, YamlLoader};
|
||||
|
||||
use super::{Context, Module, RootModuleConfig};
|
||||
use crate::configs::pulumi::PulumiConfig;
|
||||
use crate::formatter::{StringFormatter, VersionFormatter};
|
||||
|
||||
static PULUMI_HOME: &str = "PULUMI_HOME";
|
||||
|
||||
/// Creates a module with the current Pulumi version and stack name.
|
||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
let mut module = context.new_module("pulumi");
|
||||
let config = PulumiConfig::try_load(module.config);
|
||||
|
||||
let project_file = find_package_file(&context.logical_dir)?;
|
||||
|
||||
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
|
||||
formatter
|
||||
.map_meta(|variable, _| match variable {
|
||||
"symbol" => Some(config.symbol),
|
||||
_ => None,
|
||||
})
|
||||
.map_style(|variable| match variable {
|
||||
"style" => Some(Ok(config.style)),
|
||||
_ => None,
|
||||
})
|
||||
.map(|variable| match variable {
|
||||
"version" => {
|
||||
let stdout = context.exec_cmd("pulumi", &["version"])?.stdout;
|
||||
VersionFormatter::format_module_version(
|
||||
module.get_name(),
|
||||
parse_version(&stdout),
|
||||
config.version_format,
|
||||
)
|
||||
}
|
||||
.map(Ok),
|
||||
"stack" => stack_name(&project_file, context).map(Ok),
|
||||
_ => None,
|
||||
})
|
||||
.parse(None)
|
||||
});
|
||||
|
||||
match parsed {
|
||||
Ok(x) => {
|
||||
module.set_segments(x);
|
||||
Some(module)
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("Error in module `pulumi`:\n{}", e);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse the output of `pulumi version` into just the version string.
|
||||
///
|
||||
/// Normally, this just means returning it. When Pulumi is being developed, it
|
||||
/// can return results like `3.12.0-alpha.1630554544+f89e9a29.dirty`, which we
|
||||
/// don't want to see. Instead we display that as `3.12.0-alpha`.
|
||||
fn parse_version(version: &str) -> &str {
|
||||
let mut periods = 0;
|
||||
for (i, c) in version.as_bytes().iter().enumerate() {
|
||||
if *c == b'.' {
|
||||
if periods == 2 {
|
||||
return &version[0..i];
|
||||
} else {
|
||||
periods += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// We didn't hit 3 periods, so we just return the whole string.
|
||||
version
|
||||
}
|
||||
|
||||
/// Find a file describing a Pulumi package in the current directory (or any parrent directory).
|
||||
fn find_package_file(path: &Path) -> Option<PathBuf> {
|
||||
for path in path.ancestors() {
|
||||
log::trace!("Looking for package file in {:?}", path);
|
||||
let dir = std::fs::read_dir(path).ok()?;
|
||||
let goal = dir.filter_map(Result::ok).find(|path| {
|
||||
path.file_name() == OsStr::new("Pulumi.yaml")
|
||||
|| path.file_name() == OsStr::new("Pulumi.yml")
|
||||
});
|
||||
if let Some(goal) = goal {
|
||||
return Some(goal.path());
|
||||
}
|
||||
}
|
||||
log::trace!("Did not find a Pulumi package file");
|
||||
None
|
||||
}
|
||||
|
||||
/// We get the name of the current stack.
|
||||
///
|
||||
/// Pulumi has no CLI option that is fast enough to get this for us, but finding
|
||||
/// the location is simple. We get it ourselves.
|
||||
fn stack_name(project_file: &Path, context: &Context) -> Option<String> {
|
||||
let mut file = File::open(&project_file).ok()?;
|
||||
|
||||
let mut contents = String::new();
|
||||
file.read_to_string(&mut contents).ok()?;
|
||||
let name = YamlLoader::load_from_str(&contents).ok().and_then(
|
||||
|yaml| -> Option<Option<String>> {
|
||||
log::trace!("Parsed {:?} into yaml", project_file);
|
||||
let yaml = yaml.into_iter().next()?;
|
||||
yaml.into_hash().map(|mut hash| -> Option<String> {
|
||||
hash.remove(&Yaml::String("name".to_string()))?
|
||||
.into_string()
|
||||
})
|
||||
},
|
||||
)??;
|
||||
log::trace!("Found project name: {:?}", name);
|
||||
|
||||
let workspace_file = get_pulumi_workspace(context, &name, project_file)
|
||||
.map(File::open)?
|
||||
.ok()?;
|
||||
log::trace!("Trying to read workspace_file: {:?}", workspace_file);
|
||||
let workspace: serde_json::Value = match serde_json::from_reader(workspace_file) {
|
||||
Ok(k) => k,
|
||||
Err(e) => {
|
||||
log::debug!("Failed to parse workspace file: {}", e);
|
||||
return None;
|
||||
}
|
||||
};
|
||||
log::trace!("Read workspace_file: {:?}", workspace);
|
||||
workspace
|
||||
.as_object()?
|
||||
.get("stack")?
|
||||
.as_str()
|
||||
.map(ToString::to_string)
|
||||
}
|
||||
|
||||
/// Calculates the path of the workspace settings file for a given pulumi stack.
|
||||
fn get_pulumi_workspace(context: &Context, name: &str, project_file: &Path) -> Option<PathBuf> {
|
||||
let project_file = if cfg!(test) {
|
||||
// Because this depends on the absolute path of the file, it changes in
|
||||
// each test run. We thus mock it.
|
||||
"test".to_string()
|
||||
} else {
|
||||
let mut hasher = Sha1::new();
|
||||
hasher.update(project_file.to_str()?.as_bytes());
|
||||
crate::utils::encode_to_hex(&hasher.finalize().to_vec())
|
||||
};
|
||||
let unique_file_name = format!("{}-{}-workspace.json", name, project_file);
|
||||
let mut path = pulumi_home_dir(context)?;
|
||||
path.push("workspaces");
|
||||
path.push(unique_file_name);
|
||||
Some(path)
|
||||
}
|
||||
|
||||
/// Get the Pulumi home directory. We first check `PULUMI_HOME`. If that isn't
|
||||
/// set, we return `$HOME/.pulumi`.
|
||||
fn pulumi_home_dir(context: &Context) -> Option<PathBuf> {
|
||||
if let Some(k) = context.get_env(PULUMI_HOME) {
|
||||
std::path::PathBuf::from_str(&k).ok()
|
||||
} else {
|
||||
context.get_home().map(|p| p.join(".pulumi"))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::io;
|
||||
|
||||
use super::*;
|
||||
use crate::test::ModuleRenderer;
|
||||
use ansi_term::Color;
|
||||
use clap::ArgMatches;
|
||||
|
||||
#[test]
|
||||
fn pulumi_version_release() {
|
||||
let input = "3.12.0";
|
||||
assert_eq!(parse_version(input), input);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pulumi_version_prerelease() {
|
||||
let input = "3.12.0-alpha";
|
||||
assert_eq!(parse_version(input), input);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pulumi_version_dirty() {
|
||||
let input = "3.12.0-alpha.1630554544+f89e9a29.dirty";
|
||||
assert_eq!(parse_version(input), "3.12.0-alpha");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_home_dir() {
|
||||
let mut context = Context::new(ArgMatches::default());
|
||||
context.env.insert("HOME", "/home/sweet/home".to_string());
|
||||
assert_eq!(
|
||||
pulumi_home_dir(&context),
|
||||
Some(PathBuf::from("/home/sweet/home/.pulumi"))
|
||||
);
|
||||
context.env.insert("PULUMI_HOME", "/a/dir".to_string());
|
||||
assert_eq!(pulumi_home_dir(&context), Some(PathBuf::from("/a/dir")))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_pulumi_workspace() {
|
||||
let mut context = Context::new(ArgMatches::default());
|
||||
context.env.insert("HOME", "/home/sweet/home".to_string());
|
||||
let name = "foobar";
|
||||
let project_file = PathBuf::from("/hello/Pulumi.yaml");
|
||||
assert_eq!(
|
||||
get_pulumi_workspace(&context, name, &project_file),
|
||||
Some("/home/sweet/home/.pulumi/workspaces/foobar-test-workspace.json")
|
||||
.map(PathBuf::from)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn version_render() -> io::Result<()> {
|
||||
let dir = tempfile::tempdir()?;
|
||||
let pulumi_file = File::create(dir.path().join("Pulumi.yaml"))?;
|
||||
pulumi_file.sync_all()?;
|
||||
let rendered = ModuleRenderer::new("pulumi")
|
||||
.path(dir.path())
|
||||
.config(toml::toml! {
|
||||
[pulumi]
|
||||
format = "with [$version]($style) "
|
||||
})
|
||||
.collect();
|
||||
dir.close()?;
|
||||
let expected = format!("with {} ", Color::Fixed(5).bold().paint("v1.2.3-ver"));
|
||||
|
||||
assert_eq!(expected, rendered.expect("a result"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// This test confirms a full render. This means finding a Pulumi.yml file,
|
||||
/// tracing back to the backing workspace settings file, and printing the
|
||||
/// stack name.
|
||||
fn render_valid_paths() -> io::Result<()> {
|
||||
use io::Write;
|
||||
let dir = tempfile::tempdir()?;
|
||||
let root = std::fs::canonicalize(dir.path())?;
|
||||
let mut yaml = File::create(root.join("Pulumi.yml"))?;
|
||||
yaml.write_all("name: starship\nruntime: nodejs\ndescription: A thing\n".as_bytes())?;
|
||||
yaml.sync_all()?;
|
||||
|
||||
let workspace_path = root.join(".pulumi").join("workspaces");
|
||||
let _ = std::fs::create_dir_all(&workspace_path)?;
|
||||
let workspace_path = &workspace_path.join("starship-test-workspace.json");
|
||||
let mut workspace = File::create(&workspace_path)?;
|
||||
serde_json::to_writer_pretty(
|
||||
&mut workspace,
|
||||
&serde_json::json!(
|
||||
{
|
||||
"stack": "launch"
|
||||
}
|
||||
),
|
||||
)?;
|
||||
workspace.sync_all()?;
|
||||
let rendered = ModuleRenderer::new("pulumi")
|
||||
.path(root.clone())
|
||||
.logical_path(root.clone())
|
||||
.config(toml::toml! {
|
||||
[pulumi]
|
||||
format = "in [$symbol($stack)]($style) "
|
||||
})
|
||||
.env("HOME", root.to_str().unwrap())
|
||||
.collect();
|
||||
let expected = format!("in {} ", Color::Fixed(5).bold().paint(" launch"));
|
||||
assert_eq!(expected, rendered.expect("a result"));
|
||||
dir.close()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_config_file() -> io::Result<()> {
|
||||
let dir = tempfile::tempdir()?;
|
||||
let yaml = File::create(dir.path().join("Pulumi.yaml"))?;
|
||||
yaml.sync_all()?;
|
||||
|
||||
let rendered = ModuleRenderer::new("pulumi")
|
||||
.path(dir.path())
|
||||
.logical_path(dir.path())
|
||||
.config(toml::toml! {
|
||||
[pulumi]
|
||||
format = "in [$symbol($stack)]($style) "
|
||||
})
|
||||
.collect();
|
||||
let expected = format!("in {} ", Color::Fixed(5).bold().paint(" "));
|
||||
assert_eq!(expected, rendered.expect("a result"));
|
||||
dir.close()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
29
src/utils.rs
29
src/utils.rs
|
@ -224,7 +224,11 @@ active boot switches: -d:release\n",
|
|||
stdout: String::from("7.3.8"),
|
||||
stderr: String::default(),
|
||||
})
|
||||
}
|
||||
},
|
||||
"pulumi version" => Some(CommandOutput{
|
||||
stdout: String::from("1.2.3-ver.1631311768+e696fb6c"),
|
||||
stderr: String::default(),
|
||||
}),
|
||||
"purs --version" => Some(CommandOutput {
|
||||
stdout: String::from("0.13.5\n"),
|
||||
stderr: String::default(),
|
||||
|
@ -499,6 +503,21 @@ pub fn home_dir() -> Option<PathBuf> {
|
|||
directories_next::BaseDirs::new().map(|base_dirs| base_dirs.home_dir().to_owned())
|
||||
}
|
||||
|
||||
const HEXTABLE: &[char] = &[
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||
];
|
||||
|
||||
/// Encode a u8 slice into a hexadecimal string.
|
||||
pub fn encode_to_hex(slice: &[u8]) -> String {
|
||||
// let mut j = 0;
|
||||
let mut dst = Vec::with_capacity(slice.len() * 2);
|
||||
for &v in slice {
|
||||
dst.push(HEXTABLE[(v >> 4) as usize] as u8);
|
||||
dst.push(HEXTABLE[(v & 0x0f) as usize] as u8);
|
||||
}
|
||||
String::from_utf8(dst).unwrap()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -709,4 +728,12 @@ mod tests {
|
|||
};
|
||||
assert_eq!(get_command_string_output(case2), "stderr");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sha1_hex() {
|
||||
assert_eq!(
|
||||
encode_to_hex(&[8, 13, 9, 189, 129, 94]),
|
||||
"080d09bd815e".to_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue