From 353cb210d4bf03db4ecb86985ca54cf3c643ee5c Mon Sep 17 00:00:00 2001 From: Shashank Bharadwaj Date: Wed, 14 Feb 2018 10:54:20 -0800 Subject: [PATCH] Add priliminary support for perforce SCM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds very simple support for the Perforce SCM: https://www.perforce.com/ Although perforce is proprietary software, it's somewhat prevalent in enterprise companies. This patch looks to provide some basic bash_it functionality that I've come to love for git. I base everything off of two perforce commands: $ p4 set This command does not require a connection the perforce server, it simply tells us if a directory is managed by the Perforce SCM or not. In addition the command: $ p4 opened is used to provide the list of pending changes in the client and the number of opened files in the client. The `p4 opened` command requires a connection to the perforce server, hence it's run under a `timeout` command. The "p4 opened" processing into it's own bash file that now has to be sourced at the top-level bash-it.sh. Since the processing in simple the newly added: _p4-opened-counts function returns a number of things that are not currently used, but since I had awk open and doing the processing, I've chosen to include them in the output anyway. Testing: - Tested with the powerline-multiline theme in a few perforce based workspaces/clients - Ran: ❯ shellcheck themes/p4helpers.theme.bash and fixed all the errors - Ran the test suite: ❯ test/run [...] 182 tests, 0 failures, 1 skipped --- bash_it.sh | 2 ++ themes/base.theme.bash | 35 ++++++++++++++++++++++ themes/p4helpers.theme.bash | 45 ++++++++++++++++++++++++++++ themes/powerline/powerline.base.bash | 2 ++ 4 files changed, 84 insertions(+) create mode 100644 themes/p4helpers.theme.bash diff --git a/bash_it.sh b/bash_it.sh index 70082205..6e87100d 100755 --- a/bash_it.sh +++ b/bash_it.sh @@ -60,6 +60,8 @@ done source "${BASH_IT}/themes/colors.theme.bash" # shellcheck source=./themes/githelpers.theme.bash source "${BASH_IT}/themes/githelpers.theme.bash" +# shellcheck source=./themes/p4helpers.theme.bash +source "${BASH_IT}/themes/p4helpers.theme.bash" # shellcheck source=./themes/base.theme.bash source "${BASH_IT}/themes/base.theme.bash" diff --git a/themes/base.theme.bash b/themes/base.theme.bash index a18c3729..fda845de 100644 --- a/themes/base.theme.bash +++ b/themes/base.theme.bash @@ -42,6 +42,12 @@ SCM_GIT_STAGED_CHAR="S:" SCM_GIT_STASH_CHAR_PREFIX="{" SCM_GIT_STASH_CHAR_SUFFIX="}" +SCM_P4='p4' +SCM_P4_CHAR='⌛' +SCM_P4_CHANGES_CHAR='C:' +SCM_P4_DEFAULT_CHAR='D:' +SCM_P4_OPENED_CHAR='O:' + SCM_HG='hg' SCM_HG_CHAR='☿' @@ -71,6 +77,7 @@ function scm { if [[ "$SCM_CHECK" = false ]]; then SCM=$SCM_NONE elif [[ -f .git/HEAD ]]; then SCM=$SCM_GIT elif which git &> /dev/null && [[ -n "$(git rev-parse --is-inside-work-tree 2> /dev/null)" ]]; then SCM=$SCM_GIT + elif which p4 &> /dev/null && [[ -n "$(p4 set P4CLIENT 2> /dev/null)" ]]; then SCM=$SCM_P4 elif [[ -d .hg ]]; then SCM=$SCM_HG elif which hg &> /dev/null && [[ -n "$(hg root 2> /dev/null)" ]]; then SCM=$SCM_HG elif [[ -d .svn ]]; then SCM=$SCM_SVN @@ -81,6 +88,7 @@ function scm { function scm_prompt_char { if [[ -z $SCM ]]; then scm; fi if [[ $SCM == $SCM_GIT ]]; then SCM_CHAR=$SCM_GIT_CHAR + elif [[ $SCM == $SCM_P4 ]]; then SCM_CHAR=$SCM_P4_CHAR elif [[ $SCM == $SCM_HG ]]; then SCM_CHAR=$SCM_HG_CHAR elif [[ $SCM == $SCM_SVN ]]; then SCM_CHAR=$SCM_SVN_CHAR else SCM_CHAR=$SCM_NONE_CHAR @@ -93,6 +101,7 @@ function scm_prompt_vars { SCM_DIRTY=0 SCM_STATE='' [[ $SCM == $SCM_GIT ]] && git_prompt_vars && return + [[ $SCM == $SCM_P4 ]] && p4_prompt_vars && return [[ $SCM == $SCM_HG ]] && hg_prompt_vars && return [[ $SCM == $SCM_SVN ]] && svn_prompt_vars && return } @@ -125,6 +134,7 @@ function scm_prompt_info_common { fi # TODO: consider adding minimal status information for hg and svn + [[ ${SCM} == ${SCM_P4} ]] && p4_prompt_info && return [[ ${SCM} == ${SCM_HG} ]] && hg_prompt_info && return [[ ${SCM} == ${SCM_SVN} ]] && svn_prompt_info && return } @@ -193,6 +203,26 @@ function git_prompt_vars { SCM_CHANGE=$(_git-short-sha 2>/dev/null || echo "") } +function p4_prompt_vars { + IFS=$'\t' read -r \ + opened_count non_default_changes default_count \ + add_file_count edit_file_count delete_file_count \ + <<< "$(_p4-opened-counts)" + if [[ "${opened_count}" -gt 0 ]]; then + SCM_DIRTY=1 + SCM_STATE=${SCM_THEME_PROMPT_DIRTY} + [[ "${opened_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_P4_OPENED_CHAR}${opened_count}" + [[ "${non_default_changes}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_P4_CHANGES_CHAR}${non_default_changes}" + [[ "${default_count}" -gt 0 ]] && SCM_BRANCH+=" ${SCM_P4_DEFAULT_CHAR}${default_count}" + else + SCM_DIRTY=0 + SCM_STATE=${SCM_THEME_PROMPT_DIRTY} + fi + + SCM_PREFIX=${P4_THEME_PROMPT_PREFIX:-$SCM_THEME_PROMPT_PREFIX} + SCM_SUFFIX=${P4_THEME_PROMPT_SUFFIX:-$SCM_THEME_PROMPT_SUFFIX} +} + function svn_prompt_vars { if [[ -n $(svn status 2> /dev/null) ]]; then SCM_DIRTY=1 @@ -363,6 +393,11 @@ function git_prompt_info { echo -e "${SCM_PREFIX}${SCM_BRANCH}${SCM_STATE}${SCM_SUFFIX}" } +function p4_prompt_info() { + p4_prompt_vars + echo -e "${SCM_PREFIX}${SCM_BRANCH}:${SCM_CHANGE}${SCM_STATE}${SCM_SUFFIX}" +} + function svn_prompt_info { svn_prompt_vars echo -e "${SCM_PREFIX}${SCM_BRANCH}${SCM_STATE}${SCM_SUFFIX}" diff --git a/themes/p4helpers.theme.bash b/themes/p4helpers.theme.bash new file mode 100644 index 00000000..27a777ac --- /dev/null +++ b/themes/p4helpers.theme.bash @@ -0,0 +1,45 @@ +#!/usr/bin/env bash + +function _p4-opened { + timeout 2.0s p4 opened -s 2> /dev/null +} + +function _p4-opened-counts { + # Return the following counts seperated by tabs: + # - count of opened files + # - count of pending changesets (other than defaults) + # - count of files in the default changeset + # - count of opened files in add mode + # - count of opened files in edit mode + # - count of opened files in delete mode + _p4-opened | awk ' + BEGIN { + opened=0; + type_array["edit"]=0; + type_array["add"]=0; + type_array["delete"]=0; + change_array["change"]=0; + } + { + # p4 opened prints one file per line, and all lines begin with "//" + # Here is an examples: + # + # $ p4 opened + # //depot/some/file.py#4 - edit change 716431 (text) + # //depot/another/file.py - edit default change (text) + # //now/add/a/newfile.sh - add change 435645 (text+k) + # + # + if ($1 ~ /^\/\//) { + opened += 1 + change_array[$5] += 1 + type_array[$3] += 1 + } + } + END { + default_changes=change_array["change"]; + non_default_changes=length(change_array) - 1; + print opened "\t" non_default_changes "\t" default_changes "\t" type_array["add"] "\t" type_array["edit"] "\t" type_array["delete"] + } +' +} diff --git a/themes/powerline/powerline.base.bash b/themes/powerline/powerline.base.bash index c352a87a..ade246e9 100644 --- a/themes/powerline/powerline.base.bash +++ b/themes/powerline/powerline.base.bash @@ -84,6 +84,8 @@ function __powerline_scm_prompt { fi if [[ "${SCM_GIT_CHAR}" == "${SCM_CHAR}" ]]; then scm_prompt+="${SCM_CHAR}${SCM_BRANCH}${SCM_STATE}" + elif [[ "${SCM_P4_CHAR}" == "${SCM_CHAR}" ]]; then + scm_prompt+="${SCM_CHAR}${SCM_BRANCH}${SCM_STATE}" fi echo "${scm_prompt}${scm}|${color}" fi