Skip to content

Commit 5d51f31

Browse files
authored
Merge pull request #25 from isckraa/feature/mr-status-commits-behind
MR Status: Display how many commits are behind
2 parents 77dce7c + e0f6856 commit 5d51f31

File tree

4 files changed

+139
-16
lines changed

4 files changed

+139
-16
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,11 @@ git config --global mr.jira-ok-id "xx"
225225

226226
# Network timeout (in seconds, defaults to 10)
227227
# git config --global mr.git-mr-timeout 10
228+
229+
# Auto-fetch periodically (defaults to false)
230+
# git config --global mr.git-mr-autofetch true
231+
# Auto-fetch interval (in minutes)
232+
# git config --global mr.git-mr-autofetch-interval 5
228233
```
229234

230235
**Tip:**
@@ -279,6 +284,11 @@ export JIRA_OK_ID="xx"
279284

280285
# Network timeout (in seconds, defaults to 10)
281286
#export GIT_MR_TIMEOUT=10
287+
288+
# Auto-fetch periodically (defaults to false)
289+
#GIT_MR_AUTOFETCH=true
290+
# Auto-fetch interval (in minutes)
291+
#GIT_MR_AUTOFETCH_INTERVAL=5
282292
```
283293

284294
Environment-only configuration:

git-mr

