Projects STRLCPY git-open Commits d9b95808
🤬
  • ■ ■ ■ ■ ■ ■
    git-open
    skipped 55 lines
    56 56   exit 1
    57 57  fi
    58 58   
     59 +ssh_config=${ssh_config:-"$HOME/.ssh/config"}
     60 +# Resolves an ssh alias defined in ssh_config to it's corresponding hostname
     61 +# echos out result, should be used within subshell $( ssh_resolve $host )
     62 +# echos out nothing if alias could not be resolved
     63 +function ssh_resolve() {
     64 + domain="$1"
     65 + ssh_found=true
     66 + # Filter to only ssh_config lines that start with "Host" or "HostName"
     67 + resolved=$(while read -r ssh_line; do
     68 + # Split each line by spaces, of the form:
     69 + # Host alias [alias...]
     70 + # Host regex
     71 + # HostName resolved.domain.com
     72 + read -r -a ssh_array <<<"${ssh_line}"
     73 + ssh_optcode="${ssh_array[0]}"
     74 + if [[ ${ssh_optcode^^} == HOST ]]; then
     75 + # Host
     76 + ssh_found=false
     77 + # Iterate through aliases looking for a match
     78 + for ssh_index in $(seq 1 $((${#ssh_array[@]} - 1))); do
     79 + ssh_host=${ssh_array[$ssh_index]}
     80 + # shellcheck disable=SC2053
     81 + if [[ $domain == $ssh_host ]]; then
     82 + # Found a match, next HostName entry will be returned while matched
     83 + ssh_found=true
     84 + break
     85 + fi
     86 + done
     87 + elif $ssh_found && [[ ${ssh_optcode^^} == HOSTNAME ]]; then
     88 + # HostName, but only if ssh_found is true (the last Host entry matched)
     89 + # Replace all instances of %h with the Host alias
     90 + echo "${ssh_array[1]//%h/$domain}"
     91 + fi
     92 + done < <(grep -iE "^\\s*Host(Name)?\\s+" "$ssh_config"))
     93 + # Take only the last resolved hostname (multiple are overridden)
     94 + tail -1 <<<"$resolved"
     95 +}
     96 + 
    59 97  # From git-fetch(5), native protocols:
    60 98  # ssh://[user@]host.xz[:port]/path/to/repo.git/
    61 99  # git://host.xz[:port]/path/to/repo.git/
    62 100  # http[s]://host.xz[:port]/path/to/repo.git/
    63 101  # ftp[s]://host.xz[:port]/path/to/repo.git/
    64 102  # [user@]host.xz:path/to/repo.git/ - scp-like but is an alternative to ssh.
     103 +# [user@]hostalias:path/to/repo.git/ - handles host aliases defined in ssh_config(5)
    65 104   
    66 105  # Determine whether this is a url (https, ssh, git+ssh...) or an scp-style path
    67 106  if [[ "$giturl" =~ ^[a-z\+]+://.* ]]; then
    skipped 17 lines
    85 124   # Split on first ':' to get server name and path
    86 125   domain=${uri%%:*}
    87 126   urlpath=${uri#*:}
     127 + 
     128 + # Resolve sshconfig aliases
     129 + if [[ -e "$ssh_config" ]]; then
     130 + domain_resolv=$(ssh_resolve "$domain")
     131 + if [[ ! -z "$domain_resolv" ]]; then
     132 + domain="$domain_resolv"
     133 + fi
     134 + fi
    88 135  fi
    89 136   
    90 137  # Trim "/" from beginning of URL; "/" and ".git" from end of URL
    skipped 19 lines
    110 157  branch=${2:-$(git symbolic-ref -q --short HEAD)}
    111 158   
    112 159  # Split arguments on '/'
    113  -IFS='/' pathargs=($urlpath)
     160 +IFS='/' read -r -a pathargs <<<"$urlpath"
    114 161   
    115 162  if (( is_issue )); then
    116 163   # For issues, take the numbers and preprend 'issues/'
    skipped 16 lines
    133 180   pathPref=("${pathargs[*]:0:${#pathargs[@]} - 3}")
    134 181   
    135 182   # Replace the 'scm' element, with 'projects'. Keep the first argument, the string 'repos', and finally the rest of the arguments.
     183 + # shellcheck disable=SC2206
    136 184   pathargs=(${pathPref[@]} 'projects' ${pathargs[${#pathargs[@]} - 2]} 'repos' "${pathargs[@]:${#pathargs[@]} - 1}")
    137 185   IFS='/' urlpath="${pathargs[*]}"
    138 186   providerBranchRef="/browse?at=$branch"
    skipped 32 lines
    171 219  esac
    172 220   
    173 221  # Allow printing the url if BROWSER=echo
    174  -if [[ $BROWSER != "echo" ]]; then
     222 +if [[ $BROWSER == "echo" ]]; then
     223 + openopt=''
     224 +else
    175 225   exec &>/dev/null
    176 226  fi
    177 227   
    skipped 5 lines
  • ■ ■ ■ ■ ■ ■
    test/git-open.bats
    skipped 173 lines
    174 174   assert_output "http://github.com/user/repo"
    175 175  }
    176 176   
     177 +##
     178 +## SSH config
     179 +##
     180 + 
     181 +@test "sshconfig: basic" {
     182 + create_ssh_sandbox
     183 + # Basic
     184 + git remote set-url origin "basic:user/repo.git"
     185 + run ../git-open
     186 + assert_output --partial "https://basic.com/user/repo"
     187 + # With git user
     188 + git remote set-url origin "git@nouser:user/repo.git"
     189 + run ../git-open
     190 + assert_output "https://no.user/user/repo"
     191 +}
     192 + 
     193 +@test "sshconfig: no action on no match" {
     194 + create_ssh_sandbox
     195 + git remote set-url origin "git@nomatch:user/repo.git"
     196 + run ../git-open
     197 + assert_output "https://nomatch/user/repo"
     198 + # No match due to improper casing
     199 +}
     200 + 
     201 +@test "sshconfig: check case sensitivity" {
     202 + create_ssh_sandbox
     203 + # Host and HostName keywords should be case insensitive
     204 + # But output URL will be case sensitive
     205 + git remote set-url origin "malformed:user/repo.git"
     206 + run ../git-open
     207 + assert_output "https://MaL.FoRmEd/user/repo"
     208 + # SSH aliases (hosts) are case sensitive, this should not match
     209 + git remote set-url origin "git@MALFORMED:user/repo.git"
     210 + run ../git-open
     211 + refute_output "https://MaL.FoRmEd/user/repo"
     212 +}
     213 + 
     214 +@test "sshconfig: multitarget host" {
     215 + create_ssh_sandbox
     216 + for i in $(seq 1 3); do
     217 + git remote set-url origin "multi$i:user/repo.git"
     218 + run ../git-open
     219 + assert_output "https://multi.com/user/repo"
     220 + done
     221 +}
     222 + 
     223 +@test "sshconfig: host substitution in hostname" {
     224 + create_ssh_sandbox
     225 + for i in $(seq 1 3); do
     226 + git remote set-url origin "sub$i:user/repo.git"
     227 + run ../git-open
     228 + assert_output "https://sub$i.multi.com/user/repo"
     229 + done
     230 +}
     231 + 
     232 +@test "sshconfig: host wildcard * matches zero or more chars" {
     233 + create_ssh_sandbox
     234 + # Normal *
     235 + for str in "" "-prod" "-dev"; do
     236 + git remote set-url origin "zero$str:user/repo.git"
     237 + run ../git-open
     238 + assert_output "https://zero.com/user/repo"
     239 + done
     240 + # * with substitution
     241 + for str in "" "-prod" "-dev"; do
     242 + git remote set-url origin "subzero$str:user/repo.git"
     243 + run ../git-open
     244 + assert_output "https://subzero$str.zero/user/repo"
     245 + done
     246 +}
     247 + 
     248 +@test "sshconfig: host wildcard ? matches exactly one char" {
     249 + create_ssh_sandbox
     250 + # Normal ?
     251 + for i in $(seq 1 3); do
     252 + git remote set-url origin "one$i:user/repo.git"
     253 + run ../git-open
     254 + assert_output "https://one.com/user/repo"
     255 + done
     256 + # Refute invalid match on ?
     257 + for str in "" "-test"; do
     258 + git remote set-url origin "one:user/repo.git"
     259 + run ../git-open
     260 + refute_output "https://one$str.com/user/repo"
     261 + done
     262 + 
     263 + # ? with substitution
     264 + for i in $(seq 1 3); do
     265 + git remote set-url origin "subone$i:user/repo.git"
     266 + run ../git-open
     267 + assert_output "https://subone$i.one/user/repo"
     268 + done
     269 + # Refute invalid match on ? with substitution
     270 + for str in "" "-test"; do
     271 + git remote set-url origin "subone$str:user/repo.git"
     272 + run ../git-open
     273 + refute_output "https://subone$str.one/user/repo"
     274 + done
     275 + # Refute invalid match on ? with substitution
     276 +}
     277 + 
     278 +@test "sshconfig: overriding host rules" {
     279 + create_ssh_sandbox
     280 + git remote set-url origin "zero-override:user/repo.git"
     281 + run ../git-open
     282 + assert_output "https://override.zero.com/user/repo"
     283 +}
    177 284   
    178 285  ##
    179 286  ## Bitbucket
    skipped 213 lines
    393 500  teardown() {
    394 501   cd ..
    395 502   rm -rf "$foldername"
     503 + rm -rf "$ssh_config"
     504 + refute [ -e "$ssh_config" ]
     505 + unset ssh_config
    396 506  }
    397 507   
    398 508  # helper to create a test git sandbox that won't dirty the real repo
    skipped 20 lines
    419 529   git commit -m "add file" -q
    420 530  }
    421 531   
     532 +# helper to create test SSH config file
     533 +function create_ssh_sandbox() {
     534 + export ssh_config=$(mktemp)
     535 + refute [ -z "$ssh_config" ]
     536 + 
     537 + # Populate ssh config with test data
     538 + echo "$ssh_testdata" >$ssh_config
     539 + assert [ -e "$ssh_config" ]
     540 +}
     541 + 
     542 +# Test SSH config data
     543 +ssh_testdata="
     544 +# Autogenerated test sshconfig for paulirish/git-open BATS tests
     545 +# It is safe to delete this file, a new one will be generated each test
     546 + 
     547 +Host basic
     548 + HostName basic.com
     549 + User git
     550 + 
     551 +Host nomatch
     552 + User git
     553 + 
     554 +Host nouser
     555 + HostName no.user
     556 + 
     557 +host malformed
     558 + hOsTnAmE MaL.FoRmEd
     559 + User other
     560 + 
     561 +# Multiple targets
     562 +Host multi1 multi2 multi3
     563 + HostName multi.com
     564 + User git
     565 + 
     566 +Host sub1 sub2 sub3
     567 + HostName %h.multi.com
     568 + User git
     569 + 
     570 + # Wildcard * matching (zero or more characters)
     571 +Host zero*
     572 + HostName zero.com
     573 + User git
     574 + 
     575 +Host subzero*
     576 + HostName %h.zero
     577 + User git
     578 + 
     579 +# Wildcard ? matching (exactly one character)
     580 +Host one?
     581 + HostName one.com
     582 + User git
     583 + 
     584 +Host subone?
     585 + HostName %h.one
     586 + User git
     587 + 
     588 +# Overrides rule zero*
     589 +Host zero-override
     590 + HostName override.zero.com
     591 + User git
     592 +"
     593 + 
Please wait...
Page is in error, reload to recover