git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 2/4] git-prompt.sh: rework of submodule indicator

From
SZEDER Gábor <szeder.dev@gmail.com>
Date
Jan 31, 2017, 18:06 UTC
Message-ID
<20170131180633.22369-1-szeder.dev@gmail.com>
In-Reply-To
<1485809065-11978-3-git-send-email-email@benjaminfuchs.de>
Show 71 quoted lines
> Rework of the first patch. The prompt now will look like this:
> (+name:master). I tried to considere all suggestions.
> Tests still missing.
> 
> Signed-off-by: Benjamin Fuchs <email@benjaminfuchs.de>
> ---
>  contrib/completion/git-prompt.sh | 49 ++++++++++++++++++++--------------------
>  1 file changed, 24 insertions(+), 25 deletions(-)
> 
> diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
> index 4c82e7f..c44b9a2 100644
> --- a/contrib/completion/git-prompt.sh
> +++ b/contrib/completion/git-prompt.sh
> @@ -95,8 +95,10 @@
>  # repository level by setting bash.hideIfPwdIgnored to "false".
>  #
>  # If you would like __git_ps1 to indicate that you are in a submodule,
> -# set GIT_PS1_SHOWSUBMODULE. In this case a "sub:" will be added before
> -# the branch name.
> +# set GIT_PS1_SHOWSUBMODULE to a nonempty value. In this case the name
> +# of the submodule will be prepended to the branch name (e.g. module:master).
> +# The name will be prepended by "+" if the currently checked out submodule
> +# commit does not match the SHA-1 found in the index of the containing repository.
>  
>  # check whether printf supports -v
>  __git_printf_supports_v=
> @@ -288,30 +290,27 @@ __git_eread ()
>  	test -r "$f" && read "$@" <"$f"
>  }
>  
> -# __git_is_submodule
> -# Based on:
> -# http://stackoverflow.com/questions/7359204/git-command-line-know-if-in-submodule
> -__git_is_submodule ()
> -{
> -	local git_dir parent_git module_name path
> -	# Find the root of this git repo, then check if its parent dir is also a repo
> -	git_dir="$(git rev-parse --show-toplevel)"
> -	module_name="$(basename "$git_dir")"
> -	parent_git="$(cd "$git_dir/.." && git rev-parse --show-toplevel 2> /dev/null)"
> -	if [[ -n $parent_git ]]; then
> -		# List all the submodule paths for the parent repo
> -		while read path
> -		do
> -			if [[ "$path" != "$module_name" ]]; then continue; fi
> -			if [[ -d "$git_dir/../$path" ]];    then return 0; fi
> -		done < <(cd $parent_git && git submodule --quiet foreach 'echo $path' 2> /dev/null)
> -    fi
> -    return 1
> -}
> -
> +# __git_ps1_submodule
> +#
> +# $1 - git_dir path
> +#
> +# Returns the name of the submodule if we are currently inside one. The name
> +# will be prepended by "+" if the currently checked out submodule commit does
> +# not match the SHA-1 found in the index of the containing repository.
> +# NOTE: git_dir looks like in a ...
> +# - submodule: "GIT_PARENT/.git/modules/PATH_TO_SUBMODULE"
> +# - parent: "GIT_PARENT/.git" (exception "." in .git)
>  __git_ps1_submodule ()
>  {
> -	__git_is_submodule && printf "sub:"
> +	local git_dir="$1"
> +	local submodule_name="$(basename "$git_dir")"
> +	if [ "$submodule_name" != ".git" ] && [ "$submodule_name" != "." ]; then
> +		local parent_top="${git_dir%.git*}"
> +		local submodule_top="${git_dir#*modules}"
> +		local status=""
> +		git diff -C "$parent_top" --no-ext-diff --ignore-submodules=dirty --quiet -- "$submodule_top" 2>/dev/null || status="+"

This 'git diff' has to read the index of the parent repository, right? That can be potentially very expensive, if the parent repository, and thus its index, is big.

You might want to provide finer granularity controls and separate the "$PWD is in a submodule" indicator from the "submodule commit doesn't match" indicator. Even if someone is in general interested in the former, he might have some huge repositories where he would prefer to disable the latter, because executing 'git diff' would make the prompt lag.

I'm not sure we need brand new control knobs, though. Perhaps we can get away by checking the env and config variables used for the dirty index and worktree status indicator, after all they, too, are about whether to run 'git diff' for the prompt in a repository or not.

Show 11 quoted lines
> +		printf "$status$submodule_name:"
> +	fi
>  }
>  
>  # __git_ps1 accepts 0 or 1 arguments (i.e., format string)
> @@ -545,7 +544,7 @@ __git_ps1 ()
>  
>  	local sub=""
>  	if [ -n "${GIT_PS1_SHOWSUBMODULE}" ]; then
> -		sub="$(__git_ps1_submodule)"
> +		sub="$(__git_ps1_submodule $g)"