Lines changed: 96 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,12 @@ git_remote_branch_exists() {
8787
git_check_branches() {
8888
local source_branch="$1"
8989
local target_branch="$2"
90+
local default_branch="$3"
9091

9192
[[ -n $source_branch ]] ||
9293
exit_error "$ERR_GIT" "Not on any branch"
9394

94-
[[ $source_branch != "$(git_default_branch)" ]] ||
95+
[[ $source_branch != "${default_branch:-$(git_default_branch)}" ]] ||
9596
exit_error "$ERR_GIT" "On default branch"
9697

9798
git_branch_exists "$source_branch" ||
@@ -106,6 +107,22 @@ git_check_branches() {
106107
return 0
107108
}
108109

110+
git_autofetch() {
111+
[[ "$GIT_MR_AUTOFETCH" == "true" ]] ||
112+
return 1 # autofetch is disabled
113+
114+
local git_dir; git_dir=$(git rev-parse --git-dir)
115+
116+
[[ -f "${git_dir}/FETCH_HEAD" &&
117+
-z "$(find "${git_dir}/FETCH_HEAD" -mmin +"${GIT_MR_AUTOFETCH_INTERVAL}" 2>/dev/null)" ]] &&
118+
return 1 # last fetch is recent enough
119+
120+
local remote; remote=${1:-$(gitlab_remote || git_remote)}
121+
122+
echo_debug "Fetching remote: ${remote}"
123+
git fetch --quiet "${remote}" 2>/dev/null
124+
}
125+
109126
git_commits() {
110127
local source_branch=${1:-$(git_current_branch)}
111128
local target_branch=${2:-${GIT_MR_TARGET:-$(git_base_branch "$source_branch")}}
@@ -1162,6 +1179,10 @@ mr_status_block() {
11621179
local mr_url=$6
11631180
local mr_title=$7
11641181

1182+
local current_target
1183+
local source_branch
1184+
local default_branch
1185+
11651186
local parse=()
11661187
[[ -z $merge_request && -z $mr_iid ]] && parse+=('"mr_iid=" + (.iid | @sh) + ";\n" +')
11671188
[[ -z $mr_url ]] && parse+=('"mr_url=" + (.web_url | @sh) + ";\n" +')
@@ -1178,12 +1199,31 @@ mr_status_block() {
11781199

11791200
mr_print_title "$mr_title" "$mr_url"
11801201

1202+
# Update remote references
1203+
local remote; remote=$(gitlab_remote || git_remote)
1204+
git_autofetch "${remote}"
1205+
1206+
default_branch=$(git_default_branch)
1207+
11811208
# Read merge request, approvals & threads
11821209
[[ -n $merge_request ]] || gitlab_read_mr merge_request
11831210
[[ -n $mr_approvals ]] || gitlab_read_approvals mr_approvals
11841211
[[ -n $mr_threads ]] || gitlab_read_threads mr_threads
11851212

1186-
mr_print_status "$merge_request" "$mr_approvals" "$mr_threads"
1213+
eval "$(echo "$merge_request" | jq -r '
1214+
"source_branch=" + (.source_branch | @sh) + ";\n" +
1215+
"current_target=" + (.target_branch | @sh) + ";\n"
1216+
')"
1217+
1218+
# Check branch lag
1219+
local mr_commits_behind mr_commits_behind_main
1220+
mr_commits_behind=$(git rev-list --count "${source_branch}..${remote}/${current_target}" 2>/dev/null || echo "0")
1221+
1222+
if [[ $current_target != "$default_branch" ]]; then
1223+
mr_commits_behind_main=$(git rev-list --count "${source_branch}..${remote}/${default_branch}" 2>/dev/null || echo "0")
1224+
fi
1225+
1226+
mr_print_status "$merge_request" "$mr_approvals" "$mr_threads" "$mr_commits_behind" "$mr_commits_behind_main"
11871227
}
11881228

11891229
mr_print_title() {
@@ -1200,6 +1240,8 @@ mr_print_status() {
12001240
local merge_request=$1
12011241
local approvals=$2
12021242
local threads=$3
1243+
local commits_behind=$4
1244+
local commits_behind_main=$5
12031245

12041246
[[ -n $merge_request ]] || exit_error "$ERR_MR" "merge_request not provided"
12051247

@@ -1318,12 +1360,26 @@ mr_print_status() {
13181360
ci_str="CI: $pipeline_icon"
13191361

13201362
# Merge target
1363+
local target_str_len=$((${#current_target} + 4))
13211364
local target_display
13221365
target_display="${target_display}$(colorize "(\U000021A3 " "gray")"
13231366
target_display="${target_display}$(colorize "$current_target" "lightpurple")"
1367+
1368+
if [[ $commits_behind -gt 0 || $commits_behind_main -gt 0 ]]; then
1369+
if [[ $commits_behind -gt 0 ]]
1370+
then target_display="${target_display} $(colorize "$commits_behind" "red" "bold")"
1371+
else target_display="${target_display} $(colorize "↓0" "green")"
1372+
fi
1373+
(( target_str_len += 4 )) # space, arrow, 2 digits
1374+
fi
1375+
1376+
if [[ $commits_behind_main -gt 0 ]]; then
1377+
target_display="${target_display} $(colorize "$commits_behind_main" "red")"
1378+
(( target_str_len += 4 )) # space, arrow, 2 digits
1379+
fi
1380+
13241381
target_display="${target_display}$(colorize ")" "gray")"
13251382

1326-
local target_str_len=$((${#current_target} + 4))
13271383

13281384
# Draft status
13291385
local draft_str=
@@ -1337,15 +1393,18 @@ mr_print_status() {
13371393
# Spacers for draft & target branch indicators
13381394
local display_width=76 # not counting 3 leading spaces
13391395
local spacer_chars=$((display_width - labels_str_len - target_str_len - draft_str_len))
1340-
local spacer_chars_l=0
1341-
local spacer_chars_r=0
1396+
local draft_spacer_l=0
1397+
local draft_spacer_r=0
13421398

13431399
if [[ $spacer_chars -gt 0 ]]; then
1344-
spacer_chars_l=$((43 - labels_str_len)) # 42: roughly at the same level as CI indicator
1345-
spacer_chars_r=$((spacer_chars - spacer_chars_l))
1346-
if [[ $spacer_chars_r -lt 0 ]]; then
1347-
spacer_chars_l=$((spacer_chars_l + spacer_chars_r))
1348-
spacer_chars_r=0
1400+
draft_spacer_l=$((43 - labels_str_len)) # 43: roughly at the same level as CI indicator
1401+
draft_spacer_r=$((spacer_chars - draft_spacer_l))
1402+
if [[ $draft_spacer_r -lt 0 ]]; then
1403+
draft_spacer_l=$((draft_spacer_l + draft_spacer_r))
1404+
draft_spacer_r=0
1405+
elif [[ $draft_spacer_l -lt 0 ]]; then
1406+
draft_spacer_r=$((draft_spacer_l + draft_spacer_r))
1407+
draft_spacer_l=0
13491408
fi
13501409
fi
13511410

@@ -1355,14 +1414,14 @@ mr_print_status() {
13551414
# 1st row ------------------------------------------------------------------
13561415
# Labels
13571416
echo -en " \U0001F3F7 ${labels_display}"
1358-
echo_spacer "$spacer_chars_l"
1417+
echo_spacer "$draft_spacer_l"
13591418
# Draft status
13601419
if [[ -n $draft_str ]]; then
13611420
echo -en " $(colorize "$draft_str" "orange") "
13621421
else
1363-
echo_spacer $((2 - spacer_chars_l - spacer_chars_r))
1422+
echo_spacer $((2 - draft_spacer_l - draft_spacer_r))
13641423
fi
1365-
echo_spacer "$spacer_chars_r"
1424+
echo_spacer "$draft_spacer_r"
13661425
# Target
13671426
echo "$target_display"
13681427

@@ -2321,7 +2380,9 @@ mr_update() {
23212380

23222381
local source_branch=${1:-$(git_current_branch)}
23232382
local target_branch=${GIT_MR_TARGET:-$(git_base_branch "$source_branch")}
2324-
git_check_branches "$source_branch" "$target_branch"
2383+
local default_branch; default_branch=$(git_default_branch)
2384+
2385+
git_check_branches "$source_branch" "$target_branch" "$default_branch"
23252386

23262387
# Search existing merge request
23272388
local mr_summary; mr_summary=$(gitlab_merge_request_summary "$source_branch")
@@ -2615,9 +2676,22 @@ mr_update() {
26152676
gitlab_read_approvals mr_approvals
26162677
gitlab_read_threads mr_threads
26172678

2679+
# Re-read current_target from MR (might have changed)
2680+
eval "$(echo "$merge_request" | jq -r '
2681+
"current_target=" + (.target_branch | @sh) + ";\n"
2682+
')"
2683+
2684+
# Check branch lag
2685+
local mr_commits_behind mr_commits_behind_main
2686+
mr_commits_behind=$(git rev-list --count "${source_branch}..${remote}/${current_target}" 2>/dev/null || echo "0")
2687+
2688+
if [[ $current_target != "$default_branch" ]]; then
2689+
mr_commits_behind_main=$(git rev-list --count "${source_branch}..${remote}/${default_branch}" 2>/dev/null || echo "0")
2690+
fi
2691+
26182692
# --------------------------------------------------------------------------------
26192693
mr_print_title "$mr_title" "$mr_url"
2620-
mr_print_status "$merge_request" "$mr_approvals" "$mr_threads"
2694+
mr_print_status "$merge_request" "$mr_approvals" "$mr_threads" "$mr_commits_behind" "$mr_commits_behind_main"
26212695
}
26222696

26232697
mr_merge() {
@@ -3013,6 +3087,9 @@ EOF
30133087
| mr.git-mr-required-upvotes | GIT_MR_REQUIRED_UPVOTES |
30143088
| | |
30153089
| mr.git-mr-timeout | GIT_MR_TIMEOUT |
3090+
| | |
3091+
| mr.git-mr-autofetch | GIT_MR_AUTOFETCH |
3092+
| mr.git-mr-autofetch-interval | GIT_MR_AUTOFETCH_INTERVAL |
30163093
+---------------------------------------------+---------------------------------------+
30173094
30183095
To create a Jira API Token, go to: https://id.atlassian.com/manage-profile/security/api-tokens
@@ -3109,12 +3186,16 @@ GIT_MR_EXTENDED=${GIT_MR_EXTENDED-$(git config --get mr.git-mr-extended || true)
31093186
GIT_MR_REQUIRED_UPVOTES=${GIT_MR_REQUIRED_UPVOTES:-$(git config --get mr.git-mr-required-upvotes || true)}
31103187
GITLAB_REMOVE_SOURCE_BRANCH_ON_MERGE=${GITLAB_REMOVE_SOURCE_BRANCH_ON_MERGE:-$(git config --get mr.gitlab-remove-source-branch-on-merge || true)}
31113188
GIT_MR_TIMEOUT=${GIT_MR_TIMEOUT:-$(git config --get mr.git-mr-timeout || true)}
3189+
GIT_MR_AUTOFETCH=${GIT_MR_AUTOFETCH:-$(git config --get mr.git-mr-autofetch || true)}
3190+
GIT_MR_AUTOFETCH_INTERVAL=${GIT_MR_AUTOFETCH_INTERVAL:-$(git config --get mr.git-mr-autofetch-interval || true)}
31123191

31133192
# Defaults
31143193
GITLAB_PROJECTS_LIMIT_MEMBER=${GITLAB_PROJECTS_LIMIT_MEMBER:-1}
31153194
GIT_MR_REQUIRED_UPVOTES=${GIT_MR_REQUIRED_UPVOTES:-2}
31163195
GITLAB_REMOVE_SOURCE_BRANCH_ON_MERGE=${GITLAB_REMOVE_SOURCE_BRANCH_ON_MERGE:-1}
31173196
GIT_MR_TIMEOUT=${GIT_MR_TIMEOUT:-10}
3197+
GIT_MR_AUTOFETCH=${GIT_MR_AUTOFETCH:-false}
3198+
GIT_MR_AUTOFETCH_INTERVAL=${GIT_MR_AUTOFETCH_INTERVAL:-5}
31183199

31193200
GIT_MR_MENU_STATUS_SHOW=both
31203201
#GIT_MR_MENU_STATUS_SHOW=title

test/.gitconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,6 @@
3737
git-mr-required-upvotes = 2
3838
gitlab-remove-source-branch-on-merge = 1
3939
git-mr-timeout = 1
40+
41+
git-mr-autofetch = false
42+
git-mr-autofetch-interval = 1

test/git-mr.bats

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ setup_file() {
1515
GITLAB_IP_LABELS GITLAB_CR_LABELS GITLAB_QA_LABELS GITLAB_OK_LABELS \
1616
JIRA_IP_ID JIRA_CR_ID JIRA_QA_ID JIRA_OK_ID \
1717
GITLAB_PROJECTS_LIMIT_MEMBER \
18-
GIT_MR_EXTENDED GIT_MR_REQUIRED_UPVOTES GIT_MR_TIMEOUT
18+
GIT_MR_EXTENDED GIT_MR_REQUIRED_UPVOTES GIT_MR_TIMEOUT \
19+
GIT_MR_AUTOFETCH GIT_MR_AUTOFETCH_INTERVAL
1920

2021
export GIT_MR_NO_COLORS=1
2122
export GIT_MR_NO_TERMINAL_LINK=1
@@ -283,6 +284,34 @@ sha_link() {
283284
assert_output "Branch 'wrong' does not exist"
284285
}
285286

287+
@test "Auto-fetches remote" {
288+
GIT_MR_VERBOSE=1
289+
290+
# Not fetched yet
291+
[ ! -f .git/FETCH_HEAD ]
292+
293+
# No auto-fetch if not configured
294+
GIT_MR_AUTOFETCH=false
295+
run git_autofetch
296+
assert_output ""
297+
298+
# Auto-fetch if configured
299+
GIT_MR_AUTOFETCH=true
300+
run git_autofetch
301+
assert_output "Fetching remote: gitlab"
302+
303+
# Remote was fetched
304+
[ -f .git/FETCH_HEAD ]
305+
306+
# No auto-fetch if fetch is recent enough
307+
run git_autofetch
308+
assert_output ""
309+
310+
# reset
311+
GIT_MR_AUTOFETCH=false
312+
GIT_MR_VERBOSE=0
313+
}
314+
286315
@test "Lists current branch commits" {
287316
testSha1=$(short_sha "Feature test - 1")
288317
testSha2=$(short_sha "Feature test - 2")

0 commit comments

Comments
 (0)