diff --git a/docs/config/README.md b/docs/config/README.md index 1a08e8c7..6113747b 100644 --- a/docs/config/README.md +++ b/docs/config/README.md @@ -1407,22 +1407,23 @@ current directory. ### Options -| Option | Default | Description | -| ------------ | --------------------------------------------- | ----------------------------------- | -| `format` | `'([\[$all_status$ahead_behind\]]($style) )'` | The default format for `git_status` | -| `conflicted` | `"="` | This branch has merge conflicts. | -| `ahead` | `"⇡"` | The format of `ahead` | -| `behind` | `"⇣"` | The format of `behind` | -| `diverged` | `"⇕"` | The format of `diverged` | -| `up_to_date` | `""` | The format of `up_to_date` | -| `untracked` | `"?"` | The format of `untracked` | -| `stashed` | `"$"` | The format of `stashed` | -| `modified` | `"!"` | The format of `modified` | -| `staged` | `"+"` | The format of `staged` | -| `renamed` | `"»"` | The format of `renamed` | -| `deleted` | `"✘"` | The format of `deleted` | -| `style` | `"bold red"` | The style for the module. | -| `disabled` | `false` | Disables the `git_status` module. | +| Option | Default | Description | +| ------------------- | --------------------------------------------- | ----------------------------------- | +| `format` | `'([\[$all_status$ahead_behind\]]($style) )'` | The default format for `git_status` | +| `conflicted` | `"="` | This branch has merge conflicts. | +| `ahead` | `"⇡"` | The format of `ahead` | +| `behind` | `"⇣"` | The format of `behind` | +| `diverged` | `"⇕"` | The format of `diverged` | +| `up_to_date` | `""` | The format of `up_to_date` | +| `untracked` | `"?"` | The format of `untracked` | +| `stashed` | `"$"` | The format of `stashed` | +| `modified` | `"!"` | The format of `modified` | +| `staged` | `"+"` | The format of `staged` | +| `renamed` | `"»"` | The format of `renamed` | +| `deleted` | `"✘"` | The format of `deleted` | +| `style` | `"bold red"` | The style for the module. | +| `ignore_submodules` | `false` | Ignore changes to submodules. | +| `disabled` | `false` | Disables the `git_status` module. | ### Variables diff --git a/src/configs/git_status.rs b/src/configs/git_status.rs index 213ad214..8a014044 100644 --- a/src/configs/git_status.rs +++ b/src/configs/git_status.rs @@ -18,6 +18,7 @@ pub struct GitStatusConfig<'a> { pub modified: &'a str, pub staged: &'a str, pub untracked: &'a str, + pub ignore_submodules: bool, pub disabled: bool, } @@ -37,6 +38,7 @@ impl<'a> Default for GitStatusConfig<'a> { modified: "!", staged: "+", untracked: "?", + ignore_submodules: false, disabled: false, } } diff --git a/src/modules/git_status.rs b/src/modules/git_status.rs index 7a5f20ab..db02083f 100644 --- a/src/modules/git_status.rs +++ b/src/modules/git_status.rs @@ -27,11 +27,11 @@ const ALL_STATUS_FORMAT: &str = "$conflicted$stashed$deleted$renamed$modified$st /// - `»` — 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> { - let info = Arc::new(GitStatusInfo::load(context)); - let mut module = context.new_module("git_status"); let config: GitStatusConfig = GitStatusConfig::try_load(module.config); + let info = Arc::new(GitStatusInfo::load(context, config.clone())); + //Return None if not in git repository context.get_repo().ok()?; @@ -116,14 +116,16 @@ pub fn module<'a>(context: &'a Context) -> Option> { struct GitStatusInfo<'a> { context: &'a Context<'a>, + config: GitStatusConfig<'a>, repo_status: OnceCell>, stashed_count: OnceCell>, } impl<'a> GitStatusInfo<'a> { - pub fn load(context: &'a Context) -> Self { + pub fn load(context: &'a Context, config: GitStatusConfig<'a>) -> Self { Self { context, + config, repo_status: OnceCell::new(), stashed_count: OnceCell::new(), } @@ -135,7 +137,7 @@ impl<'a> GitStatusInfo<'a> { pub fn get_repo_status(&self) -> &Option { self.repo_status - .get_or_init(|| match get_repo_status(self.context) { + .get_or_init(|| match get_repo_status(self.context, &self.config) { Some(repo_status) => Some(repo_status), None => { log::debug!("get_repo_status: git status execution failed"); @@ -181,21 +183,37 @@ impl<'a> GitStatusInfo<'a> { } /// Gets the number of files in various git states (staged, modified, deleted, etc...) -fn get_repo_status(context: &Context) -> Option { +fn get_repo_status(context: &Context, config: &GitStatusConfig) -> Option { log::debug!("New repo status created"); let mut repo_status = RepoStatus::default(); - let status_output = context.exec_cmd( - "git", - &[ - OsStr::new("-C"), - context.current_dir.as_os_str(), - OsStr::new("--no-optional-locks"), - OsStr::new("status"), - OsStr::new("--porcelain=2"), - OsStr::new("--branch"), - ], - )?; + let mut args = vec![ + OsStr::new("-C"), + context.current_dir.as_os_str(), + OsStr::new("--no-optional-locks"), + OsStr::new("status"), + OsStr::new("--porcelain=2"), + ]; + + // for performance reasons, only pass flags if necessary... + let has_ahead_behind = !config.ahead.is_empty() || !config.behind.is_empty(); + let has_up_to_date_diverged = !config.up_to_date.is_empty() || !config.diverged.is_empty(); + if has_ahead_behind || has_up_to_date_diverged { + args.push(OsStr::new("--branch")); + } + + // ... and add flags that omit information the user doesn't want + let has_untracked = !config.untracked.is_empty(); + if !has_untracked { + args.push(OsStr::new("--untracked-files=no")); + } + if config.ignore_submodules { + args.push(OsStr::new("--ignore-submodules=dirty")); + } else if !has_untracked { + args.push(OsStr::new("--ignore-submodules=untracked")); + } + + let status_output = context.exec_cmd("git", &args)?; let statuses = status_output.stdout.lines(); statuses.for_each(|status| {