mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 13:37:30 +00:00
Automatically generate bash completions for kubectl
This commit is contained in:
parent
f318da8344
commit
ebb0affc21
60
cmd/genbashcomp/gen_kubectl_bash_comp.go
Normal file
60
cmd/genbashcomp/gen_kubectl_bash_comp.go
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 Google Inc. All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd"
|
||||||
|
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// use os.Args instead of "flags" because "flags" will mess up the man pages!
|
||||||
|
outDir := "contrib/completions/bash/"
|
||||||
|
if len(os.Args) == 2 {
|
||||||
|
outDir = os.Args[1]
|
||||||
|
} else if len(os.Args) > 2 {
|
||||||
|
fmt.Fprintf(os.Stderr, "usage: %s [output directory]\n", os.Args[0])
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
outDir, err := filepath.Abs(outDir)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
stat, err := os.Stat(outDir)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "output directory %s does not exist\n", outDir)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !stat.IsDir() {
|
||||||
|
fmt.Fprintf(os.Stderr, "output directory %s is not a directory\n", outDir)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
outFile := outDir + "/kubectl"
|
||||||
|
|
||||||
|
//TODO os.Stdin should really be something like ioutil.Discard, but a Reader
|
||||||
|
kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard)
|
||||||
|
kubectl.GenBashCompletionFile(outFile)
|
||||||
|
}
|
@ -149,73 +149,6 @@ __handle_word()
|
|||||||
__handle_word
|
__handle_word
|
||||||
}
|
}
|
||||||
|
|
||||||
# call kubectl get $1,
|
|
||||||
# use the first column in compgen
|
|
||||||
# we could use templates, but then would need a template per resource
|
|
||||||
__kubectl_parse_get()
|
|
||||||
{
|
|
||||||
local kubectl_output out
|
|
||||||
if kubectl_output=$(kubectl get --no-headers "$1" 2>/dev/null); then
|
|
||||||
out=($(echo "${kubectl_output}" | awk '{print $1}'))
|
|
||||||
COMPREPLY=( $( compgen -W "${out[*]}" -- "$cur" ) )
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
__kubectl_get_resource()
|
|
||||||
{
|
|
||||||
if [[ ${#nouns[@]} -eq 0 ]]; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
__kubectl_parse_get ${nouns[${#nouns[@]} -1]}
|
|
||||||
if [[ $? -eq 0 ]]; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# $1 is the name of the pod we want to get the list of containers inside
|
|
||||||
__kubectl_get_containers()
|
|
||||||
{
|
|
||||||
local template
|
|
||||||
template="{{ range .desiredState.manifest.containers }}{{ .name }} {{ end }}"
|
|
||||||
__debug ${FUNCNAME} "nouns are ${nouns[@]}"
|
|
||||||
|
|
||||||
local len="${#nouns[@]}"
|
|
||||||
if [[ ${len} -ne 1 ]]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
local last=${nouns[${len} -1]}
|
|
||||||
local kubectl_out
|
|
||||||
if kubectl_out=$(kubectl get -o template --template="${template}" pods "${last}" 2>/dev/null); then
|
|
||||||
COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) )
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Require both a pod and a container to be specified
|
|
||||||
__kubectl_require_pod_and_container()
|
|
||||||
{
|
|
||||||
if [[ ${#nouns[@]} -eq 0 ]]; then
|
|
||||||
__kubectl_parse_get pods
|
|
||||||
return 0
|
|
||||||
fi;
|
|
||||||
__kubectl_get_containers
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
__custom_func() {
|
|
||||||
case ${last_command} in
|
|
||||||
kubectl_get | kubectl_describe | kubectl_delete | kubectl_stop)
|
|
||||||
__kubectl_get_resource
|
|
||||||
return
|
|
||||||
;;
|
|
||||||
kubectl_log)
|
|
||||||
__kubectl_require_pod_and_container
|
|
||||||
return
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
_kubectl_get()
|
_kubectl_get()
|
||||||
{
|
{
|
||||||
last_command="kubectl_get"
|
last_command="kubectl_get"
|
||||||
@ -242,19 +175,6 @@ _kubectl_get()
|
|||||||
|
|
||||||
must_have_one_flag=()
|
must_have_one_flag=()
|
||||||
must_have_one_noun=()
|
must_have_one_noun=()
|
||||||
must_have_one_noun+=("limitrange")
|
|
||||||
must_have_one_noun+=("resourcequota")
|
|
||||||
must_have_one_noun+=("persistentvolume")
|
|
||||||
must_have_one_noun+=("service")
|
|
||||||
must_have_one_noun+=("event")
|
|
||||||
must_have_one_noun+=("namespace")
|
|
||||||
must_have_one_noun+=("pod")
|
|
||||||
must_have_one_noun+=("secret")
|
|
||||||
must_have_one_noun+=("replicationcontroller")
|
|
||||||
must_have_one_noun+=("node")
|
|
||||||
must_have_one_noun+=("status")
|
|
||||||
must_have_one_noun+=("persistentvolumeclaim")
|
|
||||||
must_have_one_noun+=("endpoints")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_kubectl_describe()
|
_kubectl_describe()
|
||||||
@ -272,15 +192,6 @@ _kubectl_describe()
|
|||||||
|
|
||||||
must_have_one_flag=()
|
must_have_one_flag=()
|
||||||
must_have_one_noun=()
|
must_have_one_noun=()
|
||||||
must_have_one_noun+=("persistentvolume")
|
|
||||||
must_have_one_noun+=("persistentvolumeclaim")
|
|
||||||
must_have_one_noun+=("pod")
|
|
||||||
must_have_one_noun+=("service")
|
|
||||||
must_have_one_noun+=("node")
|
|
||||||
must_have_one_noun+=("limitrange")
|
|
||||||
must_have_one_noun+=("resourcequota")
|
|
||||||
must_have_one_noun+=("replicationcontroller")
|
|
||||||
must_have_one_noun+=("minion")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_kubectl_create()
|
_kubectl_create()
|
||||||
@ -294,17 +205,11 @@ _kubectl_create()
|
|||||||
flags_completion=()
|
flags_completion=()
|
||||||
|
|
||||||
flags+=("--filename=")
|
flags+=("--filename=")
|
||||||
flags_with_completion+=("--filename")
|
|
||||||
flags_completion+=("_filedir '@(json|yaml|yml)'")
|
|
||||||
two_word_flags+=("-f")
|
two_word_flags+=("-f")
|
||||||
flags_with_completion+=("-f")
|
|
||||||
flags_completion+=("_filedir '@(json|yaml|yml)'")
|
|
||||||
flags+=("--help")
|
flags+=("--help")
|
||||||
flags+=("-h")
|
flags+=("-h")
|
||||||
|
|
||||||
must_have_one_flag=()
|
must_have_one_flag=()
|
||||||
must_have_one_flag+=("--filename=")
|
|
||||||
must_have_one_flag+=("-f")
|
|
||||||
must_have_one_noun=()
|
must_have_one_noun=()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,19 +224,12 @@ _kubectl_update()
|
|||||||
flags_completion=()
|
flags_completion=()
|
||||||
|
|
||||||
flags+=("--filename=")
|
flags+=("--filename=")
|
||||||
flags_with_completion+=("--filename")
|
|
||||||
flags_completion+=("_filedir '@(json|yaml|yml)'")
|
|
||||||
two_word_flags+=("-f")
|
two_word_flags+=("-f")
|
||||||
flags_with_completion+=("-f")
|
|
||||||
flags_completion+=("_filedir '@(json|yaml|yml)'")
|
|
||||||
flags+=("--help")
|
flags+=("--help")
|
||||||
flags+=("-h")
|
flags+=("-h")
|
||||||
flags+=("--patch=")
|
flags+=("--patch=")
|
||||||
|
|
||||||
must_have_one_flag=()
|
must_have_one_flag=()
|
||||||
must_have_one_flag+=("--filename=")
|
|
||||||
must_have_one_flag+=("-f")
|
|
||||||
must_have_one_flag+=("--patch=")
|
|
||||||
must_have_one_noun=()
|
must_have_one_noun=()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,11 +245,7 @@ _kubectl_delete()
|
|||||||
|
|
||||||
flags+=("--all")
|
flags+=("--all")
|
||||||
flags+=("--filename=")
|
flags+=("--filename=")
|
||||||
flags_with_completion+=("--filename")
|
|
||||||
flags_completion+=("_filedir '@(json|yaml|yml)'")
|
|
||||||
two_word_flags+=("-f")
|
two_word_flags+=("-f")
|
||||||
flags_with_completion+=("-f")
|
|
||||||
flags_completion+=("_filedir '@(json|yaml|yml)'")
|
|
||||||
flags+=("--help")
|
flags+=("--help")
|
||||||
flags+=("-h")
|
flags+=("-h")
|
||||||
flags+=("--selector=")
|
flags+=("--selector=")
|
||||||
@ -409,11 +303,7 @@ _kubectl_rolling-update()
|
|||||||
flags_completion=()
|
flags_completion=()
|
||||||
|
|
||||||
flags+=("--filename=")
|
flags+=("--filename=")
|
||||||
flags_with_completion+=("--filename")
|
|
||||||
flags_completion+=("_filedir '@(json|yaml|yml)'")
|
|
||||||
two_word_flags+=("-f")
|
two_word_flags+=("-f")
|
||||||
flags_with_completion+=("-f")
|
|
||||||
flags_completion+=("_filedir '@(json|yaml|yml)'")
|
|
||||||
flags+=("--help")
|
flags+=("--help")
|
||||||
flags+=("-h")
|
flags+=("-h")
|
||||||
flags+=("--poll-interval=")
|
flags+=("--poll-interval=")
|
||||||
@ -421,8 +311,6 @@ _kubectl_rolling-update()
|
|||||||
flags+=("--update-period=")
|
flags+=("--update-period=")
|
||||||
|
|
||||||
must_have_one_flag=()
|
must_have_one_flag=()
|
||||||
must_have_one_flag+=("--filename=")
|
|
||||||
must_have_one_flag+=("-f")
|
|
||||||
must_have_one_noun=()
|
must_have_one_noun=()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,7 +331,6 @@ _kubectl_resize()
|
|||||||
flags+=("--resource-version=")
|
flags+=("--resource-version=")
|
||||||
|
|
||||||
must_have_one_flag=()
|
must_have_one_flag=()
|
||||||
must_have_one_flag+=("--replicas=")
|
|
||||||
must_have_one_noun=()
|
must_have_one_noun=()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -469,10 +356,6 @@ _kubectl_exec()
|
|||||||
flags+=("-t")
|
flags+=("-t")
|
||||||
|
|
||||||
must_have_one_flag=()
|
must_have_one_flag=()
|
||||||
must_have_one_flag+=("--container=")
|
|
||||||
must_have_one_flag+=("-c")
|
|
||||||
must_have_one_flag+=("--pod=")
|
|
||||||
must_have_one_flag+=("-p")
|
|
||||||
must_have_one_noun=()
|
must_have_one_noun=()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -492,8 +375,6 @@ _kubectl_port-forward()
|
|||||||
two_word_flags+=("-p")
|
two_word_flags+=("-p")
|
||||||
|
|
||||||
must_have_one_flag=()
|
must_have_one_flag=()
|
||||||
must_have_one_flag+=("--pod=")
|
|
||||||
must_have_one_flag+=("-p")
|
|
||||||
must_have_one_noun=()
|
must_have_one_noun=()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -550,7 +431,6 @@ _kubectl_run-container()
|
|||||||
two_word_flags+=("-t")
|
two_word_flags+=("-t")
|
||||||
|
|
||||||
must_have_one_flag=()
|
must_have_one_flag=()
|
||||||
must_have_one_flag+=("--image=")
|
|
||||||
must_have_one_noun=()
|
must_have_one_noun=()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -566,11 +446,7 @@ _kubectl_stop()
|
|||||||
|
|
||||||
flags+=("--all")
|
flags+=("--all")
|
||||||
flags+=("--filename=")
|
flags+=("--filename=")
|
||||||
flags_with_completion+=("--filename")
|
|
||||||
flags_completion+=("_filedir '@(json|yaml|yml)'")
|
|
||||||
two_word_flags+=("-f")
|
two_word_flags+=("-f")
|
||||||
flags_with_completion+=("-f")
|
|
||||||
flags_completion+=("_filedir '@(json|yaml|yml)'")
|
|
||||||
flags+=("--help")
|
flags+=("--help")
|
||||||
flags+=("-h")
|
flags+=("-h")
|
||||||
flags+=("--selector=")
|
flags+=("--selector=")
|
||||||
@ -613,7 +489,6 @@ _kubectl_expose()
|
|||||||
two_word_flags+=("-t")
|
two_word_flags+=("-t")
|
||||||
|
|
||||||
must_have_one_flag=()
|
must_have_one_flag=()
|
||||||
must_have_one_flag+=("--port=")
|
|
||||||
must_have_one_noun=()
|
must_have_one_noun=()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
|
|||||||
source "${KUBE_ROOT}/hack/lib/init.sh"
|
source "${KUBE_ROOT}/hack/lib/init.sh"
|
||||||
|
|
||||||
kube::golang::setup_env
|
kube::golang::setup_env
|
||||||
"${KUBE_ROOT}/hack/build-go.sh" cmd/gendocs cmd/genman
|
"${KUBE_ROOT}/hack/build-go.sh" cmd/gendocs cmd/genman cmd/genbashcomp
|
||||||
|
|
||||||
# Get the absolute path of the directory component of a file, i.e. the
|
# Get the absolute path of the directory component of a file, i.e. the
|
||||||
# absolute path of the dirname of $1.
|
# absolute path of the dirname of $1.
|
||||||
@ -67,28 +67,35 @@ case "$(uname -m)" in
|
|||||||
esac
|
esac
|
||||||
|
|
||||||
# Find binary
|
# Find binary
|
||||||
doc_locations=(
|
locations=(
|
||||||
"${KUBE_ROOT}/_output/dockerized/bin/${host_os}/${host_arch}/gendocs"
|
"${KUBE_ROOT}/_output/dockerized/bin/${host_os}/${host_arch}/gendocs"
|
||||||
"${KUBE_ROOT}/_output/local/bin/${host_os}/${host_arch}/gendocs"
|
"${KUBE_ROOT}/_output/local/bin/${host_os}/${host_arch}/gendocs"
|
||||||
"${KUBE_ROOT}/platforms/${host_os}/${host_arch}/gendocs"
|
"${KUBE_ROOT}/platforms/${host_os}/${host_arch}/gendocs"
|
||||||
)
|
)
|
||||||
gendocs=$( (ls -t "${doc_locations[@]}" 2>/dev/null || true) | head -1 )
|
gendocs=$( (ls -t "${locations[@]}" 2>/dev/null || true) | head -1 )
|
||||||
man_locations=(
|
locations=(
|
||||||
"${KUBE_ROOT}/_output/dockerized/bin/${host_os}/${host_arch}/genman"
|
"${KUBE_ROOT}/_output/dockerized/bin/${host_os}/${host_arch}/genman"
|
||||||
"${KUBE_ROOT}/_output/local/bin/${host_os}/${host_arch}/genman"
|
"${KUBE_ROOT}/_output/local/bin/${host_os}/${host_arch}/genman"
|
||||||
"${KUBE_ROOT}/platforms/${host_os}/${host_arch}/genman"
|
"${KUBE_ROOT}/platforms/${host_os}/${host_arch}/genman"
|
||||||
)
|
)
|
||||||
genman=$( (ls -t "${man_locations[@]}" 2>/dev/null || true) | head -1 )
|
genman=$( (ls -t "${locations[@]}" 2>/dev/null || true) | head -1 )
|
||||||
|
locations=(
|
||||||
|
"${KUBE_ROOT}/_output/dockerized/bin/${host_os}/${host_arch}/genbashcomp"
|
||||||
|
"${KUBE_ROOT}/_output/local/bin/${host_os}/${host_arch}/genbashcomp"
|
||||||
|
"${KUBE_ROOT}/platforms/${host_os}/${host_arch}/genbashcomp"
|
||||||
|
)
|
||||||
|
genbashcomp=$( (ls -t "${locations[@]}" 2>/dev/null || true) | head -1 )
|
||||||
|
|
||||||
if [[ ! -x "$gendocs" || ! -x "$genman" ]]; then
|
if [[ ! -x "$gendocs" || ! -x "$genman" || ! -x "$genbashcomp" ]]; then
|
||||||
{
|
{
|
||||||
echo "It looks as if you don't have a compiled gendocs or genman binary"
|
echo "It looks as if you don't have a compiled gendocs, genman, or genbashcomp binary"
|
||||||
echo
|
echo
|
||||||
echo "If you are running from a clone of the git repo, please run"
|
echo "If you are running from a clone of the git repo, please run"
|
||||||
echo "'./hack/build-go.sh cmd/gendocs cmd/genman'."
|
echo "'./hack/build-go.sh cmd/gendocs cmd/genman cmd/genbashcomp'."
|
||||||
} >&2
|
} >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
${gendocs} "${KUBE_ROOT}/docs/"
|
${gendocs} "${KUBE_ROOT}/docs/"
|
||||||
${genman} "${KUBE_ROOT}/docs/man/man1/"
|
${genman} "${KUBE_ROOT}/docs/man/man1/"
|
||||||
|
${genbashcomp} "${KUBE_ROOT}/contrib/completions/bash/"
|
||||||
|
@ -22,7 +22,7 @@ KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
|
|||||||
source "${KUBE_ROOT}/hack/lib/init.sh"
|
source "${KUBE_ROOT}/hack/lib/init.sh"
|
||||||
|
|
||||||
kube::golang::setup_env
|
kube::golang::setup_env
|
||||||
"${KUBE_ROOT}/hack/build-go.sh" cmd/gendocs cmd/genman
|
"${KUBE_ROOT}/hack/build-go.sh" cmd/gendocs cmd/genman cmd/genbashcomp
|
||||||
|
|
||||||
# Get the absolute path of the directory component of a file, i.e. the
|
# Get the absolute path of the directory component of a file, i.e. the
|
||||||
# absolute path of the dirname of $1.
|
# absolute path of the dirname of $1.
|
||||||
@ -81,12 +81,19 @@ locations=(
|
|||||||
)
|
)
|
||||||
genman=$( (ls -t "${locations[@]}" 2>/dev/null || true) | head -1 )
|
genman=$( (ls -t "${locations[@]}" 2>/dev/null || true) | head -1 )
|
||||||
|
|
||||||
if [[ ! -x "$gendocs" || ! -x "$genman" ]]; then
|
locations=(
|
||||||
|
"${KUBE_ROOT}/_output/dockerized/bin/${host_os}/${host_arch}/genbashcomp"
|
||||||
|
"${KUBE_ROOT}/_output/local/bin/${host_os}/${host_arch}/genbashcomp"
|
||||||
|
"${KUBE_ROOT}/platforms/${host_os}/${host_arch}/genbashcomp"
|
||||||
|
)
|
||||||
|
genbashcomp=$( (ls -t "${locations[@]}" 2>/dev/null || true) | head -1 )
|
||||||
|
|
||||||
|
if [[ ! -x "$gendocs" || ! -x "$genman" || ! -x "$genbashcomp" ]]; then
|
||||||
{
|
{
|
||||||
echo "It looks as if you don't have a compiled gendocs or genman binary"
|
echo "It looks as if you don't have a compiled gendocs, genman, or genbashcomp binary"
|
||||||
echo
|
echo
|
||||||
echo "If you are running from a clone of the git repo, please run"
|
echo "If you are running from a clone of the git repo, please run"
|
||||||
echo "'./hack/build-go.sh cmd/gendocs cmd/genman'."
|
echo "'./hack/build-go.sh cmd/gendocs cmd/genman cmd/genbashcomp'."
|
||||||
} >&2
|
} >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@ -109,3 +116,20 @@ else
|
|||||||
echo "${DOCROOT} is out of date. Please run hack/run-gendocs.sh"
|
echo "${DOCROOT} is out of date. Please run hack/run-gendocs.sh"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
COMPROOT="${KUBE_ROOT}/contrib/completions"
|
||||||
|
TMP_COMPROOT="${KUBE_ROOT}/contrib/completions_tmp"
|
||||||
|
cp -a "${COMPROOT}" "${TMP_COMPROOT}"
|
||||||
|
${genbashcomp} "${TMP_COMPROOT}/bash/"
|
||||||
|
set +e
|
||||||
|
diff -Naupr "${COMPROOT}" "${TMP_COMPROOT}"
|
||||||
|
ret=$?
|
||||||
|
set -e
|
||||||
|
rm -rf ${TMP_COMPROOT}
|
||||||
|
if [ $ret -eq 0 ]
|
||||||
|
then
|
||||||
|
echo "${COMPROOT} up to date."
|
||||||
|
else
|
||||||
|
echo "${COMPROOT} is out of date. Please run hack/run-gendocs.sh"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
Loading…
Reference in New Issue
Block a user