First commit
A modified copy of portzap repurposed for management of the hardenedbsd source tree.
This commit is contained in:
commit
ea06f0dfbc
17 changed files with 534 additions and 0 deletions
16
.github/workflows/shellcheck.yml
vendored
Normal file
16
.github/workflows/shellcheck.yml
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
name: srczap
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
shellcheck:
|
||||
name: shellcheck
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ludeeus/action-shellcheck@master
|
||||
- run: make shellcheck
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
1
.projectile
Normal file
1
.projectile
Normal file
|
@ -0,0 +1 @@
|
|||
-/.git
|
15
LICENSE
Normal file
15
LICENSE
Normal file
|
@ -0,0 +1,15 @@
|
|||
Copyright (C) 2023 by 0x1eef <0x1eef@protonmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this
|
||||
software for any purpose with or without fee is hereby
|
||||
granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS
|
||||
ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
||||
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
OF THIS SOFTWARE.
|
24
Makefile
Normal file
24
Makefile
Normal file
|
@ -0,0 +1,24 @@
|
|||
PREFIX = /usr/local
|
||||
BINDIR = $(PREFIX)/bin
|
||||
MANDIR = $(PREFIX)/man/man8
|
||||
LIBEXECDIR = $(PREFIX)/libexec/srczap
|
||||
SHAREDIR = $(PREFIX)/share/srczap
|
||||
|
||||
install:
|
||||
install -d $(BINDIR) $(LIBEXECDIR) $(SHAREDIR) $(MANDIR)
|
||||
install -m 0755 bin/srczap $(BINDIR)
|
||||
install -m 0755 bin/setup-srczap $(BINDIR)
|
||||
install -m 0755 libexec/srczap/* $(LIBEXECDIR)
|
||||
install -m 0644 share/srczap/* $(SHAREDIR)
|
||||
install -m 0644 man/man8/srczap.8 $(MANDIR)
|
||||
|
||||
deinstall:
|
||||
rm $(BINDIR)/srczap
|
||||
rm $(BINDIR)/setup-srczap
|
||||
rm $(MANDIR)/srczap.8
|
||||
rm -rf $(LIBEXECDIR)
|
||||
rm -rf $(SHAREDIR)
|
||||
|
||||
shellcheck:
|
||||
shellcheck bin/srczap
|
||||
shellcheck libexec/srczap/*
|
36
bin/setup-srczap
Executable file
36
bin/setup-srczap
Executable file
|
@ -0,0 +1,36 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
##
|
||||
# variables
|
||||
localbase="${LOCALBASE:-/usr/local}"
|
||||
conf=$(cat "${localbase}"/share/srczap/doas.conf)
|
||||
doas="${localbase}"/etc/doas.conf
|
||||
|
||||
##
|
||||
# main
|
||||
if [ "$(id -u)" != "0" ]; then
|
||||
echo "[-] This command must be run by root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if id -u _srczap > /dev/null 2>&1; then
|
||||
echo "[-] The _srczap user exists"
|
||||
echo "[-] Add user(s) to the _srczap group:"
|
||||
echo "root# pw groupmod -n _srczap -m user1,user2"
|
||||
else
|
||||
pw useradd -n _srczap \
|
||||
-c "srczap user" \
|
||||
-m \
|
||||
-s /sbin/nologin
|
||||
chmod u=rwX,g=rX,o= /home/_srczap/
|
||||
echo "[-] The _srczap user, group and home directory have been created."
|
||||
echo "[-] Add user(s) to the _srczap group:"
|
||||
echo "root# pw groupmod -n _srczap -m user1,user2"
|
||||
fi
|
||||
|
||||
if grep -F "^${conf}$" "${doas}" > /dev/null 2>&1; then
|
||||
echo "[-] No changes made to ${doas}"
|
||||
else
|
||||
echo "$conf" >> "$doas"
|
||||
echo "[-] ${doas} has been changed. Please review the changes"
|
||||
fi
|
64
bin/srczap
Executable file
64
bin/srczap
Executable file
|
@ -0,0 +1,64 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
##
|
||||
# variables
|
||||
localbase="${LOCALBASE:-/usr/local}"
|
||||
gitdir="/home/_srczap/src"
|
||||
giturl="${SRCZAP_GITURL:-https://git.hardenedbsd.org/hardenedbsd/HardenedBSD/}"
|
||||
branch="${SRCZAP_BRANCH:-hardened/14-stable/master}"
|
||||
installdir="${SRCZAP_INSTALLDIR:-/usr/src}"
|
||||
revision="${installdir}"/.srczap
|
||||
libexec="${localbase}"/libexec/srczap
|
||||
|
||||
##
|
||||
# functions
|
||||
require_dependency() {
|
||||
deps=$1
|
||||
for dep in $deps; do
|
||||
if ! which -s "$dep"; then
|
||||
echo "[-] This command requires ${dep}, but ${dep} wasn't found"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
##
|
||||
# main
|
||||
i=1
|
||||
while [ "${i}" -le "$#" ]; do
|
||||
eval "_srczap_option=\$${i}"
|
||||
# shellcheck disable=SC2154
|
||||
if [ "${_srczap_option}" = "-v" ]; then
|
||||
cat "${localbase}"/share/srczap/VERSION
|
||||
exit 0
|
||||
fi
|
||||
# shellcheck disable=SC2003
|
||||
i=$(expr "${i}" + 1);
|
||||
done
|
||||
|
||||
case $1 in
|
||||
"clone")
|
||||
require_dependency "git doas"
|
||||
"${libexec}"/srczap-clone "${giturl}" "${gitdir}" "${branch}"
|
||||
;;
|
||||
"pull")
|
||||
require_dependency "git doas"
|
||||
"${libexec}"/srczap-pull "${gitdir}" "${branch}"
|
||||
;;
|
||||
"erase")
|
||||
"${libexec}"/srczap-erase "${gitdir}" "${installdir}"
|
||||
;;
|
||||
"install")
|
||||
require_dependency "git doas"
|
||||
"${libexec}"/srczap-install "${gitdir}" "${installdir}" "${revision}"
|
||||
;;
|
||||
*)
|
||||
printf "Usage: srczap COMMAND [OPTIONS]\n"
|
||||
printf "\n"
|
||||
printf "Commands:\n"
|
||||
printf " clone Clone the HardenedBSD source code\n"
|
||||
printf " pull Pull source code updates\n"
|
||||
printf " erase Erase /usr/src/ and /home/_srczap/src/\n"
|
||||
printf " install Install the source tree into /usr/src/\n"
|
||||
;;
|
||||
esac
|
25
libexec/srczap/git-changed-files
Normal file
25
libexec/srczap/git-changed-files
Normal file
|
@ -0,0 +1,25 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
##
|
||||
# variables
|
||||
localbase=${LOCALBASE:-/usr/local}
|
||||
git="${localbase}"/bin/git
|
||||
gitdir=$1
|
||||
commit=$2
|
||||
mode=u=rwX,g=rX,o=
|
||||
|
||||
##
|
||||
# functions
|
||||
gitexec()
|
||||
{
|
||||
doas -n -u _srczap \
|
||||
/bin/sh -c "umask ${mode}; ${git} ${1}"
|
||||
}
|
||||
|
||||
##
|
||||
# main
|
||||
cd "${gitdir}"
|
||||
add=$(gitexec "diff --name-only --diff-filter=A ${commit} HEAD")
|
||||
mod=$(gitexec "diff --name-only --diff-filter=M ${commit} HEAD")
|
||||
echo "${add}"
|
||||
echo "${mod}"
|
22
libexec/srczap/git-removed-files
Normal file
22
libexec/srczap/git-removed-files
Normal file
|
@ -0,0 +1,22 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
##
|
||||
# variables
|
||||
localbase=${LOCALBASE:-/usr/local}
|
||||
git="${localbase}"/bin/git
|
||||
gitdir=$1
|
||||
commit=$2
|
||||
mode=u=rwX,g=rX,o=
|
||||
|
||||
##
|
||||
# functions
|
||||
gitexec()
|
||||
{
|
||||
doas -n -u _srczap \
|
||||
/bin/sh -c "umask ${mode}; ${git} ${1}"
|
||||
}
|
||||
|
||||
##
|
||||
# main
|
||||
cd "${gitdir}"
|
||||
gitexec "diff --name-only --diff-filter=D ${commit} HEAD"
|
20
libexec/srczap/git-rev
Normal file
20
libexec/srczap/git-rev
Normal file
|
@ -0,0 +1,20 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
##
|
||||
# variables
|
||||
git=/usr/local/bin/git
|
||||
gitdir=$1
|
||||
mode=u=rwX,g=rX,o=
|
||||
|
||||
##
|
||||
# functions
|
||||
gitexec()
|
||||
{
|
||||
doas -n -u _srczap \
|
||||
/bin/sh -c "umask ${mode}; ${git} ${1}"
|
||||
}
|
||||
|
||||
##
|
||||
# main
|
||||
cd "${gitdir}"
|
||||
gitexec "rev-parse HEAD"
|
11
libexec/srczap/issrczap-member
Normal file
11
libexec/srczap/issrczap-member
Normal file
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
group="_srczap"
|
||||
if id -Gn | \
|
||||
tr ' ' '\n' | \
|
||||
grep -e "^${group}$" \
|
||||
> /dev/null 2>&1; then
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
41
libexec/srczap/srczap-clone
Executable file
41
libexec/srczap/srczap-clone
Executable file
|
@ -0,0 +1,41 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
##
|
||||
# variables
|
||||
localbase=${LOCALBASE:-/usr/local}
|
||||
libexec=$(dirname "$0")
|
||||
git="${localbase}"/bin/git
|
||||
giturl=$1
|
||||
gitdir=$2
|
||||
branch=$3
|
||||
mode=u=rwX,g=rX,o=
|
||||
|
||||
##
|
||||
# functions
|
||||
gitexec()
|
||||
{
|
||||
doas -n -u _srczap \
|
||||
/bin/sh -c "umask ${mode}; ${git} ${1}"
|
||||
}
|
||||
|
||||
##
|
||||
# main
|
||||
if ! "${libexec}"/issrczap-member; then
|
||||
echo "[-] This command must be run by a member of the '_srczap' group"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -e "${gitdir}/.git" ]; then
|
||||
echo "[-] ${gitdir} exists."
|
||||
echo "[-] Try 'srczap pull'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -x
|
||||
gitexec "clone ${giturl} ${gitdir}"
|
||||
cd "${gitdir}"
|
||||
gitexec "config core.filemode off"
|
||||
set +x
|
||||
echo "[-] git checkout ${branch}"
|
||||
gitexec "checkout -t origin/${branch} > /dev/null 2>&1"
|
||||
echo "[-] Done"
|
43
libexec/srczap/srczap-erase
Normal file
43
libexec/srczap/srczap-erase
Normal file
|
@ -0,0 +1,43 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
##
|
||||
# variables
|
||||
gitdir=$1
|
||||
installdir=$2
|
||||
|
||||
##
|
||||
# main
|
||||
if [ "$(id -u)" != "0" ]; then
|
||||
echo "[-] This command must be run by root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf "[-] Are you sure ? \n"
|
||||
printf "[-] These directories will be erased:\n"
|
||||
printf " [*] %s \n" "${gitdir}"
|
||||
printf " [*] %s \n" "${installdir}"
|
||||
printf "[y|n] "
|
||||
while true; do
|
||||
read -r r
|
||||
if [ "${r}" = "y" ]; then
|
||||
break
|
||||
elif [ "${r}" = "n" ]; then
|
||||
printf "[-] Nothing to do\n"
|
||||
exit
|
||||
else
|
||||
printf "[-] '%s' is not a valid option.\n" "${r}"
|
||||
printf "[y|n] "
|
||||
fi
|
||||
done
|
||||
for dir in "${gitdir}" "${installdir}"; do
|
||||
printf "%s " "${dir}"
|
||||
find "${dir}" \
|
||||
-maxdepth 1 \
|
||||
\! -name "." \
|
||||
\! -name ".." \
|
||||
\! -name "src" \
|
||||
-exec printf . \; \
|
||||
-exec rm -rf "{}" \;
|
||||
echo
|
||||
done
|
||||
printf "[-] Done\n"
|
77
libexec/srczap/srczap-install
Executable file
77
libexec/srczap/srczap-install
Executable file
|
@ -0,0 +1,77 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
##
|
||||
# variables
|
||||
gitdir=$1
|
||||
installdir=$2
|
||||
revfile=$3
|
||||
libexec=$(dirname "$0")
|
||||
mode="u=rwX,g=rX,o="
|
||||
|
||||
##
|
||||
# functions
|
||||
perform_update()
|
||||
{
|
||||
rev=$(cat "${revfile}")
|
||||
add=$("${libexec}"/git-changed-files "${gitdir}" "${rev}")
|
||||
del=$("${libexec}"/git-removed-files "${gitdir}" "${rev}")
|
||||
for file in ${del}; do
|
||||
target="${installdir}/${file}"
|
||||
parent=$(dirname "${target}")
|
||||
echo "rm ${target}"
|
||||
rm -f "${target}"
|
||||
find "${parent}" -type d -maxdepth 0 -empty -delete
|
||||
done
|
||||
for file in ${add}; do
|
||||
target="${installdir}/${file}"
|
||||
parent=$(dirname "${target}")
|
||||
parents=""
|
||||
while [ ! -e "${parent}" ]; do
|
||||
parents="${parent} ${parents}"
|
||||
parent=$(dirname "${parent}")
|
||||
done
|
||||
for dir in ${parents}; do
|
||||
run_install "-d" "${dir}"
|
||||
done
|
||||
run_install "${file}" "${target}"
|
||||
done
|
||||
}
|
||||
|
||||
perform_install()
|
||||
{
|
||||
find -s . \
|
||||
-maxdepth 1 \
|
||||
! -name "." \
|
||||
! -name ".git" \
|
||||
! -name ".gitignore" \
|
||||
! -name ".hooks" \
|
||||
! -name ".arcconfig" \
|
||||
-exec cp -Rpv {} "${installdir}" \;
|
||||
set -x
|
||||
chown -R root "${installdir}"
|
||||
}
|
||||
|
||||
run_install()
|
||||
{
|
||||
install -o root -g _srczap -m "${mode}" -v "$@"
|
||||
}
|
||||
|
||||
##
|
||||
# main
|
||||
if [ "$(id -u)" != "0" ]; then
|
||||
echo "[-] This command must be run by root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -x
|
||||
umask ${mode}
|
||||
cd "${gitdir}"
|
||||
set +x
|
||||
run_install "-d" "${installdir}"
|
||||
chmod ${mode} "${installdir}"
|
||||
if [ -e "${revfile}" ]; then
|
||||
perform_update
|
||||
else
|
||||
perform_install
|
||||
fi
|
||||
"${libexec}"/git-rev "${gitdir}" > "${revfile}"
|
59
libexec/srczap/srczap-pull
Executable file
59
libexec/srczap/srczap-pull
Executable file
|
@ -0,0 +1,59 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
##
|
||||
# variables
|
||||
libexec=$(dirname "$0")
|
||||
localbase=${LOCALBASE:-/usr/local}
|
||||
git="${localbase}"/bin/git
|
||||
gitdir=$1
|
||||
branch=$2
|
||||
mode="u=rwX,g=rX,o="
|
||||
|
||||
##
|
||||
# functions
|
||||
gitexec()
|
||||
{
|
||||
doas -n -u _srczap \
|
||||
/bin/sh -c "umask ${mode}; ${git} ${1}"
|
||||
}
|
||||
|
||||
change_branch()
|
||||
{
|
||||
set +e
|
||||
remote=$1
|
||||
branch=$2
|
||||
echo "[-] Attempt to change branch: ${branch}"
|
||||
gitexec "fetch ${remote} > /dev/null 2>&1"
|
||||
if ! gitexec "checkout ${branch} > /dev/null 2>&1" ||
|
||||
gitexec "checkout -t ${remote}/${branch} > /dev/null 2>&1"; then
|
||||
r="${?}"
|
||||
echo "[-] 'git checkout' exited with an error"
|
||||
exit "${r}"
|
||||
else
|
||||
echo "[-] Done"
|
||||
fi
|
||||
set -e
|
||||
}
|
||||
|
||||
##
|
||||
# main
|
||||
if ! "${libexec}"/issrczap-member; then
|
||||
echo "[-] This command must be run by a member of the '_srczap' group"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -e "${gitdir}/.git" ]; then
|
||||
set +x
|
||||
echo "[-] ${gitdir} is not a valid git repository."
|
||||
echo "[-] Try 'srczap clone'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "${gitdir}"
|
||||
remote=$(gitexec "remote" | head -n1)
|
||||
cbranch=$(gitexec "branch --show-current")
|
||||
if [ "${cbranch}" != "${branch}" ]; then
|
||||
change_branch "${remote}" "${branch}"
|
||||
fi
|
||||
set -x
|
||||
gitexec "pull --rebase ${remote} ${branch}"
|
75
man/man8/srczap.8
Normal file
75
man/man8/srczap.8
Normal file
|
@ -0,0 +1,75 @@
|
|||
.Dd May 2023
|
||||
.Dt SRCZAP 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm srczap
|
||||
.Nd manages a copy of the HardenedBSD source code
|
||||
.Sh SYNOPSIS
|
||||
.br
|
||||
srczap clone
|
||||
.br
|
||||
srczap pull
|
||||
.br
|
||||
srczap install
|
||||
.br
|
||||
srczap erase
|
||||
.Sh DESCRIPTION
|
||||
.Nm srczap
|
||||
manages a copy of the HardenedBSD source code.
|
||||
The copy of the source tree is maintained by members of
|
||||
the '_srczap' group, and a copy of the source tree
|
||||
can be installed to /usr/src/ by root.
|
||||
.Sh EXAMPLES
|
||||
.sp
|
||||
.sp
|
||||
.Nm srczap clone
|
||||
.br
|
||||
Clone the hardenedbsd ports tree into /home/_srczap/src/.
|
||||
.br
|
||||
This command is delegated to the '_srczap' user.
|
||||
.Pp
|
||||
.Nm srczap pull
|
||||
.br
|
||||
Pull updates into /home/_srczap/src/.
|
||||
.br
|
||||
This command is delegated to the '_srczap' user.
|
||||
.Pp
|
||||
.Nm srczap install
|
||||
.br
|
||||
Install /home/_srczap/src/ into /usr/src/.
|
||||
.br
|
||||
This command requires root privileges.
|
||||
.Pp
|
||||
.Nm srczap erase
|
||||
.br
|
||||
Start over: erase /usr/src/ and /home/_srczap/src/.
|
||||
.br
|
||||
This command requires root privileges.
|
||||
.br
|
||||
.Sh ENVIRONMENT
|
||||
.sp
|
||||
.sp
|
||||
.Nm SRCZAP_GITURL
|
||||
.br
|
||||
The URL to a git repository.
|
||||
.br
|
||||
Default: https://git.hardenedbsd.org/hardenedbsd/HardenedBSD/
|
||||
.sp
|
||||
.Nm SRCZAP_BRANCH
|
||||
.br
|
||||
The git branch to clone and pull updates from.
|
||||
.br
|
||||
Default: hardened/14-stable/master
|
||||
.br
|
||||
.sp
|
||||
.Nm SRCZAP_INSTALLDIR
|
||||
.br
|
||||
The directory where the ports collection will be installed.
|
||||
.br
|
||||
Default: /usr/src/
|
||||
.sp
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm srczap
|
||||
utility and this manual page were written by
|
||||
0x1eef <0x1eef@protonmail.com>.
|
1
share/srczap/VERSION
Normal file
1
share/srczap/VERSION
Normal file
|
@ -0,0 +1 @@
|
|||
v0.1.0-dev
|
4
share/srczap/doas.conf
Normal file
4
share/srczap/doas.conf
Normal file
|
@ -0,0 +1,4 @@
|
|||
##
|
||||
# srczap
|
||||
permit nopass root as _srczap cmd /bin/sh
|
||||
permit nopass :_srczap as _srczap cmd /bin/sh
|
Loading…
Reference in a new issue