git-compose
Advanced tools
+1
-1
| { | ||
| "name": "git-compose", | ||
| "version": "0.1.2", | ||
| "version": "0.1.3", | ||
| "description": "Compose GIT branches and cascade merge updates", | ||
@@ -5,0 +5,0 @@ "repository": { |
+16
-9
@@ -6,7 +6,7 @@ GIT Compose | ||
| Assumes your project is using the ``IIF™`` branching pattern: | ||
| Assumes your project is using the ``IIP™`` branching pattern: | ||
| - Isolation Branches | ||
| - Integration Branches | ||
| - Feature Branches | ||
| - Package Branches | ||
@@ -25,9 +25,8 @@ ### Isolation Branch | ||
| ### Feature Branch | ||
| ### Package Branch | ||
| > One or more Isolation and/or Integration Branches composed to create a foundation upon which a feature is built, prefixed with ``feat__``. | ||
| > Isolation, muliple Isolation and/or Integration Branches on their own or composed to create a foundation upon which a reusable package (eg. NPM package) is built, prefixed with ``pkg__``. | ||
| [read more ...](docs/branches-package.md) | ||
| [read more ...](docs/branches-feature.md) | ||
| ### Other Branches | ||
@@ -45,3 +44,3 @@ | ||
| - Make sure your branches follow the ``IIF™`` branch naming conventions. | ||
| - Make sure your branches follow the ``IIP™`` branch naming conventions. | ||
@@ -57,2 +56,10 @@ - Use the commands below | ||
| ``` | ||
| verbose mode (shows full branch names) | ||
| ``` | ||
| npx git-compose print_heirarchy -v | ||
| ``` | ||
| fetch remotes | ||
| ``` | ||
| npx git-compose print_heirarchy -f | ||
| ``` | ||
| - [build an integration branch](docs/commands-build-integration-branch.md) | ||
@@ -74,3 +81,3 @@ ``` | ||
| ``` | ||
| ROOT_BRANCH=master | ||
| ROOT_BRANCH=iso__base | ||
| ERROR_LOG_PATH=git-branch-errors.txt | ||
@@ -82,3 +89,3 @@ ``` | ||
| The ``IIF™`` standard is an experiment, use with discretion. | ||
| The ``IIP™`` standard is an experiment, use with discretion. | ||
| I take no responsibility for any damage or loss resulting from the use of this package. |
+250
-38
| #!/usr/bin/env bash | ||
| # -------------------------------------- | ||
| # print constants | ||
| # -------------------------------------- | ||
| LIGHTER_GREY=246 | ||
| LIGHT_GREY=244 | ||
| GREY=243 | ||
| DARK_GREY=237 | ||
| DARKER_GREY=235 | ||
| BLACK=233 | ||
| BLUE=4 | ||
| GOLD=214 | ||
| LIGHTBLUE=74 | ||
| LIME=106 | ||
| RED=124 | ||
| LIGHTRED=202 | ||
| PINK=219 | ||
| WHITE=255 | ||
| PURPLE=99 | ||
| DETAULT_THEME=$LIME | ||
| BOLD=1 | ||
| DIM=2 | ||
| ITALIC=3 | ||
| UNDERLINED=4 | ||
| NORMAL=5 | ||
| RESET="\033[0m" | ||
| # -------------------------------------- | ||
| # print utils | ||
| # -------------------------------------- | ||
| function _getBG() { | ||
| echo "\033[48;5;${1}m" | ||
| } | ||
| function _getFG() { | ||
| local mod="${!2:-$NORMAL}" | ||
| echo "\033[${mod};38;5;${1}m" | ||
| } | ||
| function _print() { | ||
| printf '%b%b %s %b' $1 $2 "${3}" $RESET | ||
| } | ||
| function h1() { | ||
| local color="${!2:-$DETAULT_THEME}" | ||
| _print $(_getBG $color) $(_getFG $BLACK BOLD) "${1}" | ||
| } | ||
| function h2() { | ||
| local color="${!2:-$DETAULT_THEME}" | ||
| _print $(_getBG $BLACK) $(_getFG $color) "${1}" | ||
| } | ||
| function h3() { | ||
| local color="${!2:-$DETAULT_THEME}" | ||
| _print $(_getBG $BLACK) $(_getFG $LIGHTER_GREY BOLD) "${1}" | ||
| } | ||
| function print() { | ||
| local color="${!2:-$DETAULT_THEME}" | ||
| local mod="${3:-NORMAL}" | ||
| _print $RESET $(_getFG $color $mod) "${1}" | ||
| } | ||
| # -------------------------------------- | ||
| # env | ||
@@ -16,6 +85,11 @@ # -------------------------------------- | ||
| DIR_SYMBOL=" +--" | ||
| DIR_SPACER=" | " | ||
| #DIR_SYMBOL=" +--" | ||
| DIR_SYMBOL=" -" | ||
| DIR_SPACER=" |" | ||
| ROOT_BRANCH="${ROOT_BRANCH:-master}" | ||
| BRANCH_STATUS_NO_REMOTE=0 | ||
| BRANCH_STATUS_REMOTE=1 | ||
| BRANCH_STATUS_CURRENT=2 | ||
| TREE=() | ||
@@ -66,4 +140,4 @@ TREE+=("${ROOT_BRANCH}") | ||
| local OUTPUT="" | ||
| for (( i=2 ; i<${#TREE[*]} ; i++ )) ; do | ||
| OUTPUT+="${DIR_SPACER}" | ||
| for (( i=1 ; i<${#TREE[*]} ; i++ )) ; do | ||
| OUTPUT+="${DIR_SPACER} " | ||
| done | ||
@@ -82,30 +156,149 @@ echo -e "${OUTPUT}" | ||
| print_hierarchy_branch () { | ||
| print_hierarchy_item_branch () { | ||
| local BRANCH="${1}" | ||
| set_parent_branch "${BRANCH}" | ||
| local DIR_SPACERS=$(build_dir_spacers) | ||
| local DIR="${DIR_SPACERS}${DIR_SYMBOL}" | ||
| DIR="${2:-$DIR}" | ||
| echo -e "${DIR} ${BRANCH}" | ||
| local BRANCH_STATUS="${2}" | ||
| local IS_VERBOSE="${3}" | ||
| # ... parent branch | ||
| if [[ "${BRANCH}" != "${ROOT_BRANCH}" ]] ; then | ||
| set_parent_branch "${BRANCH}" | ||
| fi | ||
| local DIR="${DIR_SYMBOL}" | ||
| # ... dir spacer | ||
| if [[ "${BRANCH}" != "${ROOT_BRANCH}" ]] ; then | ||
| local DIR_SPACERS=$(build_dir_spacers) | ||
| DIR="${DIR_SPACERS}${DIR_SYMBOL}" | ||
| fi | ||
| DIR="${4:-$DIR}" | ||
| # ... color | ||
| local COLOR="${WHITE}" | ||
| # abbreviate if not verbose | ||
| if [[ $IS_VERBOSE == 0 ]] ; then | ||
| BRANCH="${BRANCH/$PARENT_BRANCH/}" | ||
| BRANCH="${BRANCH/iso__/}" | ||
| fi | ||
| if [[ "${BRANCH_STATUS}" == "${BRANCH_STATUS_NO_REMOTE}" ]] ; then | ||
| COLOR=$LIGHT_GREY | ||
| print "${DIR}" LIGHT_GREY; print "${BRANCH}" COLOR; | ||
| fi | ||
| if [[ "${BRANCH_STATUS}" == "${BRANCH_STATUS_REMOTE}" ]] ; then | ||
| COLOR=$WHITE | ||
| print "${DIR}" LIGHT_GREY; print "${BRANCH}" COLOR; | ||
| fi | ||
| if [[ "${BRANCH_STATUS}" == "${BRANCH_STATUS_CURRENT}" ]] ; then | ||
| COLOR=$LIME | ||
| h2 "${DIR}" COLOR; h2 " ${BRANCH}" COLOR; | ||
| fi | ||
| } | ||
| print_hierarchy_item () { | ||
| IFS=':' read -ra DATA_ARR <<< "${1}" | ||
| local IS_VERBOSE="${2}" | ||
| local DIR="${3}" | ||
| local BRANCH="${DATA_ARR[0]}" | ||
| local LOCAL="${DATA_ARR[1]}" | ||
| local REMOTE="${DATA_ARR[2]}" | ||
| local BRANCH_STATUS="${BRANCH_STATUS_REMOTE}" | ||
| local DIFF="" | ||
| local DIFF_COLOR=$LIME | ||
| # ... no remote | ||
| if [[ -z "${REMOTE}" ]] ; then | ||
| BRANCH_STATUS="${BRANCH_STATUS_NO_REMOTE}" | ||
| # ... has remote | ||
| else | ||
| BRANCH_STATUS="${BRANCH_STATUS_REMOTE}" | ||
| DIFF=$(get_local_remote_diff "${LOCAL}" "${REMOTE}") | ||
| if [[ $DIFF -gt 0 ]] ; then | ||
| DIFF="+${DIFF}" | ||
| DIFF_COLOR=$LIME | ||
| elif [[ $DIFF -lt 0 ]] ; then | ||
| DIFF_COLOR=$LIGHTRED | ||
| else | ||
| DIFF="" | ||
| fi | ||
| fi | ||
| # ... is current | ||
| if [[ "${BRANCH}" == "${CURRENT_BRANCH}" ]] ; then | ||
| BRANCH_STATUS="${BRANCH_STATUS_CURRENT}" | ||
| fi | ||
| print_hierarchy_item_branch "${BRANCH}" $BRANCH_STATUS $IS_VERBOSE $DIR; print "${DIFF}" DIFF_COLOR ; echo "" | ||
| } | ||
| print_hierarchy () { | ||
| # ... args | ||
| local args=( ) | ||
| for x; do | ||
| case "$x" in | ||
| --fetch|-f) args+=( -f ) ;; | ||
| --verbose|-v) args+=( -v ) ;; | ||
| *) args+=( "$x" ) ;; | ||
| esac | ||
| done | ||
| set -- "${args[@]}" | ||
| local SHOULD_FETCH=0 | ||
| local IS_VERBOSE=0 | ||
| unset OPTIND | ||
| while getopts ":fv" x; do | ||
| case "$x" in | ||
| f) SHOULD_FETCH=1 ;; | ||
| v) IS_VERBOSE=1 ;; | ||
| esac | ||
| done | ||
| local BRANCH="" | ||
| echo -e "Isolation Branches\n----------------------" | ||
| for BRANCH in $(ls .git/refs/heads | grep '^iso__') ; do | ||
| print_hierarchy_branch "${BRANCH}" | ||
| if [[ "${SHOULD_FETCH}" -eq "1" ]]; then | ||
| git fetch --all | ||
| fi | ||
| # ... Isolation branches | ||
| h1 "Isolation Branches"; echo "" ; echo "" | ||
| # ROOT branch | ||
| for ROOT_DATA in $(git for-each-ref refs/heads --format='%(refname:lstrip=2):%(refname:short):%(upstream:short)' | grep "${ROOT_BRANCH}"); do | ||
| print_hierarchy_item "${ROOT_DATA}" $IS_VERBOSE | ||
| done | ||
| echo "" | ||
| echo -e "Integration Branches\n----------------------" | ||
| for BRANCH in $(ls .git/refs/heads | grep '^int__') ; do | ||
| print_hierarchy_branch "${BRANCH}" " -" | ||
| # other branches | ||
| for DATA in $(git for-each-ref refs/heads --format='%(refname:lstrip=2):%(refname:short):%(upstream:short)' | grep '^iso__'); do | ||
| IFS=':' read -ra DATA_ARR <<< "${DATA}" | ||
| local BRANCH="${DATA_ARR[0]}" | ||
| if [[ "${BRANCH}" != "${ROOT_BRANCH}" ]] ; then | ||
| print_hierarchy_item "${DATA}" $IS_VERBOSE | ||
| fi | ||
| done | ||
| echo "" | ||
| echo -e "Feature Branches\n----------------------" | ||
| for BRANCH in $(ls .git/refs/heads | grep '^feat__') ; do | ||
| print_hierarchy_branch "${BRANCH}" | ||
| # ... Integration branches | ||
| h1 "Integration Branches"; echo "" ; echo "" | ||
| for DATA in $(git for-each-ref refs/heads --format='%(refname:lstrip=2):%(refname:short):%(upstream:short)' | grep '^int__'); do | ||
| print_hierarchy_item "${DATA}" $IS_VERBOSE " -" | ||
| done | ||
| echo "" | ||
| } | ||
@@ -125,4 +318,4 @@ | ||
| strip_prefix_feature_branch () { | ||
| echo "${1}" | sed -e 's/^feat__//' | ||
| strip_prefix_package_branch () { | ||
| echo "${1}" | sed -e 's/^pkg__//' | ||
| } | ||
@@ -135,3 +328,3 @@ | ||
| # - merge parent into child for | ||
| # all Isolation/Feature branches | ||
| # all Isolation/Package branches | ||
| # - merge all component Isolation branches | ||
@@ -167,3 +360,3 @@ # into all Integration branches | ||
| local ERROR_TYPE="${4:-FAILURE}" | ||
| echo "${DIR} ${BRANCH} < ${MERGE_BRANCH} * ${ERROR_TYPE}" | ||
| print "${DIR} ${BRANCH} < ${MERGE_BRANCH} * ${ERROR_TYPE}" LIGHTRED ; echo "" | ||
| } | ||
@@ -175,3 +368,3 @@ | ||
| local DIR=$3 | ||
| echo "${DIR} ${BRANCH} < ${MERGE_BRANCH}" | ||
| print "${DIR} ${BRANCH} < ${MERGE_BRANCH}" WHITE ; echo "" | ||
| } | ||
@@ -236,2 +429,20 @@ | ||
| # TODO: update to return ahead and behind (to indicate diverge) | ||
| get_local_remote_diff () { | ||
| local LOCAL="${1}" | ||
| local REMOTE="${2}" | ||
| git rev-list --left-right ${LOCAL}...${REMOTE} -- 2>/dev/null >/tmp/git_upstream_status_delta | ||
| LEFT_AHEAD=$(grep -c '^<' /tmp/git_upstream_status_delta) | ||
| RIGHT_AHEAD=$(grep -c '^>' /tmp/git_upstream_status_delta) | ||
| if [[ "$LEFT_AHEAD" -gt 0 ]] ; then | ||
| echo "${LEFT_AHEAD}" | ||
| elif [[ "$RIGHT_AHEAD" -gt 0 ]] ; then | ||
| echo "-${RIGHT_AHEAD}" | ||
| else | ||
| echo 0 | ||
| fi | ||
| } | ||
| cascade_merge () { | ||
@@ -244,5 +455,10 @@ cascade_merge_prechecks | ||
| # ... cascade merge Isolation branches | ||
| echo -e "Isolation Branches\n----------------------" | ||
| for BRANCH in $(ls .git/refs/heads | grep '^iso__') ; do | ||
| cascade_merge_isolation_branch "${BRANCH}" | ||
| h1 "Isolation Branches"; echo "" ; echo "" | ||
| echo -e "${DIR_SYMBOL} ${ROOT_BRANCH}" | ||
| for BRANCH in $(git for-each-ref refs/heads --format='%(refname:lstrip=2)' | grep '^iso__'); do | ||
| if [[ "${BRANCH}" != "${ROOT_BRANCH}" ]] ; then | ||
| cascade_merge_isolation_branch "${BRANCH}" | ||
| fi | ||
| done | ||
@@ -252,4 +468,6 @@ echo "" | ||
| # ... cascade merge Integration branches | ||
| echo -e "Integration Branches\n----------------------" | ||
| for BRANCH in $(ls .git/refs/heads | grep '^int__') ; do | ||
| h1 "Integration Branches"; echo "" ; echo "" | ||
| for BRANCH in $(git for-each-ref refs/heads --format='%(refname:lstrip=2)' | grep '^int__'); do | ||
| cascade_merge_integration_branch "${BRANCH}" | ||
@@ -259,9 +477,2 @@ done | ||
| # ... cascade merge Feature branches | ||
| echo -e "Feature Branches\n----------------------" | ||
| for BRANCH in $(ls .git/refs/heads | grep '^feat__') ; do | ||
| cascade_merge_feature_branch "${BRANCH}" | ||
| done | ||
| echo "" | ||
| # ... re-checkout current branch | ||
@@ -282,3 +493,4 @@ git checkout "${CURRENT_BRANCH}" -q | ||
| echo -e "Building Integration Branch\n${BRANCH}\n----------------------" | ||
| h1 "Building Integration Branch"; echo "" ; h2 "${BRANCH}" ; echo "" ; echo "" | ||
| git checkout -b "${BRANCH}" | ||
@@ -285,0 +497,0 @@ cascade_merge_integration_branch "${BRANCH}" |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
14042
48.29%86
8.86%2
100%