gitbash 2.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,6 +20,21 @@ _gb_color_ok() {
20
20
  [[ -z "${NO_COLOR:-}" && -t "$1" ]]
21
21
  }
22
22
 
23
+ # NO_COLOR (https://no-color.org): a non-empty value turns off all colors.
24
+ # GB_COLOR is the --color value for git and bat in fzf previews; it is
25
+ # exported because previews run in a separate bash started by fzf.
26
+ if [[ -n "${NO_COLOR:-}" ]]; then
27
+ GB_COLOR="never"
28
+ # Also for git's own output (added to any GIT_CONFIG_* entries already set)
29
+ _gb_n="${GIT_CONFIG_COUNT:-0}"
30
+ export "GIT_CONFIG_KEY_$_gb_n=color.ui" "GIT_CONFIG_VALUE_$_gb_n=never"
31
+ export GIT_CONFIG_COUNT=$((_gb_n + 1))
32
+ unset _gb_n
33
+ else
34
+ GB_COLOR="always"
35
+ fi
36
+ export GB_COLOR
37
+
23
38
  _gb_print() {
24
39
  local fd="$1" color="$2" symbol="$3"
25
40
  shift 3
@@ -35,6 +50,26 @@ print_info() { _gb_print 1 "0;34" "ℹ" "$@"; }
35
50
  print_warning() { _gb_print 2 "0;33" "⚠" "$@"; }
36
51
  print_error() { _gb_print 2 "0;31" "✗" "$@"; }
37
52
 
53
+ # Print help text from stdin, coloring the section headings
54
+ # ("Options:", "See also:", ...) and the "Usage:" label.
55
+ gb_help() {
56
+ if ! _gb_color_ok 1; then
57
+ cat
58
+ return 0
59
+ fi
60
+ local h=$'\033[1;38;5;209m' r=$'\033[0m' line
61
+ local heading='^[A-Z][A-Za-z ()]*:$'
62
+ while IFS= read -r line || [[ -n "$line" ]]; do
63
+ if [[ "$line" =~ $heading ]]; then
64
+ printf '%s%s%s\n' "$h" "$line" "$r"
65
+ elif [[ "$line" == "Usage: "* ]]; then
66
+ printf '%sUsage:%s%s\n' "$h" "$r" "${line#Usage:}"
67
+ else
68
+ printf '%s\n' "$line"
69
+ fi
70
+ done
71
+ }
72
+
38
73
  # =============================================================================
39
74
  # Prompts
40
75
  # =============================================================================
@@ -101,7 +136,7 @@ gb_choice() {
101
136
  GB_CONFIG_KEYS="GITBASH_CREATE_BRANCH_PREFIX GITBASH_FEATURE_BRANCH_PREFIX GITBASH_MERGE_COMMAND \
102
137
  GITBASH_CREATE_NO_ISSUE_PARSING GITBASH_CREATE_ISSUE_PARSING_FALLBACK GITBASH_CREATE_AUTO_PUSH \
103
138
  GITBASH_THEME GITBASH_STALE_MONTHS GITBASH_CLEANUP_DAYS GITBASH_PROTECTED_BRANCHES \
104
- GITBASH_BASE_BRANCH GITBASH_REMOTE"
139
+ GITBASH_BASE_BRANCH GITBASH_REMOTE GITBASH_NO_UPDATE_CHECKS GITBASH_RESET_KEEP"
105
140
 
106
141
  _gb_config_key_allowed() {
107
142
  [[ " $GB_CONFIG_KEYS " == *" $1 "* ]]
@@ -179,6 +214,7 @@ _gb_normalize_config() {
179
214
  GITBASH_CREATE_ISSUE_PARSING_FALLBACK="${GITBASH_CREATE_ISSUE_PARSING_FALLBACK:-NOISSUE}"
180
215
  GITBASH_PROTECTED_BRANCHES="${GITBASH_PROTECTED_BRANCHES:-main master develop release/*}"
181
216
  GITBASH_BASE_BRANCH="${GITBASH_BASE_BRANCH:-}"
217
+ GITBASH_RESET_KEEP="${GITBASH_RESET_KEEP:-}"
182
218
 
183
219
  case "${GITBASH_CREATE_NO_ISSUE_PARSING:-no}" in
184
220
  yes|no) GITBASH_CREATE_NO_ISSUE_PARSING="${GITBASH_CREATE_NO_ISSUE_PARSING:-no}" ;;
@@ -195,6 +231,12 @@ _gb_normalize_config() {
195
231
  *) print_warning "Invalid GITBASH_THEME '$GITBASH_THEME', using 'auto'."
196
232
  GITBASH_THEME="auto" ;;
197
233
  esac
234
+ case "${GITBASH_NO_UPDATE_CHECKS:-no}" in
235
+ yes|1|true) GITBASH_NO_UPDATE_CHECKS="yes" ;;
236
+ no|0|false) GITBASH_NO_UPDATE_CHECKS="no" ;;
237
+ *) print_warning "Invalid GITBASH_NO_UPDATE_CHECKS '$GITBASH_NO_UPDATE_CHECKS', using 'no'."
238
+ GITBASH_NO_UPDATE_CHECKS="no" ;;
239
+ esac
198
240
  if ! [[ "${GITBASH_STALE_MONTHS:-3}" =~ ^[1-9][0-9]*$ ]]; then
