Gustavo Jose de Sousa
10 years ago
committed by
Andrew Tridgell
1 changed files with 202 additions and 0 deletions
@ -0,0 +1,202 @@ |
|||||||
|
#!/bin/bash |
||||||
|
|
||||||
|
SCRIPT_DIR=$(dirname $(realpath ${BASH_SOURCE[0]})) |
||||||
|
GIT_DIR=$(git rev-parse --git-dir) |
||||||
|
GIT_ROOT=$(git rev-parse --show-toplevel) |
||||||
|
|
||||||
|
usage() { |
||||||
|
cat >&$1 <<EOF |
||||||
|
Usage: git commit-subsystems [OPTIONS] |
||||||
|
|
||||||
|
Ardupilot's git extension. |
||||||
|
|
||||||
|
Create a different commit for each ardupilot's subsystem (vehicles, libraries |
||||||
|
and folders in the project's root). The items in OPTIONS are passed down to the |
||||||
|
original git commit command with exception of options --message and --file (and |
||||||
|
their short versions). Boths are related to the commit message: |
||||||
|
commit-subsystems will treat the commit message from one of those two options |
||||||
|
as a template such that occurrences of \$subsystem are replaced with the |
||||||
|
subsystem being currently committed. |
||||||
|
|
||||||
|
If neither --message or --file are passed, then the first commit's message will |
||||||
|
be used as a template for the other messages and option --edit will be used for |
||||||
|
the next commits. To avoid that behavior use --naive. |
||||||
|
|
||||||
|
Another custom option is --raw: don't use commit message as a template. |
||||||
|
EOF |
||||||
|
} |
||||||
|
|
||||||
|
MSG_FILE="$GIT_DIR/COMMIT_SUBSYSTEM_MSG" |
||||||
|
extra_options= |
||||||
|
|
||||||
|
process_msg() { |
||||||
|
local subsystem=$1 |
||||||
|
local prev_subsystem=$2 |
||||||
|
if [[ -n "$option_m" || -n "$option_F" ]]; then |
||||||
|
if [[ $option_F == - ]]; then |
||||||
|
echo "Please, type the commits message template:" |
||||||
|
option_F="$GIT_DIR/COMMIT_SUBSYSTEM_TEMPLATE" |
||||||
|
cat - > "$option_F" |
||||||
|
fi |
||||||
|
|
||||||
|
if [[ -n "$option_m" ]]; then |
||||||
|
echo "$option_m" |
||||||
|
else |
||||||
|
cat "$option_F" |
||||||
|
fi | if $option_raw; then |
||||||
|
cat |
||||||
|
else |
||||||
|
sed "s,\$subsystem,$cur_subsystem,g" |
||||||
|
fi > "$MSG_FILE" |
||||||
|
|
||||||
|
|
||||||
|
extra_options=(-F "$MSG_FILE") |
||||||
|
elif [[ -n $prev_subsystem ]] && ! $option_naive; then # try to be "smart" |
||||||
|
cat $GIT_DIR/COMMIT_EDITMSG \ |
||||||
|
| sed -e "/^\s*#/d" \ |
||||||
|
-e "s/.*\<$prev_subsystem\>.*/\0\n#\0/" \ |
||||||
|
| sed "/^[^#]/ s/\<$prev_subsystem\>/$subsystem/g" > "$MSG_FILE" |
||||||
|
echo >> "$MSG_FILE" |
||||||
|
echo "# This commit message was adapted by commit-subsystems" >> "$MSG_FILE" |
||||||
|
extra_options=(-F "$MSG_FILE" --edit) |
||||||
|
fi |
||||||
|
} |
||||||
|
|
||||||
|
commit_subsystem() { |
||||||
|
local subsystem=$1 |
||||||
|
local prev_subsystem=$2 |
||||||
|
shift 2 |
||||||
|
process_msg $subsystem $prev_subsystem |
||||||
|
if ! git commit ${extra_options[*]} "$@"; then |
||||||
|
echo "Couldn't commit subsystem $subsystem, aborting..." >&2 |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
} |
||||||
|
|
||||||
|
args=() |
||||||
|
|
||||||
|
option_m= |
||||||
|
option_F= |
||||||
|
option_naive=false |
||||||
|
option_raw=false |
||||||
|
|
||||||
|
while [[ -n "$1" ]]; do |
||||||
|
opt="$1" |
||||||
|
case "$opt" in |
||||||
|
-h|--help) |
||||||
|
usage 1 |
||||||
|
exit 0 |
||||||
|
;; |
||||||
|
-m|--message) |
||||||
|
shift |
||||||
|
if [[ -z "$1" ]]; then |
||||||
|
echo "Option $opt requires a commit message." >&2 |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
option_m="$1" |
||||||
|
;; |
||||||
|
-F|--file) |
||||||
|
shift |
||||||
|
if [[ -z "$1" ]]; then |
||||||
|
echo "Option $opt requires a file name." >&2 |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
option_F="$1" |
||||||
|
;; |
||||||
|
--naive) |
||||||
|
option_naive=true |
||||||
|
;; |
||||||
|
--raw) |
||||||
|
option_raw=true |
||||||
|
;; |
||||||
|
*) |
||||||
|
args+=("$1") |
||||||
|
;; |
||||||
|
esac |
||||||
|
shift |
||||||
|
done |
||||||
|
|
||||||
|
if [[ -n $option_m && -n $option_F ]]; then |
||||||
|
echo "Options -m and -F can't be combined." >&2 |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
|
||||||
|
set -- "${args[@]}" |
||||||
|
|
||||||
|
LIST=$GIT_DIR/COMMIT_SUBSYSTEMS_LIST |
||||||
|
|
||||||
|
git diff --name-only --staged | $SCRIPT_DIR/path-libraries.sh -p > $LIST |
||||||
|
git diff --name-only --staged | $SCRIPT_DIR/path-nonlibraries.sh -p >> $LIST |
||||||
|
|
||||||
|
if [[ $(cat "$LIST" | wc -l) -eq 0 ]]; then |
||||||
|
echo "Nothing to commit." >&2 |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
|
||||||
|
echo "Reseting changes in order to add files separately..." |
||||||
|
git reset >/dev/null |
||||||
|
|
||||||
|
# head before commits - for recovery |
||||||
|
RECOVERY_HEAD=$(git log -n 1 --format=%H) |
||||||
|
exit_hook() { |
||||||
|
local last_error=$? |
||||||
|
|
||||||
|
set +e |
||||||
|
|
||||||
|
[[ -a /dev/fd/3 ]] && exec 3<&- |
||||||
|
|
||||||
|
[[ $last_error -eq 0 ]] && return 0 |
||||||
|
|
||||||
|
echo |
||||||
|
echo "Program interrupted or finished with error(s), reseting head..." >&2 |
||||||
|
git reset $RECOVERY_HEAD >/dev/null |
||||||
|
echo "Trying to re-add files..." >&2 |
||||||
|
if [[ ! -f $LIST ]]; then |
||||||
|
echo "File with list of added files not found..." >&2 |
||||||
|
else |
||||||
|
error=false |
||||||
|
cat $LIST | while read subsystem path; do |
||||||
|
if ! git add -- "$GIT_ROOT/$path"; then |
||||||
|
echo "Couldn't add \"$path\"..." >&2 |
||||||
|
error=true |
||||||
|
fi |
||||||
|
done |
||||||
|
|
||||||
|
if $error; then |
||||||
|
echo "This is embarrassing, couldn't re-add all files. Sorry." >&2 |
||||||
|
else |
||||||
|
echo "Files re-added." >&2 |
||||||
|
fi |
||||||
|
fi |
||||||
|
|
||||||
|
return 1 |
||||||
|
} |
||||||
|
|
||||||
|
set -e |
||||||
|
trap "exit 1" SIGINT |
||||||
|
trap exit_hook EXIT |
||||||
|
|
||||||
|
echo "Adding and committing subsystems..." |
||||||
|
exec 3< $LIST |
||||||
|
cur_subsystem= |
||||||
|
prev_subsystem= |
||||||
|
empty=true |
||||||
|
while read -u 3 subsystem path; do |
||||||
|
empty=false |
||||||
|
if [[ $cur_subsystem != $subsystem ]]; then |
||||||
|
if [[ -n $cur_subsystem ]]; then |
||||||
|
commit_subsystem "$cur_subsystem" "$prev_subsystem" "$@" |
||||||
|
echo |
||||||
|
fi |
||||||
|
prev_subsystem=$cur_subsystem |
||||||
|
cur_subsystem=$subsystem |
||||||
|
fi |
||||||
|
if ! git add -- "$GIT_ROOT/$path"; then |
||||||
|
echo "Couldn't add \"$path\", aborting..." >&2 |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
done |
||||||
|
|
||||||
|
# the last one |
||||||
|
commit_subsystem "$cur_subsystem" "$prev_subsystem" "$@" |
||||||
|
echo |
Loading…
Reference in new issue