Skip to content

Commit

Permalink
commands: display tree's current branch alongside the tree name
Browse files Browse the repository at this point in the history
Add a `tree_branches` field to the configuration and default it to true.
Teach garden to display branch names alongside tree names.
Add a "garden.tree-branches" configuration value to disable the feature.

Closes: #18
  • Loading branch information
davvid committed Dec 4, 2023
1 parent 66339dd commit 5a54973
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 15 deletions.
3 changes: 3 additions & 0 deletions doc/src/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

**Features**

- Commands now display the tree's current branch alongside the tree name.
([#18](https://github.com/davvid/garden/issues/18))

- `garden -vv exec` and `garden -vv shell` now display the command being run.

## v0.9.1
Expand Down
11 changes: 11 additions & 0 deletions doc/src/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,17 @@ when `garden.shell` is omitted. The first one found is the one that's used.
* `bash`
* `sh`

## Tree Display

Garden will display the tree's current branch when running commands.
While this has a marginal performance impact, this feature can be disabled by either
passing the `garden -D garden.tree-branches=0` option or by configuring the
`garden.tree-branches` option to `false` in the `garden.yaml` configuration.

```yaml
garden:
tree-branches: false
```

## Includes

Expand Down
2 changes: 1 addition & 1 deletion src/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ where
path = tree.path_as_ref()?;

// Sparse gardens/missing trees are ok -> skip these entries.
if !model::print_tree(tree, verbose, quiet) {
if !model::print_tree(tree, config.tree_branches, verbose, quiet) {
return Ok(());
}
} else {
Expand Down
6 changes: 2 additions & 4 deletions src/cmds/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ pub fn run_cmd_breadth_first(
// Run each command in the tree's context
let path = tree.path_as_ref()?.to_string();
// Sparse gardens/missing trees are ok -> skip these entries.
if !model::print_tree(tree, verbose, quiet) {
if !model::print_tree(tree, config.tree_branches, verbose, quiet) {
continue;
}

Expand Down Expand Up @@ -282,12 +282,10 @@ pub fn run_cmd_depth_first(
}
// Evaluate the tree environment
let env = eval::environment(app_context, config, context);

// Run each command in the tree's context
let path = tree.path_as_ref()?.to_string();

// Sparse gardens/missing trees are ok -> skip these entries.
if !model::print_tree(tree, verbose, quiet) {
if !model::print_tree(tree, config.tree_branches, verbose, quiet) {
continue;
}

Expand Down
2 changes: 1 addition & 1 deletion src/cmds/grow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ fn grow_tree_from_context(
};

let path = tree.path_as_ref()?.clone();
model::print_tree_details(tree, verbose, quiet);
model::print_tree_details(tree, config.tree_branches, verbose, quiet);

let pathbuf = std::path::PathBuf::from(&path);
let parent = pathbuf.parent().ok_or_else(|| {
Expand Down
4 changes: 4 additions & 0 deletions src/config/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ fn parse_recursive(
if get_str(&doc["garden"]["shell"], &mut config.shell) && config_verbose > 0 {
debug!("yaml: garden.shell = {}", config.shell);
}
// garden.tree-branches
if get_bool(&doc["garden"]["tree-branches"], &mut config.tree_branches) && config_verbose > 0 {
debug!("yaml: garden.tree-branches = {}", config.tree_branches);
}

// GARDEN_ROOT and GARDEN_CONFIG_DIR are relative to the root configuration.
// Referencing these variables from garden files included using garden.includes
Expand Down
23 changes: 23 additions & 0 deletions src/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,26 @@ pub fn branches(path: &std::path::Path) -> Vec<String> {

branches
}

/// Return the current branch name for the specified repository path.
pub fn branch(path: &std::path::Path) -> Option<String> {
let cmd = ["git", "symbolic-ref", "--quiet", "--short", "HEAD"];
let exec = cmd::exec_in_dir(&cmd, &path);
if let Ok(capture_data) = cmd::capture_stdout(exec) {
let output = cmd::trim_stdout(&capture_data);
if !output.is_empty() {
return Some(output);
}
}
// Detached head? Show an abbreviated commit ID. This respects `git config core.abbrev`.
let cmd = ["git", "rev-parse", "--short", "HEAD"];
let exec = cmd::exec_in_dir(&cmd, &path);
if let Ok(capture_data) = cmd::capture_stdout(exec) {
let output = cmd::trim_stdout(&capture_data);
if !output.is_empty() {
return Some(output);
}
}
// Unknown branch is an empty string.
None
}
59 changes: 50 additions & 9 deletions src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use super::collections::{append_hashmap, append_indexset};
use super::config;
use super::errors;
use super::eval;
use super::git;
use super::path;
use super::syntax;

Expand Down Expand Up @@ -460,6 +461,7 @@ pub struct Configuration {
/// highest precedence and override variables defined by any configuration or tree.
pub override_variables: VariableHashMap,
pub verbose: u8,
pub tree_branches: bool,
pub parent_id: Option<ConfigId>,
id: Option<ConfigId>,
}
Expand All @@ -473,6 +475,7 @@ impl Configuration {
id: None,
parent_id: None,
shell: get_default_shell(),
tree_branches: true,
..std::default::Default::default()
}
}
Expand Down Expand Up @@ -602,8 +605,17 @@ impl Configuration {
} else {
error!("unable to split '{}'", k_eq_v);
}
self.override_variables
.insert(name, Variable::new(expr, None));
// Allow overridding garden.tree-branches using "garden -D garden.tree-branches=false".
if name == "garden.tree-branches" {
if let Some(value) = syntax::string_to_bool(&expr) {
self.tree_branches = value;
} else {
error!("'{}' is not a valid value for \"garden.tree-branches\". Must be true, false, 0 or 1", expr);
}
} else {
self.override_variables
.insert(name, Variable::new(expr, None));
}
}

Ok(())
Expand Down Expand Up @@ -1145,21 +1157,46 @@ pub fn display_missing_tree(tree: &Tree, path: &str, verbose: u8) -> String {
}
}

pub fn display_tree(tree: &Tree, path: &str, verbose: u8) -> String {
pub fn display_tree(tree: &Tree, path_str: &str, tree_branches: bool, verbose: u8) -> String {
if verbose > 0 {
if tree_branches {
if let Some(path) = tree.canonical_pathbuf() {
if let Some(branch) = git::branch(&path) {
return format!(
"{} {} ({}) {}",
Color::cyan("#"),
Color::blue(&tree.name).bold(),
Color::blue(&branch),
Color::blue(&path_str)
);
}
}
}
format!(
"{} {} {}",
"{} {} {}",
Color::cyan("#"),
Color::blue(&tree.name).bold(),
Color::blue(&path)
Color::blue(&path_str)
)
} else {
if tree_branches {
if let Some(path) = tree.canonical_pathbuf() {
if let Some(branch) = git::branch(&path) {
return format!(
"{} {} ({})",
Color::cyan("#"),
Color::blue(&tree.name).bold(),
Color::blue(&branch)
);
}
}
}
format!("{} {}", Color::cyan("#"), Color::blue(&tree.name).bold())
}
}

/// Print a tree if it exists, otherwise print a missing tree
pub fn print_tree(tree: &Tree, verbose: u8, quiet: bool) -> bool {
pub fn print_tree(tree: &Tree, tree_branches: bool, verbose: u8, quiet: bool) -> bool {
if let Ok(path) = tree.path_as_ref() {
// Sparse gardens/missing trees are ok -> skip these entries.
if !std::path::PathBuf::from(&path).exists() {
Expand All @@ -1169,7 +1206,7 @@ pub fn print_tree(tree: &Tree, verbose: u8, quiet: bool) -> bool {
return false;
}

print_tree_details(tree, verbose, quiet);
print_tree_details(tree, tree_branches, verbose, quiet);
return true;
} else if !quiet {
eprintln!("{}", display_missing_tree(tree, "[invalid-path]", verbose));
Expand All @@ -1179,10 +1216,10 @@ pub fn print_tree(tree: &Tree, verbose: u8, quiet: bool) -> bool {
}

/// Print a tree
pub fn print_tree_details(tree: &Tree, verbose: u8, quiet: bool) {
pub fn print_tree_details(tree: &Tree, tree_branches: bool, verbose: u8, quiet: bool) {
if !quiet {
if let Ok(path) = tree.path_as_ref() {
eprintln!("{}", display_tree(tree, path, verbose));
eprintln!("{}", display_tree(tree, path, tree_branches, verbose));
}
}
}
Expand Down Expand Up @@ -1322,6 +1359,10 @@ impl ApplicationContext {
let path = path.to_path_buf();
let config_verbose = self.options.debug_level("config");
let mut graft_config = Configuration::new();
// Propogate the current config's "garden.tree-branches" setting down to child grafts.
// The graft's configuration override the parent's "garden.tree-branches" setting.
graft_config.tree_branches = self.get_config(config_id).tree_branches;
// Parse the config file for the graft.
graft_config.update(self, Some(&path), root, config_verbose, Some(config_id))?;

// The app Arena takes ownershp of the Configuration.
Expand Down

0 comments on commit 5a54973

Please sign in to comment.