Refactor logic from gerrit.sh into gerrit/filters.  Add modular usage/help

Change-Id: I2ff1d0eda2bb7e80dab8d345721f39c621357774
diff --git a/gerrit/bin/gerrit.sh b/gerrit/bin/gerrit.sh
new file mode 100755
index 0000000..4900ab1
--- /dev/null
+++ b/gerrit/bin/gerrit.sh
@@ -0,0 +1,517 @@
+#!/bin/bash
+## -----------------------------------------------------------------------
+## Intent: Construct gerrit server queries and URLs based on arguments
+## -----------------------------------------------------------------------
+
+{ # loader
+    declare pgm=''
+    pgm="$(realpath --canonicalize-existing "$0")"
+    readonly pgm
+
+    declare libdir="${pgm%/*}"
+    libdir="${libdir%/*}/gerrit"
+    readonly libdir
+
+    declare root=''
+    root="${pgm%%/gerrit/bin/gerrit.sh}"
+    source "$root/lf/onf-common/common.sh" '--common-args-begin--'
+}
+
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
+declare -g serv='gerrit.opencord.org'
+declare -x -g BROWSER="${BROWSER:-/usr/local/bin/firefox}"
+declare -g -a me=()
+
+##--------------------##
+##---]  INCLUDES  [---##
+##--------------------##
+source "${libdir}/filters/status.sh"
+source "${libdir}/usage/include.sh"
+# source "${libdir}/usage/main.sh"
+
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+# function join_by_orig()
+function join_by()
+{
+    local d=${1-} f=${2-}; if shift 2; then printf %s "$f" "${@/#/$d}"; fi;
+}
+
+## -----------------------------------------------------------------------
+## Usage: $0 --repo voltha-go --search --wip
+## -----------------------------------------------------------------------
+function do_gerrit_search()
+{
+    local -n ref_urls=$1   ; shift
+    local -n ref_repos=$1   ; shift
+    local -n ref_status=$1 ; shift
+
+    ref_urls=()
+
+    # local stem='https://gerrit.opencord.org/q/project:voltha-go+status:open'
+    local stem='https://gerrit.opencord.org/q/'
+
+    local -a common=()
+    [[ -v me ]] && { common+=("${me[@]}"); }
+    common+=("${ref_status[@]}")
+
+    local repo
+    for repo in "${ref_repos[@]}";
+    do
+        local -a args=()
+        args+=("project:${repo}")
+        args+=("${common[@]}")
+
+        local url="$stem"
+        url+="$(join_by '+' "${args[@]}")"
+        ref_urls+=("$url")
+    done
+
+    if [[ ${#ref_urls[@]} -eq 0 ]]; then
+        local -a args=()
+        args=("${common[@]}")
+
+        local url="$stem"
+        url+="$(join_by '+' "${args[@]}")"
+        ref_urls+=("$url")
+    fi
+
+	# --debug)  declare -g -i debug=1 ;;
+    # --search) declare -g -i search=1 ;;
+    # --wip)    declare -g -i status_is_open=1 ;;
+
+    return
+}
+
+
+## -----------------------------------------------------------------------
+## Intent: Iterate over --admin values and generate repositories
+## -----------------------------------------------------------------------
+function gen_admin_urls()
+{
+    local -n ref=$1     ; shift
+    local -n _repos=$1  ; shift
+    local -n _admins=$1 ; shift
+
+    local repo
+    for repo in "${_repos[@]}";
+    do
+        local attr
+        for admin in "${_admins[@]}";
+        do
+            # https://gerrit.opencord.org/admin/repos/voltha-go
+            case "$admin" in
+                branches)
+                    ref+=("https://gerrit.opencord.org/admin/repos/${repo},branches")
+                    ;;
+                tags)
+                    ref+=("https://gerrit.opencord.org/admin/repos/${repo},tags")
+                    ;;
+                *) error "Unknown --admin type [$admin]" ;;
+            esac
+
+        done # admins[@]
+    done # repos[@]
+    return
+}
+
+## -----------------------------------------------------------------------
+## Intent: Iterate over --admin values and generate repositories
+## -----------------------------------------------------------------------
+function gen_view_urls()
+{
+    local -n ref=$1    ; shift
+    local -n _repos=$1 ; shift
+    local -n _views=$1 ; shift
+
+    local -a view_keys=("${!_views[@]}")
+    local stem0="https://gerrit.opencord.org/plugins/gitiles"
+
+    # https://gerrit.opencord.org/plugins/gitiles/ofagent-go
+
+    local repo
+    for repo in "${_repos[@]}";
+    do
+        local stem="${stem0}/$repo"
+        local view
+        for view in "${view_keys[@]}";
+        do
+            # https://gerrit.opencord.org/admin/repos/voltha-go
+            case "$view" in
+                # https://gerrit.opencord.org/plugins/gitiles/voltha-system-tests
+                search) continue ;;
+                default) ref+=("$stem")                      ;;
+                # repo*) ref+=("$stem/$repo")                ;;
+                  repo*) ref+=("$stem")                      ;;
+                  master)
+                      ref+=("$stem/+/refs/heads/master")
+                      ;;
+
+                  voltha-*)
+                      echo "STEM: $stem"
+                      if false; then
+                          ref+=("$stem/+/refs/tags/${view}")
+                          ref+=("$stem/+/refs/heads/${view}")
+                      fi
+                      # ref+=("$stem/+/refs/heads/${view}")
+                      ref+=("$stem/+/refs/heads/${view}")
+                    ;;
+
+                    v*)  ref+=("$stem/+/refs/tags/${view}")  ;;
+                *) error "Unknown --view type [$view]"       ;;
+            esac
+        done # views[@]
+    done # repos[@]
+
+    for r in "${ref[@]}";
+    do
+        echo "REPO: $r"
+    done
+
+    return
+}
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+function get_urls()
+{
+    local -n ref="$1"; shift
+    local _srv="$1"; shift
+
+    local gerrit="https://${_srv}"
+    ref=(\
+         ['admin']="$gerrit/admin/repos"
+         ['base']="$gerrit"\
+         ['dashboard']="$gerrit/dashboard/self"\
+    )
+    return
+}
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+function changeset()
+{
+    local _repo="$1"; shift
+    local _id="$1";   shift
+    local -n ref=$1;  shift
+
+    local url="https://gerrit.opencord.org/c/${repo}/+/${id}"
+    ref+=("$url")
+    return
+}
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+function browse()
+{
+    local -n _urls=$1; shift
+    "${BROWSER}" "${_urls[@]}" >/dev/null 2>/dev/null &
+    return
+}
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+function access_url()
+{
+    local -n ref=$1; shift
+    local _repo="$1"; shift
+
+    declare -A data=()
+    get_urls data "$serv"
+
+    # declare -p data | tr '=' '\n'
+    # ref+=("https://gerrit.opencord.org/admin/repos/${_repo},access")
+    ref+=("${data['admin']}/${_repo},access")
+
+    # browse urls
+    return
+}
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+function branch_url()
+{
+    local _repo="$1"; shift
+    local -a urls=()
+    urls+=("https://gerrit.opencord.org/admin/repos/${_repo},branches")
+    browse urls
+    return
+}
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+function do_gerrit_dashboard()
+{
+    local -n ref=$1; shift
+
+    declare -A data=()
+    get_urls data "$serv"
+    ref+=("${data['dashboard']}")
+    return
+}
+
+# https://gerrit.opencord.org/q/status:open+-is:wip
+
+# repo=''
+declare -a urls=()
+
+##----------------##
+##---]  MAIN  [---##
+##----------------##
+[[ $# -eq 0 ]] && { set -- '--help'; }
+
+while [ $# -ne 0 ]; do
+    arg="$1"; shift
+    case "$arg" in
+        --help) usage; exit 0 ;;
+        --help-*)
+            case "$arg" in
+                --help-status) usage_verbose "$arg" ;;
+                *) usage ;;
+            esac
+            exit 0
+            ;;
+
+        ## Modes
+	    --debug)
+            declare -g -i argv_debug=1
+            declare -g -i debug=1
+            ;;
+        --search) declare -g -i argv_search=1 ;;
+
+        --me)
+            # declare -g -i argv_me=1
+            me+=("owner:${USER}@opennetworking.org")
+            ;;
+
+        --todo) source "$root/gerrit/todo.sh" ;;
+
+        --wip)
+            declare -a args=()
+            args=('--status' 'open')
+            [[ $# -gt 0 ]] && { args+=("$@"); }
+            set -- "${args[@]}"
+            ;;
+
+        --admin)
+            [[ ! -v admins ]] && { declare -a admins=(); }
+            arg="$1"; shift
+            case "$arg" in
+                br*) admins+=('branches') ;;
+                ta*) admins+=('tags') ;;
+                *) error "Unknown --attr value [$attr]" ;;
+                ## Also master and voltha-2.12
+                # https://gerrit.opencord.org/plugins/gitiles/voltha-go/+/refs/heads/voltha-2.12
+            esac
+            ;;
+
+        --all)
+            repo="$1"; shift
+            declare -a args=()
+            args+=('--repo'  "$repo")
+            #
+            args+=('--admin' 'branches')
+            args+=('--admin' 'tags')
+
+            # args+=('--view') # post getopts expansion
+            #   if @versions() else master
+            if [[ ${#versions[@]} -eq 0 ]]; then
+                versions+=('master')
+            fi
+
+#            args+=('--view'  'voltha-2.11')
+            args+=('--view'  'voltha-2.12')
+            set -- "${args[@]}" "$@"
+            ;;
+
+        --repo)
+            repo="$1"; shift
+            [[ ! -v repos ]] && { declare -a repos=(); }
+            repos+=("$repo")
+            ;;
+
+        --serv) serv="$1"; shift
+                case "$serv" in
+                    *cord*) serv='gerrit.opencord.org'    ;;
+                    *onos*) serv='gerrit.onosproject.org' ;;
+                    *) error "Detected invalid --serv $serv" ;;
+                esac
+                ;;
+
+        --access)
+            [[ ! -v repo ]] && { error "--repo is required"; }
+            access_url urls "$repo"
+            ;;
+
+        --branch)
+            [[ ! -v repo ]] && { error "--repo is required"; }
+            branch_url "$repo"
+            ;;
+
+        --crowd*)
+            # https://crowd.opennetworking.org/crowd/console/secure/group/browse.action?directoryId=163841&updateSuccessful=
+            declare https='https://crowd.opennetworking.org'
+            declare base_url="${https}/crowd/console/secure/group/browse.action"
+            case "$arg" in
+                --crowd-*)
+                    # urls+=("${base_url}?directoryId=163841&updateSuccessful=")
+                    urls+=("${base_url}")
+                    ;;
+                *)
+                    # https://crowd.opennetworking.org/crowd/console/secure/group/browse.action?search=%22VOLTHACore%22
+                    [[ $# -eq 0 ]] && { error "--crowd requires an argument"; }
+                    arg="$1"; shift
+                    urls+=("${base_url}?search=%22${arg}%22")
+                    ;;
+            esac
+            ;;
+
+        --*desk) error "Try --dashboard instead" ;;
+        --dash*) do_gerrit_dashboard urls ;;
+
+        #
+        --group*)
+            case "$arg" in
+                --group*)
+                    urls+=("https://${serv}/admin/groups")
+                    ;;
+                *)
+                    [[ $# -eq 0 ]] && { error "--group requires an argument"; }
+                    arg="$1"; shift
+                    urls+=("https://${serv}/admin/groups/q/filter:${arg}}")
+                    ;;
+            esac
+            ;;
+
+        --id)
+            id="$1"; shift
+            [[ ${#repo} -eq 0 ]] && { error "--repo is required"; }
+            changeset "$repo" "$id" urls
+            ;;
+
+        --status)
+            arg="$1"; shift # open, closed, merged
+            case "$arg" in
+                closed|open|merged) add_filter_status "$arg";;
+                *) error "Detected invalid --status [$arg]" ;;
+            esac
+            ;;
+
+        --patch*)
+            repo="$1"; shift
+            urls+=("https://gerrit.opencord.org/q/${repo}+stats:open")
+            # https://gerrit.opencord.org/q/voltha-openolt-adapter-go
+            ;;
+        --review)
+            urls+=('https://gerrit.opencord.org/c/aether-ci-management/+/34900')
+            ;;
+
+        --ver*)
+            [[ $# -eq 0 ]] && { error "Usage: $arg [str]"; }
+            arg="$1"; shift
+            [[ ! -v versions ]] && { declare -a versions=(); }
+            versions+=("$arg")
+            ;;
+
+        # post getopt expansion to support --version x --version y
+        --view)
+            [[ $# -eq 0 ]] && { set -- '--default'; }
+            arg="$1"; shift
+            # [[ "${#views[@]}" -gt 0 ]]
+            [[ ! -v views ]] && { declare -A views=(); }
+            case "$arg" in
+
+                search*)
+                    urls+=('https://gerrit.opencord.org/admin/repos')
+                    ;;
+
+                repo) views['repository']=1 ;;
+
+                # https://gerrit.opencord.org/plugins/gitiles/voltha-go
+                master) views['master']=1 ;;
+                voltha*) views["$arg"]=1  ;;
+                v*) views["$arg"]=1       ;;
+                *)
+                    # Missing latest tags
+                    views['default']=1
+                    views['master']=1
+                    ;;
+            esac
+            ;;
+
+	    -*)
+	        echo "ERROR: Unknown argument [$arg]"
+	        exit 1
+	        ;;
+
+	    [[:alnum:]]*)
+            declare -a what=()
+            # whats+=('patches')
+            whats+=('versions')
+
+            stem="https://gerrit.opencord.org/q/${arg}"
+
+            for what in "${whats[@]}";
+            do
+                case "$what" in
+                    patches) urls+=("https://gerrit.opencord.org/q/${arg}") ;;
+                    versions)
+                        urls+=("https://gerrit.opencord.org/plugins/gitiles/${arg}/+/refs/heads/master/VERSION")
+                        # urls+=("https://gerrit.opencord.org/plugins/gitiles/${arg}/+/refs/tags/v0.3.6/VERSION")
+                        urls+=("https://gerrit.opencord.org/plugins/gitiles/${arg}/+/refs/heads/voltha-2.12/VERSION")
+                        ;;
+                    '??') urls+=("https://gerrit.opencord.org/plugins/gitiles/${arg}") ;;
+                    *) urls+=("https://gerrit.opencord.org/q/${arg}") ;;
+                esac
+            done
+    esac
+done
+
+[[ -v argv_search ]] && { do_gerrit_search urls repos argv_status; }
+[[ -v admins ]] && { gen_admin_urls urls repos admins; }
+
+## are --views working ?
+[[ "${#views[@]}" -gt 0 ]] && { gen_view_urls  urls repos views;  }
+# [[ ! -v views  ]] && { echo 'called'; gen_view_urls  urls repos views;  }
+
+if [[ ${#urls[@]} -eq 0 ]]; then
+    declare -a show_all=() # show all for visiblity
+    do_gerrit_search urls repos show_all
+fi
+
+
+[[ -v debug ]] && { echo "$BROWSER" "${urls[@]}"; }
+
+if [[ ${#urls[@]} -gt 0 ]]; then
+    apply_filter_status urls
+    browse urls
+fi
+
+## -----------------------------------------------------------------------
+## [TODO]
+## Query patches by repo:voltha-lib-go
+##     ssh gerrit.opencord.org  gerrit query --patch-sets projects:voltha-lib-go | grep -i description
+#      ssh gerrit.opencord.org  gerrit query --patch-sets 'projects:voltha-lib-go AND status:open limit:2' |
+
+# Show URL and Commit message
+# ssh gerrit.opencord.org  gerrit query --format=JSON --patch-sets 'projects:voltha-lib-go AND status:open limit:2' | jq '.url,.commitMessage'
+## -----------------------------------------------------------------------
+
+# [EOF]
+
+
+# 1) gerrit.sh --search --me --wip
+#    query> owner:joey@opennetworking.org status:open
+
+# --search --me
+#            args+=("owner:${USER}@opennetworking.org")
+
+#        --wip)
+#            argv_status+=('status:open')
+#            ;;
+
+
+# [EOF]