Skip to content
This repository has been archived by the owner on Oct 23, 2023. It is now read-only.

Commit

Permalink
New which implementation (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
jpalomaki authored Aug 9, 2021
1 parent 4fe8cfe commit e1403da
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 107 deletions.
58 changes: 29 additions & 29 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "terve"
version = "0.6.0-beta.1"
version = "0.6.0-beta.2"
edition = "2018"

[dependencies]
Expand All @@ -14,7 +14,6 @@ sha2 = "~0.9"
hex = "~0.4"
pgp = "~0.7"
bytes = "~1.0"
same-file = "~1.0"

[dependencies.reqwest]
version = "~0.11"
Expand All @@ -28,6 +27,7 @@ features = ["https"]
[dev-dependencies]
assert_cmd = "~1.0"
predicates = "~2.0"
same-file = "~1.0"

[profile.release]
codegen-units = 1
Expand Down
26 changes: 16 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

![Release](https://img.shields.io/github/v/release/superblk/terve)
![License](https://img.shields.io/github/license/superblk/terve)
![OS](https://img.shields.io/badge/os-Linux%20%7C%20MacOS%20%7C%20Windows-ff69b4)
![OS](https://img.shields.io/badge/os-Linux%20%7C%20macOS%20%7C%20Windows-ff69b4)

Unified, minimal [terraform](https://www.terraform.io/downloads.html) and [terragrunt](https://github.com/gruntwork-io/terragrunt/releases) version manager.

Expand Down Expand Up @@ -47,14 +47,20 @@ All files are kept in directory `~/.terve` like so (example directory tree for L
│   └── terragrunt
├── etc
│   └── terraform.asc
└── opt
├── opt
│   ├── terraform
│   │   ├── 0.1.0
│   │   ├── 1.0.2
│   │   └── 1.0.3
│   └── terragrunt
│   ├── 0.0.4
│   ├── 0.1.0
│   └── 0.31.2
└── var
├── terraform
│   ├── 0.14.11
│   └── 0.15.4
│   └── version
└── terragrunt
├── 0.28.10
├── 0.28.39
└── 0.29.4
└── version
```

## Usage
Expand Down Expand Up @@ -92,7 +98,7 @@ WARNING: terragrunt releases < `0.18.1` do not ship `SHA256SUMS` files, so their

### Select

Selects a specific version for use. That version must be installed first.
Selects an installed version for use.

Syntax: `terve s[elect] <binary> <semver>`

Expand All @@ -101,7 +107,7 @@ Syntax: `terve s[elect] <binary> <semver>`

### Remove

Removes a specific version. If that version is currently selected, the selection will be reset.
Removes an installed version. NOTE: does not reset selection

Syntax: `terve r[emove] <binary> <semver>`

Expand All @@ -110,7 +116,7 @@ Syntax: `terve r[emove] <binary> <semver>`

### Which

Tells which version is selected.
Tells which version is currently selected.

Syntax: `terve w[hich] <binary>`

Expand Down
53 changes: 18 additions & 35 deletions src/shared.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use std::{
error::Error,
fmt::Display,
fs::{create_dir_all, hard_link, read_dir, remove_file},
fs::{create_dir_all, hard_link, read_dir, read_to_string, remove_file, write},
path::{Path, PathBuf},
str::FromStr,
};

use crate::utils::{self, is_same_file};
use semver::{Prerelease, Version};

use crate::utils::{git_list_remote_tags, to_sorted_multiline_string};

pub enum Action {
List,
Install,
Expand Down Expand Up @@ -88,6 +89,7 @@ pub struct DotDir {
pub bin: PathBuf,
pub etc: PathBuf,
pub opt: PathBuf,
pub var: PathBuf,
}

impl DotDir {
Expand All @@ -96,27 +98,31 @@ impl DotDir {
let bin = root.join("bin");
let etc = root.join("etc");
let opt = root.join("opt");
let var = root.join("var");
create_dir_all(&bin)?;
create_dir_all(&etc)?;
create_dir_all(opt.join(Binary::Terraform))?;
create_dir_all(opt.join(Binary::Terragrunt))?;
create_dir_all(var.join(Binary::Terraform))?;
create_dir_all(var.join(Binary::Terragrunt))?;
Ok(DotDir {
root,
bin,
etc,
opt,
var,
})
}
}

pub fn list_available_versions(git_repo_url: &str) -> Result<String, Box<dyn Error>> {
let mut versions: Vec<Version> = utils::git_list_remote_tags(git_repo_url)?
let mut versions: Vec<Version> = git_list_remote_tags(git_repo_url)?
.iter()
.map(|t| t.trim_start_matches('v'))
.filter_map(|s| Version::parse(s).ok())
.filter(|v| v.pre == Prerelease::EMPTY)
.collect();
let result = utils::to_sorted_multiline_string(&mut versions);
let result = to_sorted_multiline_string(&mut versions);
Ok(result)
}

Expand All @@ -127,7 +133,7 @@ pub fn list_installed_versions(binary: Binary, dot_dir: DotDir) -> Result<String
.filter_map(|p| Some(p.strip_prefix(&opt_dir).ok()?.to_owned()))
.filter_map(|p| Version::parse(p.to_string_lossy().as_ref()).ok())
.collect();
let result = utils::to_sorted_multiline_string(&mut installed_versions);
let result = to_sorted_multiline_string(&mut installed_versions);
Ok(result)
}

Expand All @@ -142,13 +148,11 @@ pub fn select_binary_version(
}
let bin_file_path = dot_dir.bin.join(&binary);
if bin_file_path.exists() {
if !is_same_file(&bin_file_path, &opt_file_path)? {
remove_file(&bin_file_path)?;
hard_link(&opt_file_path, &bin_file_path)?;
}
} else {
hard_link(&opt_file_path, &bin_file_path)?;
remove_file(&bin_file_path)?;
}
hard_link(&opt_file_path, &bin_file_path)?;
let version_file_path = dot_dir.var.join(&binary).join("version");
write(version_file_path, &version)?;
Ok(format!("Selected {} {}", binary, version))
}

Expand All @@ -159,39 +163,18 @@ pub fn remove_binary_version(
) -> Result<String, Box<dyn Error>> {
let opt_file_path = dot_dir.opt.join(&binary).join(&version);
if opt_file_path.exists() {
let bin_file_path = dot_dir.bin.join(&binary);
if bin_file_path.exists() && is_same_file(&opt_file_path, &bin_file_path)? {
remove_file(bin_file_path)?;
}
remove_file(&opt_file_path)?;
}
Ok(format!("Removed {} {}", binary, version))
}

// We use hard links, so we need to compare the executable ~/.terve/bin/<binary>
// to all ~/.terve/opt/<binary>/<version> files (version is encoded in file name)
pub fn get_selected_version(binary: Binary, dot_dir: DotDir) -> Result<String, Box<dyn Error>> {
let bin_file_path = dot_dir.bin.join(&binary);
let result = if bin_file_path.exists() {
let opt_dir_path = dot_dir.opt.join(&binary);
find_selected_binary_version(bin_file_path, opt_dir_path)?
let version_file_path = dot_dir.var.join(&binary).join("version");
let result = if bin_file_path.exists() && version_file_path.exists() {
read_to_string(version_file_path)?
} else {
"".to_string()
};
Ok(result)
}

fn find_selected_binary_version(
bin_file_path: PathBuf,
opt_dir_path: PathBuf,
) -> Result<String, Box<dyn Error>> {
let path: Option<PathBuf> = read_dir(&opt_dir_path)?
.filter_map(|r| Some(r.ok()?.path()))
.find(|p| is_same_file(&bin_file_path, p).unwrap_or(false));
if let Some(p) = path {
if let Some(s) = p.file_name() {
return Ok(s.to_string_lossy().to_string());
}
}
Ok("".to_string())
}
Loading

0 comments on commit e1403da

Please sign in to comment.