summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Luka Šijanec <anton@sijanec.eu>2024-03-12 20:48:29 +0100
committerAnton Luka Šijanec <anton@sijanec.eu>2024-03-12 20:48:29 +0100
commita4c48186950ff6fc2fc90800d14eede98e8789a7 (patch)
tree9f0c10e4dfa0190040393c1ea5c6b05f7f0bcfc6
parentsearc-0.0.27 (diff)
downloadg-master.tar
g-master.tar.gz
g-master.tar.bz2
g-master.tar.lz
g-master.tar.xz
g-master.tar.zst
g-master.zip
-rw-r--r--eclass/go.eclass730
-rw-r--r--eclass/version.eclass257
-rw-r--r--net-im/dendrite/Manifest2
-rw-r--r--net-im/dendrite/dendrite-0.13.6.ebuild42
-rw-r--r--net-im/dendrite/files/dendrite-monolith.confd3
-rw-r--r--net-im/dendrite/files/dendrite-monolith.initd28
-rw-r--r--net-im/dendrite/files/dendrite-monolith.service17
-rw-r--r--net-im/dendrite/files/dendrite.confd5
-rw-r--r--net-im/dendrite/files/dendrite.initd27
-rw-r--r--net-im/dendrite/files/dendrite.service17
-rw-r--r--net-im/dendrite/metadata.xml12
11 files changed, 1140 insertions, 0 deletions
diff --git a/eclass/go.eclass b/eclass/go.eclass
new file mode 100644
index 0000000..748f89f
--- /dev/null
+++ b/eclass/go.eclass
@@ -0,0 +1,730 @@
+# Copyright 2022 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+# @ECLASS: go.eclass
+# @MAINTAINER:
+# Ryan Qian <i@bitbili.net>
+# @AUTHOR:
+# Ryan Qian <i@bitbili.net>
+# @SUPPORTED_EAPIS: 7 8
+# @BLURB: basic eclass for building software written in golang
+# @DESCRIPTION:
+# This eclass provides basic settings and functions needed by software
+# written in the go programming language.
+#
+# This eclass has three methods for offline building and one methods for online building:
+#
+# THREE OFFLINE BUILDING METHODS:
+#
+# ** priority: 1. > 2. > 3. **
+#
+# 1. for packages with the go.sum file which line number is less than GO_SUM_LIST_MAX (default to 100),
+# if the corresponding go.sum file exists in the 'files' directory with name 'go.sum.$PV', this ebuild
+# will automatically set the local proxy url for all modules in the 'go.sum' file. You just need to
+# add the GO_SUM_LIST_SRC_URI variable into the SRC_URI variable.
+#
+# @CODE
+#
+# inherit go
+#
+# SRC_URI="https://github.com/example-org/reponame/archive/refs/tags/v${PV}.tar.gz -> ${P}.tar.gz"
+# SRC_URI+=" ${GO_SUM_LIST_SRC_URI}"
+#
+# @CODE
+#
+# 2. use project embedded 'vendor' directory to build.
+# just inherit this eclass, don't need to do other special works
+#
+# @CODE
+#
+# inherit go
+#
+# @CODE
+#
+# 3. use extra 'vendor' directory to offer offline building, the vendor tarball can
+# be generated by the script https://github.com/bekcpear/vendor-for-go .
+# The tarball should consist of the directory architecture:
+# (name quoted by '[]' means optional)
+#
+# [any-parent-directory/]
+#
+# vendor/
+#
+# [go-mod-sum.diff] # should and expected to be empty if
+# # the upstream did `go mod tidy` before releasing
+#
+# @CODE
+#
+# inherit go
+#
+# SRC_URI="https://github.com/example-org/reponame/archive/refs/tags/v${PV}.tar.gz -> ${P}.tar.gz
+# https://some.url/corresponding-vendor-path.tar.gz -> ${P}-vendor.tar.gz"
+#
+# @CODE
+#
+# THE ONLINE BUILDING METHOD:
+#
+# 1. If there is no corresponding 'go.sum.$PV' file in the 'files' directory and
+# also no embedded 'vendor' directory under the $S path.
+# This eclass will check whether the 'live' PROPERTY exists, if it is, this eclass
+# will use `go mod vendor` to generate the 'vendor' directory through the network
+# instead of checking the vendor tarball.
+#
+# @CODE
+#
+# inherit git-r3 go
+#
+# EGIT_REPO_URI="https://github.com/example-org/reponame.git"
+#
+# src_unpack() {
+# git-r3_src_unpack
+# go_set_go_cmd
+# go_setup_vendor
+# }
+#
+# OR without using the git-r3 eclass and specifying the PROPERTIES manually:
+# #PROPERTIES="live"
+# #SRC_URI="https://github.com/example-org/reponame/archive/refs/tags/v${PV}.tar.gz -> ${P}.tar.gz"
+# #src_unpack() {
+# # go_src_unpack # OR just omit this whole "src_unpack" function
+# #}
+#
+# @CODE
+#
+#
+# #############################################################
+# #############################################################
+#
+# Why use this eclass instead of the offical go-module.eclass, please refer to
+# https://github.com/bekcpear/ryans-repos/issues/4
+#
+# Since Go programs are statically linked, it is important that your ebuild's
+# LICENSE= setting includes the licenses of all modules.
+# This script will be helpful to get the job done:
+# https://github.com/bekcpear/go-licenses-for-gentoo
+#
+if [[ -z ${_ECLASS_GO} ]]; then
+_ECLASS_GO=1
+
+case ${EAPI} in
+ 7|8) ;;
+ *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
+esac
+
+inherit edo version
+
+BDEPEND=">=dev-lang/go-1.16"
+
+EXPORT_FUNCTIONS src_unpack src_compile src_install
+
+IUSE="pie"
+
+# @ECLASS_VARIABLE: GOFLAGS
+# @DESCRIPTION:
+# the default GOFLAGS.
+# -trimpath remove all file system paths from the resulting executable
+# -v prints the names of packages as they are compiled
+# -work prints the temporary work dir's name and don't delete it when exiting
+# -x prints the commands
+export GOFLAGS="-trimpath -v -work -x"
+
+# Respect the job number explictly set in the MAKEOPTS variable if exists.
+# No number means the max number of available cpus which should be the same
+# as the default GOMAXPROCS (defaults to nproc), so should be ignored.
+# Should use GOMAXPROCS env var instead of the '-p' flag here due to:
+# 1. '-p' only limits the number of parallel building goroutines
+# 2. '-p' leaves the parallel number of GC, compiling and so on unchanged
+# 3. when '-p' is set to 1, the default '-c' for the compile tool will be set to
+# the GOMAXPROCS instead of min(4, GOMAXPROCS)
+# 4. GOMAXPROCS env variable can affect through the whole process,
+# N means N building goroutines and each building goroutine will call the compile
+# tool with '-c=I' which I=min(4, N). This is the behavior that best matches -j.
+# (The max number of -c may change in the future)
+# Also see https://go-review.googlesource.com/c/go/+/41192 for the performance of
+# concurrency of compiling process.
+[[ $MAKEOPTS =~ (-[a-z]*j|--jobs[=[:space:]])[[:space:]]*([0-9]+) ]] || true
+_MAXPROCS=${BASH_REMATCH[2]}
+if [[ -n $_MAXPROCS ]]; then
+ export GOMAXPROCS=$_MAXPROCS
+fi
+unset _MAXPROCS
+
+# @ECLASS_VARIABLE: EXTRA_GOFLAGS
+# @DESCRIPTION:
+# the extra GOFLAGS environment variable, default is empty,
+# this value will be appended to the GOFLAGS if provided.
+# Only valid when using the default src_compile of this eclass
+# or 'go_build' function of this eclass.
+
+# @ECLASS_VARIABLE: QA_FLAGS_IGNORED
+# @INTERNAL
+# @DESCRIPTION:
+# ignore FLAGS due to go projects do not use them,
+# this is a regex used by sed (without leading ^ and ending $).
+QA_FLAGS_IGNORED='.*'
+
+# Go packages should not be stripped with strip(1).
+RESTRICT+=" strip"
+
+# @ECLASS_VARIABLE: GO_LDFLAGS
+# @DESCRIPTION:
+# Flags pass to -ldflags, '-s' and '-w' flags will always be
+# applied except calling go command directly.
+
+# @ECLASS_VARIABLE: GO_SBIN
+# @DESCRIPTION:
+# names of binaries which should be installed as sbin
+
+# @ECLASS_VARIABLE: GO_TAGS
+# @DESCRIPTION:
+# a comma-separated list of additional build tags to consider satisfied
+# during the build
+#
+# @ECLASS_VARIABLE: GO_TARGET_PKGS
+# @DESCRIPTION:
+# A space-separated list of patterns which describe paths and target names
+# of packages which should be built instead of the default '.' or './cmd/...' .
+# The pattern has the following form:
+# <PACKAGE-PATH>[ -> <TARGET-NAME>]
+# <PACKAGE-PATH> is relative to the current temporary build dir (normally $S)
+# <TARGET-NAME> is the binary name instead of the package path name
+# e.g.:
+# ./main -> foo
+# ./cmd/bar
+
+# @ECLASS_VARIABLE: GO_LDFLAGS_EXMAP
+# @DESCRIPTION:
+# Extra "variable name <-> output command" maps, the output command will be called
+# and assign the standard output to the corresponding variable in src_compile phase.
+# These variables will replace the corresponding formatted strings in GO_LDFLAGS.
+# The formatted string should be like '@@VARIABLE-NAME@@'
+# e.g.:
+# GO_LDFLAGS_EXMAP[BUILD_DATE]="date '+%F %T%z'"
+# GO_LDFLAGS="-X 'main.buildDate=@@BUILD_DATE@@'"
+declare -A -g GO_LDFLAGS_EXMAP
+
+# @ECLASS_VARIABLE: _GO_LDFLAGS_EXMAP_CACHE
+# @INTERNAL
+# @DESCRIPTION:
+# cache for GO_LDFLAGS_EXMAP
+declare -A -g _GO_LDFLAGS_EXMAP_CACHE
+
+# @ECLASS_VARIABLE: GO_CMD
+# @DESCRIPTION:
+# The version matched Go command used to build packages.
+# Default is 'go'.
+# When dev-lang/go is installed from the 'ryans' repo, the slot is enabled,
+# and the default is the latest version, may be restricted to the penultimate
+# latest version due to the requirement of BDEPEND.
+GO_CMD=go
+
+# @ECLASS_VARIABLE: GO_SUM_LIST_MAX
+# @DESCRIPTION:
+# The max line number of go.sum which can be used to set a local proxy,
+# default to 100. This variable should be set before the eclass inherited.
+: "${GO_SUM_LIST_MAX:=100}"
+
+# @ECLASS_VARIABLE: GO_SUM_LIST_SRC_URI
+# @DESCRIPTION:
+# SRC_URI for go.sum entiries
+GO_SUM_LIST_SRC_URI=
+
+# @ECLASS_VARIABLE: GO_SUM_LIST_SRC_URI_R
+# @INTERNAL
+# @DESCRIPTION:
+# (internal variable) reversed map for GO_SUM_LIST_SRC_URI
+declare -A -g GO_SUM_LIST_SRC_URI_R
+
+# @FUNCTION: _go_escape_go_sum_path
+# @INTERNAL
+# @DESCRIPTION:
+# convert all capital letters in path to '!<lowercase>' format
+_go_escape_go_sum_path() {
+ local path="${1}" l
+ while [[ "${path}" =~ (.*)([[:upper:]])(.*) ]]; do
+ l=${BASH_REMATCH[2]@L}
+ path="${BASH_REMATCH[1]}!${l}${BASH_REMATCH[3]}"
+ done
+ echo -n "${path}"
+}
+
+# @FUNCTION: _go_set_go_sum_list_src_uri
+# @INTERNAL
+# @DESCRIPTION:
+# set GO_SUM_LIST_SRC_URI
+_go_set_go_sum_list_src_uri() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ if [[ -n ${GO_SUM_LIST_SRC_URI} ]]; then
+ return 0
+ fi
+
+ local _go_sum_list_file="${EBUILD%/*}/files/go.sum.$PV"
+ if [[ ! -f "${_go_sum_list_file}" ]]; then
+ return 0
+ fi
+ local -a _go_sum_list
+ while read -r line; do
+ _go_sum_list+=("${line}")
+ done <"${_go_sum_list_file}"
+ if [[ ${#_go_sum_list[@]} -gt ${GO_SUM_LIST_MAX} ]]; then
+ return 0
+ fi
+
+ local _distfile_name _src_uri _ver _ext
+ for line in "${_go_sum_list[@]}"; do
+ <<<$(_go_escape_go_sum_path "${line}") read -r path ver _
+ _ext=".zip"
+ _ver=${ver%/go.mod}
+ if [[ ${_ver} != ${ver} ]]; then
+ _ext=".mod"
+ fi
+ path="${path}/@v/${_ver}${_ext}"
+ _distfile_name="${path//\//%2F}"
+ eval "GO_SUM_LIST_SRC_URI_R['${_distfile_name}']='${path}'"
+ GO_SUM_LIST_SRC_URI+=" mirror://goproxy/${path} -> ${_distfile_name}"
+ done
+
+ export GOPROXY="file://${T}/go-proxy"
+}
+_go_set_go_sum_list_src_uri
+
+# @FUNCTION: go_version
+# @USAGE: [-f]
+# @DESCRIPTION:
+# Get version with format major.minor of the current executing go binary,
+# optionally specify -f to show the full version with the patch number.
+go_version() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ local output=$($GO_CMD version | cut -d' ' -f3) \
+ major= minor= patch=
+
+ IFS='.' read major minor patch <<<"$output"
+ major=${major#go}
+
+ if [[ $1 == '-f' ]] && [[ -n $patch ]]; then
+ output="${major}.${minor}.${patch}"
+ else
+ output="${major}.${minor}"
+ fi
+
+ echo -n $output
+}
+
+# @FUNCTION: go_set_go_cmd
+# @DESCRIPTION:
+# Try to get the version matched Go command, this is useful when the
+# go module to compile is restricted to the penultimate latest go version,
+# only functional when used with multi-version support of Go from
+# the ryans repository or other similar.
+# This function is called within the src_unpack phase by default.
+go_set_go_cmd() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ local goCmdPath=
+ local -a versions=() goCmds=()
+ for goCmdPath in $(ls -1v "${EROOT}"/usr/bin/go[[:digit:]].[[:digit:]]* 2>/dev/null); do
+ [[ -x "$goCmdPath" ]] || continue
+ goCmds+=( ${goCmdPath} )
+ versions+=( ${goCmdPath##*go} )
+ done
+
+ if [[ ${#versions[@]} -eq 0 ]]; then
+ # just return it if has no multi-version go binaries
+ return 0
+ fi
+
+ local _bdeps bdeps i d _ver_range _opt _ver _slot use usemark
+ local -a contained
+ local -i depth=0
+ local ver_range slot
+ _bdeps=( $(echo "$BDEPEND" | sed -E 's@(^|[[:space:]])[>=<~]{0,2}[[:alnum:]_\.-]+/[^g][^o][^[:space:]]*@ @g') )
+ contained[0]=1
+ for d in ${_bdeps[@]}; do
+ if [[ $d =~ ^(!?)([[:alpha:]][[:alnum:]]+)\?$ ]]; then
+ usemark=${BASH_REMATCH[1]}
+ use=${BASH_REMATCH[2]}
+ (( depth+=1 ))
+ if eval "$usemark use $use"; then
+ eval "contained[$depth]=1"
+ else
+ eval "contained[$depth]=0"
+ fi
+ elif [[ $d == "(" ]]; then
+ :
+ elif [[ $d == ")" ]]; then
+ (( depth-=1 ))
+ elif [[ $d == "||" ]]; then
+ # ignore it due to dev-lang/go dependency should not inside this
+ (( depth+=1 ))
+ eval "contained[$depth]=0"
+ else
+ if [[ ${contained[$depth]} == 1 ]]; then
+ bdeps+=( "$d" )
+ fi
+ fi
+ done
+ for d in ${bdeps[@]}; do
+ if [[ $d =~ ([>=<~]*)dev-lang/go(-([^[:space:]:]+))?(:([^[:space:]=]*))? ]]; then
+ _opt=${BASH_REMATCH[1]}
+ _ver=${BASH_REMATCH[3]}
+ _slot="${BASH_REMATCH[5]}"
+
+ if [[ $_opt =~ ^[=~] && -n $_ver ]]; then
+ ver_range="= $_ver"
+ # break loop when caught an exact version
+ break
+ elif [[ $_opt =~ [\>\<] && -n $_ver ]]; then
+ _ver_range="$_opt $_ver"
+ elif [[ -z $_slot ]]; then
+ _ver_range=
+ elif [[ -n $_slot ]]; then
+ slot=$_slot
+ fi
+
+ if [[ -n $_ver_range ]]; then
+ ver_range=$(version_make_range "$ver_range" "$_ver_range")
+ fi
+ fi
+ done
+
+ local ver oS oE vS vE
+ # match non-zero slot first then ver_range
+ for (( i = 0; i < ${#versions[@]}; i++ )); do
+ ver=${versions[$i]}
+ if [[ -n $slot && $slot != 0 ]]; then
+ if ! version_compare e $ver $slot; then
+ continue
+ fi
+ elif [[ -n $ver_range ]]; then
+ read -r oS vS oE vE <<<"$ver_range"
+ if [[ $oS == "=" ]]; then
+ VERSION_COMPARED_PARTS="minor"
+ if ! version_compare e $ver $vS; then
+ continue
+ fi
+ else
+ if [[ ${oS:1:1} == "=" ]]; then
+ if version_compare l $ver $vS; then
+ continue
+ fi
+ else
+ if version_compare le $ver $vS; then
+ continue
+ fi
+ fi
+ if [[ -n $oE ]]; then
+ if [[ ${oE:1:1} == "=" ]]; then
+ if version_compare g $ver $vE; then
+ continue
+ fi
+ else
+ if version_compare ge $ver $vE; then
+ continue
+ fi
+ fi
+ fi
+ fi
+ fi
+ GO_CMD="${goCmds[$i]}"
+ done
+}
+
+# @FUNCTION: go_set_pie
+# @DESCRIPTION:
+# Setup the buildmode to pie when pie USE enabled and supported.
+go_set_pie() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ if ! use pie; then
+ return 0
+ fi
+
+ local pie_supported=0 supported_platform="" target_platform=""
+ target_platform="$($GO_CMD env GOOS)/$($GO_CMD env GOARCH)"
+ local supported_platforms=(
+ "linux/386" "linux/amd64" "linux/arm" "linux/arm64" "linux/ppc64le" "linux/riscv64" "linux/s390x"
+ "android/amd64" "android/arm" "android/arm64" "android/386"
+ "freebsd/amd64"
+ "darwin/amd64" "darwin/arm64"
+ "ios/amd64" "ios/arm64"
+ "aix/ppc64"
+ "windows/386" "windows/amd64" "windows/arm" "windows/arm64"
+ )
+ for supported_platform in "${supported_platforms[@]}"; do
+ if [[ $supported_platform == "$target_platform" ]]; then
+ pie_supported=1
+ break
+ fi
+ done
+ if [[ $pie_supported == 1 ]]; then
+ GOFLAGS="-buildmode=pie ${GOFLAGS}"
+ else
+ eerror "PIE: unsupported platform '${target_platform}', ignore the 'pie' USE flag!"
+ fi
+}
+
+# @FUNCTION: go_setup_proxy
+# @DESCRIPTION:
+# Setup the local proxy for downloading go modules.
+go_setup_proxy() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ local -a _default_A
+ local _f _go_proxy_dir="${GOPROXY#file:\/\/}"
+
+ mkdir -p ${_go_proxy_dir} || die
+
+ for f in ${A}; do
+ _f="${GO_SUM_LIST_SRC_URI_R[${f}]}"
+ if [[ -n ${_f} ]]; then
+ _f="${_go_proxy_dir}/${_f}"
+ mkdir -p "$(dirname ${_f})" || die
+ ln -sf ${DISTDIR}/${f} ${_f} || die
+ else
+ _default_A+=("${f}")
+ fi
+ done
+
+ if [[ "$1" == "i" ]]; then
+ declare -p _default_A
+ fi
+}
+
+# @FUNCTION: go_setup_vendor
+# @DESCRIPTION:
+# setup vendor directory
+go_setup_vendor() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ if [[ ! -d "${S}/vendor" ]]; then
+ if [[ ${PROPERTIES} =~ (^|[[:space:]])live([[:space:]]|$) ]]; then
+ # Golang does not support the 'socks5h://' schema for http[s]_proxy env variable:
+ # https://github.com/golang/go/blob/9123221ccf3c80c741ead5b6f2e960573b1676b9/src/vendor/golang.org/x/net/http/httpproxy/proxy.go#L152-L159
+ # while libcurl supports it:
+ # https://github.com/curl/curl/blob/ae98b85020094fb04eee7e7b4ec4eb1a38a98b98/docs/libcurl/opts/CURLOPT_PROXY.3#L48-L59
+ # So, if a 'https_proxy=socks5h://127.0.0.1:1080' env has been set in the
+ # make.conf to make curl (assuming curl is the current download command) to
+ # download all packages through the proxy, go-module_live_vendor will
+ # fail.
+ # The only difference between these two schemas is, 'socks5h' will solve
+ # the hostname via the proxy while 'socks5' will not. I think it's ok to
+ # fallback 'socks5h' to 'socks5' for `go vendor` command and warn user,
+ # until golang supports it.
+ # related to issue: https://github.com/golang/go/issues/24135
+ local hp
+ local -a hps
+ if [[ -n $HTTP_PROXY ]]; then
+ hps+=( HTTP_PROXY )
+ elif [[ -n $http_proxy ]]; then
+ hps+=( http_proxy )
+ fi
+ if [[ -n $HTTPS_PROXY ]]; then
+ hps+=( HTTPS_PROXY )
+ elif [[ -n $https_proxy ]]; then
+ hps+=( https_proxy )
+ fi
+ for hp in "${hps[@]}"; do
+ if [[ -n ${!hp} ]] && [[ ${!hp} =~ ^socks5h:// ]]; then
+ set -- export ${hp}="socks5${!hp#socks5h}"
+ ewarn "golang does not support the 'socks5h://' schema for '${hp}', fallback to the 'socks5://' schema"
+ einfo "${@}"
+ "${@}"
+ fi
+ done
+ pushd "${S}" >/dev/null || die
+ # We don't care the compatibility with other go versions due to it's a temporary dir and the
+ # only purpose here is to build this package under current version of the go binary,
+ # so specify a compatible go version with current version number here to avoid incompatibility,
+ # such as go1.16 and go1.17 has different build list calculation methods (https://go.dev/ref/mod#graph-pruning).
+ edo $GO_CMD mod tidy -compat $(go_version)
+ edo $GO_CMD mod vendor
+ popd >/dev/null || die
+ else
+ local -a vendors
+ local vendor go_mod_sum_diff
+ vendors=($(find "${WORKDIR}" -maxdepth 2 -name 'vendor' 2>/dev/null || true))
+ if [[ ${#vendors[@]} -gt 0 ]]; then
+ vendor="${vendors[0]}"
+ mv "${vendor}" "${S}" || die
+ go_mod_sum_diff="$(dirname ${vendor})/go-mod-sum.diff"
+ if [[ -s "${go_mod_sum_diff}" ]]; then
+ pushd "${S}" >/dev/null || die
+ eapply "${go_mod_sum_diff}"
+ popd >/dev/null || die
+ fi
+ fi
+ fi
+ fi
+}
+
+# @FUNCTION: go_src_unpack
+# @DESCRIPTION:
+# src_unpack
+go_src_unpack() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ go_set_go_cmd
+ go_set_pie
+
+ if [[ -n ${GO_SUM_LIST_SRC_URI} ]]; then
+ # prepare local proxy
+ eval "$(go_setup_proxy i)" || die
+ for f in "${_default_A[@]}"; do
+ unpack "${f}"
+ done
+ else
+ # prepare vendor directory
+ default
+ go_setup_vendor
+ fi
+}
+
+# @FUNCTION: _go_print_cmd
+# @INTERNAL
+# @USAGE: <message>...
+# @DESCRIPTION:
+# print the command and arguments with a pretty format
+_go_print_cmd() {
+ local msg is_cmd
+ echo -ne "\x1b[32;01m===\x1b[0m"
+ for msg; do
+ if [[ ${msg} =~ [[:space:]] ]] && [[ -n ${is_cmd} ]]; then
+ msg="\"${msg//\"/\\\"}\""
+ elif [[ ${msg} == $GO_CMD ]]; then
+ is_cmd=1
+ fi
+ echo -ne " ${msg}"
+ done
+ echo
+}
+
+# @FUNCTION: go_build
+# @USAGE: [-o <output>] <package>...
+# @DESCRIPTION:
+# parse necessary arguments for go build and build packages,
+# the binaries will be installed into the ${T}/go-bin/ directory by default.
+go_build() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ local go_ldflags="${GO_LDFLAGS}"
+
+ [[ "${go_ldflags}" =~ (^|[[:space:]])-w([[:space:]]|$) ]] || go_ldflags="-w ${go_ldflags}"
+ [[ "${go_ldflags}" =~ (^|[[:space:]])-s([[:space:]]|$) ]] || go_ldflags="-s ${go_ldflags}"
+
+ local key value
+ for key in "${!GO_LDFLAGS_EXMAP[@]}"; do
+ if [[ -n "${_GO_LDFLAGS_EXMAP_CACHE[$key]}" ]]; then
+ value="${_GO_LDFLAGS_EXMAP_CACHE[$key]}"
+ else
+ value=$(eval "${GO_LDFLAGS_EXMAP[$key]}" || true)
+ if [[ -z ${value} ]]; then
+ die "the stdout of command '$GO_LDFLAGS_EXMAP[$key]' (GO_LDFLAGS_EXMAP[$key]) is empty"
+ fi
+ _GO_LDFLAGS_EXMAP_CACHE[$key]=${value}
+ fi
+ go_ldflags=$(<<<"${go_ldflags}" sed "s/@@${key}@@/${value}/g")
+ done
+
+ local output="${T}/go-bin/"
+ local -a args
+ while :; do
+ case "${1}" in
+ -o)
+ shift
+ output="${1}"
+ shift
+ ;;
+ "")
+ break
+ ;;
+ *)
+ args+=( "${1}" )
+ shift
+ ;;
+ esac
+ done
+ set -- "${args[@]}"
+
+ GOFLAGS="${GOFLAGS}${EXTRA_GOFLAGS:+ }${EXTRA_GOFLAGS}"
+ set -- $GO_CMD build -o "${output}" ${GO_TAGS:+-tags} ${GO_TAGS} -ldflags "${go_ldflags}" "${@}"
+ $GO_CMD env
+ _go_print_cmd " GOFLAGS:" "${GOFLAGS}"
+ _go_print_cmd "Build command:" "${@}"
+ "${@}" || die
+}
+
+# @FUNCTION: go_src_compile
+# @DESCRIPTION:
+# src_compile
+go_src_compile() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ if [[ -d "cmd" ]] && [[ -z ${GO_TARGET_PKGS} ]] && \
+ [[ $(find cmd/ -maxdepth 2 -type f -name '*.go' -exec \
+ grep -E '^package[[:space:]]+main([[:space:]]|$)' '{}' \; 2>/dev/null || true) != "" ]]; then
+ go_build ./cmd/...
+ elif [[ -z ${GO_TARGET_PKGS} ]]; then
+ go_build .
+ else
+ local pkg_path
+ local -a pkg_paths
+ set -- ${GO_TARGET_PKGS}
+ while :; do
+ case "${1}" in
+ '')
+ break
+ ;;
+ '->')
+ shift
+ go_build -o "${T}/go-bin/${1}" ${pkg_path}
+ pkg_path=
+ shift
+ ;;
+ *)
+ if [[ ${pkg_path} != "" ]]; then
+ pkg_paths+=( "${pkg_path}" )
+ pkg_path=
+ fi
+ pkg_path="${1}"
+ shift
+ ;;
+ esac
+ done
+ if [[ ${pkg_path} != "" ]]; then
+ pkg_paths+=( "${pkg_path}" )
+ fi
+ if [[ ${#pkg_paths[@]} -gt 0 ]]; then
+ go_build "${pkg_paths[@]}"
+ fi
+ fi
+}
+
+# @FUNCTION: go_src_install
+# @DESCRIPTION:
+# src_install
+go_src_install() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ pushd "${T}"/go-bin >/dev/null || die
+
+ local _sb _sbin
+ if [[ $(declare -p GO_SBIN 2>/dev/null) =~ declare[[:space:]]+-a ]]; then
+ _sbin="${GO_SBIN[*]}"
+ else
+ _sbin="${GO_SBIN}"
+ fi
+ for _sb in ${_sbin}; do
+ if ls ${_sb} &>/dev/null; then
+ dosbin ${_sb}
+ rm -f ${_sb} || die
+ fi
+ done
+
+ dobin *
+
+ popd >/dev/null || die
+}
+
+fi
diff --git a/eclass/version.eclass b/eclass/version.eclass
new file mode 100644
index 0000000..b0f3264
--- /dev/null
+++ b/eclass/version.eclass
@@ -0,0 +1,257 @@
+# Copyright 2023
+# Distributed under the terms of the GNU General Public License v2
+
+# @ECLASS: version.eclass
+# @MAINTAINER:
+# Ryan Qian <i@bitbili.net>
+# @AUTHOR:
+# Ryan Qian <i@bitbili.net>
+# @SUPPORTED_EAPIS: 7 8
+# @BLURB: functions to handle the version number
+# @DESCRIPTION:
+# This eclass provides functions to handle the version number.
+
+if [[ -z ${_ECLASS_VERSION} ]]; then
+_ECLASS_VERSION=1
+
+# @ECLASS_VARIABLE: VERSION_COMPARED_PARTS
+# @DESCRIPTION:
+# the version parts to compare, default is the full parts,
+# avaliable values are:
+# major # major parts
+# minor # major and minor parts
+# patch # major, minor and patch parts
+# full # major, minor, patch and pre-release parts
+VERSION_COMPARED_PARTS="full"
+
+# @FUNCTION: _version_compare_ver
+# @INTERNAL
+# @DESCRIPTION:
+# _version_compare_ver sub function
+_version_compare_ver() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ local v0=${1} v1=${2} is_num=1 res=
+ if [[ ! ${v0} =~ ^[0-9]+$ ]] || [[ ! ${v1} =~ ^[0-9]+$ ]]; then
+ is_num=0
+ : "${v0/-1/\\/}"
+ : "${v1/-1/\\/}"
+ fi
+ if [[ ${is_num} == 1 ]]; then
+ if (( ${v0} > ${v1} )); then
+ res="g"
+ elif (( ${v0} == ${v1} )); then
+ res="e"
+ elif (( ${v0} < ${v1} )); then
+ res="l"
+ fi
+ else
+ if [[ ${v0} > ${v1} ]]; then
+ res="g"
+ elif [[ ${v0} == ${v1} ]]; then
+ res="e"
+ elif [[ ${v0} < ${v1} ]]; then
+ res="l"
+ fi
+ fi
+ echo -n "${res}"
+}
+
+# @FUNCTION: _version_compare
+# @INTERNAL
+# @DESCRIPTION:
+# _version_compare sub function
+_version_compare() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ local v0 v1 vv0 vv1 len _len res
+ OIFS=$IFS; IFS="."
+ v0=(${1}) v1=(${2})
+ IFS=$OIFS
+ if [[ ${#v0[@]} -ge ${#v1[@]} ]]; then
+ len=${#v0[@]}
+ else
+ len=${#v1[@]}
+ fi
+ case $VERSION_COMPARED_PARTS in
+ major)
+ _len=1
+ ;;
+ minor)
+ _len=2
+ ;;
+ patch)
+ _len=3
+ ;;
+ esac
+ if [[ -n $_len && $_len -lt $len ]]; then
+ len=$_len
+ fi
+ for (( i=0; i<${len}; i++ )); do
+ vv0=${v0[$i]:--1}
+ vv1=${v1[$i]:--1}
+ res=$(_version_compare_ver ${vv0} ${vv1})
+ if [[ ${res} != "e" ]]; then
+ break
+ fi
+ done
+ echo -n "${res}"
+}
+
+# @FUNCTION: version_compare
+# @USAGE: g|ge|l|le|e STRING0 STRING1
+# @DESCRIPTION:
+# Compare the version numbers contained in the two strings to determine their precedence
+# according to the specifications defined in https://semver.org/spec/v2.0.0.html
+# The build metadata will be ignored.
+#
+# The prefixed package name will be removed automatically if exists.
+#
+# options:
+#
+# g: compare if the version contained in STRING0 is greater than the version in STRING1
+# ge: compare if the version contained in STRING0 is greater than or equal to the version in STRING1
+# l: compare if the version contained in STRING0 is less than the version in STRING1
+# le compare if the version contained in STRING0 is less than or equal to the version in STRING1
+# e: compare if the version contained in STRING0 is equal to the version in STRING1
+#
+# The return code is
+#
+# 0: when the above comparison holds
+# 1: when the above comparison does not hold
+#
+version_compare() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ local LC_ALL=C
+ local action result
+ case ${1} in
+ g|ge|l|le|e)
+ action="${1}"
+ ;;
+ *)
+ die "unexpected argument '${1}'"
+ ;;
+ esac
+ shift
+
+ local -a str0 str1
+ local str0_pkgname str0_ver str0_pre
+ local str1_pkgname str1_ver str1_pre
+
+ OIFS=$IFS; IFS="-"
+ str0=( ${1} ) str1=( ${2} )
+ IFS=$OIFS
+
+ for _str in "str0" "str1"; do
+ local _strA="${_str}[@]" _strV="${_str}_ver" _strP="${_str}_pre" _strN="${_str}_pkgname"
+ for _s in "${!_strA}"; do
+ if [[ -n ${!_strV} ]]; then
+ eval "${_str}_pre=\"${_s}\""
+ elif [[ ${_s} =~ ^[vV]?[0-9]+\.? ]]; then
+ _s="${_s#v}"
+ eval "${_str}_ver=\"${_s#V}\""
+ else
+ if [[ -n ${!_strN} ]]; then
+ eval "${_str}_pkgname+=\"-\""
+ fi
+ eval "${_str}_pkgname+=\"${_s}\""
+ fi
+ done
+ done
+
+ if [[ ${str0_pkgname} != ${str1_pkgname} ]]; then
+ die "compare with different package names '${str0_pkgname}', '${str1_pkgname}'"
+ fi
+
+ result=$(_version_compare ${str0_ver} ${str1_ver})
+ if [[ ${result} == "e" ]]; then
+ result=$(_version_compare ${str0_pre:-zzzz} ${str1_pre:-zzzz})
+ fi
+
+ if [[ ${result} =~ [${action}] ]]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+# @FUNCTION: version_make_range
+# @USAGE: CURRENT_RANGE NEW_CONDITION
+# @DESCRIPTION:
+# create a version range through the NEW_CONDITION
+# input format:
+# CURRENT_RANGE: ">[=] version-str <[=] version-str"
+# NEW_CONDITION: "(>|<)[=] version-str"
+# output:
+# NEW_RANGE: ">[=] version-str <[=] version-str"
+version_make_range() {
+ debug-print-function "${FUNCNAME}" "${@}"
+
+ if [[ -z $2 ]]; then
+ die "no new condition provided"
+ fi
+
+ local oS vS oE vE o v equal replace
+ read -r oS vS oE vE <<<"$1"
+ read -r o v <<<"$2"
+ if [[ ! $o =~ ^[\>\<]=?$ ]] || ! version_is_valid $v; then
+ die "wrong format of the new condition"
+ fi
+ if [[ ${o:1:1} == "=" ]]; then
+ equal=1
+ fi
+ case ${o:0:1} in
+ ">")
+ if [[ -z $oS ]]; then
+ replace=1
+ elif [[ ${oS:1:1} == "=" ]] && \
+ version_compare ge $v $vS; then
+ replace=1
+ else
+ if [[ -n $equal ]] && \
+ version_compare g $v $vS; then
+ replace=1
+ elif version_compare ge $v $vS; then
+ replace=1
+ fi
+ fi
+ if [[ -n $replace ]]; then
+ oS=$o
+ vS=$v
+ fi
+ ;;
+ "<")
+ if [[ -z $oE ]]; then
+ replace=1
+ elif [[ ${oE:1:1} == "=" ]] && \
+ version_compare le $v $vE; then
+ replace=1
+ else
+ if [[ -n $equal ]] && \
+ version_compare le $v $vE; then
+ replace=1
+ elif version_compare l $v $vE; then
+ replace=1
+ fi
+ fi
+ if [[ -n $replace ]]; then
+ oE=$o
+ vE=$v
+ fi
+ ;;
+ esac
+
+ echo -n "${oS:->=} ${vS:-0} ${oE:-<=} ${vE:-9999}"
+}
+
+# @FUNCTION: version_is_valid
+# @USAGE: version-str
+# @DESCRIPTION:
+# check the version-str is a valid semantic version
+version_is_valid() {
+ # TODO
+ :
+}
+
+fi
diff --git a/net-im/dendrite/Manifest b/net-im/dendrite/Manifest
new file mode 100644
index 0000000..0e4c9b9
--- /dev/null
+++ b/net-im/dendrite/Manifest
@@ -0,0 +1,2 @@
+DIST dendrite-0.13.6-vendor.tar.gz 38675509 BLAKE2B ba4b1c438870948a15b3ef544986cafa42ee26ce8a3b9b293650cb4217e6a8748caefa361a54bec32a0a35025c65f8eb5afbcabe39f7a45530e26eeb4da5404e SHA512 75ed0000f59257ba68d4ad111fa3876742f8dec3728e3d8a5c45a42ffac1203c19bdd54b370df013f572e937483c8f177f9086a8dbd7213ea9b9d6b57107c715
+DIST dendrite-0.13.6.tar.gz 1311877 BLAKE2B b833a045b22529ce0941612cf49c1e2955c7821d0b42346c4eb542eb0931ba667720f393f8677f4eda468e111d4907d3cc074a69bee7ecff0551454414104b22 SHA512 96294309e091382a2d96e508caab447c7e0d0366719beca14da6db56b27e098cfa5939e532f7d9ee69b12ff7745add9a642bec411bb8c6ce0dd521f033e23ec9
diff --git a/net-im/dendrite/dendrite-0.13.6.ebuild b/net-im/dendrite/dendrite-0.13.6.ebuild
new file mode 100644
index 0000000..8f9438c
--- /dev/null
+++ b/net-im/dendrite/dendrite-0.13.6.ebuild
@@ -0,0 +1,42 @@
+# Copyright 2023 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=8
+
+inherit go systemd
+
+DESCRIPTION="Dendrite is a second-generation Matrix homeserver written in Go!"
+HOMEPAGE="https://github.com/matrix-org/dendrite"
+
+SRC_URI="https://github.com/matrix-org/dendrite/archive/refs/tags/v${PV}.tar.gz -> ${P}.tar.gz
+ https://github.com/bekcpear/gopkg-vendors/archive/refs/tags/vendor-${P}.tar.gz -> ${P}-vendor.tar.gz"
+
+LICENSE="Apache-2.0 BSD-2 BSD ISC LGPL-3 MIT MPL-2.0 ZLIB"
+SLOT="0"
+KEYWORDS="~amd64 ~arm64"
+
+BDEPEND="
+ >dev-lang/go-1.19.9999:=
+"
+RDEPEND="
+ acct-user/dendrite
+ acct-group/dendrite
+"
+RESTRICT="strip"
+
+src_install() {
+ go_src_install
+
+ insinto /etc/dendrite
+ doins dendrite-sample.yaml
+
+ keepdir /var/log/dendrite
+ fowners dendrite:dendrite /var/log/dendrite
+ fperms 750 /var/log/dendrite
+
+ dodoc -r docs/*
+
+ newinitd "${FILESDIR}/dendrite.initd" dendrite
+ newconfd "${FILESDIR}/dendrite.confd" dendrite
+ systemd_dounit "${FILESDIR}"/dendrite.service
+}
diff --git a/net-im/dendrite/files/dendrite-monolith.confd b/net-im/dendrite/files/dendrite-monolith.confd
new file mode 100644
index 0000000..8c09541
--- /dev/null
+++ b/net-im/dendrite/files/dendrite-monolith.confd
@@ -0,0 +1,3 @@
+# extra arguments for dendrite monolith
+
+EXTRA_ARGS=""
diff --git a/net-im/dendrite/files/dendrite-monolith.initd b/net-im/dendrite/files/dendrite-monolith.initd
new file mode 100644
index 0000000..52dba9e
--- /dev/null
+++ b/net-im/dendrite/files/dendrite-monolith.initd
@@ -0,0 +1,28 @@
+#!/sbin/openrc-run
+# Copyright 2022 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+name="dendrite-monolith daemon"
+description="Dendrite (Matrix Homeserver)"
+command=/usr/bin/dendrite-monolith-server
+command_args="--config /etc/dendrite/dendrite.monolith.yaml ${EXTRA_ARGS}"
+pidfile="/run/dendrite-monolith.pid"
+command_background="yes"
+command_user="dendrite:dendrite"
+directory="/var/lib/dendrite"
+output_log="/var/log/dendrite/dendrite.log"
+error_log="/var/log/dendrite/dendrite.log"
+
+depend() {
+ need net
+}
+
+start_pre() {
+ _pem="/var/lib/dendrite/matrix_key.pem"
+ if [[ ! -e "${_pem}" ]]; then
+ /usr/bin/generate-keys --private-key "${_pem}"
+ chown dendrite:dendrite "${_pem}"
+ chmod 600 "${_pem}"
+ fi
+ ulimit -n 65535
+}
diff --git a/net-im/dendrite/files/dendrite-monolith.service b/net-im/dendrite/files/dendrite-monolith.service
new file mode 100644
index 0000000..55c1d6f
--- /dev/null
+++ b/net-im/dendrite/files/dendrite-monolith.service
@@ -0,0 +1,17 @@
+[Unit]
+Description=Dendrite (Matrix Homeserver)
+After=syslog.target
+After=network.target
+
+[Service]
+RestartSec=2s
+Type=simple
+User=dendrite
+Group=dendrite
+WorkingDirectory=/var/lib/dendrite/
+ExecStart=/usr/bin/dendrite-monolith-server
+Restart=always
+LimitNOFILE=65535
+
+[Install]
+WantedBy=multi-user.target
diff --git a/net-im/dendrite/files/dendrite.confd b/net-im/dendrite/files/dendrite.confd
new file mode 100644
index 0000000..0c4a069
--- /dev/null
+++ b/net-im/dendrite/files/dendrite.confd
@@ -0,0 +1,5 @@
+# extra arguments for dendrite
+
+EXTRA_ARGS=""
+
+rc_ulimit="-n 65535"
diff --git a/net-im/dendrite/files/dendrite.initd b/net-im/dendrite/files/dendrite.initd
new file mode 100644
index 0000000..ee210a2
--- /dev/null
+++ b/net-im/dendrite/files/dendrite.initd
@@ -0,0 +1,27 @@
+#!/sbin/openrc-run
+# Copyright 2023 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+name="dendrite daemon"
+description="Dendrite (Matrix Homeserver)"
+command=/usr/bin/dendrite
+command_args="--config /etc/dendrite/dendrite.yaml ${EXTRA_ARGS}"
+pidfile="/run/dendrite.pid"
+command_background="yes"
+command_user="dendrite:dendrite"
+directory="/var/lib/dendrite"
+output_log="/var/log/dendrite/dendrite.log"
+error_log="/var/log/dendrite/dendrite.log"
+
+depend() {
+ need net
+}
+
+start_pre() {
+ _pem="/var/lib/dendrite/matrix_key.pem"
+ if [ ! -e "${_pem}" ]; then
+ /usr/bin/generate-keys --private-key "${_pem}"
+ chown dendrite:dendrite "${_pem}"
+ chmod 600 "${_pem}"
+ fi
+}
diff --git a/net-im/dendrite/files/dendrite.service b/net-im/dendrite/files/dendrite.service
new file mode 100644
index 0000000..0b7a1da
--- /dev/null
+++ b/net-im/dendrite/files/dendrite.service
@@ -0,0 +1,17 @@
+[Unit]
+Description=Dendrite (Matrix Homeserver)
+After=syslog.target
+After=network.target
+
+[Service]
+RestartSec=2s
+Type=simple
+User=dendrite
+Group=dendrite
+WorkingDirectory=/var/lib/dendrite/
+ExecStart=/usr/bin/dendrite
+Restart=always
+LimitNOFILE=65535
+
+[Install]
+WantedBy=multi-user.target
diff --git a/net-im/dendrite/metadata.xml b/net-im/dendrite/metadata.xml
new file mode 100644
index 0000000..9bd4781
--- /dev/null
+++ b/net-im/dendrite/metadata.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<pkgmetadata>
+ <maintainer type="person">
+ <email>a@sijanec.eu</email>
+ <name>Anton Luka Šijanec</name>
+ </maintainer>
+ <upstream>
+ <remote-id type="github">matrix-org/dendrite</remote-id>
+ <bugs-to>https://github.com/matrix-org/dendrite/issues</bugs-to>
+ </upstream>
+</pkgmetadata>