199
241
  print_warning "Invalid GITBASH_STALE_MONTHS '$GITBASH_STALE_MONTHS', using 3."
200
242
  GITBASH_STALE_MONTHS=3
@@ -310,6 +352,29 @@ gb_base_ref() {
310
352
  fi
311
353
  }
312
354
 
355
+ # Fetch the current branch's upstream and, if it has new commits, offer to
356
+ # fast-forward. Returns 1 only when the fast-forward fails.
357
+ gb_offer_fast_forward() {
358
+ local branch upstream_remote upstream_merge behind
359
+ branch=$(gb_current_branch) || return 0
360
+ upstream_remote=$(git config "branch.$branch.remote" 2>/dev/null) || return 0
361
+ upstream_merge=$(git config "branch.$branch.merge" 2>/dev/null) || return 0
362
+ git fetch --quiet "$upstream_remote" "$upstream_merge" 2>/dev/null || return 0
363
+ behind=$(git rev-list --count "HEAD..@{upstream}" 2>/dev/null) || return 0
364
+ if [[ "$behind" -gt 0 ]]; then
365
+ print_warning "Branch is $behind commit(s) behind its upstream."
366
+ if gb_confirm "Fast-forward to the latest changes?" y; then
367
+ if git merge --ff-only --quiet "@{upstream}"; then
368
+ print_success "Up to date."
369
+ else
370
+ print_error "Could not fast-forward (you have local commits or changes). Run 'git pull' to reconcile."
371
+ return 1
372
+ fi
373
+ fi
374
+ fi
375
+ return 0
376
+ }
377
+
313
378
  # Returns 0 if the branch is protected (base branch or GITBASH_PROTECTED_BRANCHES).
314
379
  # Set GB_BASE beforehand to avoid detecting the base branch on every call.
315
380
  gb_is_protected() {
@@ -454,9 +519,9 @@ gb_sync_and_push() {
454
519
  # Previews
455
520
  # =============================================================================
456
521
 
457
- # Command that colors a diff read from stdin (delta if installed)
522
+ # Command that colors a diff read from stdin (delta if installed and colors are on)
458
523
  gb_diff_pager() {
459
- if command -v delta >/dev/null 2>&1; then
524
+ if [[ "$GB_COLOR" == "always" ]] && command -v delta >/dev/null 2>&1; then
460
525
  case "${GITBASH_THEME:-auto}" in
461
526
  dark) echo "delta --dark" ;;
462
527
  light) echo "delta --light" ;;
@@ -480,9 +545,9 @@ gb_bat_cmd() {
480
545
  return 0
481
546
  fi
482
547
  case "${GITBASH_THEME:-auto}" in
483
- dark) echo "$bat --color=always --style=numbers --theme=Dracula" ;;
484
- light) echo "$bat --color=always --style=numbers --theme=GitHub" ;;
485
- *) echo "$bat --color=always --style=numbers" ;;
548
+ dark) echo "$bat --color=$GB_COLOR --style=numbers --theme=Dracula" ;;
549
+ light) echo "$bat --color=$GB_COLOR --style=numbers --theme=GitHub" ;;
550
+ *) echo "$bat --color=$GB_COLOR --style=numbers" ;;
486
551
  esac
487
552
  }
488
553
 
@@ -518,6 +583,52 @@ gb_urlencode() {
518
583
  printf '%s' "$out"
519
584
  }
520
585
 
