Compare commits

..

No commits in common. "2db6f1bf02ff4fc5645eab1b1a006b64a26ce40d" and "fa62b8a09410ccf8493d40b056c2ce52f7947007" have entirely different histories.

2 changed files with 18 additions and 81 deletions

View file

@ -13,12 +13,8 @@ It was inspired by [[https://wiki.ros.org/wstool][wstool]], [[https://github.com
Usage: gis [OPTIONS] [COMMAND] Usage: gis [OPTIONS] [COMMAND]
Show a status summary of all Git repositories which are found recursively in Show a status summary of all Git repositories which are found recursively in
current work directory. The colon colon-separated environment variable current work directory. If the colon-separated environment variable $GIS_PATH
$GIS_PATH or the '-p' argument can be used to modify the search path. is set, the declared directories will be used instead.
All 'fetch' and 'pull' operations are executed in parallel. The number of
background jobs can be limited with the environment variable $GIS_JOBS or the
'-j' argument.
COMMANDS COMMANDS
fetch Execute 'git fetch --prune --all' for all found repositories fetch Execute 'git fetch --prune --all' for all found repositories
@ -26,7 +22,6 @@ It was inspired by [[https://wiki.ros.org/wstool][wstool]], [[https://github.com
which are behind upstream, includes 'gis fetch' which are behind upstream, includes 'gis fetch'
OPTIONS OPTIONS
-j, --jobs N Limit 'fetch' and 'pull' commands to N parallel jobs
-p, --path PATH Use PATH for searching Git repositories -p, --path PATH Use PATH for searching Git repositories
-h, --help Show this help message and exit -h, --help Show this help message and exit
#+end_example #+end_example

90
gis
View file

@ -14,12 +14,8 @@ function print_usage {
Usage: gis [OPTIONS] [COMMAND] Usage: gis [OPTIONS] [COMMAND]
Show a status summary of all Git repositories which are found recursively in Show a status summary of all Git repositories which are found recursively in
current work directory. The colon colon-separated environment variable current work directory. If the colon-separated environment variable \$GIS_PATH
\$GIS_PATH or the '-p' argument can be used to modify the search path. is set, the declared directories will be used instead.
All 'fetch' and 'pull' operations are executed in parallel. The number of
background jobs can be limited with the environment variable \$GIS_JOBS or the
'-j' argument.
COMMANDS COMMANDS
fetch Execute 'git fetch --prune --all' for all found repositories fetch Execute 'git fetch --prune --all' for all found repositories
@ -27,7 +23,6 @@ COMMANDS
which are behind upstream, includes 'gis fetch' which are behind upstream, includes 'gis fetch'
OPTIONS OPTIONS
-j, --jobs N Limit 'fetch' and 'pull' commands to N parallel jobs
-p, --path PATH Use PATH for searching Git repositories -p, --path PATH Use PATH for searching Git repositories
-h, --help Show this help message and exit -h, --help Show this help message and exit
EOF EOF
@ -39,38 +34,11 @@ function error {
exit 1 exit 1
} }
function execute_git_command_on_list {
IFS=";" read -r -a git_dirs <<< "$2"
for dir in "${git_dirs[@]}"; do
cd "$dir" || echo "Failed to cd into ${text_bold}${text_red}${dir}${text_reset}"
# Get repository name
repository_name=$(basename "$dir")
# Execute 'fetch' or 'pull'
if [ "$1" == "fetch" ]; then
output=$(git fetch --prune --all --porcelain &> >(sed "s/^/${text_bold}${text_blue}${repository_name}${text_reset} /"))
[ "$?" != 0 ] && echo -e "${text_bold}${text_blue}${repository_name}${text_reset} ${text_bold}${text_red}ERROR${text_reset} while fetching\n${output}"
elif [ "$1" == "pull" ]; then
git pull --recurse-submodules > >(sed "s/^/${text_bold}${text_magenta}${repository_name}${text_reset} /")
fi
done
}
# Parse arguments # Parse arguments
jobs=0
fetch=false fetch=false
pull=false pull=false
while (( "$#" )); do while (( "$#" )); do
case "$1" in case "$1" in
-j|--jobs)
if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then
jobs="$2"
shift 2
else
error "Argument for ${text_bold}$1${text_reset} is missing"
fi
;;
-p|--path) -p|--path)
if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then
paths+=("$(realpath "$2")") paths+=("$(realpath "$2")")
@ -139,18 +107,6 @@ for path in "${paths[@]}"; do
git_dirs+=("${found_git_dirs[@]}") git_dirs+=("${found_git_dirs[@]}")
done done
# Set default number of jobs if argument or $GIS_JOBS wasn't set
if [ "$jobs" == 0 ]; then
if [ "$GIS_JOBS" ]; then
jobs="$GIS_JOBS"
else
jobs="${#git_dirs[@]}"
fi
fi
if ! [[ "$jobs" =~ ^[0-9]+$ ]]; then
error "Number of parallel jobs must be a positive number"
fi
# Fetch Git repositories # Fetch Git repositories
if [ "$fetch" == true ]; then if [ "$fetch" == true ]; then
@ -161,24 +117,17 @@ if [ "$fetch" == true ]; then
fi fi
echo "${text_bold}${text_blue}Fetching${text_reset} ${#git_dirs[@]} repositor${suffix}" echo "${text_bold}${text_blue}Fetching${text_reset} ${#git_dirs[@]} repositor${suffix}"
# Create n lists of repositories where n is the number of parallel jobs for dir in "${git_dirs[@]}"; do
declare -a fetch_lists cd "$dir" || echo "Failed to cd into ${text_bold}${text_red}${dir}${text_reset}"
for i in "${!git_dirs[@]}"; do
list_index=$((i % jobs))
if [ "${fetch_lists[$list_index]}" == "" ]; then
fetch_lists[list_index]="${git_dirs[$i]}"
else
fetch_lists[list_index]="${fetch_lists[$list_index]};${git_dirs[$i]}"
fi
done
# Fetch all lists in background # Get repository name
for fetch_list in "${fetch_lists[@]}"; do repository_name=$(basename "$dir")
execute_git_command_on_list "fetch" "${fetch_list}" &
# Fetch all Git repositories in background
git fetch --prune --all 1> /dev/null 2> >(trap 'kill $! 2> /dev/null' INT TERM; sed "s/^/${text_bold}${text_blue}${repository_name}${text_reset} /") &
fetch_pids+=("$!") fetch_pids+=("$!")
done done
# Wait for fetching of all lists
for pid in "${fetch_pids[@]}"; do for pid in "${fetch_pids[@]}"; do
wait "$pid" wait "$pid"
done done
@ -205,24 +154,17 @@ if [ "$pull" == true ]; then
fi fi
echo "${text_bold}${text_magenta}Pulling${text_reset} ${#pull_dirs[@]} repositor${suffix}" echo "${text_bold}${text_magenta}Pulling${text_reset} ${#pull_dirs[@]} repositor${suffix}"
# Create n lists of repositories where n is the number of parallel jobs # Pull all Git repositories which are behind upstream in background
declare -a pull_lists for dir in "${pull_dirs[@]}"; do
for i in "${!pull_dirs[@]}"; do cd "$dir" || echo "Failed to cd into ${text_bold}${text_red}${dir}${text_reset}"
list_index=$((i % jobs))
if [ "${pull_lists[$list_index]}" == "" ]; then
pull_lists[list_index]="${pull_dirs[$i]}"
else
pull_lists[list_index]="${pull_lists[$list_index]};${pull_dirs[$i]}"
fi
done
# Pull all lists in background # Get repository name
for pull_list in "${pull_lists[@]}"; do repository_name=$(basename "$dir")
execute_git_command_on_list "pull" "${pull_list}" &
git pull --recurse-submodules > >(trap 'kill $! 2> /dev/null' INT TERM; sed "s/^/${text_bold}${text_magenta}${repository_name}${text_reset} /") &
pull_pids+=("$!") pull_pids+=("$!")
done done
# Wait for pulling of all lists
for pid in "${pull_pids[@]}"; do for pid in "${pull_pids[@]}"; do
wait "$pid" wait "$pid"
done done