1#!/bin/bash
2#
3#  Copyright (c) 2018, The OpenThread Authors.
4#  All rights reserved.
5#
6#  Redistribution and use in source and binary forms, with or without
7#  modification, are permitted provided that the following conditions are met:
8#  1. Redistributions of source code must retain the above copyright
9#     notice, this list of conditions and the following disclaimer.
10#  2. Redistributions in binary form must reproduce the above copyright
11#     notice, this list of conditions and the following disclaimer in the
12#     documentation and/or other materials provided with the distribution.
13#  3. Neither the name of the copyright holder nor the
14#     names of its contributors may be used to endorse or promote products
15#     derived from this software without specific prior written permission.
16#
17#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27#  POSSIBILITY OF SUCH DAMAGE.
28#
29
30die()
31{
32    echo " *** ERROR: " "$*"
33    exit 1
34}
35
36display_usage()
37{
38    echo "Squash merge a given branch into the current branch"
39    echo ""
40    echo "This command squash merges all commits from a given branch into the current branch"
41    echo "By default, the changes are committed with a commit message which includes the list of all squashed commits"
42    echo "(use --no-commit and --no-list options to change default behavior)."
43    echo ""
44    echo "Usage: $(basename "$0") [--no-list] [--no-commit] <branch> [<commit msg>]"
45    echo ""
46    echo "     <branch>       Specifies the name of branch to merge into current branch"
47    echo "     <commit msg>   An optional parameter specifying text to add to the commit message"
48    echo "Options:"
49    echo "     --no-list      The commit message will not include the list of squashed commits"
50    echo "     --no-commit    Squash and stage the changes but do not commit "
51    echo ""
52}
53
54SHOULD_ADD_LIST=true
55SHOULD_COMMIT=true
56
57while test $# != 0; do
58    case "$1" in
59        --help | -h | -[?])
60            display_usage
61            exit 0
62            ;;
63
64        --no-list)
65            SHOULD_ADD_LIST=false
66            ;;
67        --no-commit)
68            SHOULD_COMMIT=false
69            ;;
70        --debug) set -x ;;
71        --*) die "Unknown argument $1" ;;
72        -*) die "Unknown argument $1" ;;
73        *)
74            break
75            ;;
76    esac
77    shift
78done
79
80if [ "$#" -eq 0 ]; then
81    display_usage
82    die "No branch name"
83fi
84
85if [ "$#" -gt 2 ]; then
86    display_usage
87    die "Extra argument"
88fi
89
90NEWLINE=$'\n'
91
92branch="$1"
93cur_branch=$(git rev-parse --abbrev-ref HEAD)
94
95# Get the list of commits (diff between current and new branch)
96# Note that the list starts with older commits
97
98if ${SHOULD_ADD_LIST}; then
99    commit_list=$(git log HEAD.."$branch" --oneline --decorate=no --reverse)
100else
101    commit_list=""
102fi
103
104commit_msg_header="Squash merge '$branch' into '$cur_branch'"
105
106if [ -z "$2" ]; then
107    commit_msg="${commit_msg_header}${NEWLINE}${NEWLINE}${commit_list}"
108else
109    commit_msg="${commit_msg_header}${NEWLINE}${NEWLINE}$2${NEWLINE}${NEWLINE}${commit_list}"
110fi
111
112git merge --squash "$branch" 1>/dev/null 2>/dev/null || die "Failed to perform 'git merge -squash $branch'"
113
114# Check if there is anything staged
115if ! git diff --cached --quiet; then
116    echo "No changes to commit when squash merging branch '$branch' into '$cur_branch'"
117    exit 0
118fi
119
120if ${SHOULD_COMMIT}; then
121    # Commit the staged changes
122    git commit -m "$commit_msg" 1>/dev/null 2>/dev/null || die "git commit failed${NEWLINE}${NEWLINE}$(cat "$TMP")"
123
124    git log -1
125
126    echo "${NEWLINE}Successfully squash merged branch '$branch' into '$cur_branch'"
127else
128    echo "Successfully prepared squash merge of branch '$branch' into '$cur_branch' - ready to commit"
129fi
130