1
\$\begingroup\$

I'm learning bash and my goal here is from any repository on my computer to be able to type github and it will open the remote in a browser for me.

This works but I feel like I over complicated the remote=$(..) logic and arguably the get_ext() method.

get_ext() allows you to type github issues and it will open the issues page for that repo on github. I know it could work better if there was a hash map equivalent in bash but from what I can find, there's not.

code:

#! /bin/bash

endpoint=$1

get_ext() {
  case $1 in
    *github*)
      case $endpoint in
        pr)
          echo "/pulls";;
        issues)
          echo "/issues";;
        *)
          echo "";;
      esac;;
    *bitbucket*)
      case $endpoint in
        pr)
          echo "/pull-requests";;
        issues)
          # issues doesn't exist for bitbucket
          echo "";;
        *)
          echo "";;
      esac;;
  esac
}

open_site() {
  # currently only works for SSH addresses
  if [[ $remote == *@* ]]; then
    name=$(echo $remote | sed  "s/^.*:\(.*\)\.git/\1/g")
    ext=$(get_ext $1)
    open "$1/${name}${ext}"
  fi
}
remote=$(grep -A 1 "remote \"origin\"" $(pwd)/.git/config | sed -n 2p)

case $remote in
  *github*)
    open_site "https://github.com";;
  *bitbucket*)
    open_site "https://bitbucket.org";;
esac
\$\endgroup\$
1
\$\begingroup\$

Getting the url of origin

This is a bit awkward:

remote=$(grep -A 1 "remote \"origin\"" $(pwd)/.git/config | sed -n 2p)

Because:

  • The grep + sed is a bit hacky
  • $(pwd) can be replaced with a simple .
  • It's awkward to rely on .git/config content instead of some git command

Try to look for native Git commands to extract this kind of information, for example:

git remote show -n origin | grep Fetch.URL

The output is not exactly same as the original, but it will work fine with the rest of your script.

Named parameters

In Bash there are no named parameters. As a consequence, in this function it can be hard to remember what $1 refers to:

open_site() {
  # currently only works for SSH addresses
  if [[ $remote == *@* ]]; then
    name=$(echo $remote | sed  "s/^.*:\(.*\)\.git/\1/g")
    ext=$(get_ext $1)
    open "$1/${name}${ext}"
  fi
}

As a workaround, I recommend assigning the parameter to a well-named local variable, like this:

open_site() {
  local baseurl=$1
  # currently only works for SSH addresses
  if [[ $remote == *@* ]]; then
    name=$(echo $remote | sed  "s/^.*:\(.*\)\.git/\1/g")
    ext=$(get_ext $baseurl)
    open "$baseurl/${name}${ext}"
  fi
}

Pattern replacement

Instead of this:

name=$(echo $remote | sed  "s/^.*:\(.*\)\.git/\1/g")

I recommend simple pattern substitution:

# chop off the start until the last :
remote=${remote##*:}
# chop off .git at the end
remote=${remote%.git}

The benefit of this approach is that it doesn't run extra programs (no sed, no echo, no piping).

A minor note, the original sed didn't need the g flag.

Printing a blank line

You don't need "" to just echo a blank line:

echo ""

This is exactly the same:

echo
\$\endgroup\$
  • \$\begingroup\$ Really wonderful feedback janos, it is much appreciated. \$\endgroup\$ – Anthony Apr 13 '16 at 14:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.