1
0
mirror of https://github.com/Llewellynvdm/starship.git synced 2024-09-22 02:39:01 +00:00

feat: Show git_status counts (#434)

The git_status module can show the count of files next to their respective symbols.
This commit is contained in:
Brian Low 2019-10-26 00:20:20 -06:00 committed by Matan Kushner
parent 59148ac4ad
commit 2710d02709
6 changed files with 523 additions and 187 deletions

View File

@ -471,23 +471,37 @@ current directory.
### Options
| Variable | Default | Description |
| ----------------- | ------------ | ------------------------------------------------------- |
| `conflicted` | `"="` | This branch has merge conflicts. |
| `ahead` | `"⇡"` | This branch is ahead of the branch being tracked. |
| `behind` | `"⇣"` | This branch is behind of the branch being tracked. |
| `diverged` | `"⇕"` | This branch has diverged from the branch being tracked. |
| `untracked` | `"?"` | There are untracked files in the working directory. |
| `stashed` | `"$"` | A stash exists for the local repository. |
| `modified` | `"!"` | There are file modifications in the working directory. |
| `staged` | `"+"` | A new file has been added to the staging area. |
| `renamed` | `"»"` | A renamed file has been added to the staging area. |
| `deleted` | `"✘"` | A file's deletion has been added to the staging area. |
| `show_sync_count` | `false` | Show ahead/behind count of the branch being tracked. |
| `prefix` | `[` | Prefix to display immediately before git status. |
| `suffix` | `]` | Suffix to display immediately after git status. |
| `style` | `"bold red"` | The style for the module. |
| `disabled` | `false` | Disables the `git_status` module. |
| Variable | Default | Description |
| ------------------- | -------------------------- | --------------------------------------------------------------- |
| `conflicted` | `"="` | This branch has merge conflicts. |
| `conflicted_count` | [link](#git-status-counts) | Show and style the number of conflicts. |
| `ahead` | `"⇡"` | This branch is ahead of the branch being tracked. |
| `behind` | `"⇣"` | This branch is behind of the branch being tracked. |
| `diverged` | `"⇕"` | This branch has diverged from the branch being tracked. |
| `untracked` | `"?"` | There are untracked files in the working directory. |
| `untracked_count` | [link](#git-status-counts) | Show and style the number of untracked files. |
| `stashed` | `"$"` | A stash exists for the local repository. |
| `modified` | `"!"` | There are file modifications in the working directory. |
| `modified_count` | [link](#git-status-counts) | Show and style the number of modified files. |
| `staged` | `"+"` | A new file has been added to the staging area. |
| `staged_count` | [link](#git-status-counts) | Show and style the number of files staged files. |
| `renamed` | `"»"` | A renamed file has been added to the staging area. |
| `renamed_count` | [link](#git-status-counts) | Show and style the number of renamed files. |
| `deleted` | `"✘"` | A file's deletion has been added to the staging area. |
| `deleted_count` | [link](#git-status-counts) | Show and style the number of deleted files. |
| `show_sync_count` | `false` | Show ahead/behind count of the branch being tracked. |
| `prefix` | `[` | Prefix to display immediately before git status. |
| `suffix` | `]` | Suffix to display immediately after git status. |
| `style` | `"bold red"` | The style for the module. |
| `disabled` | `false` | Disables the `git_status` module. |
#### Git Status Counts
| Variable | Default | Description |
| ----------- | ------- | ------------------------------------------------------ |
| `enabled` | `false` | Show the number of files |
| `style` | | Optionally style the count differently than the module |
### Example
@ -502,7 +516,10 @@ diverged = "😵"
untracked = "🤷‍"
stashed = "📦"
modified = "📝"
staged = ""
staged.value = "++"
staged.style = "green"
staged_count.enabled = true
staged_count.style = "green"
renamed = "👅"
deleted = "🗑"
```

View File

@ -242,10 +242,10 @@ impl<'a> SegmentConfig<'a> {
}
/// Immutably set style
pub fn with_style(&self, style: Style) -> Self {
pub fn with_style(&self, style: Option<Style>) -> Self {
Self {
value: self.value,
style: Some(style),
style,
}
}
}

63
src/configs/git_status.rs Normal file
View File

@ -0,0 +1,63 @@
use crate::config::{ModuleConfig, RootModuleConfig, SegmentConfig};
use ansi_term::{Color, Style};
use starship_module_config_derive::ModuleConfig;
#[derive(Clone, ModuleConfig)]
pub struct GitStatusConfig<'a> {
pub stashed: SegmentConfig<'a>,
pub ahead: SegmentConfig<'a>,
pub behind: SegmentConfig<'a>,
pub diverged: SegmentConfig<'a>,
pub show_sync_count: bool,
pub conflicted: SegmentConfig<'a>,
pub conflicted_count: CountConfig,
pub deleted: SegmentConfig<'a>,
pub deleted_count: CountConfig,
pub renamed: SegmentConfig<'a>,
pub renamed_count: CountConfig,
pub modified: SegmentConfig<'a>,
pub modified_count: CountConfig,
pub staged: SegmentConfig<'a>,
pub staged_count: CountConfig,
pub untracked: SegmentConfig<'a>,
pub untracked_count: CountConfig,
pub prefix: &'a str,
pub suffix: &'a str,
pub style: Style,
pub disabled: bool,
}
impl<'a> RootModuleConfig<'a> for GitStatusConfig<'a> {
fn new() -> Self {
GitStatusConfig {
stashed: SegmentConfig::new("$"),
ahead: SegmentConfig::new(""),
behind: SegmentConfig::new(""),
diverged: SegmentConfig::new(""),
conflicted: SegmentConfig::new("="),
show_sync_count: false,
conflicted_count: CountConfig::default(),
deleted: SegmentConfig::new(""),
deleted_count: CountConfig::default(),
renamed: SegmentConfig::new("»"),
renamed_count: CountConfig::default(),
modified: SegmentConfig::new("!"),
modified_count: CountConfig::default(),
staged: SegmentConfig::new("+"),
staged_count: CountConfig::default(),
untracked: SegmentConfig::new("?"),
untracked_count: CountConfig::default(),
prefix: "[",
suffix: "] ",
style: Color::Red.bold(),
disabled: false,
}
}
}
#[derive(Clone, Copy, ModuleConfig, Default)]
pub struct CountConfig {
pub enabled: bool,
pub style: Option<Style>,
}

View File

@ -7,6 +7,7 @@ pub mod directory;
pub mod dotnet;
pub mod env_var;
pub mod git_branch;
pub mod git_status;
pub mod go;
pub mod hostname;
pub mod jobs;

View File

@ -1,7 +1,9 @@
use ansi_term::Color;
use git2::{Repository, Status};
use super::{Context, Module};
use super::{Context, Module, RootModuleConfig};
use crate::config::SegmentConfig;
use crate::configs::git_status::{CountConfig, GitStatusConfig};
/// Creates a module with the Git branch in the current directory
///
@ -18,48 +20,23 @@ use super::{Context, Module};
/// - `»` — A renamed file has been added to the staging area
/// - `✘` — A file's deletion has been added to the staging area
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
// This is the order that the sections will appear in
const GIT_STATUS_CONFLICTED: &str = "=";
const GIT_STATUS_AHEAD: &str = "";
const GIT_STATUS_BEHIND: &str = "";
const GIT_STATUS_DIVERGED: &str = "";
const GIT_STATUS_UNTRACKED: &str = "?";
const GIT_STATUS_STASHED: &str = "$";
const GIT_STATUS_MODIFIED: &str = "!";
const GIT_STATUS_ADDED: &str = "+";
const GIT_STATUS_RENAMED: &str = "»";
const GIT_STATUS_DELETED: &str = "";
const PREFIX: &str = "[";
const SUFFIX: &str = "] ";
let repo = context.get_repo().ok()?;
let branch_name = repo.branch.as_ref()?;
let repo_root = repo.root.as_ref()?;
let repository = Repository::open(repo_root).ok()?;
let mut module = context.new_module("git_status");
let show_sync_count = module.config_value_bool("show_sync_count").unwrap_or(false);
let module_style = module
.config_value_style("style")
.unwrap_or_else(|| Color::Red.bold());
let start_symbol = module
.config_value_str("prefix")
.unwrap_or(PREFIX)
.to_owned();
let end_symbol = module
.config_value_str("suffix")
.unwrap_or(SUFFIX)
.to_owned();
let config: GitStatusConfig = GitStatusConfig::try_load(module.config);
module
.get_prefix()
.set_value(start_symbol)
.set_style(module_style);
.set_value(config.prefix)
.set_style(config.style);
module
.get_suffix()
.set_value(end_symbol)
.set_style(module_style);
module.set_style(module_style);
.set_value(config.suffix)
.set_style(config.style);
module.set_style(config.style);
let ahead_behind = get_ahead_behind(&repository, branch_name);
if ahead_behind == Ok((0, 0)) {
@ -80,33 +57,47 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
// Add the conflicted segment
if let Ok(repo_status) = repo_status {
if repo_status.is_conflicted() {
module.new_segment("conflicted", GIT_STATUS_CONFLICTED);
}
create_segment_with_count(
&mut module,
"conflicted",
repo_status.conflicted,
&config.conflicted,
config.conflicted_count,
);
}
// Add the ahead/behind segment
if let Ok((ahead, behind)) = ahead_behind {
let add_ahead = |m: &mut Module<'a>| {
m.new_segment("ahead", GIT_STATUS_AHEAD);
if show_sync_count {
m.new_segment("ahead_count", &ahead.to_string());
}
create_segment_with_count(
m,
"ahead",
ahead,
&config.ahead,
CountConfig {
enabled: config.show_sync_count,
style: None,
},
);
};
let add_behind = |m: &mut Module<'a>| {
m.new_segment("behind", GIT_STATUS_BEHIND);
if show_sync_count {
m.new_segment("behind_count", &behind.to_string());
}
create_segment_with_count(
m,
"behind",
behind,
&config.behind,
CountConfig {
enabled: config.show_sync_count,
style: None,
},
);
};
if ahead > 0 && behind > 0 {
module.new_segment("diverged", GIT_STATUS_DIVERGED);
module.create_segment("diverged", &config.diverged);
if show_sync_count {
if config.show_sync_count {
add_ahead(&mut module);
add_behind(&mut module);
}
@ -123,30 +114,50 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
// Add the stashed segment
if stash_object.is_ok() {
module.new_segment("stashed", GIT_STATUS_STASHED);
module.create_segment("stashed", &config.stashed);
}
// Add all remaining status segments
if let Ok(repo_status) = repo_status {
if repo_status.is_wt_deleted() || repo_status.is_index_deleted() {
module.new_segment("deleted", GIT_STATUS_DELETED);
}
create_segment_with_count(
&mut module,
"deleted",
repo_status.deleted,
&config.deleted,
config.deleted_count,
);
if repo_status.is_wt_renamed() || repo_status.is_index_renamed() {
module.new_segment("renamed", GIT_STATUS_RENAMED);
}
create_segment_with_count(
&mut module,
"renamed",
repo_status.renamed,
&config.renamed,
config.renamed_count,
);
if repo_status.is_wt_modified() {
module.new_segment("modified", GIT_STATUS_MODIFIED);
}
create_segment_with_count(
&mut module,
"modified",
repo_status.modified,
&config.modified,
config.modified_count,
);
if repo_status.is_index_modified() || repo_status.is_index_new() {
module.new_segment("staged", GIT_STATUS_ADDED);
}
create_segment_with_count(
&mut module,
"staged",
repo_status.staged,
&config.staged,
config.staged_count,
);
if repo_status.is_wt_new() {
module.new_segment("untracked", GIT_STATUS_UNTRACKED);
}
create_segment_with_count(
&mut module,
"untracked",
repo_status.untracked,
&config.untracked,
config.untracked_count,
);
}
if module.is_empty() {
@ -156,8 +167,27 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
Some(module)
}
/// Gets the bitflags associated with the repo's git status
fn get_repo_status(repository: &Repository) -> Result<Status, git2::Error> {
fn create_segment_with_count<'a>(
module: &mut Module<'a>,
name: &str,
count: usize,
config: &SegmentConfig<'a>,
count_config: CountConfig,
) {
if count > 0 {
module.create_segment(name, &config);
if count_config.enabled {
module.create_segment(
&format!("{}_count", name),
&SegmentConfig::new(&count.to_string()).with_style(count_config.style),
);
}
}
}
/// Gets the number of files in various git states (staged, modified, deleted, etc...)
fn get_repo_status(repository: &Repository) -> Result<RepoStatus, git2::Error> {
let mut status_options = git2::StatusOptions::new();
match repository.config()?.get_entry("status.showUntrackedFiles") {
@ -168,17 +198,52 @@ fn get_repo_status(repository: &Repository) -> Result<Status, git2::Error> {
status_options.renames_head_to_index(true);
status_options.renames_index_to_workdir(true);
let repo_file_statuses = repository.statuses(Some(&mut status_options))?;
let statuses: Vec<Status> = repository
.statuses(Some(&mut status_options))?
.iter()
.map(|s| s.status())
.collect();
// Statuses are stored as bitflags, so use BitOr to join them all into a single value
let repo_status: Status = repo_file_statuses.iter().map(|e| e.status()).collect();
if repo_status.is_empty() {
if statuses.is_empty() {
return Err(git2::Error::from_str("Repo has no status"));
}
let repo_status: RepoStatus = RepoStatus {
conflicted: statuses.iter().filter(|s| is_conflicted(**s)).count(),
deleted: statuses.iter().filter(|s| is_deleted(**s)).count(),
renamed: statuses.iter().filter(|s| is_renamed(**s)).count(),
modified: statuses.iter().filter(|s| is_modified(**s)).count(),
staged: statuses.iter().filter(|s| is_staged(**s)).count(),
untracked: statuses.iter().filter(|s| is_untracked(**s)).count(),
};
Ok(repo_status)
}
fn is_conflicted(status: Status) -> bool {
status.is_conflicted()
}
fn is_deleted(status: Status) -> bool {
status.is_wt_deleted() || status.is_index_deleted()
}
fn is_renamed(status: Status) -> bool {
status.is_wt_renamed() || status.is_index_renamed()
}
fn is_modified(status: Status) -> bool {
status.is_wt_modified()
}
fn is_staged(status: Status) -> bool {
status.is_index_modified() || status.is_index_new()
}
fn is_untracked(status: Status) -> bool {
status.is_wt_new()
}
/// Compares the current branch with the branch it is tracking to determine how
/// far ahead or behind it is in relation
fn get_ahead_behind(
@ -194,3 +259,13 @@ fn get_ahead_behind(
repository.graph_ahead_behind(branch_oid, tracking_oid)
}
#[derive(Default, Debug, Copy, Clone)]
struct RepoStatus {
conflicted: usize,
deleted: usize,
renamed: usize,
modified: usize,
staged: usize,
untracked: usize,
}

View File

@ -1,6 +1,7 @@
use ansi_term::Color;
use ansi_term::{ANSIStrings, Color};
use std::fs::{self, File};
use std::io;
use std::path::PathBuf;
use std::process::Command;
use crate::common::{self, TestCommand};
@ -22,11 +23,7 @@ fn barrier() {
fn shows_behind() -> io::Result<()> {
let repo_dir = common::create_fixture_repo()?;
Command::new("git")
.args(&["reset", "--hard", "HEAD^"])
.current_dir(repo_dir.as_path())
.output()?;
barrier();
behind(&repo_dir)?;
let output = common::render_module("git_status")
.arg("--path")
@ -45,11 +42,7 @@ fn shows_behind() -> io::Result<()> {
fn shows_behind_with_count() -> io::Result<()> {
let repo_dir = common::create_fixture_repo()?;
Command::new("git")
.args(&["reset", "--hard", "HEAD^"])
.current_dir(repo_dir.as_path())
.output()?;
barrier();
behind(&repo_dir)?;
let output = common::render_module("git_status")
.use_config(toml::toml! {
@ -73,12 +66,7 @@ fn shows_ahead() -> io::Result<()> {
let repo_dir = common::create_fixture_repo()?;
File::create(repo_dir.join("readme.md"))?.sync_all()?;
Command::new("git")
.args(&["commit", "-am", "Update readme"])
.current_dir(&repo_dir)
.output()?;
barrier();
ahead(&repo_dir)?;
let output = common::render_module("git_status")
.arg("--path")
@ -98,12 +86,7 @@ fn shows_ahead_with_count() -> io::Result<()> {
let repo_dir = common::create_fixture_repo()?;
File::create(repo_dir.join("readme.md"))?.sync_all()?;
Command::new("git")
.args(&["commit", "-am", "Update readme"])
.current_dir(&repo_dir)
.output()?;
barrier();
ahead(&repo_dir)?;
let output = common::render_module("git_status")
.use_config(toml::toml! {
@ -126,19 +109,7 @@ fn shows_ahead_with_count() -> io::Result<()> {
fn shows_diverged() -> io::Result<()> {
let repo_dir = common::create_fixture_repo()?;
Command::new("git")
.args(&["reset", "--hard", "HEAD^"])
.current_dir(repo_dir.as_path())
.output()?;
fs::write(repo_dir.join("Cargo.toml"), " ")?;
Command::new("git")
.args(&["commit", "-am", "Update readme"])
.current_dir(repo_dir.as_path())
.output()?;
barrier();
diverge(&repo_dir)?;
let output = common::render_module("git_status")
.arg("--path")
@ -157,19 +128,7 @@ fn shows_diverged() -> io::Result<()> {
fn shows_diverged_with_count() -> io::Result<()> {
let repo_dir = common::create_fixture_repo()?;
Command::new("git")
.args(&["reset", "--hard", "HEAD^"])
.current_dir(repo_dir.as_path())
.output()?;
fs::write(repo_dir.join("Cargo.toml"), " ")?;
Command::new("git")
.args(&["commit", "-am", "Update readme"])
.current_dir(repo_dir.as_path())
.output()?;
barrier();
diverge(&repo_dir)?;
let output = common::render_module("git_status")
.use_config(toml::toml! {
@ -195,33 +154,7 @@ fn shows_diverged_with_count() -> io::Result<()> {
fn shows_conflicted() -> io::Result<()> {
let repo_dir = common::create_fixture_repo()?;
Command::new("git")
.args(&["reset", "--hard", "HEAD^"])
.current_dir(repo_dir.as_path())
.output()?;
barrier();
fs::write(repo_dir.join("readme.md"), "# goodbye")?;
barrier();
Command::new("git")
.args(&["add", "."])
.current_dir(repo_dir.as_path())
.output()?;
barrier();
Command::new("git")
.args(&["commit", "-m", "Change readme"])
.current_dir(repo_dir.as_path())
.output()?;
barrier();
Command::new("git")
.args(&["pull", "--rebase"])
.current_dir(repo_dir.as_path())
.output()?;
barrier();
create_conflict(&repo_dir)?;
let output = common::render_module("git_status")
.arg("--path")
@ -235,12 +168,35 @@ fn shows_conflicted() -> io::Result<()> {
Ok(())
}
#[test]
#[ignore]
fn shows_conflicted_with_count() -> io::Result<()> {
let repo_dir = common::create_fixture_repo()?;
create_conflict(&repo_dir)?;
let output = common::render_module("git_status")
.use_config(toml::toml! {
[git_status]
conflicted_count.enabled = true
})
.arg("--path")
.arg(repo_dir)
.output()?;
let actual = String::from_utf8(output.stdout).unwrap();
let expected = Color::Red.bold().paint(format!("[{}] ", "=1")).to_string();
assert_eq!(expected, actual);
Ok(())
}
#[test]
#[ignore]
fn shows_untracked_file() -> io::Result<()> {
let repo_dir = common::create_fixture_repo()?;
File::create(repo_dir.join("license"))?.sync_all()?;
create_untracked(&repo_dir)?;
let output = common::render_module("git_status")
.arg("--path")
@ -254,12 +210,35 @@ fn shows_untracked_file() -> io::Result<()> {
Ok(())
}
#[test]
#[ignore]
fn shows_untracked_file_with_count() -> io::Result<()> {
let repo_dir = common::create_fixture_repo()?;
create_untracked(&repo_dir)?;
let output = common::render_module("git_status")
.use_config(toml::toml! {
[git_status]
untracked_count.enabled = true
})
.arg("--path")
.arg(repo_dir)
.output()?;
let actual = String::from_utf8(output.stdout).unwrap();
let expected = Color::Red.bold().paint(format!("[{}] ", "?1")).to_string();
assert_eq!(expected, actual);
Ok(())
}
#[test]
#[ignore]
fn doesnt_show_untracked_file_if_disabled() -> io::Result<()> {
let repo_dir = common::create_fixture_repo()?;
File::create(repo_dir.join("license"))?.sync_all()?;
create_untracked(&repo_dir)?;
Command::new("git")
.args(&["config", "status.showUntrackedFiles", "no"])
@ -318,7 +297,7 @@ fn shows_stashed() -> io::Result<()> {
fn shows_modified() -> io::Result<()> {
let repo_dir = common::create_fixture_repo()?;
File::create(repo_dir.join("readme.md"))?.sync_all()?;
create_modified(&repo_dir)?;
let output = common::render_module("git_status")
.arg("--path")
@ -332,18 +311,35 @@ fn shows_modified() -> io::Result<()> {
Ok(())
}
#[test]
#[ignore]
fn shows_modified_with_count() -> io::Result<()> {
let repo_dir = common::create_fixture_repo()?;
create_modified(&repo_dir)?;
let output = common::render_module("git_status")
.use_config(toml::toml! {
[git_status]
modified_count.enabled = true
})
.arg("--path")
.arg(repo_dir)
.output()?;
let actual = String::from_utf8(output.stdout).unwrap();
let expected = Color::Red.bold().paint(format!("[{}] ", "!1")).to_string();
assert_eq!(expected, actual);
Ok(())
}
#[test]
#[ignore]
fn shows_staged_file() -> io::Result<()> {
let repo_dir = common::create_fixture_repo()?;
File::create(repo_dir.join("license"))?.sync_all()?;
Command::new("git")
.args(&["add", "."])
.current_dir(repo_dir.as_path())
.output()?;
barrier();
create_staged(&repo_dir)?;
let output = common::render_module("git_status")
.arg("--path")
@ -357,21 +353,43 @@ fn shows_staged_file() -> io::Result<()> {
Ok(())
}
#[test]
#[ignore]
fn shows_staged_file_with_count() -> io::Result<()> {
let repo_dir = common::create_fixture_repo()?;
create_staged(&repo_dir)?;
let output = common::render_module("git_status")
.use_config(toml::toml! {
[git_status]
staged_count.enabled = true
staged_count.style = "green"
})
.arg("--path")
.arg(repo_dir)
.output()?;
let actual = String::from_utf8(output.stdout).unwrap();
let expected = format!(
"{}",
ANSIStrings(&[
Color::Red.bold().paint("[+"),
Color::Green.paint("1"),
Color::Red.bold().paint("] "),
])
);
assert_eq!(expected, actual);
Ok(())
}
#[test]
#[ignore]
fn shows_renamed_file() -> io::Result<()> {
let repo_dir = common::create_fixture_repo()?;
Command::new("git")
.args(&["mv", "readme.md", "readme.md.bak"])
.current_dir(repo_dir.as_path())
.output()?;
Command::new("git")
.args(&["add", "-A"])
.current_dir(repo_dir.as_path())
.output()?;
barrier();
create_renamed(&repo_dir)?;
let output = common::render_module("git_status")
.arg("--path")
@ -385,12 +403,35 @@ fn shows_renamed_file() -> io::Result<()> {
Ok(())
}
#[test]
#[ignore]
fn shows_renamed_file_with_count() -> io::Result<()> {
let repo_dir = common::create_fixture_repo()?;
create_renamed(&repo_dir)?;
let output = common::render_module("git_status")
.use_config(toml::toml! {
[git_status]
renamed_count.enabled = true
})
.arg("--path")
.arg(repo_dir)
.output()?;
let actual = String::from_utf8(output.stdout).unwrap();
let expected = Color::Red.bold().paint(format!("[{}] ", "»1")).to_string();
assert_eq!(expected, actual);
Ok(())
}
#[test]
#[ignore]
fn shows_deleted_file() -> io::Result<()> {
let repo_dir = common::create_fixture_repo()?;
fs::remove_file(repo_dir.join("readme.md"))?;
create_deleted(&repo_dir)?;
let output = common::render_module("git_status")
.arg("--path")
@ -404,6 +445,29 @@ fn shows_deleted_file() -> io::Result<()> {
Ok(())
}
#[test]
#[ignore]
fn shows_deleted_file_with_count() -> io::Result<()> {
let repo_dir = common::create_fixture_repo()?;
create_deleted(&repo_dir)?;
let output = common::render_module("git_status")
.use_config(toml::toml! {
[git_status]
deleted_count.enabled = true
})
.arg("--path")
.arg(repo_dir)
.output()?;
let actual = String::from_utf8(output.stdout).unwrap();
let expected = Color::Red.bold().paint(format!("[{}] ", "✘1")).to_string();
assert_eq!(expected, actual);
Ok(())
}
#[test]
#[ignore]
fn prefix() -> io::Result<()> {
@ -445,3 +509,119 @@ fn suffix() -> io::Result<()> {
assert!(actual.ends_with(&expected));
Ok(())
}
fn ahead(repo_dir: &PathBuf) -> io::Result<()> {
File::create(repo_dir.join("readme.md"))?.sync_all()?;
Command::new("git")
.args(&["commit", "-am", "Update readme"])
.current_dir(&repo_dir)
.output()?;
barrier();
Ok(())
}
fn behind(repo_dir: &PathBuf) -> io::Result<()> {
Command::new("git")
.args(&["reset", "--hard", "HEAD^"])
.current_dir(repo_dir.as_path())
.output()?;
barrier();
Ok(())
}
fn diverge(repo_dir: &PathBuf) -> io::Result<()> {
Command::new("git")
.args(&["reset", "--hard", "HEAD^"])
.current_dir(repo_dir.as_path())
.output()?;
barrier();
fs::write(repo_dir.join("Cargo.toml"), " ")?;
Command::new("git")
.args(&["commit", "-am", "Update readme"])
.current_dir(repo_dir.as_path())
.output()?;
barrier();
Ok(())
}
fn create_conflict(repo_dir: &PathBuf) -> io::Result<()> {
Command::new("git")
.args(&["reset", "--hard", "HEAD^"])
.current_dir(repo_dir.as_path())
.output()?;
barrier();
fs::write(repo_dir.join("readme.md"), "# goodbye")?;
Command::new("git")
.args(&["add", "."])
.current_dir(repo_dir.as_path())
.output()?;
barrier();
Command::new("git")
.args(&["commit", "-m", "Change readme"])
.current_dir(repo_dir.as_path())
.output()?;
barrier();
Command::new("git")
.args(&["pull", "--rebase"])
.current_dir(repo_dir.as_path())
.output()?;
barrier();
Ok(())
}
fn create_untracked(repo_dir: &PathBuf) -> io::Result<()> {
File::create(repo_dir.join("license"))?.sync_all()?;
Ok(())
}
fn create_modified(repo_dir: &PathBuf) -> io::Result<()> {
File::create(repo_dir.join("readme.md"))?.sync_all()?;
Ok(())
}
fn create_staged(repo_dir: &PathBuf) -> io::Result<()> {
File::create(repo_dir.join("license"))?.sync_all()?;
Command::new("git")
.args(&["add", "."])
.current_dir(repo_dir.as_path())
.output()?;
barrier();
Ok(())
}
fn create_renamed(repo_dir: &PathBuf) -> io::Result<()> {
Command::new("git")
.args(&["mv", "readme.md", "readme.md.bak"])
.current_dir(repo_dir.as_path())
.output()?;
barrier();
Command::new("git")
.args(&["add", "-A"])
.current_dir(repo_dir.as_path())
.output()?;
barrier();
Ok(())
}
fn create_deleted(repo_dir: &PathBuf) -> io::Result<()> {
fs::remove_file(repo_dir.join("readme.md"))?;
Ok(())
}