diff --git a/README.md b/README.md index 926a2064..fe4cc9e5 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,8 @@ I'm very new to Rust, so any help is appreciated when it comes to improving deve - [x] Current Node.js version(`⬢`). - [x] Current Rust version (`🦀`). - [x] Current Python version (`🐍`). -- [ ] Package version of package in current directory (`📦`). +- [x] Current Go version (`🐹`). +- [x] Package version of package in current directory (`📦`). - [ ] Current battery level and status - [ ] Current Git branch and rich repo status. - [ ] Indicator for jobs in the background (`✦`). diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e3af9504..8bb7e572 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -56,6 +56,10 @@ jobs: - task: NodeTool@0 inputs: versionSpec: "12.0.0" + # Install Go + - task: GoTool@0 + inputs: + versionSpec: "1.10" # Install Rust at a fixed version for integration tests - template: ".build/install-rust.yml" parameters: diff --git a/src/modules/go.rs b/src/modules/go.rs new file mode 100644 index 00000000..f6b2f2c9 --- /dev/null +++ b/src/modules/go.rs @@ -0,0 +1,96 @@ +use ansi_term::Color; +use std::path::PathBuf; +use std::process::Command; + +use super::{Context, Module}; + +/// Creates a segment with the current Python version +/// +/// Will display the Python version if any of the following criteria are met: +/// - Current directory contains a `.go` file +/// - Current directory contains a `go.mod` file +/// - Current directory contains a `go.sum` file +/// - Current directory contains a `Godeps` directory +/// - Current directory contains a `glide.yaml` file +/// - Current directory contains a `Gopkg.yml` file +/// - Current directory contains a `Gopkg.lock` file +pub fn segment(context: &Context) -> Option { + let is_go_project = context.dir_files.iter().any(has_go_files); + if !is_go_project { + return None; + } + + const GO_CHAR: &str = "🐹 "; + let module_color = Color::Cyan.bold(); + + let mut module = Module::new("go"); + module.set_style(module_color); + + let go_version = get_go_version()?; + let formatted_version = format_go_version(go_version)?; + module.new_segment("symbol", GO_CHAR); + module.new_segment("version", formatted_version); + + Some(module) +} + +fn has_go_files(dir_entry: &PathBuf) -> bool { + let is_go_mod = + |d: &PathBuf| -> bool { d.is_file() && d.file_name().unwrap_or_default() == "go.mod" }; + let is_go_sum = + |d: &PathBuf| -> bool { d.is_file() && d.file_name().unwrap_or_default() == "go.sum" }; + let is_godeps = + |d: &PathBuf| -> bool { d.is_dir() && d.file_name().unwrap_or_default() == "Godeps" }; + let is_glide_yaml = + |d: &PathBuf| -> bool { d.is_file() && d.file_name().unwrap_or_default() == "glide.yaml" }; + let is_go_file = + |d: &PathBuf| -> bool { d.is_file() && d.extension().unwrap_or_default() == "go" }; + let is_gopkg_yml = + |d: &PathBuf| -> bool { d.is_file() && d.file_name().unwrap_or_default() == "Gopkg.yml" }; + let is_gopkg_lock = + |d: &PathBuf| -> bool { d.is_file() && d.file_name().unwrap_or_default() == "Gopkg.lock" }; + + is_go_mod(&dir_entry) + || is_go_sum(&dir_entry) + || is_godeps(&dir_entry) + || is_glide_yaml(&dir_entry) + || is_go_file(&dir_entry) + || is_gopkg_yml(&dir_entry) + || is_gopkg_lock(&dir_entry) +} + +fn get_go_version() -> Option { + Command::new("go") + .arg("version") + .output() + .ok() + .and_then(|output| String::from_utf8(output.stdout).ok()) +} + +fn format_go_version(go_stdout: String) -> Option { + let mut version = go_stdout + // split into ["", "1.12.4 linux/amd64"] + .splitn(2, "go version go") + // return "1.12.4 linux/amd64" + .nth(1)? + // split into ["1.12.4", "linux/amd64"] + .split_whitespace() + // return "1.12.4" + .next()?; + + let mut formatted_version = String::with_capacity(version.len() + 1); + formatted_version.push('v'); + formatted_version.push_str(version); + Some(formatted_version) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_format_go_version() { + let input = String::from("go version go1.12 darwin/amd64"); + assert_eq!(format_go_version(input), Some("v1.12".to_string())); + } +} diff --git a/src/modules/mod.rs b/src/modules/mod.rs index 911486c4..2a9f433b 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -1,6 +1,7 @@ mod character; mod directory; mod git_branch; +mod go; mod line_break; mod nodejs; mod package; @@ -17,6 +18,7 @@ pub fn handle(module: &str, context: &Context) -> Option { "node" | "nodejs" => nodejs::segment(context), "rust" | "rustlang" => rust::segment(context), "python" => python::segment(context), + "go" | "golang" => go::segment(context), "line_break" => line_break::segment(context), "package" => package::segment(context), "git_branch" => git_branch::segment(context), diff --git a/src/print.rs b/src/print.rs index 3020f9de..2f26ddcc 100644 --- a/src/print.rs +++ b/src/print.rs @@ -14,6 +14,7 @@ pub fn prompt(args: ArgMatches) { "nodejs", "rust", "python", + "go", "line_break", "character", ]; diff --git a/tests/Dockerfile b/tests/Dockerfile index bd1bcaa4..80757356 100644 --- a/tests/Dockerfile +++ b/tests/Dockerfile @@ -9,15 +9,31 @@ RUN curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | ba && nvm use default ENV PATH /root/.nvm/versions/node/v$NODE_VERSION/bin:$PATH # Check that Node.js was correctly installed -RUN node --version +RUN node --version + +# Install Go +ENV GO_VERSION 1.10.0 +ENV GOENV_ROOT /root/.goenv +ENV GO_ROOT /root/go +# RUN git clone https://github.com/wfarr/goenv.git $GOENV_ROOT +RUN git clone https://github.com/syndbg/goenv.git $GOENV_ROOT +ENV PATH $GOENV_ROOT/bin:$GOENV_ROOT/shims:$PATH +RUN eval "$(goenv init -)" +RUN mkdir -p $GO_ROOT +ENV GOPATH $GO_ROOT +ENV PATH $GO_ROOT/bin:$PATH +RUN goenv install $GO_VERSION +RUN goenv global $GO_VERSION +# Check that Go was correctly installed +RUN go version # Create blank project RUN USER=root cargo new --bin starship WORKDIR /starship # We want dependencies cached, so copy those first -COPY ./Cargo.lock ./Cargo.lock -COPY ./Cargo.toml ./Cargo.toml +COPY ./Cargo.lock ./Cargo.lock +COPY ./Cargo.toml ./Cargo.toml # Cargo.toml will fail to parse without my_benchmark RUN mkdir benches diff --git a/tests/go.rs b/tests/go.rs new file mode 100644 index 00000000..369530ab --- /dev/null +++ b/tests/go.rs @@ -0,0 +1,134 @@ +use ansi_term::Color; +use starship::segment::Segment; +use std::fs::{self, File}; +use std::io; +use tempfile::TempDir; + +mod common; + +#[test] +#[ignore] +fn folder_with_go_file() -> io::Result<()> { + let dir = TempDir::new()?; + File::create(dir.path().join("main.go"))?; + + let expected = format!( + "via {} ", + Segment::new("go") + .set_value("🐹 v1.10") + .set_style(Color::Cyan.bold()) + ); + let actual = common::render_module("go", &dir.path()); + assert_eq!(expected, actual); + + Ok(()) +} + +#[test] +#[ignore] +fn folder_with_go_mod() -> io::Result<()> { + let dir = TempDir::new()?; + File::create(dir.path().join("go.mod"))?; + + let expected = format!( + "via {} ", + Segment::new("go") + .set_value("🐹 v1.10") + .set_style(Color::Cyan.bold()) + ); + let actual = common::render_module("go", &dir.path()); + assert_eq!(expected, actual); + + Ok(()) +} + +#[test] +#[ignore] +fn folder_with_go_sum() -> io::Result<()> { + let dir = TempDir::new()?; + File::create(dir.path().join("go.sum"))?; + + let expected = format!( + "via {} ", + Segment::new("go") + .set_value("🐹 v1.10") + .set_style(Color::Cyan.bold()) + ); + let actual = common::render_module("go", &dir.path()); + assert_eq!(expected, actual); + + Ok(()) +} + +#[test] +#[ignore] +fn folder_with_godeps() -> io::Result<()> { + let dir = TempDir::new()?; + let godeps = dir.path().join("Godeps"); + fs::create_dir_all(&godeps)?; + + let expected = format!( + "via {} ", + Segment::new("go") + .set_value("🐹 v1.10") + .set_style(Color::Cyan.bold()) + ); + let actual = common::render_module("go", &dir.path()); + assert_eq!(expected, actual); + + Ok(()) +} + +#[test] +#[ignore] +fn folder_with_glide_yaml() -> io::Result<()> { + let dir = TempDir::new()?; + File::create(dir.path().join("glide.yaml"))?; + + let expected = format!( + "via {} ", + Segment::new("go") + .set_value("🐹 v1.10") + .set_style(Color::Cyan.bold()) + ); + let actual = common::render_module("go", &dir.path()); + assert_eq!(expected, actual); + + Ok(()) +} + +#[test] +#[ignore] +fn folder_with_gopkg_yml() -> io::Result<()> { + let dir = TempDir::new()?; + File::create(dir.path().join("Gopkg.yml"))?; + + let expected = format!( + "via {} ", + Segment::new("go") + .set_value("🐹 v1.10") + .set_style(Color::Cyan.bold()) + ); + let actual = common::render_module("go", &dir.path()); + assert_eq!(expected, actual); + + Ok(()) +} + +#[test] +#[ignore] +fn folder_with_gopkg_lock() -> io::Result<()> { + let dir = TempDir::new()?; + File::create(dir.path().join("Gopkg.lock"))?; + + let expected = format!( + "via {} ", + Segment::new("go") + .set_value("🐹 v1.10") + .set_style(Color::Cyan.bold()) + ); + let actual = common::render_module("go", &dir.path()); + assert_eq!(expected, actual); + + Ok(()) +}