git: 5fadc606e856 - main - devel/soft-serve: New port: Self-hosted Git server

From: Ashish SHUKLA <ashish_at_FreeBSD.org>
Date: Wed, 08 Dec 2021 19:09:21 UTC
The branch main has been updated by ashish:

URL: https://cgit.FreeBSD.org/ports/commit/?id=5fadc606e8569ad395bcac52c72c072dd511014f

commit 5fadc606e8569ad395bcac52c72c072dd511014f
Author:     Ashish SHUKLA <ashish@FreeBSD.org>
AuthorDate: 2021-12-08 19:06:44 +0000
Commit:     Ashish SHUKLA <ashish@FreeBSD.org>
CommitDate: 2021-12-08 19:09:00 +0000

    devel/soft-serve: New port: Self-hosted Git server
    
    A tasty, self-hosted Git server for the command line.
    
    Features:
    
     o Configure with git
     o Create repos on demand with git push
     o Browse repos with an SSH-accessible TUI
     o Easy access control
        - Allow/disallow anonymous access
        - Add collaborators with SSH public keys
        - Repos can be public or private
    
    WWW: https://github.com/charmbracelet/soft-serve
---
 devel/Makefile                                     |  1 +
 devel/soft-serve/Makefile                          | 87 +++++++++++++++++++
 devel/soft-serve/distinfo                          | 99 ++++++++++++++++++++++
 ...charmbracelet_bubbletea_cancelreader__select.go | 10 +++
 devel/soft-serve/files/soft-serve.in               | 93 ++++++++++++++++++++
 devel/soft-serve/pkg-descr                         | 13 +++
 6 files changed, 303 insertions(+)

diff --git a/devel/Makefile b/devel/Makefile
index 90c0a13af5a4..6e6d89dedb41 100644
--- a/devel/Makefile
+++ b/devel/Makefile
@@ -7030,6 +7030,7 @@
     SUBDIR += soapui
     SUBDIR += sobjectizer
     SUBDIR += socket_wrapper
+    SUBDIR += soft-serve
     SUBDIR += sol2
     SUBDIR += sonar-scanner-cli
     SUBDIR += sonarqube-ant-task