586
+ # Convert a remote URL to the repository's web URL (credentials and .git removed).
587
+ # Handles https://[user[:token]@]host/path, ssh://[user@]host[:port]/path and user@host:path.
588
+ gb_web_url() {
589
+ local url="$1" scheme="https" rest host path
590
+ case "$url" in
591
+ http://*|https://*)
592
+ scheme="${url%%://*}"
593
+ rest="${url#*://}"
594
+ host="${rest%%/*}"
595
+ host="${host##*@}"
596
+ path="${rest#*/}"
597
+ ;;
598
+ ssh://*)
599
+ rest="${url#ssh://}"
600
+ host="${rest%%/*}"
601
+ host="${host##*@}"
602
+ host="${host%%:*}"
603
+ path="${rest#*/}"
604
+ ;;
605
+ *@*:*)
606
+ host="${url%%:*}"
607
+ host="${host##*@}"
608
+ path="${url#*:}"
609
+ ;;
610
+ *)
611
+ return 1
612
+ ;;
613
+ esac
614
+ path="${path%/}"
615
+ path="${path%.git}"
616
+ if [[ -z "$host" || -z "$path" || ( -n "$rest" && "$path" == "$rest" ) ]]; then
617
+ return 1
618
+ fi
619
+
620
+ # Azure DevOps SSH: ssh.dev.azure.com:v3/org/project/repo
621
+ if [[ "$host" == "ssh.dev.azure.com" && "$path" == v3/*/*/* ]]; then
622
+ local org project repo
623
+ path="${path#v3/}"
624
+ org="${path%%/*}"; path="${path#*/}"
625
+ project="${path%%/*}"; repo="${path#*/}"
626
+ echo "https://dev.azure.com/$org/$project/_git/$repo"
627
+ return 0
628
+ fi
629
+ echo "$scheme://$host/$path"
630
+ }
631
+
521
632
  # Open a URL in the browser, or print it if no opener is available
