From 57c0eb776c7aca82d4cfca9f785dd0b0749d372b Mon Sep 17 00:00:00 2001 From: Niklas Schlimm Date: Wed, 8 Mar 2017 19:50:36 +0100 Subject: [PATCH] New Command git-bulk initial commit --- Commands.md | 68 ++++++++++ bin/git-bulk | 232 ++++++++++++++++++++++++++++++++++ etc/git-extras-completion.zsh | 1 + man/git-bulk.1 | 0 man/git-bulk.html | 0 man/git-bulk.md | 99 +++++++++++++++ 6 files changed, 400 insertions(+) create mode 100755 bin/git-bulk create mode 100644 man/git-bulk.1 create mode 100644 man/git-bulk.html create mode 100644 man/git-bulk.md diff --git a/Commands.md b/Commands.md index cba10d3..e8e6975 100644 --- a/Commands.md +++ b/Commands.md @@ -4,6 +4,7 @@ - [`git authors`](#git-authors) - [`git back`](#git-back) - [`git bug`](#git-featurerefactorbugchore) + - [`git bulk`](#git-bulk) - [`git changelog`](#git-changelog) - [`git chore`](#git-featurerefactorbugchore) - [`git clear`](#git-clear) @@ -234,6 +235,73 @@ $ git effort --above 5 $ git effort bin/* lib/* ``` +## git bulk + +`git bulk` adds covenien support for operations that you want to execute on multiple git repositories. + + * simply register workspaces that contain multiple git repos in their directory structure + * run any git command on the repositories of the registered workspaces in one command to `git bulk` + * use the "guarded mode" to check on each execution + +```bash +usage: git bulk [-g] [-w ] + git bulk --addworkspace + git bulk --removeworkspace + git bulk --addcurrent + git bulk --purge + git bulk --listall +``` + + Register a workspace so that `git bulk` knows about it: + +```bash +$ git bulk --addworkspace personal ~/workspaces/personal +``` + + Register the current directory as a workspace to `git bulk` + +```bash +$ git bulk --addcurrent personal +``` + + List all registered workspaces: + +```bash +$ git bulk --listall +bulkworkspaces.personal /Users/niklasschlimm/workspaces/personal +``` + + Run a git command on the repositories: + +```bash +$ git bulk fetch +``` + +![fetchdemo](https://cloud.githubusercontent.com/assets/876604/23709805/e8178406-041a-11e7-9a0c-01de5fbf8944.png) + + Run a git command on only one workspace ans its repositories: + +```bash +$ git bulk -w personal fetch +``` + + Run a git command but ask user for confirmation on every execution (guarded mode): + +```bash +$ git bulk -g fetch +``` + + Remove a registered workspace: + +```bash +$ git bulk --removeworkspace personal +``` + Remove all registered workspaces: + +```bash +$ git bulk --purge +``` + ## git repl Git read-eval-print-loop. Let's you run `git` commands without typing 'git'. diff --git a/bin/git-bulk b/bin/git-bulk new file mode 100755 index 0000000..0718360 --- /dev/null +++ b/bin/git-bulk @@ -0,0 +1,232 @@ +#!/usr/bin/env bash +# reset environment variables that could interfere with normal usage +export GREP_OPTIONS= +# put all utility functions here + +# make a temporary file +git_extra_mktemp() { + mktemp -t "$(basename "$0")".XXX +} + +# +# check whether current directory is inside a git repository +# + +is_git_repo() { + git rev-parse --show-toplevel > /dev/null 2>&1 + result=$? + if test $result != 0; then + >&2 echo 'Not a git repo!' + exit $result + fi +} + +is_git_repo +invers=`tput rev` +reset=`tput sgr0` +txtbld=$(tput bold) # Bold +bldred=${txtbld}$(tput setaf 1) # red +shopt -s extglob +guarded=false +singlemode=false + +# +# print usage message +# +usage() { + echo 1>&2 "usage: git bulk [-g] [-w ] " + echo 1>&2 " git bulk --addworkspace " + echo 1>&2 " git bulk --removeworkspace " + echo 1>&2 " git bulk --addcurrent " + echo 1>&2 " git bulk --purge" + echo 1>&2 " git bulk --listall" +} + +# add another workspace to global git config +function addWSDir () { + git config --global bulkworkspaces.$wsname "$wsdir" +} + +# add current directory +function addCurrWSDir () { + git config --global bulkworkspaces.$wsname "$PWD" +} + +# remove workspace from global git config +function remWSDir () { + git config --global --unset bulkworkspaces.$wsname +} + +# remove workspace from global git config +function purgeWS () { + git config --global --remove-section bulkworkspaces +} + +# list all current workspace locations defined +function listWSDir () { + git config --global --get-regexp bulkworkspaces +} + +# atomic execution of a git command in one specific repository +function guardedExecution () { + if $guarded; then + echo -n "${invers}git $gitcommand${reset} -> execute here (y/n)? " + read -n 1 -r ${reset} executing ${invers}git $gitcommand${reset}" + git $gitcommand +} + +# check if the passed command is known as a core git command +function checkGitCommand () { + if git help -a | cat | grep -o -q "$corecommand"; then + echo "Core command \"$corecommand\" accepted." + else + usage + echo "error: unknown GIT command: $corecommand" + exit 1 + fi +} + +# check if workspace name is registered +function checkWSName () { + found=0 + while read workspace; do + cwsname=$(echo $workspace | cut -f1 -d' ' | cut -f2 -d'.') + if [[ $cwsname == $wsname ]]; then return; fi + done <<< "$(echo $(listWSDir))" + # when here the ws name was not found + echo "error: unknown workspace name: $wsname" + exit 1 +} + +# execute the bulk operation +function executBulkOp () { + if $singlemode; then + echo "Selected single workspace mode in workspace: $wsname" + fi + listWSDir | while read workspacespec; do + cwsname=$(echo $workspacespec | cut -f1 -d' ' | cut -f2 -d'.') + if $singlemode && $cwsname != $wsname ]]; then continue; fi + wslocation=$(echo $workspacespec | cut -f2 -d' ') + eval cd "$wslocation" + actual=$(pwd) + echo "Executing bulk operation in workspace ${invers}$actual${reset}" + eval find . -name ".git" | while read line; do + gitrepodir=${line::${#line}-5} # cut the .git part of find results to have the root git directory of that repository + eval cd "$gitrepodir" # into git repo location + curdir=$(pwd) + echo "Current repository: ${curdir%/*}/${bldred}${curdir##*/}${reset}" + guardedExecution + eval cd "$wslocation" # back to origin location of last find command + done + done +} + +initialcount="${#}" +initialarguments="${@}" + +# if no arguments show registered workspaces +if [[ $initialcount -le 0 ]]; then + listWSDir +fi + +# parse command parameters +while [ "${#}" -ge 1 ] ; do + + case "$1" in + --listall) + butilcommand="listWSDir" + break + ;; + --purge) + butilcommand="purgeWS" + break + ;; + --removeworkspace) + shift + wsname="$1" + butilcommand="remWSDir" + break + ;; + --addcurrent) + shift + wsname="$1" + butilcommand="addCurrWSDir" + break + ;; + --addworkspace) + shift + wsname="$1" + shift + wsdir="$1" + butilcommand="addWSDir" + break + ;; + -g) + guarded=true + ;; + -w) + singlemode=true + shift + wsname="$1" + checkWSName + ;; + -*) + usage + echo 1>&2 "error: unknown argument $1" + exit 1 + ;; + --*) + usage + echo 1>&2 "error: unknown argument $1" + exit 1 + ;; + *) + butilcommand="executBulkOp" + corecommand="$1" + gitcommand="$@" + checkGitCommand + butilcommand="executBulkOp" + break + ;; + esac + + shift +done + +# check right number of arguments +case $butilcommand in + @(listWSDir|purgeWS) ) + if [[ $initialcount -ne 1 ]]; then + usage + echo 1>&2 "error: wrong number of arguments" + exit 1 + fi + ;; + @(addCurrWSDir|remWSDir)) + if [[ $initialcount -ne 2 ]]; then + usage + echo 1>&2 "error: wrong number of arguments" + exit 1 + fi + ;; + addWSDir) + if [[ $initialcount -ne 3 ]]; then + usage + echo 1>&2 "error: wrong number of arguments" + exit 1 + fi + ;; +esac + +$butilcommand # run user command \ No newline at end of file diff --git a/etc/git-extras-completion.zsh b/etc/git-extras-completion.zsh index b123a3f..de0db63 100644 --- a/etc/git-extras-completion.zsh +++ b/etc/git-extras-completion.zsh @@ -360,6 +360,7 @@ zstyle ':completion:*:*:git:*' user-commands \ authors:'generate authors report' \ back:'undo and stage latest commits' \ bug:'create bug branch' \ + bulk:'run bulk commands' \ changelog:'generate a changelog report' \ chore:'create chore branch' \ clear-soft:'soft clean up a repository' \ diff --git a/man/git-bulk.1 b/man/git-bulk.1 new file mode 100644 index 0000000..e69de29 diff --git a/man/git-bulk.html b/man/git-bulk.html new file mode 100644 index 0000000..e69de29 diff --git a/man/git-bulk.md b/man/git-bulk.md new file mode 100644 index 0000000..0539b2b --- /dev/null +++ b/man/git-bulk.md @@ -0,0 +1,99 @@ +git-bulk(1) -- Run git commands on multiple repositories +======================================================== + +## SYNOPSIS + +usage: git bulk [-g] [-w <ws-name>] <git command> + git bulk --addworkspace <ws-name> <ws-root-directory> + git bulk --removeworkspace <ws-name> + git bulk --addcurrent <ws-name> + git bulk --purge + git bulk --listall + +## DESCRIPTION + +git bulk adds covenien support for operations that you want to execute on multiple git repositories. + +- simply register workspaces that contain multiple git repos in their directory structure +- run any git command on the repositories of the registered workspaces in one command to `git bulk` +- use the "guarded mode" to check on each execution + +## OPTIONS + + -g + + Ask the user for confitmation on every execution. + + -w + + Run the GIT command only on the specified workspace. The workspace must be registered. + + <git command> + + Any GIT Command you wish to execute on all the Repositories. + + --addworkspace <ws-name> <ws-root-directory> + + Register a workspace for bulk operations. All repositories in the diretories below <ws-root-directory> get registered under this workspace with the name <ws-name>. + + --removeworkspace <ws-name> + + Remove the workspace with the logical name <ws-name>. + + --addcurrent <ws-name> + + Adds the current difrectory as workspace to git bulk operations. The workspace is referenced wioth ist logical name <ws-name>. + + git bulk --purge + + Removes all defined repository locations. + + git bulk --listall + + List all registered repositories. + +## EXAMPLES + + Register a workspace so that git bulk knows about it: + + $ git bulk --addworkspace personal ~/workspaces/personal + + Register the current directory as a workspace to git bulk: + + $ git bulk --addcurrent personal + + List all registered workspaces: + + $ git bulk --listall + + Run a git command on the repositories: + + $ git bulk fetch + + Run a git command on only one workspace and its repositories: + + $ git bulk -w personal fetch + + Run a git command but ask user for confirmation on every execution (guarded mode): + + $ git bulk -g fetch + + Remove a registered workspace: + + $ git bulk --removeworkspace personal + + Remove all registered workspaces: + + $ git bulk --purge + +## AUTHOR + +Written by Niklas Schlimm <> + +## REPORTING BUGS + +<https://github.com/nschlimm/git-bulk> + +## SEE ALSO + +<>