In Bash, and in shells in general, the visibility of variables works differently than in "regular" programming languages:

  - Any variable existing in a caller, even the ones declared as
    'local' in the caller, are visible in all callees.
    
    This means you don't have to pass $g as parameter to
    __git_ps1_submodule(), because you can access it inside that
    function directly.  This has the benefit that there is one less
    place where you can forget to quote a path variable :)
  - If the callee modifies any variable that isn't declared as local
    in the callee, then the caller will see the modified value of that
    variable, unless the callee was invoked in a subshell.
    Here your sole purpose is to set $sub to something like "+sub:",
    which is determined in __git_ps1_submodule().  You don't need the
    command substitution for that, you can set $sub directly in
    __git_ps1_submodule(), sparing the overhead of fork()ing a
    subshell.  That's important for the sake of git users on Windows.
>  	fi
>  
>  	local f="$w$i$s$u"
-- 
2.7.4
Previous: Benjamin FuchsNext: Benjamin Fuchs
Message 46 of 53 in “git-prompt.sh: Full patch for submodule indicator”
  1. 0/4 git-prompt.sh: Full patch for submodule indicatorBenjamin Fuchs, Jan 30, 2017
  2. 3/4 git-prompt.sh: fix for submodule 'dirty' indicatorBenjamin Fuchs, Jan 30, 2017
  3. 4/4 git-prompt.sh: add tests for submodule indicatorBenjamin Fuchs, Jan 30, 2017
  4. SZEDER GáborJan 31, 2017
  5. Junio C HamanoJan 31, 2017
  6. Stefan BellerJan 31, 2017
  7. rev-parse: add --show-superproject-working-treeStefan Beller, Mar 7, 2017
  8. Junio C HamanoMar 7, 2017
  9. Junio C HamanoMar 7, 2017
  10. Junio C HamanoMar 7, 2017
  11. Junio C HamanoMar 7, 2017
  12. Stefan BellerMar 7, 2017
  13. Junio C HamanoMar 7, 2017
  14. [PATCHv2] rev-parse: add --show-superproject-working-treeStefan Beller, Mar 8, 2017
  15. Junio C HamanoMar 8, 2017
  16. [PATCHv3] rev-parse: add --show-superproject-working-treeStefan Beller, Mar 8, 2017
  17. Junio C HamanoMar 8, 2017
  18. [PATCHv4] rev-parse: add --show-superproject-working-treeStefan Beller, Mar 8, 2017
  19. Junio C HamanoMar 8, 2017
  20. Jonathan NiederMar 17, 2017
  21. Documentation/git-worktree: use working tree for trees on the file systemStefan Beller, Mar 17, 2017
  22. Jonathan NiederMar 17, 2017
  23. Stefan BellerMar 17, 2017
  24. Junio C HamanoMar 18, 2017
  25. Junio C HamanoMar 18, 2017
  26. Junio C HamanoMar 18, 2017
  27. Stefan BellerMar 20, 2017
  28. Junio C HamanoMar 20, 2017
  29. Jonathan NiederMar 20, 2017
  30. 0/2 use "working trees" instead of "worktree" in our APIStefan Beller, Mar 20, 2017
  31. 2/2 revparse: introduce --is-inside-working-treeStefan Beller, Mar 20, 2017
  32. Jonathan NiederMar 20, 2017
  33. 1/2 git.c: introduce --working-tree superseding --work-treeStefan Beller, Mar 20, 2017
  34. Jonathan NiederMar 20, 2017
  35. Junio C HamanoMar 20, 2017
  36. Duy NguyenMar 21, 2017
  37. Junio C HamanoMar 21, 2017
  38. Michael J GruberMar 23, 2017
  39. Junio C HamanoMar 23, 2017
  40. Duy NguyenMar 25, 2017
  41. Michael J GruberApr 7, 2017
  42. Jacob KellerApr 7, 2017
  43. Duy NguyenMar 25, 2017
  44. Junio C HamanoMar 8, 2017
  45. 2/4 git-prompt.sh: rework of submodule indicatorBenjamin Fuchs, Jan 30, 2017
  46. SZEDER GáborJan 31, 2017
  47. 1/4 git-prompt.sh: add submodule indicatorBenjamin Fuchs, Jan 30, 2017
  48. Junio C HamanoJan 30, 2017
  49. Benjamin FuchsJan 31, 2017
  50. Junio C HamanoJan 31, 2017
  51. Stefan BellerFeb 6, 2017
  52. Jacob KellerFeb 6, 2017
  53. Stefan BellerFeb 6, 2017

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.