mirror of
https://github.com/Llewellynvdm/starship.git
synced 2024-11-24 21:57:41 +00:00
perf(git_status): tweak exec flags to omit unnecessary info (#3287)
* perf(git_status): tweak flags to omit extra info `git status` can be prohibitively slow on some repos, so allow the config to influence what flags are passed to git. For instance, if there is no configured symbol for untracked files, tell git to omit them from its output. This can easily result in a 2~10x speedup in many cases, but requires the user to opt-in to hiding information from the prompt. * docs(git_status): add ignore_submodules option
This commit is contained in:
parent
1c305c9de7
commit
a95332485b
@ -1408,7 +1408,7 @@ 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` |
|
||||
@ -1422,6 +1422,7 @@ current directory.
|
||||
| `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
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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<Module<'a>> {
|
||||
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<Module<'a>> {
|
||||
|
||||
struct GitStatusInfo<'a> {
|
||||
context: &'a Context<'a>,
|
||||
config: GitStatusConfig<'a>,
|
||||
repo_status: OnceCell<Option<RepoStatus>>,
|
||||
stashed_count: OnceCell<Option<usize>>,
|
||||
}
|
||||
|
||||
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<RepoStatus> {
|
||||
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<RepoStatus> {
|
||||
fn get_repo_status(context: &Context, config: &GitStatusConfig) -> Option<RepoStatus> {
|
||||
log::debug!("New repo status created");
|
||||
|
||||
let mut repo_status = RepoStatus::default();
|
||||
let status_output = context.exec_cmd(
|
||||
"git",
|
||||
&[
|
||||
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"),
|
||||
OsStr::new("--branch"),
|
||||
],
|
||||
)?;
|
||||
];
|
||||
|
||||
// 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| {
|
||||
|
Loading…
Reference in New Issue
Block a user