-
Notifications
You must be signed in to change notification settings - Fork 43
/
Copy pathgit_s_fe_check_fix_status.sh
executable file
·177 lines (155 loc) · 5.55 KB
/
git_s_fe_check_fix_status.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#!/usr/bin/env bash
# Run this as:
# git submodule foreach '$toplevel/git_s_fe_check_fix_status.sh $name $path $sha1 $toplevel <--dry-run>'
name=$1; shift
path=$1; shift
sha1_super=$1; shift
toplevel=$1; shift
dryrun=$1; shift
if [[ ${dryrun} == --dry-run ]]; then
dryrun=yes
elif [[ -z ${dryrun} ]]; then
dryrun=no
else
echo "ERROR :: Unknown command: ${dryrun}, did you mean to pass: --dry-run"
exit 1
fi
sha1_h=$(git rev-parse HEAD)
function anc_print() {
if git merge-base --is-ancestor $1 $2; then
echo "1"
else
echo "0"
fi
}
function maybe_do() {
if [[ ${dry_run} == yes ]]; then
echo "DRYRUN: $*"
else
$*
fi
}
function git_dirty {
[[ $(git diff --shortstat 2> /dev/null | tail -n1) != "" ]] && echo "1"
echo 0
}
function git_num_untracked_files {
expr echo $(git status --porcelain 2>/dev/null| grep "^??" | wc -l)
}
function git_num_added_to_index {
expr $(git status --porcelain 2>/dev/null| grep "^M" | wc -l)
}
SUCCESS=0
# DEBUG=yes
if [[ $name == dbus-feedstock-no ]]; then
DEBUG=yes
fi
if [[ ${DEBUG} == yes ]]; then
SUCCESS=1
# set -x
fi
# There is a '--name-only' flag to 'git config', but no '--value-only' flag .. onward and awkward
wanted_branch=$(git config -f ${toplevel}/.gitmodules --get-regexp "^submodule\.${name}\.branch$" | awk '{ print $2 }')
if [[ ! ${wanted_branch} ]]; then
echo "FATAL: Could not detemine branch for ${name}, please fix .gitmodules"
exit 1
fi
# We have sha1s for each of HEAD, master (really wanted) and other
sha1_m=$(git rev-parse ${wanted_branch})
sha1_o=$(git rev-parse origin/${wanted_branch})
if [[ ${DEBUG} == yes ]]; then
echo name = ${name}
echo path = ${path}
echo sha1_super = ${sha1_super}
echo sha1_HEAD = ${sha1_h}
echo sha1_${wanted_branch} = ${sha1_m}
echo sha1_origin/${wanted_branch} = ${sha1_o}
echo toplevel = ${toplevel}
fi
on_wanted=no
if current_branch=$(git symbolic-ref --short -q HEAD); then
if [[ ${current_branch} != ${wanted_branch} ]]; then
echo "${name} not on wanted branch: ${wanted_branch}"
maybe_do git checkout ${wanted_branch}
[[ ${dryrun} == no ]] && current_branch=wanted_branch
[[ ${dryrun} == no ]] && on_wanted=yes
maybe_do git branch -u origin/${wanted_branch}
maybe_do git pull --rebase
else
on_wanted=yes
fi
fi
if [[ ! ${current_branch} ]]; then
echo "${name} not on any branch, wanted branch: ${wanted_branch}"
fi
if [[ ${sha1_h} == ${sha1_m} ]] && [[ ${sha1_h} == ${sha1_o} ]]; then
# Simple case, maybe checkout ${wanted_branch} and move on
if [[ ${on_wanted} == no ]]; then
maybe_do git checkout ${wanted_branch}
fi
# echo SUCCESS=$SUCCESS
exit ${SUCCESS}
fi
h_anc_m=$(anc_print ${sha1_h} ${sha1_m})
h_anc_o=$(anc_print ${sha1_h} ${sha1_o})
m_anc_h=$(anc_print ${sha1_m} ${sha1_h})
m_anc_o=$(anc_print ${sha1_m} ${sha1_o})
o_anc_m=$(anc_print ${sha1_o} ${sha1_m})
o_anc_h=$(anc_print ${sha1_o} ${sha1_h})
if [[ ${DEBUG} == yes ]]; then
spaces=" "
echo " sha1_h: ${sha1_h} sha1_m: ${sha1_m} sha1_o: ${sha1_o}"
echo "is_anc of:"
echo "sha1_h: ${spaces}1${spaces}${spaces}${m_anc_h}${spaces}${spaces}${o_anc_h}"
echo "sha1_m: ${spaces}${h_anc_m}${spaces}${spaces}1${spaces}${spaces}${o_anc_m}"
echo "sha1_o: ${spaces}${h_anc_o}${spaces}${spaces}${m_anc_o}${spaces}${spaces}1"
fi
# There are 4 stages to worry about and they need to be progressed in that order
# 1. Local uncommitted changes => commit them to HEAD
# 2. Committed changes to HEAD => get master to agree
# 3. Agreement b/ HEAD, master => get origin to agree
# 4. Agreement b/ master, origin => all done
# Agreement between the branches, but HEAD differs.
if [[ ${sha1_m} == ${sha_o} ]]; then
# If HEAD is an ancestor of (both of) the branches ..
if ${h_anc_m}; then
echo "${name} HEAD is an ancestor of origin/${wanted_branch} (which is equal to ${wanted_branch}), I suggest you:\$ git checkout ${wanted_branch}"
exit ${SUCCESS}
else
echo "${name} HEAD is *not* an ancestor of origin/${wanted_branch} (which is equal to ${wanted_branch}), your branches have diverged. Please manually rectify this"
exit 1
fi
fi
if [[ ${sha1_h} == ${sha1_o} ]]; then
# HEAD is equal to origin ..
if [[ ${m_anc_o} ]]; then
# .. and master is an ancestor of these
if [[ ${on_wanted} == no ]]; then
maybe_do git checkout ${wanted_branch}
[[ ${dryrun} == no ]] && on_wanted=yes
fi
maybe_do git branch -u origin/${wanted_branch}
maybe_do git pull --rebase
exit ${SUCCESS}
fi
fi
# Suggestions only after this point.
if [[ ${on_wanted} == no ]]; then
echo "# ${name} :: You are not on the wanted branch, I suggest you:"
echo "pushd ${name} && git checkout ${wanted_branch} && popd"
fi
if [[ ${o_anc_m} == 1 ]] && [[ ${sha1_o} != ${sha1_m} ]]; then
echo "# ${name} :: Your local ${wanted_branch} has new commits, I suggest you:"
echo "pushd ${name} && git checkout ${wanted_branch} && git push origin/${wanted_branch} && popd"
exit ${SUCCESS}
elif [[ ${m_anc_o} == 1 ]] && [[ ${sha1_m} != ${sha1_o} ]]; then
echo "# ${name} :: Your local ${wanted_branch} is behind origin/${wanted_branch}, I suggest you:"
echo "pushd ${name} && git checkout ${wanted_branch} && git pull --rebase origin/${wanted_branch} && popd"
exit ${SUCCESS}
elif [[ ${m_anc_o} == 0 ]]; then
echo "# ${name} :: Your local ${wanted_branch} is *not* an ancestor of origin/${wanted_branch}, has origin/${wanted_branch} been rebased? I suggest you:"
echo "pushd ${name} && git reset ${wanted_branch} origin/${wanted_branch} && popd"
exit ${SUCCESS}
fi
echo "${name} :: We should not get to here"
exit 0