522
633
  gb_open_url() {
523
634
  local url="$1"
@@ -14,7 +14,7 @@ branch() {
14
14
  return 0
15
15
  fi
16
16
  if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
17
- cat << 'EOF'
17
+ gb_help << 'EOF'
18
18
  Usage: branch [OPTIONS]
19
19
 
20
20
  Interactive menu to manage git branches.
@@ -86,8 +86,8 @@ Examples:
86
86
  ✓ 'feature/PROJ-123-add-new-feature' is now up-to-date with 'main'.
87
87
 
88
88
  Actions:
89
- 🌿 Create - Create a new feature branch with Jira parsing
90
- 🔀 Switch - Switch to another branch using fzf
89
+ 🌿 Create - Create a new feature branch with Jira parsing
90
+ 🔀 Switch - Switch to another branch using fzf
91
91
  ⬆️ Update - Update current branch with latest main/master
92
92
 
93
93
  Requirements:
@@ -13,7 +13,7 @@ cleanstash() {
13
13
  return 0
14
14
  fi
15
15
  if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
16
- cat << 'EOF'
16
+ gb_help << 'EOF'
17
17
  Usage: cleanstash [OPTIONS]
18
18
 
19
19
  Delete git stashes without applying them.
@@ -37,7 +37,7 @@ cleanup() {
37
37
  return 0
38
38
  ;;
39
39
  -h|--help)
40
- cat << 'EOF'
40
+ gb_help << 'EOF'
41
41
  Usage: cleanup [OPTIONS]
42
42
 
43
43
  Find and delete local branches that are no longer needed.
@@ -273,14 +273,14 @@ ${#sorted[@]} branches, $preselect_count pre-selected" \
273
273
  if [[ -z "$branch" ]]; then echo "Exit without action"; exit 0; fi
274
274
  echo "Branch: $branch"
275
275
  echo
276
- unpushed=$(git log --oneline --color=always "refs/heads/$branch" --not --remotes 2>/dev/null)
276
+ unpushed=$(git log --oneline --color=$GB_COLOR "refs/heads/$branch" --not --remotes 2>/dev/null)
277
277
  if [[ -n "$unpushed" ]]; then
278
278
  echo "Unpushed commits (only on this machine):"
279
279
  echo "$unpushed"
280
280
  echo
281
281
  fi
282
282
  echo "Recent commits:"
283
- git log --oneline --color=always -n 15 "refs/heads/$branch" 2>/dev/null
283
+ git log --oneline --color=$GB_COLOR -n 15 "refs/heads/$branch" 2>/dev/null
284
284
  ' \
285
285
  --preview-window=right:40% \
286
286
  --bind "load:$toggle_sequence" \
@@ -23,7 +23,7 @@ commit() {
23
23
  return 0
24
24
  ;;
25
25
  -h|--help)
26
- cat << 'EOF'
26
+ gb_help << 'EOF'
27
27
  Usage: commit [OPTIONS] [MESSAGE...] [-- MESSAGE...]
28
28
 
29
29
  Commit your changes with a message.
@@ -5,21 +5,28 @@ SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
5
  # shellcheck source=_utils.sh
6
6
  source "$SOURCE_DIR/_utils.sh"
7
7
 
8
- # List recent commits and optionally revert selected ones
8
+ # List the current branch's own commits and optionally revert selected ones
9
9
  commits() {
10
10
  if [[ "${1:-}" == "-v" || "${1:-}" == "--version" ]]; then
11
11
  echo "gitbash ${FUNCNAME[0]} v$VERSION"
12
12
  return 0
13
13
  fi
14
14
  if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
15
- cat << 'EOF'
16
- Usage: commits [COUNT]
15
+ gb_help << 'EOF'
16
+ Usage: commits [-a|--all] [COUNT]
17
17
 
18
- List recent commits in the current branch with option to revert selected ones.
18
+ List the commits made on the current branch with option to revert selected ones.
19
+
20
+ On a feature branch only the commits that are not in the base branch are
21
+ shown. On the base branch its own history is shown (--first-parent), so
22
+ merged branches appear as their merge commit.
19
23
 
20
24
  Arguments:
21
25
  COUNT Number of commits to show (default: 20)
22
26
 
27
+ Options:
28
+ -a, --all Show all recent commits reachable from HEAD
29
+
23
30
  Navigation:
24
31
  ↑/↓ Navigate through commits
25
32
  TAB Select/deselect commit for revert
@@ -27,6 +34,7 @@ Navigation:
27
34
  ESC/Ctrl-C Exit without action
28
35
 
29
36
  Notes:
37
+ - If the upstream has new commits, offers to fast-forward first
30
38
  - Preview shows the full commit diff
31
39
  - Selected commits are reverted newest first, whatever order you picked them in
32
40
  - Merge commits are reverted against their first parent (the branch they were merged into)
@@ -35,6 +43,7 @@ Notes:
35
43
  Examples:
36
44
  $ commits
37
45
  $ commits 50
46
+ $ commits --all
38
47
 
39
48
  Requirements:
40
49
  - Must be in a git repository
@@ -46,16 +55,56 @@ EOF
46
55
 
47
56
  require_git_repo || return 1
48
57
 
49
- local count="${1:-20}"
58
+ local all=false count=""
59
+ while [[ $# -gt 0 ]]; do
60
+ case "$1" in
61
+ -a|--all) all=true ;;
62
+ -*) print_error "Unknown option '$1'. See 'commits --help'."; return 1 ;;
63
+ *)
64
+ if [[ -n "$count" ]]; then
65
+ print_error "Unexpected argument '$1'. See 'commits --help'."
66
+ return 1
67
+ fi
68
+ count="$1"
69
+ ;;
70
+ esac
71
+ shift
72
+ done
73
+ count="${count:-20}"
50
74
  if ! [[ "$count" =~ ^[1-9][0-9]*$ ]]; then
51
75
  print_error "COUNT must be a positive number (got '$count')."
52
76
  return 1
53
77
  fi
54
78
  require_fzf || return 1
55
79
 
80
+ # Offer to pull remote commits first, so they show up (and can be reverted)
81
+ gb_offer_fast_forward || true
82
+
56
83
  local current_branch
57
84
  current_branch=$(gb_current_branch) || current_branch="(detached HEAD)"
58
85
 
86
+ # -----------------------------
87
+ # Which commits: the branch's own (not in the base branch) or, on the
88
+ # base branch, its first-parent history
89
+ # -----------------------------
90
+ local log_args=() scope="last $count commits" empty_hint="" base_branch base_ref
91
+ if [[ "$all" == false ]] && base_branch=$(gb_base_branch 2>/dev/null); then
92
+ base_ref=$(gb_base_ref "$base_branch")
93
+ if [[ "$current_branch" == "$base_branch" ]]; then
94
+ log_args=(--first-parent)
95
+ scope="last $count commits on '$base_branch' (merged branches as merge commits)"
96
+ elif git rev-parse --verify --quiet "$base_ref^{commit}" >/dev/null; then
97
+ log_args=(--not "$base_ref")
98
+ # Also exclude the local base branch when it is ahead of the remote one
99
+ if [[ "$base_ref" != "$base_branch" ]] &&
100
+ git show-ref --verify --quiet "refs/heads/$base_branch"; then
101
+ log_args+=("$base_branch")
102
+ fi
103
+ scope="commits not in '$base_ref' (up to $count)"
104
+ empty_hint="No commits on '$current_branch' that are not in '$base_ref'. Use 'commits --all' to show all recent commits."
105
+ fi
106
+ fi
107
+
59
108
  # -----------------------------
60
109
  # Build commit list (fields separated by \x1f, subject last)
61
110
  # -----------------------------
@@ -67,10 +116,10 @@ EOF
67
116
  fi
68
117
  commit_list+=$(printf "%-10s %-60s %-15s %s" "$hash" "$subject" "$date" "$author")
69
118
  commit_list+=$'\t'"$hash"$'\n'
70
- done < <(git log -n "$count" --format='%h%x1f%cr%x1f%an%x1f%s' 2>/dev/null)
119
+ done < <(git log -n "$count" --format='%h%x1f%cr%x1f%an%x1f%s' HEAD ${log_args[@]+"${log_args[@]}"} 2>/dev/null)
71
120
 
72
121
  if [[ -z "$commit_list" ]]; then
73
- echo "No commits found."
122
+ echo "${empty_hint:-No commits found.}"
74
123
  return 0
75
124
  fi
76
125
 
@@ -78,11 +127,11 @@ EOF
78
127
  pager=$(gb_diff_pager)
79
128
  preview='
80
129
  hash=$(printf "%s" {} | cut -f2)
81
- git show --stat --color=always "$hash" 2>/dev/null
130
+ git show --stat --color=$GB_COLOR "$hash" 2>/dev/null
82
131
  echo
83
132
  echo "─────────────────────────────────────────────────────"
84
133
  echo
85
- git show --color=always --format= "$hash" 2>/dev/null | head -300 | __PAGER__'
134
+ git show --color=$GB_COLOR --format= "$hash" 2>/dev/null | head -300 | __PAGER__'
86
135
  preview="${preview//__PAGER__/$pager}"
87
136
 
88
137
  local selection
@@ -92,7 +141,7 @@ EOF
92
141
  --reverse \
93
142
  --border \
94
143
  --header="[TAB] select for revert | [Enter] revert selected | [ESC] exit
95
- Showing last $count commits" \
144
+ Showing $scope" \
96
145
  --multi \
97
146
  --delimiter=$'\t' \
98
147
  --with-nth=1 \
@@ -51,7 +51,7 @@ create() {
51
51
  return 0
52
52
  ;;
53
53
  -h|--help)
54
- cat << 'EOF'
54
+ gb_help << 'EOF'
55
55
  Usage: create [OPTIONS] [JIRA_LINK] [TITLE...]
56
56
 
57
57
  Create a new git branch from the latest base branch, with optional Jira issue parsing.
package/commands/pr.sh CHANGED
@@ -5,52 +5,6 @@ SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
5
  # shellcheck source=_utils.sh
6
6
  source "$SOURCE_DIR/_utils.sh"
7
7
 
8
- # Convert a remote URL to the repository's web URL (credentials and .git removed).
9
- # Handles https://[user[:token]@]host/path, ssh://[user@]host[:port]/path and user@host:path.
10
- _pr_web_base() {
11
- local url="$1" scheme="https" rest host path
12
- case "$url" in
13
- http://*|https://*)
14
- scheme="${url%%://*}"
15
- rest="${url#*://}"
16
- host="${rest%%/*}"
17
- host="${host##*@}"
18
- path="${rest#*/}"
19
- ;;
20
- ssh://*)
21
- rest="${url#ssh://}"
22
- host="${rest%%/*}"
23
- host="${host##*@}"
24
- host="${host%%:*}"
25
- path="${rest#*/}"
26
- ;;
27
- *@*:*)
28
- host="${url%%:*}"
29
- host="${host##*@}"
30
- path="${url#*:}"
31
- ;;
32
- *)
33
- return 1
34
- ;;
35
- esac
36
- path="${path%/}"
37
- path="${path%.git}"
38
- if [[ -z "$host" || -z "$path" || ( -n "$rest" && "$path" == "$rest" ) ]]; then
39
- return 1
40
- fi
41
-
42
- # Azure DevOps SSH: ssh.dev.azure.com:v3/org/project/repo
43
- if [[ "$host" == "ssh.dev.azure.com" && "$path" == v3/*/*/* ]]; then
44
- local org project repo
45
- path="${path#v3/}"
46
- org="${path%%/*}"; path="${path#*/}"
47
- project="${path%%/*}"; repo="${path#*/}"
48
- echo "https://dev.azure.com/$org/$project/_git/$repo"
49
- return 0
50
- fi
51
- echo "$scheme://$host/$path"
52
- }
53
-
54
8
  # Web URL for creating a pull/merge request for a branch
55
9
  _pr_create_url() {
56
10
  local base="$1" branch="$2" encoded
@@ -83,7 +37,7 @@ pr() {
83
37
  return 0
84
38
  ;;
85
39
  -h|--help)
86
- cat << 'EOF'
40
+ gb_help << 'EOF'
87
41
  Usage: pr [OPTIONS]
88
42
 
89
43
  Open the current branch's pull request in your browser.
@@ -147,7 +101,7 @@ EOF
147
101
  print_error "Detached HEAD: check out a branch first."
148
102
  return 1
149
103
  fi
150
- if ! base=$(_pr_web_base "$remote_url"); then
104
+ if ! base=$(gb_web_url "$remote_url"); then
151
105
  print_error "Don't know how to open '$remote_url' in a browser."
152
106
  return 1
153
107
  fi
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Source common utilities
4
+ SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+ # shellcheck source=_utils.sh
6
+ source "$SOURCE_DIR/_utils.sh"
7
+
8
+ # Open the repository's web page
9
+ repo() {
10
+ local print_only=false
11
+
12
+ while [[ $# -gt 0 ]]; do
13
+ case "$1" in
14
+ -v|--version)
15
+ echo "gitbash ${FUNCNAME[0]} v$VERSION"
16
+ return 0
17
+ ;;
18
+ -h|--help)
19
+ gb_help << 'EOF_HELP'
20
+ Usage: repo [OPTIONS]
21
+
22
+ Open the repository's web page in your browser.
23
+
24
+ Options:
25
+ --print Print the URL instead of opening it
26
+ -h, --help Show this help message
27
+
28
+ Behavior:
29
+ - Uses the URL of the configured remote (GITBASH_REMOTE, default: origin)
30
+ - With the GitHub CLI (gh) installed and logged in, opens it with 'gh repo view --web'
31
+ - Otherwise opens the URL derived from the remote
32
+ (GitHub, GitHub Enterprise, GitLab, Bitbucket, Azure DevOps)
33
+ - Works with SSH and HTTPS remotes; credentials in the remote URL are never used
34
+ - Opens the browser with 'open' (macOS) or 'xdg-open' (Linux), otherwise prints the URL
35
+
36
+ Examples:
37
+ $ repo
38
+ $ repo --print
39
+
40
+ EOF_HELP
41
+ return 0
42
+ ;;
43
+ --print)
44
+ print_only=true
45
+ shift
46
+ ;;
47
+ *)
48
+ print_error "Unknown argument: $1"
49
+ echo "Usage: repo [--print]" >&2
50
+ return 1
51
+ ;;
52
+ esac
53
+ done
54
+
55
+ require_git_repo || return 1
56
+
57
+ local remote remote_url url
58
+ remote=$(gb_remote)
59
+ if ! remote_url=$(git config --get "remote.$remote.url"); then
60
+ print_error "No remote '$remote' found."
61
+ return 1
62
+ fi
63
+ if ! url=$(gb_web_url "$remote_url"); then
64
+ print_error "Don't know how to open '$remote_url' in a browser."
65
+ return 1
66
+ fi
67
+
68
+ if [[ "$print_only" == true ]]; then
69
+ echo "$url"
70
+ return 0
71
+ fi
72
+
73
+ if [[ "$url" != *gitlab* && "$url" != *bitbucket.org/* && "$url" != *dev.azure.com/* && "$url" != *visualstudio.com/* ]] &&
74
+ command -v gh >/dev/null 2>&1; then
75
+ if GH_PROMPT_DISABLED=1 gh repo view "$url" --web >/dev/null 2>&1; then
76
+ print_success "Opened $url"
77
+ return 0
78
+ fi
79
+ fi
80
+
81
+ gb_open_url "$url"
82
+ }