From 08060ff792ae5f548328af7573c7aa4c0d682bd7 Mon Sep 17 00:00:00 2001 From: Jerome Reybert <jerome.reybert@tiempo-secure.com> Date: Thu, 4 Jan 2024 16:55:48 +0100 Subject: [PATCH] feat: add update mode to speed up update Update can be slow, especially when the repository has a lot of (recursive) submodules. To speed up update, submodules status can be lighter. By setting update mode to normal, git status performs the default behavior. By setting update mode to fast, git status will use the option `--ignore-submodules=dirty`. This option will only search for commit changes in the submodules. All modified and untracked changes will be ignored. It is possible to control this option by two ways: - globally, by setting the vim option `g:magit_update_mode` - at repository level, by setting the git option: `git config vimagit.update-mode fast` - for the record, it is also possible to set the option globally with git: `git config --global vimagit.update-mode fast` g:magit_update_mode * Can be set to 'normal' and 'fast'. * Default value is 'normal'. --- autoload/magit/git.vim | 19 +++++++++------- autoload/magit/state.vim | 2 +- common/magit_common.vim | 1 + doc/vimagit.txt | 23 +++++++++++++++++++ plugin/magit.vim | 48 ++++++++++++++++++++++++++++++++++++++-- syntax/magit.vim | 2 ++ 6 files changed, 84 insertions(+), 11 deletions(-) diff --git a/autoload/magit/git.vim b/autoload/magit/git.vim index 0705b7e..5455215 100644 --- a/autoload/magit/git.vim +++ b/autoload/magit/git.vim @@ -17,14 +17,19 @@ endfunction " magit#git#get_status: this function returns the git status output formated " into a List of Dict as " [ {staged', 'unstaged', 'filename'}, ... ] -function! magit#git#get_status() +function! magit#git#get_status(update_mode) let file_list = [] " systemlist v7.4.248 problem again " we can't use git status -z here, because system doesn't make the " difference between NUL and NL. -status z terminate entries with NUL, " instead of NF - let status_list=magit#sys#systemlist(g:magit_git_cmd . " status --porcelain") + if a:update_mode == 'fast' + let ignore_flag = 'dirty' + else + let ignore_flag = 'none' + endif + let status_list=magit#sys#systemlist(g:magit_git_cmd . " status --porcelain --ignore-submodules=" . ignore_flag) for file_status_line in status_list let line_match = matchlist(file_status_line, '\(.\)\(.\) \%(.\{-\} -> \)\?"\?\(.\{-\}\)"\?$') let filename = line_match[3] @@ -153,10 +158,8 @@ endfunction " untracked content " param[in] submodule: submodule path " param[in] check_level: can be modified or untracked -function! magit#git#sub_check(submodule, check_level) - let ignore_flag = ( a:check_level == 'modified' ) ? - \ '--ignore-submodules=untracked' : '' - let git_cmd=g:magit_git_cmd . " status --porcelain " . ignore_flag . " " . a:submodule +function! magit#git#sub_check(submodule, ignore_flag) + let git_cmd=g:magit_git_cmd . " status --porcelain --ignore-submodules=" . a:ignore_flag . " " . a:submodule return ( !empty(magit#sys#systemlist(git_cmd)) ) endfunction @@ -172,10 +175,10 @@ function! magit#git#git_sub_summary(filename, mode) silent let diff_list=magit#sys#systemlist(git_cmd) if ( empty(diff_list) ) if ( a:mode == 'unstaged' ) - if ( magit#git#sub_check(a:filename, 'modified') ) + if ( magit#git#sub_check(a:filename, 'untracked') ) return "modified content" endif - if ( magit#git#sub_check(a:filename, 'untracked') ) + if ( magit#git#sub_check(a:filename, 'none') ) return "untracked content" endif endif diff --git a/autoload/magit/state.vim b/autoload/magit/state.vim index 5148853..2ccde39 100644 --- a/autoload/magit/state.vim +++ b/autoload/magit/state.vim @@ -277,7 +277,7 @@ function! magit#state#update() dict try call magit#utils#chdir(magit#git#top_dir()) call magit#utils#refresh_submodule_list() - let status_list = magit#git#get_status() + let status_list = magit#git#get_status(b:magit_update_mode) for [mode, diff_dict_mode] in items(self.dict) for file_status in status_list let status=file_status[mode] diff --git a/common/magit_common.vim b/common/magit_common.vim index f1f8123..72b7f26 100644 --- a/common/magit_common.vim +++ b/common/magit_common.vim @@ -16,6 +16,7 @@ let g:magit_section_info = { \ 'cur_upstream': 'Upstream:', \ 'cur_push': 'Push:', \ 'commit_mode': 'Commit mode:', + \ 'update_mode': 'Update mode:', \ } let g:magit_git_status_code = { diff --git a/doc/vimagit.txt b/doc/vimagit.txt index e0ef71e..aeaa4a0 100644 --- a/doc/vimagit.txt +++ b/doc/vimagit.txt @@ -366,6 +366,24 @@ section only. ------------------------------------------------------------------------------ +UPDATE MODE *vimagit-update-mode* + +Update can be slow, especially when the repository has a lot of (recursive) +submodules. To speed up update, submodules status can be lighter. + +By setting update mode to normal, git status performs the default behavior. +By setting update mode to fast, git status will use the option +`--ignore-submodules=dirty`. This option will only search for commit changes +in the submodules. All modified and untracked changes will be ignored. + +It is possible to control this option by two ways: +- globally, by setting the vim option `g:magit_update_mode` +- at repository level, by setting the git option: + `git config vimagit.update-mode fast` +- for the record, it is also possible to set the option globally with git: + `git config --global vimagit.update-mode fast` + +------------------------------------------------------------------------------ AUTOCMD *vimagit-autocmd* @@ -517,6 +535,11 @@ empty). Default value is 0. let g:magit_auto_close=[01] + *vimagit-g:magit_update_mode* +See |vimagit-update-mode|. +Can be set to 'normal' and 'fast'. +Default value is 'normal'. + =============================================================================== 6. FAQ *vimagit-FAQ* diff --git a/plugin/magit.vim b/plugin/magit.vim index 4fb36e4..1dd5b8e 100644 --- a/plugin/magit.vim +++ b/plugin/magit.vim @@ -33,6 +33,10 @@ let g:magit_default_sections = get(g:, 'magit_default_sections', let g:magit_discard_untracked_do_delete = get(g:, 'magit_discard_untracked_do_delete', 0) let g:magit_refresh_gutter = get(g:, 'magit_refresh_gutter' , 1) + +let g:magit_update_mode = get(g:, 'magit_update_mode', 'normal') +let g:magit_update_modes = ['normal', 'fast'] + " Should deprecate the following let g:magit_refresh_gitgutter = get(g:, 'magit_refresh_gitgutter', 0) @@ -95,7 +99,12 @@ function! s:mg_get_info() let upstream_msg=s:mg_cut_str(magit#git#get_commit_subject(upstream_br), limit) let push_msg=s:mg_cut_str(magit#git#get_commit_subject(push_br), limit) - let head_line=magit#utils#strip(printf("%-*s %-*s %s", + let update_msg = "" + if b:magit_last_update_time > 1.0 && b:magit_update_mode_undefined == 1 + \ && b:magit_update_mode != 'fast' + let update_msg = "update is slow, consider fast update `:help vimagit-update-mode`" + endif + let head_line=magit#utils#strip(printf("%-*s %-*s %s", \ align_w, g:magit_section_info.cur_head, \ max_br_w, head_br, head_msg)) let upstream_line=magit#utils#strip(printf("%-*s %-*s %s", @@ -104,7 +113,9 @@ function! s:mg_get_info() let push_line=magit#utils#strip(printf("%-*s %-*s %s", \ align_w, g:magit_section_info.cur_push, \ max_br_w, push_br, push_msg)) - + let update_line=magit#utils#strip(printf("%-*s %-*s %s", + \ align_w, g:magit_section_info.update_mode, + \ max_br_w, b:magit_update_mode, update_msg)) silent put =g:magit_sections.info silent put =magit#utils#underline(g:magit_sections.info) @@ -113,6 +124,7 @@ function! s:mg_get_info() silent put =head_line silent put =upstream_line silent put =push_line + silent put =update_line if ( b:magit_current_commit_mode != '' ) let commit_mode_line=printf("%-*s %s", @@ -615,7 +627,15 @@ function! magit#update_buffer(...) let prev_filename = (pos > 0) ? filenames[pos-1] : '' endif + if has('reltime') + let start_time = reltime() + endif call b:state.update() + if has('reltime') + let b:magit_last_update_time = reltimefloat(start_time) + else + let b:magit_last_update_time = 0 + endif if ( g:magit_auto_close == 1 && \ b:magit_just_commited == 1 && @@ -866,6 +886,30 @@ function! magit#show_magit(display, ...) return endif + if index(g:magit_update_modes, g:magit_update_mode) == -1 + echohl WarningMsg + echom "g:magit_update_mode='" . g:magit_update_mode . "' must be one of the following: " . join(g:magit_update_modes, ',') + echom "Reset to normal" + echohl None + let g:magit_update_mode = 'normal' + endif + + let update_mode = magit#git#get_config('vimagit.update-mode', 'undefined') + if update_mode == 'undefined' + let b:magit_update_mode_undefined = 1 + let b:magit_update_mode = g:magit_update_mode + else + let b:magit_update_mode_undefined = 0 + if index(g:magit_update_modes, update_mode) == -1 + echohl WarningMsg + echom "vimagit.update-mode='" . update_mode . "' (gitconfig) must be one of the following: " . join(g:magit_update_modes, ',') + echom "Reset to g:magit_update_mode" + echohl None + let update_mode = g:magit_update_mode + endif + let b:magit_update_mode = update_mode + endif + let b:state = deepcopy(g:magit#state#state) call magit#utils#setbufnr(bufnr(buffer_name)) call magit#sign#init() diff --git a/syntax/magit.vim b/syntax/magit.vim index 3726ead..40521d6 100644 --- a/syntax/magit.vim +++ b/syntax/magit.vim @@ -39,6 +39,7 @@ execute 'syn match gitInfoRepo "\%(' . g:magit_section_info.cur_repo . '\)\@<= execute 'syn match gitInfoHead "\%(' . g:magit_section_info.cur_head . '\s*\)\@<=\S\+" oneline' execute 'syn match gitInfoUpstream "\%(' . g:magit_section_info.cur_upstream . '\s*\)\@<=\S\+" oneline' execute 'syn match gitInfoPush "\%(' . g:magit_section_info.cur_push . '\s*\)\@<=\S\+" oneline' +execute 'syn match gitUpdateMode "\%(' . g:magit_section_info.update_mode . '\s*\)\@<=\S\+" oneline' execute 'syn match gitCommitMode "\%(' . g:magit_section_info.commit_mode . '\)\@<=.*$" oneline' "execute 'syn match gitInfoCommit "\%(' . g:magit_section_info.cur_commit . '\)\@<=.*$" contains=infoSha1 oneline' "syntax match infoSha1 containedin=gitInfoCommit "\x\{7,}" @@ -47,6 +48,7 @@ highlight default link gitInfoRepo Directory highlight default link gitInfoHead Identifier highlight default link gitInfoUpstream Identifier highlight default link gitInfoPush Identifier +highlight default link gitUpdateMode Identifier highlight default link gitCommitMode Special highlight default link infoSha1 Identifier -- GitLab