diff --git a/devel/soft-serve/Makefile b/devel/soft-serve/Makefile
new file mode 100644
index 000000000000..32d1148f6875
--- /dev/null
+++ b/devel/soft-serve/Makefile
@@ -0,0 +1,87 @@
+PORTNAME=	soft-serve
+DISTVERSIONPREFIX=	v
+DISTVERSION=	0.1.0
+CATEGORIES=	devel
+
+MAINTAINER=	ashish@FreeBSD.org
+COMMENT=	Self-hosted Git server for the command line
+
+LICENSE=	MIT
+LICENSE_FILE=	${WRKSRC}/LICENSE
+
+RUN_DEPENDS=	git:devel/git
+
+USES=		go:modules
+USE_GITHUB=	yes
+GH_ACCOUNT=	charmbracelet
+GH_TUPLE=	Microsoft:go-winio:v0.4.16:microsoft_go_winio/vendor/github.com/Microsoft/go-winio \
+		ProtonMail:go-crypto:04723f9f07d7:protonmail_go_crypto/vendor/github.com/ProtonMail/go-crypto \
+		acomagu:bufpipe:v1.0.3:acomagu_bufpipe/vendor/github.com/acomagu/bufpipe \
+		alecthomas:chroma:v0.8.2:alecthomas_chroma/vendor/github.com/alecthomas/chroma \
+		anmitsu:go-shlex:38f4b401e2be:anmitsu_go_shlex/vendor/github.com/anmitsu/go-shlex \
+		aymerick:douceur:v0.2.0:aymerick_douceur/vendor/github.com/aymerick/douceur \
+		charmbracelet:bubbles:v0.9.0:charmbracelet_bubbles/vendor/github.com/charmbracelet/bubbles \
+		charmbracelet:bubbletea:v0.19.0:charmbracelet_bubbletea/vendor/github.com/charmbracelet/bubbletea \
+		charmbracelet:glamour:v0.3.0:charmbracelet_glamour/vendor/github.com/charmbracelet/glamour \
+		charmbracelet:keygen:v0.1.2:charmbracelet_keygen/vendor/github.com/charmbracelet/keygen \
+		charmbracelet:lipgloss:v0.4.0:charmbracelet_lipgloss/vendor/github.com/charmbracelet/lipgloss \
+		charmbracelet:wish:v0.1.1:charmbracelet_wish/vendor/github.com/charmbracelet/wish \
+		containerd:console:v1.0.2:containerd_console/vendor/github.com/containerd/console \
+		danwakefield:fnmatch:cbb64ac3d964:danwakefield_fnmatch/vendor/github.com/danwakefield/fnmatch \
+		dlclark:regexp2:v1.2.0:dlclark_regexp2/vendor/github.com/dlclark/regexp2 \
+		dustin:go-humanize:v1.0.0:dustin_go_humanize/vendor/github.com/dustin/go-humanize \
+		emirpasic:gods:v1.12.0:emirpasic_gods/vendor/github.com/emirpasic/gods \
+		gliderlabs:ssh:v0.3.3:gliderlabs_ssh/vendor/github.com/gliderlabs/ssh \
+		go-git:gcfg:v1.5.0:go_git_gcfg/vendor/github.com/go-git/gcfg \
+		go-git:go-billy:v5.3.1:go_git_go_billy_v5/vendor/github.com/go-git/go-billy/v5 \
+		go-git:go-git:v5.4.2:go_git_go_git_v5/vendor/github.com/go-git/go-git/v5 \
+		go-warnings:warnings:v0.1.2:go_warnings_warnings/vendor/gopkg.in/warnings.v0 \
+		go-yaml:yaml:v2.3.0:go_yaml_yaml/vendor/gopkg.in/yaml.v2 \
+		golang:crypto:32db794688a5:golang_crypto/vendor/golang.org/x/crypto \
+		golang:net:0fccb6fa2b5c:golang_net/vendor/golang.org/x/net \
+		golang:sys:0f9fa26af87c:golang_sys/vendor/golang.org/x/sys \
+		golang:term:f5beecf764ed:golang_term/vendor/golang.org/x/term \
+		gorilla:css:v1.0.0:gorilla_css/vendor/github.com/gorilla/css \
+		imdario:mergo:v0.3.12:imdario_mergo/vendor/github.com/imdario/mergo \
+		jbenet:go-context:d14ea06fba99:jbenet_go_context/vendor/github.com/jbenet/go-context \
+		kevinburke:ssh_config:4977a11b4351:kevinburke_ssh_config/vendor/github.com/kevinburke/ssh_config \
+		lucasb-eyer:go-colorful:v1.2.0:lucasb_eyer_go_colorful/vendor/github.com/lucasb-eyer/go-colorful \
+		mattn:go-isatty:504425e14f74:mattn_go_isatty/vendor/github.com/mattn/go-isatty \
+		mattn:go-runewidth:v0.0.13:mattn_go_runewidth/vendor/github.com/mattn/go-runewidth \
+		meowgorithm:babyenv:v1.3.1:meowgorithm_babyenv/vendor/github.com/meowgorithm/babyenv \
+		microcosm-cc:bluemonday:v1.0.6:microcosm_cc_bluemonday/vendor/github.com/microcosm-cc/bluemonday \
+		mikesmitty:edkey:3356ea4e686a:mikesmitty_edkey/vendor/github.com/mikesmitty/edkey \
+		mitchellh:go-homedir:v1.1.0:mitchellh_go_homedir/vendor/github.com/mitchellh/go-homedir \
+		muesli:ansi:2e021307bc4b:muesli_ansi/vendor/github.com/muesli/ansi \
+		muesli:reflow:v0.3.0:muesli_reflow/vendor/github.com/muesli/reflow \
+		muesli:termenv:v0.9.0:muesli_termenv/vendor/github.com/muesli/termenv \
+		olekukonko:tablewriter:v0.0.5:olekukonko_tablewriter/vendor/github.com/olekukonko/tablewriter \
+		pkg:errors:v0.9.1:pkg_errors/vendor/github.com/pkg/errors \
+		rivo:uniseg:v0.2.0:rivo_uniseg/vendor/github.com/rivo/uniseg \
+		sergi:go-diff:v1.1.0:sergi_go_diff/vendor/github.com/sergi/go-diff \
+		xanzy:ssh-agent:v0.3.0:xanzy_ssh_agent/vendor/github.com/xanzy/ssh-agent \
+		yuin:goldmark-emoji:v1.0.1:yuin_goldmark_emoji/vendor/github.com/yuin/goldmark-emoji \
+		yuin:goldmark:v1.3.3:yuin_goldmark/vendor/github.com/yuin/goldmark
+
+USE_RC_SUBR=	soft-serve
+SUB_LIST+=	CHOWN="${CHOWN}" \
+		CUT="${CUT}" \
+		DEFAULTHOST=0.0.0.0 \
+		DEFAULTKEY=.ssh/soft_serve_server_ed25519 \
+		DEFAULTPORT=23231 \
+		DEFAULTREPO=.repos \
+		DIRNAME="${DIRNAME}" \
+		GITUSER="${USERS}" \
+		MKDIR="${MKDIR}" \
+		PW="${PW}" \
+		SETENV="${SETENV}"
+USERS=		git
+GROUPS=		git
+PLIST_FILES=	${DOCSDIR_REL}/README.md \
+		bin/${PORTNAME}
+
+post-install:
+		${MKDIR} ${STAGEDIR}${DOCSDIR}
+		${INSTALL_DATA} ${WRKSRC}/README.md ${STAGEDIR}${DOCSDIR}/
+
+.include <bsd.port.mk>
diff --git a/devel/soft-serve/distinfo b/devel/soft-serve/distinfo
new file mode 100644
index 000000000000..675da792aea6
--- /dev/null
+++ b/devel/soft-serve/distinfo
@@ -0,0 +1,99 @@
+TIMESTAMP = 1638939922
+SHA256 (charmbracelet-soft-serve-v0.1.0_GH0.tar.gz) = ffe1eac8ea9ea0c1bc18840a6672f376f8abec4797242e9ac46de190ef0f769c
+SIZE (charmbracelet-soft-serve-v0.1.0_GH0.tar.gz) = 26101
+SHA256 (Microsoft-go-winio-v0.4.16_GH0.tar.gz) = 0cb82f4cdba942af6b545695d694e91b9d9d56bd38555c81744235d7c6f6485d
+SIZE (Microsoft-go-winio-v0.4.16_GH0.tar.gz) = 85568
+SHA256 (ProtonMail-go-crypto-04723f9f07d7_GH0.tar.gz) = 09ca24a9956ebb6a8564ef17ab6b0eab6387938ac608a0c429f75360d3b176f5
+SIZE (ProtonMail-go-crypto-04723f9f07d7_GH0.tar.gz) = 308315
+SHA256 (acomagu-bufpipe-v1.0.3_GH0.tar.gz) = 9d34d4a015aa069649b951c36d4dc50fdbf6a2075717812ba68b9260d5c79986
+SIZE (acomagu-bufpipe-v1.0.3_GH0.tar.gz) = 3020
+SHA256 (alecthomas-chroma-v0.8.2_GH0.tar.gz) = b7b9bd2ff49a18127dd00cee0d8e1d262b861b0641f711cbf9c615431f2b9499
+SIZE (alecthomas-chroma-v0.8.2_GH0.tar.gz) = 637306
+SHA256 (anmitsu-go-shlex-38f4b401e2be_GH0.tar.gz) = 128b9243a8ba47fb94cb6301546e665c9158a9b7e13432b53cd424cd4e94b66b
+SIZE (anmitsu-go-shlex-38f4b401e2be_GH0.tar.gz) = 3716
+SHA256 (aymerick-douceur-v0.2.0_GH0.tar.gz) = ceed015cddc99b600ccbbd6aa0ebe39063554049f70153887d3df7c21fefedbb
+SIZE (aymerick-douceur-v0.2.0_GH0.tar.gz) = 20914
+SHA256 (charmbracelet-bubbles-v0.9.0_GH0.tar.gz) = 69fc842436d023be9f52f90c301cf07c46acc05ed6da408209f1e0f901e73a7e
+SIZE (charmbracelet-bubbles-v0.9.0_GH0.tar.gz) = 32110
+SHA256 (charmbracelet-bubbletea-v0.19.0_GH0.tar.gz) = 1b06d107eabd83126e150376ce3f09cdaead20924d3b01effb653e1ad10fb8f1
+SIZE (charmbracelet-bubbletea-v0.19.0_GH0.tar.gz) = 63696
+SHA256 (charmbracelet-glamour-v0.3.0_GH0.tar.gz) = 159a9fdbc95367ee014ef6eef76e2046f97eee78849234339f61f43a39af670c
+SIZE (charmbracelet-glamour-v0.3.0_GH0.tar.gz) = 533766
+SHA256 (charmbracelet-keygen-v0.1.2_GH0.tar.gz) = d16f5ee4feb32f42f78b6e24000fa9010519abc2cbcc9413986f3775c8a9d000
+SIZE (charmbracelet-keygen-v0.1.2_GH0.tar.gz) = 6173
+SHA256 (charmbracelet-lipgloss-v0.4.0_GH0.tar.gz) = c2f5ad6afcd9e4f3c21b523c5c8ecf077451029ac7e7b36ae6e8c2ce54eba194
+SIZE (charmbracelet-lipgloss-v0.4.0_GH0.tar.gz) = 26872
+SHA256 (charmbracelet-wish-v0.1.1_GH0.tar.gz) = 52cec2e6f44a55b00eb370fd408bde3555f40e6d5d2de02e3855079e7eadb128
+SIZE (charmbracelet-wish-v0.1.1_GH0.tar.gz) = 16696
+SHA256 (containerd-console-v1.0.2_GH0.tar.gz) = b2cdc6cb8d9b9e573f43130ea396009976df534bcd5f5f8fafd77f01ab712cdf
+SIZE (containerd-console-v1.0.2_GH0.tar.gz) = 13556
+SHA256 (danwakefield-fnmatch-cbb64ac3d964_GH0.tar.gz) = 7ebff38d382142f9220d2cfcb4731d0ae90cdef71238c94a15c35f8aa746007f
+SIZE (danwakefield-fnmatch-cbb64ac3d964_GH0.tar.gz) = 4955
+SHA256 (dlclark-regexp2-v1.2.0_GH0.tar.gz) = 9b4d25630d0ce86bcd518d79ce47365a84c7c75de2334b2708f1bddcc1df47fe
+SIZE (dlclark-regexp2-v1.2.0_GH0.tar.gz) = 204926
+SHA256 (dustin-go-humanize-v1.0.0_GH0.tar.gz) = e4540bd50ac855143b4f2e509313079c50cf5d8774f09cc10dbca5ae9803d8ba
+SIZE (dustin-go-humanize-v1.0.0_GH0.tar.gz) = 17260
+SHA256 (emirpasic-gods-v1.12.0_GH0.tar.gz) = 889d06b5f88db9e2dae19a799a35324c4f59305aa5e966dcdb4b637e70607ff9
+SIZE (emirpasic-gods-v1.12.0_GH0.tar.gz) = 76825
+SHA256 (gliderlabs-ssh-v0.3.3_GH0.tar.gz) = 37b4bf369a813bdfe7488462ab67e9a139c07d4e0a9cdb0ef4544176db9afb54
+SIZE (gliderlabs-ssh-v0.3.3_GH0.tar.gz) = 23902
+SHA256 (go-git-gcfg-v1.5.0_GH0.tar.gz) = 662e46a93aba5ffe383e55597ce5749447e5c8e9409b1452f5790bfd6e1f8a11
+SIZE (go-git-gcfg-v1.5.0_GH0.tar.gz) = 28522
+SHA256 (go-git-go-billy-v5.3.1_GH0.tar.gz) = 7d715d7cf11f731dc0466bf93903ba7fe6ac70d086bb862fc24e718d9ddc209e
+SIZE (go-git-go-billy-v5.3.1_GH0.tar.gz) = 29365
+SHA256 (go-git-go-git-v5.4.2_GH0.tar.gz) = bbdb5f61f027fb949f4091160e26af07c62ca80089b6efbb4d524c69158bbdcf
+SIZE (go-git-go-git-v5.4.2_GH0.tar.gz) = 461782
+SHA256 (go-warnings-warnings-v0.1.2_GH0.tar.gz) = 4712c4ceae321433d8c1d9ebc6afd154d7932c849129ded48b1c4a51c21275e8
+SIZE (go-warnings-warnings-v0.1.2_GH0.tar.gz) = 3769
+SHA256 (go-yaml-yaml-v2.3.0_GH0.tar.gz) = 42027002bf258009d498600b04b8c9cbb29d2193185ea7bfa8fefe194fe72a07
+SIZE (go-yaml-yaml-v2.3.0_GH0.tar.gz) = 72816
+SHA256 (golang-crypto-32db794688a5_GH0.tar.gz) = c971927593630ecfa6531da54a579bf04186c354e365975cd86ea0e4c2c82fb7
+SIZE (golang-crypto-32db794688a5_GH0.tar.gz) = 1732714
+SHA256 (golang-net-0fccb6fa2b5c_GH0.tar.gz) = 0f9f90bd3a26998655de85f44b046d0c427ce9b07302a35659a69999eff70682
+SIZE (golang-net-0fccb6fa2b5c_GH0.tar.gz) = 1249131
+SHA256 (golang-sys-0f9fa26af87c_GH0.tar.gz) = 4a7725e85ddaba8f2efc9b799eb00f4b3d522ea8ed9ad0ce08783febe3ec97a1
+SIZE (golang-sys-0f9fa26af87c_GH0.tar.gz) = 1202044
+SHA256 (golang-term-f5beecf764ed_GH0.tar.gz) = 60905cd7d54380fe6954f0e693da134115b2bfb49aeda969336ef6a95a709aa1
+SIZE (golang-term-f5beecf764ed_GH0.tar.gz) = 15022
+SHA256 (gorilla-css-v1.0.0_GH0.tar.gz) = 9decf83063b85bcd5392f645fac322e986b5fc596b3e44c3be02ee5939106f4c
+SIZE (gorilla-css-v1.0.0_GH0.tar.gz) = 6443
+SHA256 (imdario-mergo-v0.3.12_GH0.tar.gz) = f0ad95fe47f1a9c15545fe3e8abf4364b8163a0f872ce25d6f6ae85e7c885302
+SIZE (imdario-mergo-v0.3.12_GH0.tar.gz) = 22319
+SHA256 (jbenet-go-context-d14ea06fba99_GH0.tar.gz) = b5a5c4fe8d73dea7dc838f1c428c5fff0db9b50a2c014208a2761de4e94fa5ba
+SIZE (jbenet-go-context-d14ea06fba99_GH0.tar.gz) = 5945
+SHA256 (kevinburke-ssh_config-4977a11b4351_GH0.tar.gz) = 568ea6be8d237ca16dcd03e2fa5e07461ab596ccff40197ac34dac43f97389ec
+SIZE (kevinburke-ssh_config-4977a11b4351_GH0.tar.gz) = 17407
+SHA256 (lucasb-eyer-go-colorful-v1.2.0_GH0.tar.gz) = b3ee835cc398287452377266313edcc231043bae4168f8d2706e5d34ce1ce755
+SIZE (lucasb-eyer-go-colorful-v1.2.0_GH0.tar.gz) = 970830
+SHA256 (mattn-go-isatty-504425e14f74_GH0.tar.gz) = 7089b4bb7537d58bae623e67cd9bf290712799c00bbeac61558b3c1e14766bb6
+SIZE (mattn-go-isatty-504425e14f74_GH0.tar.gz) = 4705
+SHA256 (mattn-go-runewidth-v0.0.13_GH0.tar.gz) = 9b2aeafa5d95a40b32067ba22accdf42cc83414ec5b433ea7de330791beaa196
+SIZE (mattn-go-runewidth-v0.0.13_GH0.tar.gz) = 17353
+SHA256 (meowgorithm-babyenv-v1.3.1_GH0.tar.gz) = 04cd4888aa36d9e974235c2fc1c150cfbf0678bff97eb432a056e40e022897ca
+SIZE (meowgorithm-babyenv-v1.3.1_GH0.tar.gz) = 5082
+SHA256 (microcosm-cc-bluemonday-v1.0.6_GH0.tar.gz) = e9a04210d3e661057acc7c15d819ab25dfa789ff4c11e373a6a4e41ac7b240f0
+SIZE (microcosm-cc-bluemonday-v1.0.6_GH0.tar.gz) = 161636
+SHA256 (mikesmitty-edkey-3356ea4e686a_GH0.tar.gz) = 755e5ad2b0124f2197ccc92c909f3dd295771c518872d81b2656acf939e6af2c
+SIZE (mikesmitty-edkey-3356ea4e686a_GH0.tar.gz) = 2296
+SHA256 (mitchellh-go-homedir-v1.1.0_GH0.tar.gz) = 646671c73a84a8dfb4a5a76b80c7b63549ffefa906524d45077301bc7da76600
+SIZE (mitchellh-go-homedir-v1.1.0_GH0.tar.gz) = 3362
+SHA256 (muesli-ansi-2e021307bc4b_GH0.tar.gz) = 9b4b1adb94684fd8fd02cc74df118b79540af26a6895d241d6cd35dcf40b2952
+SIZE (muesli-ansi-2e021307bc4b_GH0.tar.gz) = 4762
+SHA256 (muesli-reflow-v0.3.0_GH0.tar.gz) = f797b8c25d447e314ad92b155433562446c683924171be1698ad44f24c79f651
+SIZE (muesli-reflow-v0.3.0_GH0.tar.gz) = 21245
+SHA256 (muesli-termenv-v0.9.0_GH0.tar.gz) = 6f664fb4a0c79a030c5cff540d45d269406e568963a4e502c9bcb90e285f6313
+SIZE (muesli-termenv-v0.9.0_GH0.tar.gz) = 408240
+SHA256 (olekukonko-tablewriter-v0.0.5_GH0.tar.gz) = 14a1294a8267facc9bc99a230b8871517e6db284ccc7e39030313befa124677f
+SIZE (olekukonko-tablewriter-v0.0.5_GH0.tar.gz) = 19568
+SHA256 (pkg-errors-v0.9.1_GH0.tar.gz) = 56bfd893023daa498508bfe161de1be83299fcf15376035e7df79cbd7d6fa608
+SIZE (pkg-errors-v0.9.1_GH0.tar.gz) = 13415
+SHA256 (rivo-uniseg-v0.2.0_GH0.tar.gz) = 3ad738b5c9162ede110d75b23564b6e40e52dd9150ebbced402f4f70be106197
+SIZE (rivo-uniseg-v0.2.0_GH0.tar.gz) = 44036
+SHA256 (sergi-go-diff-v1.1.0_GH0.tar.gz) = 3d4362670655e970366d555418f3c8d179c217c0499ef5573ab7176352229451
+SIZE (sergi-go-diff-v1.1.0_GH0.tar.gz) = 43552
+SHA256 (xanzy-ssh-agent-v0.3.0_GH0.tar.gz) = 7ce80a93d0fdbeb6760f97d6d166d11c215b809e50f0a80c78b8730c61582858
+SIZE (xanzy-ssh-agent-v0.3.0_GH0.tar.gz) = 8421
+SHA256 (yuin-goldmark-emoji-v1.0.1_GH0.tar.gz) = 9188fe9ed18f4560fdae3577a4bb63e3cbd20e0ae4ed68ae1058788b6aa0cec0
+SIZE (yuin-goldmark-emoji-v1.0.1_GH0.tar.gz) = 31694
+SHA256 (yuin-goldmark-v1.3.3_GH0.tar.gz) = b1423fc123efa29014d7d79696dbe7d9f4e26c2dd1a4c26d014b60d55680b7b6
+SIZE (yuin-goldmark-v1.3.3_GH0.tar.gz) = 232581
diff --git a/devel/soft-serve/files/patch-vendor_github.com_charmbracelet_bubbletea_cancelreader__select.go b/devel/soft-serve/files/patch-vendor_github.com_charmbracelet_bubbletea_cancelreader__select.go
new file mode 100644
index 000000000000..b091888d371d
--- /dev/null
+++ b/devel/soft-serve/files/patch-vendor_github.com_charmbracelet_bubbletea_cancelreader__select.go
@@ -0,0 +1,10 @@
+--- vendor/github.com/charmbracelet/bubbletea/cancelreader_select.go.orig	2021-10-30 17:04:27 UTC
++++ vendor/github.com/charmbracelet/bubbletea/cancelreader_select.go
+@@ -1,5 +1,5 @@
+-//go:build solaris || darwin
+-// +build solaris darwin
++//go:build solaris || darwin || freebsd || netbsd || openbsd
++// +build solaris darwin freebsd netbsd openbsd
+ 
+ // nolint:revive
+ package tea
diff --git a/devel/soft-serve/files/soft-serve.in b/devel/soft-serve/files/soft-serve.in
new file mode 100644
index 000000000000..e131c1ea1912
--- /dev/null
+++ b/devel/soft-serve/files/soft-serve.in
@@ -0,0 +1,93 @@
+#!/bin/sh
+
+# PROVIDE: soft-serve
+# REQUIRE: NETWORKING
+# KEYWORD: shutdown
+#
+# Add the following lines to /etc/rc.conf.local or /etc/rc.conf
+# to enable this service:
+#
+# soft_serve_enable (bool):	Set to NO by default.
+#				Set it to YES to enable soft_serve.
+#
+#
+# soft_serve_user (user):	User to run as. Set to %%GITUSER%% by default.
+# soft_serve_port (port):	TCP port to listen on.
+#                               Set to %%DEFAULTPORT%% by default.
+# soft_serve_host (IP):	        IP address to listen on.
+#                               Set to %%DEFAULTHOST%% by default.
+# soft_serve_key_path (path):	Path to host key.
+#                               Set to ~%%GITUSER%%/%%DEFAULTKEY%% by default.
+# soft_serve_repo_path (path):	Path to repositories root.
+#                               Set to ~%%GITUSER%%/%%DEFAULTREPO%% by default.
+# soft_serve_initial_admin_key (ssh public key): SSH public key for initial
+#                                                access to repositories (required)
+
+. /etc/rc.subr
+
+name="soft_serve"
+rcvar="soft_serve_enable"
+
+load_rc_config $name
+
+: ${soft_serve_user:="%%GITUSER%%"}
+: ${soft_serve_enable:="NO"}
+: ${soft_serve_port:=%%DEFAULTPORT%%}
+: ${soft_serve_host:="%%DEFAULTHOST%%"}
+: ${soft_serve_key_path:="%%DEFAULTKEY%%"}
+: ${soft_serve_repo_path:="%%DEFAULTREPO%%"}
+: ${soft_serve_initial_admin_key:=""}
+
+command="%%PREFIX%%/bin/soft-serve"
+procname="%%PREFIX%%/bin/soft-serve"
+githome="$(%%PW%% user show -n ${soft_serve_user} | %%CUT%% -d: -f9)"
+
+pidfile="/var/run/${name}.pid"
+
+start_cmd="${name}_start"
+
+soft_serve_start() {
+        if [ -z "${soft_serve_initial_admin_key}" ]; then
+	  echo Error: Please set soft_serve_initial_admin_key to a SSH public key
+	  echo which will initially have access to repositories.
+	  exit 1
+	fi
+
+	# Generate host key, if user has opted to use the default key
+	if [ "${soft_serve_key_path}" = "%%DEFAULTKEY%%" ]; then
+	  soft_serve_key_path=${githome}/${soft_serve_key_path}
+	  if ! [ -f $soft_serve_key_path ]; then
+	    echo Generating SSH Host Key...
+	    _soft_serve_ssh_dir=$(%%DIRNAME%% $soft_serve_key_path)
+	    if ! [ -d $_soft_serve_ssh_dir  ]; then
+	      %%MKDIR%% -m 700 $_soft_serve_ssh_dir
+	      %%CHOWN%% $soft_serve_user $_soft_serve_ssh_dir
+	    fi
+	    /usr/bin/ssh-keygen -t ed25519 -N "" -f $soft_serve_key_path
+	    %%CHOWN%% $soft_serve_user $soft_serve_key_path $soft_serve_key_path.pub
+	  fi
+	fi
+
+	if [ "${soft_serve_repo_path}" = "%%DEFAULTREPO%%" ]; then
+	  soft_serve_repo_path=${githome}/${soft_serve_repo_path}
+	  if ! [ -d $(%%DIRNAME%% $soft_serve_repo_path) ]; then
+	    echo Creating repositories directory...
+	    %%MKDIR%% $soft_serve_repo_path
+	    %%CHOWN%% $soft_serve_user $soft_serve_repo_path
+	  fi
+	fi
+
+	/usr/sbin/daemon -f \
+		-u ${soft_serve_user} -p ${pidfile} \
+		%%SETENV%% -i \
+		"SOFT_SERVE_PORT=${soft_serve_port}" \
+		"SOFT_SERVE_HOST=${soft_serve_host}" \
+		"SOFT_SERVE_KEY_PATH=${soft_serve_key_path}" \
+		"SOFT_SERVE_REPO_PATH=${soft_serve_repo_path}" \
+		"SOFT_SERVE_INITIAL_ADMIN_KEY=${soft_serve_initial_admin_key}" \
+		"PATH=%%LOCALBASE%%/bin:${PATH}" \
+		"USER=${soft_serve_user}" \
+		$command
+}
+
+run_rc_command "$1"
diff --git a/devel/soft-serve/pkg-descr b/devel/soft-serve/pkg-descr
new file mode 100644
index 000000000000..118f70889a8f
--- /dev/null
+++ b/devel/soft-serve/pkg-descr
@@ -0,0 +1,13 @@
+A tasty, self-hosted Git server for the command line.
+
+Features:
+
+ o Configure with git
+ o Create repos on demand with git push
+ o Browse repos with an SSH-accessible TUI
+ o Easy access control
+    - Allow/disallow anonymous access
+    - Add collaborators with SSH public keys
+    - Repos can be public or private
+
+WWW: https://github.com/charmbracelet/soft-serve