Add command line tool gerrit.sh

Change-Id: I264237c98f89163febd7a6458e6e39944769158f
diff --git a/.gitreview b/.gitreview
new file mode 100644
index 0000000..d60519b
--- /dev/null
+++ b/.gitreview
@@ -0,0 +1,6 @@
+[gerrit]
+host=gerrit.opencord.org
+port=29418
+project=onf-scripts.git
+defaultremote=origin
+defaultbranch=master
diff --git a/bin/gerrit.sh b/bin/gerrit.sh
new file mode 120000
index 0000000..8f6eac3
--- /dev/null
+++ b/bin/gerrit.sh
@@ -0,0 +1 @@
+../gerrit/gerrit.sh
\ No newline at end of file
diff --git a/gerrit/gerrit.sh b/gerrit/gerrit.sh
new file mode 100755
index 0000000..adabf93
--- /dev/null
+++ b/gerrit/gerrit.sh
@@ -0,0 +1,533 @@
+#!/bin/bash
+## -----------------------------------------------------------------------
+## Intent: Construct gerrit server queries and URLs based on arguments
+## -----------------------------------------------------------------------
+
+{ # loader
+    declare pgm=''
+    pgm="$(realpath --canonicalize-existing "$0")"
+    root="${pgm%/*}" # path -= /bin/
+    root="${root%/*}" # path is parent
+    source "$root/lf/onf-common/common.sh" '--common-args-begin--'
+
+    # lib_root="${pgm/.sh}" gerrit.sh => gerrit/
+}
+
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
+declare -g serv='gerrit.opencord.org'
+declare -x -g BROWSER="${BROWSER:-opera}"
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+function error_orig()
+{
+    echo "${FUNCNAME[1]} ERROR: $*"
+    exit 1
+}
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+function join_by_orig()
+{
+    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
+
+    # local stem='https://gerrit.opencord.org/q/project:voltha-go+status:open'
+    local stem='https://gerrit.opencord.org/q/'
+
+    local repo
+    for repo in "${ref_repos[@]}";
+    do 
+       local -a args=()
+        args+=("project:${repo}")
+
+        if [[ -v argv_me ]]; then
+            args+=("owner:${USER}@opennetworking.org")
+        fi
+
+        local status
+        for status in "${ref_status[@]}";
+        do
+            args+=("$status")
+        done
+
+        local url="$stem"
+        url+="$(join_by '+' "${args[@]}")"
+        ref_urls+=("$url")
+    done
+
+
+    
+	# --debug)  declare -g -i debug=1 ;;
+    # --search) declare -g -i search=1 ;;
+    # --wip)    declare -g -i status_is_open=1 ;;
+}
+
+
+## -----------------------------------------------------------------------
+## 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
+        declare -p repo
+        local stem="${stem0}/$repo"
+        local view
+        for view in "${view_keys[@]}";
+        do
+            declare -p view
+            # 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
+
+    # declare -p _urls
+    # echo "${_urls[@]}"
+    "${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
+}
+ 
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+function usage()
+{
+    cat <<EOH
+Usage: $0
+  --all r          Load all metadata for a repository
+  --reviews        Load pending code review requests
+
+  --access         Display gerrit ACLs
+  --dash(boad)     Display my patch dashboard
+  --branch         Admin branch URL
+
+  --crowd          View crowd access roles for group
+  --crowd-all      Group search (crowd)
+
+  --groups [g]     View access roles for group.
+  --groups-all     Group search (gerrit)
+
+  --repo           Repository name
+  --serv           Gerrit server name
+
+  --me             Query for my patches
+  --wip
+  --search
+
+  --admins a
+    a=branches     View repository branches
+    a=tags         View repository tags
+
+  --patch [repo]    Search for repository patches
+  --version v       Artifact versions(s) to act on
+     v=master       Mainline development
+     v=voltha-2.12  Artifact branch from a release
+     v=v2.12.0      Artifact tag derived from a release
+     v=v3.5.4       Artifact tag derived from VERSION file
+
+  --view v          View a code repository:
+    repo             View top level gerrit repository page (w/branch & tag)
+    search           Gerrit repo search page
+    master           View a branch
+    voltha-2.12      View a branch
+    v2.3.3           View a tag
+
+[FILTERS]
+  --status s         Filter query by open/merge/closed status
+    s=open (is:open)
+    s=merged
+
+  --debug
+  --help
+
+% gerrit.sh --repo voltha-go --admin tags --admin branches
+
+## Search for umerged patches in repo:voltha-go
+% gerrit.sh --repo voltha-go --search --wip
+EOH
+    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 ;;
+
+        ## 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 ;;
+        
+        --wip)
+            [[ ! -v argv_status ]] && { declare -g -a argv_status=(); }
+            argv_status+=('status:open')
+            ;;
+
+        --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
+            ;;
+
+        --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)
+            status="$1"; shift # open, closed, merged
+            urls[-1]+="+status:${status}"
+            ;;
+
+        --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;  }
+
+[[ -v debug ]] && { echo "$BROWSER" "${urls[@]}"; }
+# "$BROWSER" "${urls[@]}" >/dev/null 2>/dev/null
+[[ -v argv_debug ]] && { set -x; }
+"$BROWSER" "${urls[@]}"
+[[ -v argv_debug ]] && { set +x; }
+
+## -----------------------------------------------------------------------
+## [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]