setup update complete
This commit is contained in:
@@ -2,6 +2,51 @@
|
|||||||
version: 2.1
|
version: 2.1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
test-setup:
|
||||||
|
parameters:
|
||||||
|
image:
|
||||||
|
type: string
|
||||||
|
# alpine has no supported installer, so setup can only *verify*
|
||||||
|
# dependencies there; unresolved ones are expected, not a failure
|
||||||
|
strict:
|
||||||
|
type: string
|
||||||
|
default: '--strict'
|
||||||
|
docker:
|
||||||
|
- image: << parameters.image >>
|
||||||
|
steps:
|
||||||
|
- run:
|
||||||
|
name: install test prerequisites
|
||||||
|
command: |
|
||||||
|
if command -v pacman >/dev/null 2>&1
|
||||||
|
then pacman -Syu --noconfirm --needed git zsh sudo openssh tar gzip
|
||||||
|
elif command -v dnf >/dev/null 2>&1
|
||||||
|
then dnf install -y git zsh sudo openssh-clients tar gzip
|
||||||
|
elif command -v apt-get >/dev/null 2>&1
|
||||||
|
then apt-get update && apt-get install -y git zsh sudo openssh-client ca-certificates tar gzip
|
||||||
|
elif command -v apk >/dev/null 2>&1
|
||||||
|
then apk add --no-cache git zsh sudo openssh-client shadow tar
|
||||||
|
fi
|
||||||
|
- checkout
|
||||||
|
- run:
|
||||||
|
name: run setup as an unprivileged user
|
||||||
|
command: |
|
||||||
|
useradd -m tester 2>/dev/null || adduser -D tester
|
||||||
|
echo 'tester ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/tester
|
||||||
|
|
||||||
|
TESTER_HOME="$(getent passwd tester | cut -d: -f6)"
|
||||||
|
cp -a . "${TESTER_HOME}/.wryn"
|
||||||
|
chown -R tester "${TESTER_HOME}/.wryn"
|
||||||
|
|
||||||
|
# a LOGIN shell, so /etc/profile contributes to PATH exactly as
|
||||||
|
# it would in a real session (debian puts /usr/games there)
|
||||||
|
su - tester -c "cd ~/.wryn && ./setup/run \
|
||||||
|
--only packages \
|
||||||
|
--min \
|
||||||
|
--ci \
|
||||||
|
<< parameters.strict >> \
|
||||||
|
--no-logfile \
|
||||||
|
"
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
docker:
|
docker:
|
||||||
- image: docker:git
|
- image: docker:git
|
||||||
@@ -16,7 +61,26 @@ workflows:
|
|||||||
version: 2
|
version: 2
|
||||||
main:
|
main:
|
||||||
jobs:
|
jobs:
|
||||||
|
- test-setup:
|
||||||
|
name: test-arch
|
||||||
|
image: archlinux:base-devel
|
||||||
|
- test-setup:
|
||||||
|
name: test-fedora
|
||||||
|
image: fedora:latest
|
||||||
|
- test-setup:
|
||||||
|
name: test-debian
|
||||||
|
image: debian:stable
|
||||||
|
- test-setup:
|
||||||
|
name: test-alpine
|
||||||
|
image: alpine:latest
|
||||||
|
strict: ''
|
||||||
|
|
||||||
- deploy:
|
- deploy:
|
||||||
|
requires:
|
||||||
|
- test-arch
|
||||||
|
- test-fedora
|
||||||
|
- test-debian
|
||||||
|
- test-alpine
|
||||||
context:
|
context:
|
||||||
- yage-docker
|
- yage-docker
|
||||||
filters:
|
filters:
|
||||||
|
|||||||
+20
-10
@@ -13,15 +13,13 @@ RUN : \
|
|||||||
git \
|
git \
|
||||||
grep \
|
grep \
|
||||||
iproute2 \
|
iproute2 \
|
||||||
|
jo \
|
||||||
|
jq \
|
||||||
ncurses \
|
ncurses \
|
||||||
ncurses-terminfo \
|
ncurses-terminfo \
|
||||||
nodejs \
|
|
||||||
npm \
|
|
||||||
openssh \
|
openssh \
|
||||||
pciutils \
|
pciutils \
|
||||||
postgresql \
|
postgresql-client \
|
||||||
py3-virtualenv \
|
|
||||||
py3-nodeenv \
|
|
||||||
redis \
|
redis \
|
||||||
ripgrep \
|
ripgrep \
|
||||||
sed \
|
sed \
|
||||||
@@ -34,25 +32,37 @@ RUN : \
|
|||||||
&& apk add --update --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community/ \
|
&& apk add --update --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community/ \
|
||||||
helm \
|
helm \
|
||||||
kubectl \
|
kubectl \
|
||||||
&& apk add --update --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing/ \
|
|
||||||
&& mkdir -p /root/.wryn \
|
&& mkdir -p /root/.wryn \
|
||||||
;
|
;
|
||||||
|
|
||||||
|
# alpine's newest yq (4.25) predates the '-r' flag scwrypts relies on, so
|
||||||
|
# take it from upstream releases instead
|
||||||
|
RUN : \
|
||||||
|
&& YQ_ARCH="$(uname -m)" \
|
||||||
|
&& case "${YQ_ARCH}" in \
|
||||||
|
( x86_64 ) YQ_ARCH=amd64 ;; \
|
||||||
|
( aarch64 ) YQ_ARCH=arm64 ;; \
|
||||||
|
esac \
|
||||||
|
&& wget -qO /usr/local/bin/yq \
|
||||||
|
"https://github.com/mikefarah/yq/releases/latest/download/yq_linux_${YQ_ARCH}" \
|
||||||
|
&& chmod +x /usr/local/bin/yq \
|
||||||
|
&& yq --version \
|
||||||
|
;
|
||||||
|
|
||||||
COPY . /root/.wryn
|
COPY . /root/.wryn
|
||||||
|
|
||||||
RUN : \
|
RUN : \
|
||||||
&& echo "#!/bin/zsh" > /bin/hostnamectl && echo "echo container" > /bin/hostnamectl && chmod +x /bin/hostnamectl \
|
&& echo "#!/bin/zsh" > /bin/hostnamectl && echo "echo container" > /bin/hostnamectl && chmod +x /bin/hostnamectl \
|
||||||
&& echo "#!/bin/zsh" > /bin/scwrypts && echo '/root/.wryn/zsh/plugins/scwrypts/scwrypts $@' >> /bin/scwrypts && chmod +x /bin/scwrypts \
|
&& echo "#!/bin/zsh" > /bin/scwrypts && echo '/root/.wryn/zsh/plugins/scwrypts/scwrypts $@' >> /bin/scwrypts && chmod +x /bin/scwrypts \
|
||||||
&& mkdir /root/.wryn/bin/container \
|
&& mkdir -p /root/.wryn/config/local/container/bin \
|
||||||
&& sed -i 's|/bin/ash|/bin/zsh|g' /etc/passwd \
|
&& sed -i 's|/bin/ash|/bin/zsh|g' /etc/passwd \
|
||||||
&& /bin/zsh -c '/root/.wryn/setup/run --no-fluff --ci --force-root' \
|
&& /bin/zsh -c '/root/.wryn/setup/run --min --ci --force-root --no-logfile --skip config' \
|
||||||
|
&& echo 'source /root/.wryn/zsh/rc' > /root/.zshrc \
|
||||||
&& echo 'source /root/.wryn/config/dotwryn.env.zsh' > /root/.config/wryn/env.zsh \
|
&& echo 'source /root/.wryn/config/dotwryn.env.zsh' > /root/.config/wryn/env.zsh \
|
||||||
&& echo "WELCOME() {}" >> /root/.config/wryn/env.zsh \
|
&& echo "WELCOME() {}" >> /root/.config/wryn/env.zsh \
|
||||||
&& echo "PS1_INDICATOR_SYMBOL=''" >> /root/.config/wryn/env.zsh \
|
&& echo "PS1_INDICATOR_SYMBOL=''" >> /root/.config/wryn/env.zsh \
|
||||||
&& echo "PS1_USER=\"root@\$(ip a | grep inet | grep -v '127\\.0\\.0\.1' | sed 's|/| |g' | awk '{print \$2;}')\"" >> /root/.config/wryn/env.zsh \
|
&& echo "PS1_USER=\"root@\$(ip a | grep inet | grep -v '127\\.0\\.0\.1' | sed 's|/| |g' | awk '{print \$2;}')\"" >> /root/.config/wryn/env.zsh \
|
||||||
&& echo "source /root/.wryn/zsh/plugins/scwrypts/scwrypts.plugin.zsh" >> /root/.config/wryn/env.zsh \
|
&& echo "source /root/.wryn/zsh/plugins/scwrypts/scwrypts.plugin.zsh" >> /root/.config/wryn/env.zsh \
|
||||||
&& rm /root/dotwryn-install.log \
|
|
||||||
&& scwrypts --name scwrypts/virtualenv/update-all --group scwrypts --type zsh \
|
|
||||||
;
|
;
|
||||||
|
|
||||||
ENTRYPOINT ["/root/.wryn/.docker/entrypoint"]
|
ENTRYPOINT ["/root/.wryn/.docker/entrypoint"]
|
||||||
|
|||||||
@@ -1,170 +0,0 @@
|
|||||||
setup.config() {
|
|
||||||
echo.status 'starting application configuration'
|
|
||||||
|
|
||||||
setup.config._.generate-initial-local-config
|
|
||||||
|
|
||||||
setup.config._.zsh || return 2
|
|
||||||
setup.config._.vim || return 3
|
|
||||||
|
|
||||||
setup.config._.system || return 4
|
|
||||||
|
|
||||||
SCWRYPTS generate i3 config || return 5
|
|
||||||
|
|
||||||
echo.success 'finished application configuration'
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
setup.config._.generate-initial-local-config() {
|
|
||||||
local local_hostname="$(hostnamectl --static 2>/dev/null || hostname 2>/dev/null | sed 's/\.local$//')"
|
|
||||||
[ "${local_hostname}" ] || return 0
|
|
||||||
|
|
||||||
mkdir -p "${DOTWRYN_PATH}/bin/${local_hostname}"
|
|
||||||
|
|
||||||
local env_dir="${DOTWRYN_PATH}/config/scwrypts/environments"
|
|
||||||
local group
|
|
||||||
for group in $(find "${env_dir}" -type f -name \*env.yaml | sed -n 's|.*/local\.\([^.]*\)\.env\.yaml|\1|p')
|
|
||||||
do
|
|
||||||
[ -f "${env_dir}/local.${local_hostname}.${group}.env.yaml" ] && continue
|
|
||||||
|
|
||||||
if [ -f "${env_dir}/local.altaria.${group}.env.yaml" ]
|
|
||||||
then
|
|
||||||
cp "${env_dir}/local.altaria.${group}.env.yaml" "${env_dir}/local.${local_hostname}.${group}.env.yaml"
|
|
||||||
else
|
|
||||||
cp "${env_dir}/local.${group}.env.yaml" "${env_dir}/local.${local_hostname}.${group}.env.yaml"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
unset group
|
|
||||||
|
|
||||||
local local_override
|
|
||||||
for local_override in \
|
|
||||||
i3/local.yaml \
|
|
||||||
polybar/local.ini \
|
|
||||||
alacritty/local.toml \
|
|
||||||
;
|
|
||||||
do
|
|
||||||
mkdir -p -- "${DOTWRYN_PATH}/config/${local_hostname}/user/$(dirname -- "${local_override}")"
|
|
||||||
touch -- "${DOTWRYN_PATH}/config/${local_hostname}/user/${local_override}"
|
|
||||||
done
|
|
||||||
unset local_override
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
setup.config._.zsh() {
|
|
||||||
setup.config._.env zsh || return 1
|
|
||||||
setup.config._.rc zsh || return 2
|
|
||||||
setup.config._.set-default-shell || return 3
|
|
||||||
}
|
|
||||||
|
|
||||||
setup.config._.set-default-shell() {
|
|
||||||
local default_shell="$(awk -F: -v user="${USER}" '$1 == user {print $NF}' /etc/passwd)"
|
|
||||||
[[ "${default_shell}" =~ zsh ]] && return 0
|
|
||||||
|
|
||||||
[[ "${FORCE_ROOT}" == true ]] && return 0
|
|
||||||
|
|
||||||
echo.status 'setting zsh as default shell'
|
|
||||||
sudo chsh -s "$(which zsh)" "$(whoami)" 2>&1 \
|
|
||||||
&& echo.success "set zsh as default shell for '${USER}'" \
|
|
||||||
|| utils.fail 1 'failed to set zsh as default shell' \
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
setup.config._.vim() {
|
|
||||||
setup.config._.rc vim || return 1
|
|
||||||
|
|
||||||
echo.status 'starting vim setup'
|
|
||||||
SCWRYPTS dotwryn vundle update || return 2
|
|
||||||
|
|
||||||
setup.config._.vim.link-superuser-rc
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
setup.config._.vim.link-superuser-rc() {
|
|
||||||
sudo [ -f /root/.vimrc ] && return 0
|
|
||||||
|
|
||||||
echo "let \$DOTWRYN=\"${DOTWRYN_PATH}\"\nsource \"${DOTWRYN_PATH}/vim/rc.vim\"" \
|
|
||||||
| sudo tee /root/.vimrc >/dev/null
|
|
||||||
|
|
||||||
sudo mkdir -p /root/.vim
|
|
||||||
sudo ln -s "${HOME}/.vim/bundle" /root/.vim/bundle
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
setup.config._.system() {
|
|
||||||
SCWRYPTS dotwryn system setup
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
setup.config._.env() {
|
|
||||||
local config_type="${1}"
|
|
||||||
local default_config="${DOTWRYN_PATH}/${config_type}/env.${config_type}"
|
|
||||||
local local_config="${HOME}/.config/wryn/env.${config_type}"
|
|
||||||
|
|
||||||
[ -f "${local_config}" ] && {
|
|
||||||
case "${OVERWRITE_EXISTING}" in
|
|
||||||
( false ) return 0 ;;
|
|
||||||
( true )
|
|
||||||
echo.warning "local ${config_type} configuration exists (${local_config})"
|
|
||||||
utils.yN 'overwrite this configuration?' || return 0
|
|
||||||
|
|
||||||
mv "${local_config}" "${local_config}.bak" >/dev/null 2>&1 \
|
|
||||||
&& echo.status "created backup of local configuration (${local_config}.bak)"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
echo.status "setting up ${config_type} configuration (${local_config})"
|
|
||||||
|
|
||||||
local comment
|
|
||||||
case "${config_type}" in
|
|
||||||
( zsh ) comment='#' ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
{
|
|
||||||
echo "source ${default_config}"
|
|
||||||
echo -e "\\n${comment}\n${comment} .wryn configuration overrides\n${comment}\n"
|
|
||||||
sed "s/^[^${comment}].*/${comment}&/" "${default_config}"
|
|
||||||
} > "${local_config}" \
|
|
||||||
&& echo.success "created ${config_type} configuration" \
|
|
||||||
|| utils.fail 1 "unable to create ${config_type} configuration" \
|
|
||||||
;
|
|
||||||
|
|
||||||
EDITOR=vim VISUAL=vim utils.io.edit "${local_config}"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
setup.config._.rc() {
|
|
||||||
local config_type="${1}"
|
|
||||||
local rc
|
|
||||||
case "${config_type}" in
|
|
||||||
( vim )
|
|
||||||
rc="${XDG_CONFIG_HOME:-${HOME}/.config}/vim/vimrc"
|
|
||||||
mkdir -p -- "$(dirname -- "${rc}")"
|
|
||||||
[ -f "${HOME}/.vimrc" ] \
|
|
||||||
&& cat "${HOME}/.vimrc" >> "${XDG_CONFIG_HOME:-${HOME}/.config}/vim/vimrc" \
|
|
||||||
&& rm "${HOME}/.vimrc" \
|
|
||||||
;
|
|
||||||
;;
|
|
||||||
( * ) rc="${HOME}/.${config_type}rc" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
local source_line
|
|
||||||
case "${config_type}" in
|
|
||||||
( zsh ) source_line="source ${DOTWRYN_PATH}/zsh/rc" ;;
|
|
||||||
( vim ) source_line="source ${DOTWRYN_PATH}/vim/rc.vim" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
grep -q "^${source_line}$" "${rc}" \
|
|
||||||
|| echo "${source_line}" >> "${rc}"
|
|
||||||
|
|
||||||
grep -q "^${source_line}$" "${rc}" \
|
|
||||||
&& echo.success "${config_type}rc is configured correctly" \
|
|
||||||
|| utils.fail 1 "failed to configure ${config_type}rc" \
|
|
||||||
;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#####################################################################
|
||||||
|
|
||||||
|
for setup_library in "${0:a:h}"/*.zsh
|
||||||
|
do
|
||||||
|
case "${setup_library:t}" in
|
||||||
|
( config.module.zsh ) ;; # self
|
||||||
|
( * ) source "${setup_library}" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
unset setup_library
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
setup.config() { : \
|
||||||
|
&& echo.status 'starting application configuration' \
|
||||||
|
&& : \
|
||||||
|
&& setup.config.generate-initial-local-config \
|
||||||
|
&& setup.config.zsh \
|
||||||
|
&& setup.config.vim \
|
||||||
|
&& setup.scwrypts dotwryn system setup \
|
||||||
|
&& setup.scwrypts generate i3 config \
|
||||||
|
&& : \
|
||||||
|
&& echo.success 'finished application configuration' \
|
||||||
|
|| echo.error 'application configuration failed (see above)' \
|
||||||
|
; }
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#####################################################################
|
||||||
|
|
||||||
|
setup.config.env() {
|
||||||
|
local config_type="${1}"
|
||||||
|
local default_config="${DOTWRYN_SETUP__DOTWRYN}/${config_type}/env.${config_type}"
|
||||||
|
local local_config="${HOME}/.config/wryn/env.${config_type}"
|
||||||
|
|
||||||
|
if [[ -f "${local_config}" ]]
|
||||||
|
then
|
||||||
|
case "${DOTWRYN_SETUP__OVERWRITE_EXISTING}" in
|
||||||
|
( false ) return 0 ;;
|
||||||
|
( true )
|
||||||
|
echo.warning "local ${config_type} configuration exists (${local_config})"
|
||||||
|
utils.yN 'overwrite this configuration?' || return 0
|
||||||
|
|
||||||
|
mv -- "${local_config}" "${local_config}.bak" &>/dev/null \
|
||||||
|
&& echo.status "created backup of local configuration (${local_config}.bak)"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo.status "setting up ${config_type} configuration (${local_config})"
|
||||||
|
|
||||||
|
local comment='#'
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "source ${default_config}"
|
||||||
|
echo -e "\\n${comment}\n${comment} .wryn configuration overrides\n${comment}\n"
|
||||||
|
sed "s/^[^${comment}].*/${comment}&/" "${default_config}"
|
||||||
|
} > "${local_config}" \
|
||||||
|
&& echo.success "created ${config_type} configuration" \
|
||||||
|
|| echo.error "unable to create ${config_type} configuration" \
|
||||||
|
|| return 1
|
||||||
|
|
||||||
|
EDITOR=vim VISUAL=vim utils.io.edit "${local_config}"
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#####################################################################
|
||||||
|
|
||||||
|
setup.config.generate-initial-local-config() {
|
||||||
|
local local_hostname="$(hostnamectl --static 2>/dev/null || hostname 2>/dev/null | sed 's/\.local$//')"
|
||||||
|
[[ "${local_hostname}" ]] || return 0
|
||||||
|
|
||||||
|
mkdir -p -- "${DOTWRYN_SETUP__DOTWRYN}/config/local/${local_hostname}/bin"
|
||||||
|
|
||||||
|
local env_dir="${DOTWRYN_SETUP__DOTWRYN}/config/scwrypts/environments"
|
||||||
|
local group
|
||||||
|
for group in $(find "${env_dir}" -type f -name \*env.yaml | sed -n 's|.*/local\.\([^.]*\)\.env\.yaml|\1|p')
|
||||||
|
do
|
||||||
|
[[ -f "${env_dir}/local.${local_hostname}.${group}.env.yaml" ]] && continue
|
||||||
|
|
||||||
|
cp -- "${env_dir}/local.${group}.env.yaml" "${env_dir}/local.${local_hostname}.${group}.env.yaml"
|
||||||
|
done
|
||||||
|
unset group
|
||||||
|
|
||||||
|
local local_override
|
||||||
|
for local_override in \
|
||||||
|
i3/local.yaml \
|
||||||
|
polybar/local.ini \
|
||||||
|
alacritty/local.toml \
|
||||||
|
;
|
||||||
|
do
|
||||||
|
mkdir -p -- "${DOTWRYN_SETUP__DOTWRYN}/config/local/${local_hostname}/user/$(dirname -- "${local_override}")"
|
||||||
|
touch -- "${DOTWRYN_SETUP__DOTWRYN}/config/local/${local_hostname}/user/${local_override}"
|
||||||
|
done
|
||||||
|
unset local_override
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#####################################################################
|
||||||
|
|
||||||
|
setup.config.rc() {
|
||||||
|
local config_type="${1}"
|
||||||
|
local rc
|
||||||
|
case "${config_type}" in
|
||||||
|
( vim )
|
||||||
|
rc="${XDG_CONFIG_HOME:-${HOME}/.config}/vim/vimrc"
|
||||||
|
mkdir -p -- "$(dirname -- "${rc}")"
|
||||||
|
[[ -f "${HOME}/.vimrc" ]] \
|
||||||
|
&& cat "${HOME}/.vimrc" >> "${rc}" \
|
||||||
|
&& rm -- "${HOME}/.vimrc" \
|
||||||
|
;
|
||||||
|
;;
|
||||||
|
( * ) rc="${HOME}/.${config_type}rc" ;;
|
||||||
|
esac
|
||||||
|
touch -- "${rc}"
|
||||||
|
|
||||||
|
local source_line comment
|
||||||
|
case "${config_type}" in
|
||||||
|
( zsh )
|
||||||
|
source_line="source ${DOTWRYN_SETUP__DOTWRYN}/zsh/rc"
|
||||||
|
comment='#'
|
||||||
|
;;
|
||||||
|
( vim )
|
||||||
|
source_line="source ${DOTWRYN_SETUP__DOTWRYN}/vim/rc.vim"
|
||||||
|
comment='"'
|
||||||
|
;;
|
||||||
|
( * )
|
||||||
|
echo.error "no rc source-line defined for '${config_type}'"
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
setup.filesystem.write-managed-block "${rc}" --comment "${comment}" --tag dotwryn-rc --one-line <<-EOF
|
||||||
|
${source_line}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
grep -qF -- "${source_line}" "${rc}" \
|
||||||
|
&& echo.success "${config_type}rc is configured correctly" \
|
||||||
|
|| echo.error "failed to configure ${config_type}rc" \
|
||||||
|
|| return 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#####################################################################
|
||||||
|
|
||||||
|
setup.config.vim() { : \
|
||||||
|
&& echo.status 'configuring vim rc' \
|
||||||
|
&& setup.config.rc vim \
|
||||||
|
&& : \
|
||||||
|
&& echo.status 'starting vim setup' \
|
||||||
|
&& setup.scwrypts dotwryn vundle update \
|
||||||
|
&& setup.config.vim._.link-superuser-rc \
|
||||||
|
; }
|
||||||
|
|
||||||
|
setup.config.vim._.link-superuser-rc() {
|
||||||
|
# already root (a container build) needs no sudo, and a machine
|
||||||
|
# without sudo at all can't get one
|
||||||
|
local sudo=sudo
|
||||||
|
[[ "${EUID}" -eq 0 ]] && sudo=''
|
||||||
|
[[ -n "${sudo}" ]] && ! command -v sudo &>/dev/null \
|
||||||
|
&& echo.warning 'sudo unavailable; skipping superuser vimrc' \
|
||||||
|
&& return 0
|
||||||
|
|
||||||
|
${sudo} test -f /root/.vimrc && return 0
|
||||||
|
|
||||||
|
echo "let \$DOTWRYN=\"${DOTWRYN_SETUP__DOTWRYN}\"\nsource \"${DOTWRYN_SETUP__DOTWRYN}/vim/rc.vim\"" \
|
||||||
|
| ${sudo} tee /root/.vimrc >/dev/null
|
||||||
|
|
||||||
|
${sudo} mkdir -p -- /root/.vim
|
||||||
|
${sudo} ln -s -- "${HOME}/.vim/bundle" /root/.vim/bundle
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#####################################################################
|
||||||
|
|
||||||
|
setup.config.zsh() { : \
|
||||||
|
&& setup.config.env zsh \
|
||||||
|
&& setup.config.rc zsh \
|
||||||
|
&& setup.config._.set-default-shell \
|
||||||
|
; }
|
||||||
|
|
||||||
|
setup.config._.set-default-shell() {
|
||||||
|
local default_shell="$(awk -F: -v user="${USER}" '$1 == user {print $NF}' /etc/passwd)"
|
||||||
|
[[ "${default_shell}" =~ zsh ]] && return 0
|
||||||
|
|
||||||
|
[[ "${DOTWRYN_SETUP__FORCE_ROOT}" == true ]] && return 0
|
||||||
|
|
||||||
|
: \
|
||||||
|
&& echo.status 'setting zsh as default shell' \
|
||||||
|
&& sudo chsh -s "$(command -v zsh)" "${USER}" 2>&1 \
|
||||||
|
&& echo.success "set zsh as default shell for '${USER}'" \
|
||||||
|
|| echo.error 'failed to set zsh as default shell' \
|
||||||
|
|| return 1 \
|
||||||
|
;
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
#####################################################################
|
||||||
|
|
||||||
|
setup.filesystem.ensure-paths() {
|
||||||
|
local ERRORS=0
|
||||||
|
local directories=(
|
||||||
|
"${XDG_CONFIG_HOME:-${HOME}/.config}/wryn"
|
||||||
|
"${HOME}/.local/bin"
|
||||||
|
)
|
||||||
|
|
||||||
|
local files=(
|
||||||
|
"${HOME}/.zshrc"
|
||||||
|
)
|
||||||
|
|
||||||
|
echo.status 'ensuring required paths exist'
|
||||||
|
local directory
|
||||||
|
for directory in "${directories[@]}"
|
||||||
|
do
|
||||||
|
mkdir -p -- "${directory}" || echo.error "failed to create directory '${directory}'"
|
||||||
|
done
|
||||||
|
unset directory
|
||||||
|
|
||||||
|
local file
|
||||||
|
for file in "${files[@]}"
|
||||||
|
do
|
||||||
|
touch -- "${file}" || echo.error "failed to create file '${file}'"
|
||||||
|
done
|
||||||
|
unset file
|
||||||
|
|
||||||
|
[[ "${ERRORS}" -eq 0 ]] \
|
||||||
|
&& echo.success 'required paths ready' \
|
||||||
|
|| echo.error 'failed to ensure required paths' \
|
||||||
|
;
|
||||||
|
|
||||||
|
return "${ERRORS}"
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#####################################################################
|
||||||
|
|
||||||
|
for setup_library in "${0:a:h}"/*.zsh
|
||||||
|
do
|
||||||
|
case "${setup_library:t}" in
|
||||||
|
( filesystem.module.zsh ) ;; # self
|
||||||
|
( * ) source "${setup_library}" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
unset setup_library
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
setup.filesystem() { : \
|
||||||
|
&& setup.filesystem.ensure-paths \
|
||||||
|
&& setup.filesystem.git \
|
||||||
|
; }
|
||||||
@@ -1,41 +1,42 @@
|
|||||||
#####################################################################
|
#####################################################################
|
||||||
|
|
||||||
setup.git() {
|
setup.filesystem.git() {
|
||||||
local sources_dir="${XDG_DATA_HOME:-${HOME}/.local/share}/project-source-code"
|
local sources_dir="${XDG_DATA_HOME:-${HOME}/.local/share}/project-source-code"
|
||||||
|
|
||||||
SOURCE_DIR="${DOTWRYN_PATH}" \
|
SOURCE_DIR="${DOTWRYN_SETUP__DOTWRYN}" \
|
||||||
TARGET_DIR="${sources_dir}/yage/dotwryn" \
|
TARGET_DIR="${sources_dir}/yage/dotwryn" \
|
||||||
REMOTE_UPSTREAMS=(
|
REMOTE_UPSTREAMS=(
|
||||||
'git@github.com:wrynegade/dotwryn.git'
|
'git@github.com:wrynegade/dotwryn.git'
|
||||||
'git@yage.io:wrynegade/dotwryn.git'
|
'git@yage.io:wrynegade/dotwryn.git'
|
||||||
'git@bitbucket.org:wrynegade/dotwryn.git'
|
'git@bitbucket.org:wrynegade/dotwryn.git'
|
||||||
) setup.git._.remotes '.wryn'
|
) setup.filesystem.git._.remotes '.wryn'
|
||||||
|
|
||||||
SOURCE_DIR="${DOTWRYN_PATH}/zsh/plugins/code-activator" \
|
SOURCE_DIR="${DOTWRYN_SETUP__DOTWRYN}/zsh/plugins/code-activator" \
|
||||||
TARGET_DIR="${sources_dir}/zsh/code-activator" \
|
TARGET_DIR="${sources_dir}/zsh/code-activator" \
|
||||||
REMOTE_UPSTREAMS=(
|
REMOTE_UPSTREAMS=(
|
||||||
'git@yage.io:zsh/code-activator.git'
|
'git@yage.io:zsh/code-activator.git'
|
||||||
'git@github.com:wrynegade/code-activator.git'
|
'git@github.com:wrynegade/code-activator.git'
|
||||||
) setup.git._.remotes 'zsh-plugins/code-activator'
|
) setup.filesystem.git._.remotes 'zsh-plugins/code-activator'
|
||||||
|
|
||||||
SOURCE_DIR="${DOTWRYN_PATH}/zsh/plugins/scwrypts" \
|
SOURCE_DIR="${DOTWRYN_SETUP__DOTWRYN}/zsh/plugins/scwrypts" \
|
||||||
TARGET_DIR="${sources_dir}/zsh/scwrypts" \
|
TARGET_DIR="${sources_dir}/zsh/scwrypts" \
|
||||||
REMOTE_UPSTREAMS=(
|
REMOTE_UPSTREAMS=(
|
||||||
'git@yage.io:zsh/scwrypts'
|
'git@yage.io:zsh/scwrypts'
|
||||||
'git@github.com:wrynegade/scwrypts'
|
'git@github.com:wrynegade/scwrypts'
|
||||||
) setup.git._.remotes 'zsh-plugins/scwrypts'
|
) setup.filesystem.git._.remotes 'zsh-plugins/scwrypts'
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
setup.git._.remotes() {
|
setup.filesystem.git._.remotes() {
|
||||||
: \
|
: \
|
||||||
&& [ "${SOURCE_DIR}" ] \
|
&& [[ "${SOURCE_DIR}" ]] \
|
||||||
&& [ "${TARGET_DIR}" ] \
|
&& [[ "${TARGET_DIR}" ]] \
|
||||||
&& [[ ${#REMOTE_UPSTREAMS[@]} -gt 0 ]] \
|
&& [[ "${#REMOTE_UPSTREAMS[@]}" -gt 0 ]] \
|
||||||
|| return 1
|
|| return 1 \
|
||||||
|
;
|
||||||
|
|
||||||
[ "$1" ] && echo.status "updating remotes for '$1'"
|
[[ "${1}" ]] && echo.status "updating remotes for '${1}'"
|
||||||
|
|
||||||
git -C "${SOURCE_DIR}" remote rm upstream 2>/dev/null
|
git -C "${SOURCE_DIR}" remote rm upstream 2>/dev/null
|
||||||
git -C "${SOURCE_DIR}" remote add upstream "${REMOTE_UPSTREAMS[1]}"
|
git -C "${SOURCE_DIR}" remote add upstream "${REMOTE_UPSTREAMS[1]}"
|
||||||
@@ -62,19 +63,19 @@ setup.git._.remotes() {
|
|||||||
done
|
done
|
||||||
unset remote_upstream
|
unset remote_upstream
|
||||||
|
|
||||||
SOURCE_DIR="${SOURCE_DIR}" TARGET_DIR="${TARGET_DIR}" setup.git._.link-to-projects \
|
SOURCE_DIR="${SOURCE_DIR}" TARGET_DIR="${TARGET_DIR}" setup.filesystem.git._.link-to-projects \
|
||||||
|| echo.warning "failed to link '${TARGET_DIR}'"
|
|| echo.warning "failed to link '${TARGET_DIR}'"
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
setup.git._.link-to-projects() {
|
setup.filesystem.git._.link-to-projects() {
|
||||||
[ "${TARGET_DIR}" ] && [ "${SOURCE_DIR}" ] \
|
[[ "${TARGET_DIR}" ]] && [[ "${SOURCE_DIR}" ]] \
|
||||||
|| return 1
|
|| return 1
|
||||||
|
|
||||||
{
|
{
|
||||||
mkdir -p "${TARGET_DIR}"
|
mkdir -p -- "${TARGET_DIR}"
|
||||||
rm "${TARGET_DIR}/code"
|
rm -- "${TARGET_DIR}/code"
|
||||||
ln -s "${SOURCE_DIR}" "${TARGET_DIR}/code"
|
ln -s -- "${SOURCE_DIR}" "${TARGET_DIR}/code"
|
||||||
} &>/dev/null
|
} &>/dev/null
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
#####################################################################
|
||||||
|
|
||||||
|
setup.filesystem.write-managed-block() {
|
||||||
|
# replaces (or appends) a dotwryn-managed block in a file, taking the
|
||||||
|
# block body from stdin, so that every run refreshes the block rather
|
||||||
|
# than appending another copy of it
|
||||||
|
#
|
||||||
|
# callers should use a "<<-" heredoc: it strips leading TABS (letting
|
||||||
|
# the body stay indented with its caller) but leaves SPACES alone, so
|
||||||
|
# indent the block's own nesting with spaces to keep it in the output
|
||||||
|
#
|
||||||
|
# "--one-line" trades the begin/end banner for a trailing comment on
|
||||||
|
# the line itself, which suits a one-line entry like an rc source
|
||||||
|
local file tag
|
||||||
|
local comment='#'
|
||||||
|
local one_line=false
|
||||||
|
|
||||||
|
local _s _p
|
||||||
|
while [[ "${#}" -gt 0 ]]
|
||||||
|
do
|
||||||
|
_s=1
|
||||||
|
case "${1}" in
|
||||||
|
( --comment ) _s=2
|
||||||
|
comment="${2}"
|
||||||
|
;;
|
||||||
|
( --tag ) _s=2
|
||||||
|
tag="${2}"
|
||||||
|
;;
|
||||||
|
( --one-line )
|
||||||
|
one_line=true
|
||||||
|
;;
|
||||||
|
( * )
|
||||||
|
case "$((_p+=1))" in
|
||||||
|
( 1 ) file="${1}" ;;
|
||||||
|
( * ) echo.error "write-managed-block: unexpected argument '${1}'" ;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift "${_s}"
|
||||||
|
done
|
||||||
|
unset _s _p
|
||||||
|
|
||||||
|
[[ "${file}" ]] \
|
||||||
|
|| echo.error 'write-managed-block: no file given' \
|
||||||
|
|| return 1
|
||||||
|
|
||||||
|
# a single file can carry several managed blocks, so each one has to be
|
||||||
|
# named to know which of them it owns
|
||||||
|
[[ "${tag}" ]] \
|
||||||
|
|| echo.error "write-managed-block: no --tag given for '${file}'" \
|
||||||
|
|| return 1
|
||||||
|
|
||||||
|
local body="$(cat)"
|
||||||
|
|
||||||
|
[[ "${one_line}" == false ]] || [[ "${body}" != *$'\n'* ]] \
|
||||||
|
|| echo.error "write-managed-block: --one-line needs a single-line body for '${file}'" \
|
||||||
|
|| return 1
|
||||||
|
|
||||||
|
mkdir -p -- "${file:h}"
|
||||||
|
touch -- "${file}"
|
||||||
|
|
||||||
|
local -a lines block
|
||||||
|
lines=("${(@f)$(<"${file}")}")
|
||||||
|
[[ -s "${file}" ]] || lines=()
|
||||||
|
|
||||||
|
# an existing block is replaced where it sits, so anything the user
|
||||||
|
# wrote around it keeps its position
|
||||||
|
local begin_index end_index
|
||||||
|
case "${one_line}" in
|
||||||
|
( true )
|
||||||
|
local marker="${comment} managed by dotwryn setup (${tag})"
|
||||||
|
block=("${body} ${marker}")
|
||||||
|
|
||||||
|
# "(b)" keeps the tag's parentheses literal rather than glob
|
||||||
|
begin_index="${lines[(i)*${(b)marker}]}"
|
||||||
|
end_index="${begin_index}"
|
||||||
|
;;
|
||||||
|
( false )
|
||||||
|
local begin="${comment} >>> managed by dotwryn setup (${tag}) >>>"
|
||||||
|
local end="${comment} <<< managed by dotwryn setup (${tag}) <<<"
|
||||||
|
block=("${begin}" "${(@f)body}" "${end}")
|
||||||
|
|
||||||
|
begin_index="${lines[(ie)${begin}]}"
|
||||||
|
end_index="${lines[(ie)${end}]}"
|
||||||
|
[[ "${end_index}" -le "${#lines[@]}" ]] || end_index="${#lines[@]}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [[ "${begin_index}" -gt "${#lines[@]}" ]]
|
||||||
|
then
|
||||||
|
lines+=("${block[@]}")
|
||||||
|
else
|
||||||
|
lines=(
|
||||||
|
"${lines[@]:0:$((begin_index - 1))}"
|
||||||
|
"${block[@]}"
|
||||||
|
"${lines[@]:${end_index}}"
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
print -l -- "${lines[@]}" > "${file}"
|
||||||
|
}
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
base-devel
|
|
||||||
bat
|
|
||||||
cmake
|
|
||||||
cowsay
|
|
||||||
figlet
|
|
||||||
fzf
|
|
||||||
go-yq
|
|
||||||
htop
|
|
||||||
jo
|
|
||||||
jq
|
|
||||||
lolcat
|
|
||||||
ncurses
|
|
||||||
python
|
|
||||||
ripgrep
|
|
||||||
scwrypts
|
|
||||||
tmux
|
|
||||||
vim
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
1password
|
|
||||||
1password-cli
|
|
||||||
alacritty
|
|
||||||
arch-install-scripts
|
|
||||||
aws-cli-v2
|
|
||||||
base-devel
|
|
||||||
bat
|
|
||||||
cmake
|
|
||||||
cowsay
|
|
||||||
feh
|
|
||||||
figlet
|
|
||||||
flameshot
|
|
||||||
fprintd
|
|
||||||
fzf
|
|
||||||
go
|
|
||||||
go-yq
|
|
||||||
google-chrome
|
|
||||||
htop
|
|
||||||
i3-wm
|
|
||||||
jdk-openjdk
|
|
||||||
jo
|
|
||||||
jq
|
|
||||||
lolcat
|
|
||||||
lxappearance
|
|
||||||
mono
|
|
||||||
ncurses
|
|
||||||
fastfetch
|
|
||||||
nodejs
|
|
||||||
noto-fonts-emoji
|
|
||||||
npm
|
|
||||||
ntp
|
|
||||||
obs-studio
|
|
||||||
openssh
|
|
||||||
otf-monaspace
|
|
||||||
pam-fprint-grosshack
|
|
||||||
picom
|
|
||||||
playerctl
|
|
||||||
polybar
|
|
||||||
python
|
|
||||||
python-pip
|
|
||||||
python-pylint
|
|
||||||
python-rtmidi
|
|
||||||
python-virtualenv
|
|
||||||
rage-encryption
|
|
||||||
ripgrep
|
|
||||||
rofi
|
|
||||||
rustup
|
|
||||||
scwrypts
|
|
||||||
sudo
|
|
||||||
tmux
|
|
||||||
ttf-nerd-fonts-symbols
|
|
||||||
unipicker
|
|
||||||
vi
|
|
||||||
vim
|
|
||||||
vim-runtime
|
|
||||||
which
|
|
||||||
xclip
|
|
||||||
xdotool
|
|
||||||
yamllint
|
|
||||||
zip
|
|
||||||
zsh
|
|
||||||
zsh-completions
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
bsdextrautils
|
|
||||||
build-essential
|
|
||||||
cmake
|
|
||||||
cowsay
|
|
||||||
figlet
|
|
||||||
fzf
|
|
||||||
jo
|
|
||||||
jq
|
|
||||||
ncurses-dev
|
|
||||||
ripgrep
|
|
||||||
tmux
|
|
||||||
uuid-runtime
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
awscli
|
|
||||||
bsdextrautils
|
|
||||||
build-essential
|
|
||||||
cmake
|
|
||||||
cowsay
|
|
||||||
default-jdk
|
|
||||||
figlet
|
|
||||||
fzf
|
|
||||||
golang
|
|
||||||
jo
|
|
||||||
jq
|
|
||||||
lolcat
|
|
||||||
mono-devel
|
|
||||||
ncurses-dev
|
|
||||||
nodejs
|
|
||||||
npm
|
|
||||||
python3-dev
|
|
||||||
ripgrep
|
|
||||||
tmux
|
|
||||||
uuid-runtime
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
bat
|
|
||||||
cmake
|
|
||||||
cowsay
|
|
||||||
figlet
|
|
||||||
fzf
|
|
||||||
htop
|
|
||||||
jo
|
|
||||||
jq
|
|
||||||
lolcat
|
|
||||||
ncurses
|
|
||||||
python3-devel
|
|
||||||
ripgrep
|
|
||||||
tmux
|
|
||||||
vim-enhanced
|
|
||||||
yq
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
autoconf
|
|
||||||
automake
|
|
||||||
bat
|
|
||||||
binutils
|
|
||||||
bison
|
|
||||||
cmake
|
|
||||||
containerd.io
|
|
||||||
cowsay
|
|
||||||
docker-ce
|
|
||||||
docker-ce-cli
|
|
||||||
feh
|
|
||||||
figlet
|
|
||||||
file
|
|
||||||
findutils
|
|
||||||
flex
|
|
||||||
fzf
|
|
||||||
gcc
|
|
||||||
gcc-c++
|
|
||||||
gettext
|
|
||||||
gnupg2
|
|
||||||
go
|
|
||||||
htop
|
|
||||||
java-latest-openjdk
|
|
||||||
jo
|
|
||||||
jq
|
|
||||||
libtool
|
|
||||||
lolcat
|
|
||||||
mono-complete
|
|
||||||
ncurses
|
|
||||||
fastfetch
|
|
||||||
nodejs
|
|
||||||
npm
|
|
||||||
openssh
|
|
||||||
patch
|
|
||||||
pkg-config
|
|
||||||
python3-devel
|
|
||||||
python3-pip
|
|
||||||
python3-pylint
|
|
||||||
python3-virtualenv
|
|
||||||
redis
|
|
||||||
ripgrep
|
|
||||||
rust
|
|
||||||
sed
|
|
||||||
sudo
|
|
||||||
tmux
|
|
||||||
vi
|
|
||||||
vim-enhanced
|
|
||||||
yamllint
|
|
||||||
yq
|
|
||||||
zip
|
|
||||||
zsh
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
aws
|
|
||||||
cmake
|
|
||||||
cowsay
|
|
||||||
figlet
|
|
||||||
fzf
|
|
||||||
go
|
|
||||||
java
|
|
||||||
jo
|
|
||||||
jq
|
|
||||||
lolcat
|
|
||||||
ncurses
|
|
||||||
node
|
|
||||||
npm
|
|
||||||
python3
|
|
||||||
rg
|
|
||||||
tmux
|
|
||||||
xbuild
|
|
||||||
yq
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
bat
|
|
||||||
cmake
|
|
||||||
cowsay
|
|
||||||
figlet
|
|
||||||
fzf
|
|
||||||
htop
|
|
||||||
jo
|
|
||||||
jq
|
|
||||||
lolcat
|
|
||||||
ncurses
|
|
||||||
python
|
|
||||||
ripgrep
|
|
||||||
tmux
|
|
||||||
vim
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
autoconf
|
|
||||||
automake
|
|
||||||
bat
|
|
||||||
binutils
|
|
||||||
bison
|
|
||||||
cmake
|
|
||||||
coreutils
|
|
||||||
cowsay
|
|
||||||
fastfetch
|
|
||||||
feh
|
|
||||||
figlet
|
|
||||||
findutils
|
|
||||||
flex
|
|
||||||
fzf
|
|
||||||
gawk
|
|
||||||
gcc
|
|
||||||
gettext
|
|
||||||
go
|
|
||||||
gpatch
|
|
||||||
gpg
|
|
||||||
grep
|
|
||||||
gsed
|
|
||||||
htop
|
|
||||||
iproute2mac
|
|
||||||
jo
|
|
||||||
jq
|
|
||||||
libtool
|
|
||||||
lolcat
|
|
||||||
mono
|
|
||||||
ncurses
|
|
||||||
node
|
|
||||||
npm
|
|
||||||
openjdk
|
|
||||||
openssh
|
|
||||||
pkg-config
|
|
||||||
pylint
|
|
||||||
python
|
|
||||||
python-setuptools
|
|
||||||
redis
|
|
||||||
ripgrep
|
|
||||||
rust
|
|
||||||
tmux
|
|
||||||
vim
|
|
||||||
virtualenv
|
|
||||||
yamllint
|
|
||||||
yq
|
|
||||||
zip
|
|
||||||
zsh
|
|
||||||
-293
@@ -1,293 +0,0 @@
|
|||||||
#####################################################################
|
|
||||||
|
|
||||||
setup.os() {
|
|
||||||
setup.os._.make-required-resources || return 1
|
|
||||||
[[ "${CI}" == true ]] && { echo.status 'detected CI; skipping os setup'; return 0; }
|
|
||||||
utils.io.getsudo
|
|
||||||
|
|
||||||
local OS_NAME="$(setup.os._.get-os)"
|
|
||||||
[ ! "${OS_NAME}" ] && utils.abort
|
|
||||||
|
|
||||||
setup.os._.install-source-dependencies || return 2
|
|
||||||
setup.os._.install-managed-dependencies || return 3
|
|
||||||
}
|
|
||||||
|
|
||||||
setup.os._.get-os() {
|
|
||||||
local OS_NAME="$(lsb_release -is 2>/dev/null | tr '[:upper:]' '[:lower:]')"
|
|
||||||
|
|
||||||
[ ! "${OS_NAME}" ] \
|
|
||||||
&& OS_NAME="$(sed -n 's/^ID=//p' /etc/os-release 2>/dev/null)"
|
|
||||||
|
|
||||||
uname -s | grep -q Darwin \
|
|
||||||
&& OS_NAME=macos
|
|
||||||
|
|
||||||
[ ! "${OS_NAME}" ] \
|
|
||||||
&& echo.warning 'failed to detect operating system' \
|
|
||||||
&& OS_NAME="$(echo -e "arch\ndebian\nother" | utils.fzf 'select an operating system')" \
|
|
||||||
;
|
|
||||||
|
|
||||||
[[ "${OS_NAME}" =~ ^ubuntu$ ]] && OS_NAME=debian
|
|
||||||
|
|
||||||
[[ "${OS_NAME}" =~ ^[Ee]ndeavour[Oo][Ss]$ ]] && OS_NAME=arch
|
|
||||||
|
|
||||||
echo "${OS_NAME}"
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
setup.os._.install-from-source() { # clone + build/install a git-hosted package (AUR PKGBUILD or Makefile)
|
|
||||||
local target_url="${1}"
|
|
||||||
local name="${2:-$(echo "${target_url}" | sed 's/.*\///; s/\.git$//')}"
|
|
||||||
local install_dir="${HOME}/.local/share/source-packages"
|
|
||||||
mkdir -p "${install_dir}"
|
|
||||||
|
|
||||||
if [ -d "${install_dir}/${name}" ]
|
|
||||||
then
|
|
||||||
echo.status "updating '${name}'"
|
|
||||||
( cd "${install_dir}/${name}" && git pull origin "$(git rev-parse --abbrev-ref HEAD)" ) \
|
|
||||||
&& echo.success "successfully updated '${name}'" \
|
|
||||||
|| { echo.error "failed to update '${name}'"; return 1; }
|
|
||||||
else
|
|
||||||
echo.status "downloading '${name}'"
|
|
||||||
git clone "${target_url}" "${install_dir}/${name}" \
|
|
||||||
&& echo.success "successfully downloaded '${name}'" \
|
|
||||||
|| { echo.error "failed to download '${name}'"; return 2; }
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd "${install_dir}/${name}"
|
|
||||||
if [ -f ./PKGBUILD ]
|
|
||||||
then
|
|
||||||
echo.status "installing '${name}'"
|
|
||||||
yes | makepkg -si \
|
|
||||||
&& echo.success "successfully installed '${name}'" \
|
|
||||||
|| { echo.error "failed to install '${name}'"; return 3; }
|
|
||||||
elif [ -f ./Makefile ]
|
|
||||||
then
|
|
||||||
echo.status "building '${name}'"
|
|
||||||
make \
|
|
||||||
&& echo.success "finished building '${name}'" \
|
|
||||||
|| { echo.error "build failed for '${name}'"; return 4; }
|
|
||||||
|
|
||||||
echo.status "installing '${name}'"
|
|
||||||
utils.io.getsudo
|
|
||||||
sudo make install \
|
|
||||||
&& echo.success "successfully installed '${name}'" \
|
|
||||||
|| { echo.error "failed to install '${name}'"; return 5; }
|
|
||||||
else
|
|
||||||
echo.warning 'could not detect supported installation method'
|
|
||||||
echo.reminder "complete manual installation in the directory below:"
|
|
||||||
echo.reminder "${install_dir}/${name}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
setup.os._.install-source-dependencies() {
|
|
||||||
case "${OS_NAME}" in
|
|
||||||
( arch )
|
|
||||||
command -v yay >/dev/null 2>&1 \
|
|
||||||
|| setup.os._.install-from-source 'https://aur.archlinux.org/yay.git' 'yay' \
|
|
||||||
;
|
|
||||||
;;
|
|
||||||
|
|
||||||
( fedora ) ;;
|
|
||||||
|
|
||||||
( debian ) ;;
|
|
||||||
|
|
||||||
( macos )
|
|
||||||
xcode-select -p &>/dev/null || { # brew requires the xcode command line tools
|
|
||||||
echo.status 'installing xcode command line tools'
|
|
||||||
touch /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
|
|
||||||
local clt_package="$(softwareupdate -l | grep '\*.*Command Line' | tail -n1 | sed 's/^[^C]*\(C.*\)/\1/')"
|
|
||||||
sudo softwareupdate -i "${clt_package}" --verbose \
|
|
||||||
&& echo.success 'successfully installed xcode command line tools' \
|
|
||||||
|| echo.error 'failed to install xcode command line tools' \
|
|
||||||
;
|
|
||||||
rm -f /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
|
|
||||||
}
|
|
||||||
|
|
||||||
command -v brew &>/dev/null || {
|
|
||||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
||||||
eval "$(/opt/homebrew/bin/brew shellenv 2>/dev/null || /usr/local/bin/brew shellenv 2>/dev/null)"
|
|
||||||
}
|
|
||||||
;;
|
|
||||||
|
|
||||||
( * ) ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
[[ "${OS_NAME}" != macos ]] && [[ "${COMPILE_DMENU}" == true ]] \
|
|
||||||
&& setup.os._.install-from-source 'https://github.com/tiyn/dmenu' 'patched-dmenu'
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
setup.os._.install-managed-dependencies() {
|
|
||||||
local ERRORS=0
|
|
||||||
|
|
||||||
echo.status 'checking os dependencies'
|
|
||||||
case "${OS_NAME}" in
|
|
||||||
( arch | fedora | debian | macos )
|
|
||||||
;;
|
|
||||||
|
|
||||||
( * )
|
|
||||||
OS_NAME='generic'
|
|
||||||
echo.warning "no automated installer available for '${OS_NAME}'"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
local dependencies_file
|
|
||||||
[[ "${MIN}" == true ]] && [ -f "${DOTWRYN_PATH}/setup/os-dependencies/${OS_NAME}.min.txt" ] \
|
|
||||||
&& dependencies_file="${DOTWRYN_PATH}/setup/os-dependencies/${OS_NAME}.min.txt" \
|
|
||||||
|| dependencies_file="${DOTWRYN_PATH}/setup/os-dependencies/${OS_NAME}.txt" \
|
|
||||||
;
|
|
||||||
|
|
||||||
[[ "${CI}" != true ]] && {
|
|
||||||
echo.status 'updating system, repositories, and mirrors'
|
|
||||||
"setup.os._.update-repositories.${OS_NAME}"
|
|
||||||
}
|
|
||||||
|
|
||||||
local dependency
|
|
||||||
for dependency in $(cat "${dependencies_file}")
|
|
||||||
do
|
|
||||||
"setup.os._.install-managed.${OS_NAME}" "${dependency}"
|
|
||||||
done
|
|
||||||
unset dependency
|
|
||||||
|
|
||||||
[[ "${ERRORS}" -ne 0 ]] && {
|
|
||||||
echo.warning "detected ${ERRORS} errors; double check warnings before proceeding!"
|
|
||||||
utils.yN 'continue with install?' && return 0 || utils.abort
|
|
||||||
}
|
|
||||||
|
|
||||||
case "${OS_NAME}" in
|
|
||||||
( macos )
|
|
||||||
local shellenv_line='eval "$(/opt/homebrew/bin/brew shellenv 2>/dev/null || /usr/local/bin/brew shellenv 2>/dev/null)"'
|
|
||||||
grep -qF "${shellenv_line}" "${HOME}/.zprofile" 2>/dev/null \
|
|
||||||
|| echo "${shellenv_line}" >> "${HOME}/.zprofile"
|
|
||||||
|
|
||||||
local gnubin_path
|
|
||||||
for gnubin_path in "$(brew --prefix)"/opt/*/libexec/gnubin(N); do export PATH="${gnubin_path}:${PATH}"; done
|
|
||||||
unset gnubin_path
|
|
||||||
|
|
||||||
local gnubin_line='for P in "$(brew --prefix)"/opt/*/libexec/gnubin(N); do export PATH="${P}:${PATH}"; done'
|
|
||||||
grep -qF "${gnubin_line}" "${HOME}/.zprofile" 2>/dev/null \
|
|
||||||
|| echo "${gnubin_line}" >> "${HOME}/.zprofile"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
echo.success 'all dependencies satisfied'
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
##########################################
|
|
||||||
|
|
||||||
setup.os._.update-repositories.arch() { yay -Syu; }
|
|
||||||
setup.os._.install-managed.arch() {
|
|
||||||
local target="${1}"
|
|
||||||
[[ "${target}" =~ aws-cli-v2 ]] && {
|
|
||||||
echo.status "skipping aws-cli-v2 checks since they are bad right now"
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
yay -Qq 2>/dev/null | grep -q "^${target}$\|^${target}-git$" && {
|
|
||||||
echo.success "found '${target}'"
|
|
||||||
} || {
|
|
||||||
echo.status "installing '${target}'"
|
|
||||||
yay -Syu --noconfirm "${target}" \
|
|
||||||
&& echo.success "successfully installed '${target}'" \
|
|
||||||
|| echo.error "failed to install '${target}'" \
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
##########################################
|
|
||||||
|
|
||||||
setup.os._.update-repositories.debian() { sudo apt-get update && sudo apt-get upgrade; }
|
|
||||||
setup.os._.install-managed.debian() {
|
|
||||||
local target="${1}"
|
|
||||||
echo.status "checking / installing '${target}'"
|
|
||||||
sudo apt-get install --yes "${target}" \
|
|
||||||
&& echo.success "'${target}' installed" \
|
|
||||||
|| echo.error "failed to install ${target}" \
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
##########################################
|
|
||||||
|
|
||||||
setup.os._.update-repositories.fedora() {
|
|
||||||
: \
|
|
||||||
&& sudo dnf update \
|
|
||||||
&& sudo dnf upgrade \
|
|
||||||
&& sudo dnf install -y dnf-plugins-core \
|
|
||||||
&& sudo dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/fedora/docker-ce.repo \
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
setup.os._.install-managed.fedora() {
|
|
||||||
local target="${1}"
|
|
||||||
echo.status "checking / installing '${target}'"
|
|
||||||
sudo dnf install -y "${target}" \
|
|
||||||
&& echo.success "'${target}' installed" \
|
|
||||||
|| echo.error "failed to install ${target}" \
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
##########################################
|
|
||||||
|
|
||||||
setup.os._.update-repositories.macos() { brew update && brew upgrade; }
|
|
||||||
setup.os._.install-managed.macos() {
|
|
||||||
local target="${1}"
|
|
||||||
brew list --versions "${target}" &>/dev/null && {
|
|
||||||
echo.success "found '${target}'"
|
|
||||||
} || {
|
|
||||||
echo.status "installing '${target}'"
|
|
||||||
yes | brew install "${target}" \
|
|
||||||
&& echo.success "'${target}' installed" \
|
|
||||||
|| echo.error "failed to install ${target}" \
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
##########################################
|
|
||||||
|
|
||||||
setup.os._.update-repositories.generic() { return 0; }
|
|
||||||
setup.os._.install-managed.generic() {
|
|
||||||
local target="${1}"
|
|
||||||
command -v "${target}" >/dev/null 2>&1 \
|
|
||||||
|| echo.error "could not find '${target}'; it's up to you to install this one!"
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
setup.os._.make-required-resources() {
|
|
||||||
local ERRORS=0
|
|
||||||
local directories=(
|
|
||||||
"${XDG_CONFIG_HOME:-${HOME}/.config}/wryn"
|
|
||||||
"${HOME}/.local/bin"
|
|
||||||
)
|
|
||||||
|
|
||||||
local files=(
|
|
||||||
"${HOME}/.zshrc"
|
|
||||||
)
|
|
||||||
|
|
||||||
echo.status 'making required system resources'
|
|
||||||
local directory
|
|
||||||
for directory in "${directories[@]}"
|
|
||||||
do
|
|
||||||
[ ! -d "${directory}" ] && { mkdir -p "${directory}" || echo.error "failed to create directory '${directory}'"; }
|
|
||||||
done
|
|
||||||
unset directory
|
|
||||||
|
|
||||||
local file
|
|
||||||
for file in "${files[@]}"
|
|
||||||
do
|
|
||||||
[ ! -f "${file}" ] && { touch "${file}" || echo.error "failed to create file '${file}'"; }
|
|
||||||
done
|
|
||||||
unset file
|
|
||||||
|
|
||||||
[[ "${ERRORS}" -eq 0 ]] \
|
|
||||||
&& echo.success 'finished creating system resources' \
|
|
||||||
|| echo.error 'failed to create system resources' \
|
|
||||||
;
|
|
||||||
|
|
||||||
return "${ERRORS}"
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
#####################################################################
|
||||||
|
|
||||||
|
# current profiles:
|
||||||
|
# --extended (default) -> installs all my favorite tools
|
||||||
|
# --min -> only installs essentials (deemed by ME)
|
||||||
|
|
||||||
|
INSTALLED_BY__all=(--installed-by 'default,min,extended-macos-cask')
|
||||||
|
INSTALLED_BY__extended=(--installed-by 'default,extended-macos-cask')
|
||||||
|
INSTALLED_BY__extended_macos_cask=(--installed-by 'extended-macos-cask')
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
# base cross-platform tools
|
||||||
|
dependency_args=("${INSTALLED_BY__all[@]}")
|
||||||
|
|
||||||
|
dependency --no-executable binutils
|
||||||
|
dependency --no-executable coreutils
|
||||||
|
dependency --no-executable findutils
|
||||||
|
dependency --no-executable libtool
|
||||||
|
|
||||||
|
dependency autoconf --yay base-devel
|
||||||
|
dependency automake --yay base-devel
|
||||||
|
dependency awk --yay base-devel --dnf gawk --apt-get gawk --brew gawk
|
||||||
|
dependency aws --yay aws-cli-v2 --dnf awscli2 --apt-get awscli --brew awscli
|
||||||
|
dependency bat --no-executable
|
||||||
|
dependency bison --yay base-devel
|
||||||
|
dependency cmake
|
||||||
|
dependency cowsay
|
||||||
|
dependency figlet
|
||||||
|
dependency file
|
||||||
|
dependency flex --yay base-devel
|
||||||
|
dependency fzf
|
||||||
|
dependency gcc --yay base-devel --dnf gcc,gcc-c++ --apt-get build-essential
|
||||||
|
dependency gpg --yay gnupg --dnf gnupg2 --apt-get gnupg --brew gnupg
|
||||||
|
dependency grep
|
||||||
|
dependency htop
|
||||||
|
dependency ip --yay iproute2 --dnf iproute --apt-get iproute2 --brew iproute2mac
|
||||||
|
dependency jo
|
||||||
|
dependency jq
|
||||||
|
dependency lolcat
|
||||||
|
dependency ncurses --apt-get libncurses-dev --no-executable
|
||||||
|
dependency ssh --yay openssh --dnf openssh-clients --apt-get openssh-client --brew openssh
|
||||||
|
dependency patch --brew gpatch
|
||||||
|
dependency pkg-config --yay base-devel
|
||||||
|
dependency pylint --yay python-pylint
|
||||||
|
dependency python3 --yay python --dnf python3-devel --apt-get python3-dev --brew python-setuptools
|
||||||
|
dependency rg --yay ripgrep --dnf ripgrep --apt-get ripgrep --brew ripgrep
|
||||||
|
dependency sed --brew gsed
|
||||||
|
dependency tmux
|
||||||
|
dependency vim --dnf vim-enhanced
|
||||||
|
dependency xauth --yay xorg-xauth --dnf xorg-x11-xauth --apt-get xauth
|
||||||
|
dependency yamllint
|
||||||
|
dependency yq --yay go-yq --not-on apt-get
|
||||||
|
dependency zip
|
||||||
|
dependency zsh
|
||||||
|
|
||||||
|
# not packaged for fedora/debian
|
||||||
|
dependency --only-on yay,brew rage --yay rage-encryption
|
||||||
|
dependency --only-on yay,brew zsh-completions --no-executable
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
# extended cross-platform tools
|
||||||
|
dependency_args=("${INSTALLED_BY__extended[@]}")
|
||||||
|
|
||||||
|
dependency alacritty --brew cask:alacritty
|
||||||
|
dependency docker --dnf docker-ce,docker-ce-cli,containerd.io --brew colima
|
||||||
|
dependency go --apt-get golang
|
||||||
|
dependency java --yay jdk-openjdk --dnf java-latest-openjdk --apt-get default-jdk --brew openjdk
|
||||||
|
dependency javac --yay jdk-openjdk --dnf java-latest-openjdk --apt-get default-jdk --brew openjdk
|
||||||
|
dependency mono --dnf mono-complete --apt-get mono-devel
|
||||||
|
dependency redis-cli --yay redis --dnf valkey,valkey-compat-redis
|
||||||
|
dependency rustc --yay rustup --dnf rust --apt-get rustc --brew rust
|
||||||
|
dependency virtualenv --yay python-virtualenv --dnf python3-virtualenv --apt-get python3-virtualenv
|
||||||
|
|
||||||
|
# fedora & debian need official repositories added to dnf / apt (not yet supported)
|
||||||
|
dependency --only-on yay,brew 1password --brew cask:1password
|
||||||
|
dependency --only-on yay,brew op --yay 1password-cli --brew cask:1password-cli
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
# linux
|
||||||
|
dependency_args=("${INSTALLED_BY__all[@]}" --only-on yay,dnf,apt-get)
|
||||||
|
|
||||||
|
dependency noto-fonts-emoji --dnf google-noto-emoji-fonts --apt-get fonts-noto-color-emoji --no-executable
|
||||||
|
|
||||||
|
dependency feh
|
||||||
|
dependency fprintd --no-executable
|
||||||
|
dependency ntp --dnf chrony --apt-get chrony --no-executable
|
||||||
|
dependency pip --yay python-pip --dnf python3-pip --apt-get python3-pip
|
||||||
|
dependency sudo
|
||||||
|
dependency uuidgen --yay util-linux --dnf util-linux --apt-get uuid-runtime
|
||||||
|
dependency which
|
||||||
|
dependency xclip
|
||||||
|
dependency xdotool
|
||||||
|
|
||||||
|
#######################
|
||||||
|
|
||||||
|
# linux extended
|
||||||
|
dependency_args=("${INSTALLED_BY__extended[@]}" --only-on yay,dnf,apt-get)
|
||||||
|
|
||||||
|
dependency brave --yay brave-bin
|
||||||
|
dependency flameshot
|
||||||
|
dependency google-chrome --yay google-chrome-stable
|
||||||
|
dependency i3 --yay i3-wm --apt-get i3-wm
|
||||||
|
dependency lxappearance
|
||||||
|
dependency node --yay nodejs --dnf nodejs --apt-get nodejs
|
||||||
|
dependency npm
|
||||||
|
dependency obs-studio
|
||||||
|
dependency otf-monaspace --no-executable
|
||||||
|
dependency picom
|
||||||
|
dependency playerctl
|
||||||
|
dependency polybar
|
||||||
|
dependency rofi
|
||||||
|
dependency ttf-nerd-fonts-symbols --no-executable
|
||||||
|
|
||||||
|
##########################################
|
||||||
|
|
||||||
|
# arch linux
|
||||||
|
dependency_args=("${INSTALLED_BY__all[@]}" --only-on yay)
|
||||||
|
|
||||||
|
dependency arch-install-scripts --no-executable
|
||||||
|
dependency python-rtmidi --no-executable
|
||||||
|
|
||||||
|
dependency scwrypts
|
||||||
|
dependency unipicker
|
||||||
|
|
||||||
|
##########################################
|
||||||
|
|
||||||
|
# debian linux
|
||||||
|
dependency_args=("${INSTALLED_BY__all[@]}" --only-on apt-get)
|
||||||
|
|
||||||
|
dependency bsdextrautils --no-executable
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
# macos
|
||||||
|
dependency_args=("${INSTALLED_BY__all[@]}" --only-on brew)
|
||||||
|
|
||||||
|
#######################
|
||||||
|
|
||||||
|
# macos extended cask
|
||||||
|
dependency_args=("${INSTALLED_BY__extended_macos_cask[@]}" --only-on brew)
|
||||||
|
|
||||||
|
dependency brave --brew cask:brave-browser
|
||||||
|
dependency google-chrome --brew cask:google-chrome
|
||||||
|
dependency obs-studio --brew cask:obs
|
||||||
|
dependency xquartz --brew cask:xquartz
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
unset \
|
||||||
|
dependency_args \
|
||||||
|
INSTALLED_BY__all INSTALLED_BY__extended INSTALLED_BY__extended_macos_cask \
|
||||||
|
;
|
||||||
@@ -0,0 +1,259 @@
|
|||||||
|
#####################################################################
|
||||||
|
|
||||||
|
setup.packages.get-installer() {
|
||||||
|
# keyed on the package manager rather than the distro, so derivatives
|
||||||
|
# (manjaro, endeavouros, mint, ...) work without being enumerated; yay
|
||||||
|
# and brew are detected by their BASE manager since setup bootstraps
|
||||||
|
# them itself when missing
|
||||||
|
command -v pacman &>/dev/null && echo yay && return 0
|
||||||
|
command -v dnf &>/dev/null && echo dnf && return 0
|
||||||
|
command -v apt-get &>/dev/null && echo apt-get && return 0
|
||||||
|
command -v brew &>/dev/null && echo brew && return 0
|
||||||
|
|
||||||
|
[[ "$(uname -s)" == Darwin ]] && echo brew && return 0
|
||||||
|
|
||||||
|
echo generic
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
typeset -gA DEPENDENCY
|
||||||
|
DEPENDENCY_NAMES=()
|
||||||
|
|
||||||
|
dependency() { # declare a dependency; flags may appear in any order relative to the name; see dependency.manifest.zsh for usage
|
||||||
|
# dependency_args=(...), when set, is prepended to every call until reassigned
|
||||||
|
# or unset -- lets a block of dependencies share flags without repeating them
|
||||||
|
local -a args
|
||||||
|
(( ${+dependency_args} )) && args=("${dependency_args[@]}" "${@}") || args=("${@}")
|
||||||
|
|
||||||
|
local name installed_by yay dnf apt_get brew not_on only_on
|
||||||
|
local no_executable=false
|
||||||
|
local _s _p
|
||||||
|
while [[ "${#args[@]}" -gt 0 ]]
|
||||||
|
do
|
||||||
|
_s=1
|
||||||
|
case "${args[1]}" in
|
||||||
|
( --installed-by ) installed_by="${args[2]}"; _s=2 ;;
|
||||||
|
( --yay ) yay="${args[2]}"; _s=2 ;;
|
||||||
|
( --dnf ) dnf="${args[2]}"; _s=2 ;;
|
||||||
|
( --apt-get ) apt_get="${args[2]}"; _s=2 ;;
|
||||||
|
( --brew ) brew="${args[2]}"; _s=2 ;;
|
||||||
|
( --not-on ) not_on="${args[2]}"; _s=2 ;;
|
||||||
|
( --only-on ) only_on="${args[2]}"; _s=2 ;;
|
||||||
|
( --no-executable ) no_executable=true ;;
|
||||||
|
( -* )
|
||||||
|
echo.error "dependency: unknown option '${args[1]}'"
|
||||||
|
;;
|
||||||
|
( * )
|
||||||
|
case "$((_p+=1))" in
|
||||||
|
( 1 ) name="${args[1]}" ;;
|
||||||
|
( * ) echo.error "dependency: unexpected argument '${args[1]}'" ;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
[[ "${#args[@]}" -ge "${_s}" ]] \
|
||||||
|
&& args=("${args[@]:${_s}}") \
|
||||||
|
|| echo.error "dependency: missing value for '${args[1]}'" \
|
||||||
|
|| args=()
|
||||||
|
done
|
||||||
|
unset _s _p
|
||||||
|
|
||||||
|
[[ -n "${name}" ]] \
|
||||||
|
|| echo.error 'dependency: missing name' \
|
||||||
|
|| return 1
|
||||||
|
|
||||||
|
DEPENDENCY_NAMES+=("${name}")
|
||||||
|
DEPENDENCY[${name}:installed-by]="${installed_by:-default}"
|
||||||
|
DEPENDENCY[${name}:yay]="${yay:-${name}}"
|
||||||
|
DEPENDENCY[${name}:dnf]="${dnf:-${name}}"
|
||||||
|
DEPENDENCY[${name}:apt-get]="${apt_get:-${name}}"
|
||||||
|
DEPENDENCY[${name}:brew]="${brew:-${name}}"
|
||||||
|
DEPENDENCY[${name}:generic]="${name}" # no override -- the dependency's own name IS the generic fallback
|
||||||
|
DEPENDENCY[${name}:not-on]="${not_on:-}"
|
||||||
|
DEPENDENCY[${name}:only-on]="${only_on:-}"
|
||||||
|
DEPENDENCY[${name}:no-executable]="${no_executable}"
|
||||||
|
}
|
||||||
|
|
||||||
|
source "${0:a:h}/dependency.manifest.zsh"
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
setup.packages.list-installation-profiles() { # every profile named by an --installed-by in the manifest
|
||||||
|
local name
|
||||||
|
for name in "${DEPENDENCY_NAMES[@]}"
|
||||||
|
do
|
||||||
|
print -l -- "${(s:,:)DEPENDENCY[${name}:installed-by]}"
|
||||||
|
done \
|
||||||
|
| sort -u
|
||||||
|
}
|
||||||
|
|
||||||
|
setup.packages._.describe-package() {
|
||||||
|
# a package name isn't always 1:1 with the dependency which asked for it
|
||||||
|
# (e.g. yay's "base-devel" satisfies autoconf, automake, bison, ...), so
|
||||||
|
# name the dependencies too whenever they differ from the package itself
|
||||||
|
local package="${1}" dependency_names="${2}"
|
||||||
|
local display="${package#cask:}" # macOS casks carry a "cask:" prefix through the pipeline
|
||||||
|
|
||||||
|
[[ "${dependency_names}" == "${display}" ]] \
|
||||||
|
&& echo "'${display}'" \
|
||||||
|
&& return 0
|
||||||
|
|
||||||
|
echo "'${display}' (satisfies: ${dependency_names// /, })"
|
||||||
|
}
|
||||||
|
|
||||||
|
setup.packages.install-dependencies() {
|
||||||
|
local ERRORS=0
|
||||||
|
|
||||||
|
echo.status 'checking package dependencies'
|
||||||
|
local installer="${INSTALLER:-$(setup.packages.get-installer)}"
|
||||||
|
[[ "${installer}" != generic ]] \
|
||||||
|
|| echo.warning 'no supported package manager detected; dependencies can only be verified, not installed'
|
||||||
|
|
||||||
|
local requested_config="${DOTWRYN_SETUP__INSTALLATION_PROFILE:-default}"
|
||||||
|
|
||||||
|
local name field target
|
||||||
|
local -a targets
|
||||||
|
local -A package_names # resolved package -> space-joined logical dependency names
|
||||||
|
local -a executable_names # dependency names that must resolve via `command -v` (no-executable excluded)
|
||||||
|
[[ "${#DOTWRYN_SETUP__EXCLUDE[@]}" -eq 0 ]] \
|
||||||
|
|| echo.status "excluding dependencies: ${(j:, :)DOTWRYN_SETUP__EXCLUDE}"
|
||||||
|
|
||||||
|
for name in "${DEPENDENCY_NAMES[@]}"
|
||||||
|
do
|
||||||
|
(( ${DOTWRYN_SETUP__EXCLUDE[(Ie)${name}]} )) && continue
|
||||||
|
|
||||||
|
[[ ",${DEPENDENCY[${name}:installed-by]}," == *",${requested_config},"* ]] || continue
|
||||||
|
|
||||||
|
field="${DEPENDENCY[${name}:only-on]}"
|
||||||
|
[[ -n "${field}" ]] && [[ ",${field}," != *",${installer},"* ]] && continue
|
||||||
|
|
||||||
|
field="${DEPENDENCY[${name}:not-on]}"
|
||||||
|
[[ -n "${field}" ]] && [[ ",${field}," == *",${installer},"* ]] && continue
|
||||||
|
|
||||||
|
[[ "${DEPENDENCY[${name}:no-executable]}" == false ]] && executable_names+=("${name}")
|
||||||
|
|
||||||
|
field="${DEPENDENCY[${name}:${installer}]}"
|
||||||
|
|
||||||
|
# a dependency can require more than one physical package on a given installer
|
||||||
|
# (e.g. "docker" needing docker-ce, docker-ce-cli, and containerd.io on
|
||||||
|
# dnf) -- each --<installer> flag accepts a comma-separated list of targets
|
||||||
|
targets=("${(s:,:)field}")
|
||||||
|
for target in "${targets[@]}"
|
||||||
|
do
|
||||||
|
package_names[${target}]+=" ${name}"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
unset name field target targets
|
||||||
|
|
||||||
|
if [[ "${installer}" == generic ]]
|
||||||
|
then
|
||||||
|
for name in "${executable_names[@]}"
|
||||||
|
do
|
||||||
|
setup.packages.installer.generic.install-managed "${name}"
|
||||||
|
done
|
||||||
|
unset name
|
||||||
|
echo.success 'all dependencies satisfied'
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "${CI}" in
|
||||||
|
( true ) ;; # no system to update
|
||||||
|
( * )
|
||||||
|
echo.status 'updating system, repositories, and mirrors'
|
||||||
|
"setup.packages.installer.${installer}.update-repositories"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
local -a installed_packages
|
||||||
|
installed_packages=("${(f)$("setup.packages.installer.${installer}.list-installed")}")
|
||||||
|
|
||||||
|
local package
|
||||||
|
local -a missing_packages
|
||||||
|
for package in "${(k)package_names[@]}"
|
||||||
|
do
|
||||||
|
(( ${installed_packages[(Ie)${package}]} )) && continue
|
||||||
|
missing_packages+=("${package}")
|
||||||
|
done
|
||||||
|
unset package
|
||||||
|
|
||||||
|
if [[ "${#missing_packages[@]}" -eq 0 ]]
|
||||||
|
then
|
||||||
|
echo.success 'all dependencies satisfied'
|
||||||
|
else
|
||||||
|
for package in "${missing_packages[@]}"
|
||||||
|
do
|
||||||
|
echo.status "installing $(setup.packages._.describe-package "${package}" "${package_names[${package}]# }")"
|
||||||
|
done
|
||||||
|
unset package
|
||||||
|
|
||||||
|
"setup.packages.installer.${installer}.install-batch" "${missing_packages[@]}"
|
||||||
|
|
||||||
|
# don't trust the batch call's exit code alone: some package managers (yay in
|
||||||
|
# particular) can exit 0 after silently skipping one unresolvable AUR target
|
||||||
|
# rather than failing the whole transaction, so re-check what's actually installed
|
||||||
|
installed_packages=("${(f)$("setup.packages.installer.${installer}.list-installed")}")
|
||||||
|
|
||||||
|
local -a still_missing
|
||||||
|
for package in "${missing_packages[@]}"
|
||||||
|
do
|
||||||
|
(( ${installed_packages[(Ie)${package}]} )) || still_missing+=("${package}")
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ "${#still_missing[@]}" -gt 0 ]] \
|
||||||
|
&& echo.warning 'batched install left some packages unresolved; retrying them one at a time to isolate the failure(s)'
|
||||||
|
|
||||||
|
for package in "${missing_packages[@]}"
|
||||||
|
do
|
||||||
|
if [[ " ${still_missing[*]} " == *" ${package} "* ]]
|
||||||
|
then
|
||||||
|
"setup.packages.installer.${installer}.install-managed" "${package}"
|
||||||
|
else
|
||||||
|
echo.success "$(setup.packages._.describe-package "${package}" "${package_names[${package}]# }") installed"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
unset package still_missing
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "${installer}" in
|
||||||
|
( brew )
|
||||||
|
# especially important on macOS where BSD utilities are the default
|
||||||
|
echo.status "making sure homebrew GNU utilities are default"
|
||||||
|
|
||||||
|
local gnubin_path
|
||||||
|
for gnubin_path in "$(brew --prefix)"/opt/*/libexec/gnubin(N); do export PATH="${gnubin_path}:${PATH}"; done
|
||||||
|
unset gnubin_path
|
||||||
|
|
||||||
|
setup.filesystem.write-managed-block "${HOME}/.zprofile" --tag homebrew <<-'EOF'
|
||||||
|
# (homebrew required) : load homebrew shellenv
|
||||||
|
eval "$(/opt/homebrew/bin/brew shellenv 2>/dev/null || /usr/local/bin/brew shellenv 2>/dev/null)"
|
||||||
|
|
||||||
|
# ensure GNU utilities from homebrew load before system/BSD utils
|
||||||
|
for homebrew_gnu_bin_path in "$(brew --prefix)"/opt/*/libexec/gnubin(N)
|
||||||
|
do
|
||||||
|
export PATH="${homebrew_gnu_bin_path}:${PATH}"
|
||||||
|
done
|
||||||
|
unset homebrew_gnu_bin_path
|
||||||
|
EOF
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo.status 'verifying dependency executables'
|
||||||
|
for name in "${executable_names[@]}"
|
||||||
|
do
|
||||||
|
command -v "${name}" &>/dev/null \
|
||||||
|
|| echo.error "'${name}' is installed but its executable could not be found on PATH"
|
||||||
|
done
|
||||||
|
unset name
|
||||||
|
|
||||||
|
if [[ "${ERRORS}" -ne 0 ]]
|
||||||
|
then
|
||||||
|
echo.warning "detected ${ERRORS} errors; double check warnings before proceeding!"
|
||||||
|
case "${DOTWRYN_SETUP__STRICT}" in
|
||||||
|
( true ) return 1 ;; # never prompt; unresolved dependencies are a failure
|
||||||
|
( * ) utils.yN 'continue with install?' || return 1 ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo.success 'all dependencies satisfied'
|
||||||
|
return 0
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
#####################################################################
|
||||||
|
|
||||||
|
setup.packages.install-from-source() { # clone + build/install a git-hosted package (AUR PKGBUILD or Makefile)
|
||||||
|
local target_url="${1}"
|
||||||
|
local name="${2:-$(echo "${target_url}" | sed 's/.*\///; s/\.git$//')}"
|
||||||
|
local install_dir="${HOME}/.local/share/source-packages"
|
||||||
|
local package_dir="${install_dir}/${name}"
|
||||||
|
mkdir -p -- "${install_dir}"
|
||||||
|
|
||||||
|
local state=missing
|
||||||
|
[[ -d "${package_dir}" ]] && state=exists
|
||||||
|
|
||||||
|
case "${state}" in
|
||||||
|
( exists )
|
||||||
|
: \
|
||||||
|
&& echo.status "updating '${name}'" \
|
||||||
|
&& git -C "${package_dir}" pull origin "$(git -C "${package_dir}" rev-parse --abbrev-ref HEAD)" \
|
||||||
|
;
|
||||||
|
;;
|
||||||
|
( missing )
|
||||||
|
: \
|
||||||
|
&& echo.status "downloading '${name}'" \
|
||||||
|
&& git clone -- "${target_url}" "${package_dir}" \
|
||||||
|
;
|
||||||
|
;;
|
||||||
|
esac \
|
||||||
|
|| echo.error "failed to fetch '${name}'" \
|
||||||
|
|| return 1
|
||||||
|
|
||||||
|
local build_method=unknown
|
||||||
|
[[ -f "${package_dir}/PKGBUILD" ]] && build_method=makepkg
|
||||||
|
[[ -f "${package_dir}/Makefile" ]] && [[ "${build_method}" == unknown ]] && build_method=make
|
||||||
|
|
||||||
|
case "${build_method}" in
|
||||||
|
( makepkg )
|
||||||
|
: \
|
||||||
|
&& echo.status "installing '${name}'" \
|
||||||
|
&& ( cd -- "${package_dir}" && yes | makepkg -si ) \
|
||||||
|
&& echo.success "successfully installed '${name}'" \
|
||||||
|
|| echo.error "failed to install '${name}'" \
|
||||||
|
;
|
||||||
|
;;
|
||||||
|
( make )
|
||||||
|
: \
|
||||||
|
&& echo.status "building '${name}'" \
|
||||||
|
&& make -C "${package_dir}" \
|
||||||
|
&& : \
|
||||||
|
&& echo.status "installing '${name}'" \
|
||||||
|
&& utils.io.getsudo \
|
||||||
|
&& sudo make -C "${package_dir}" install \
|
||||||
|
&& echo.success "successfully installed '${name}'" \
|
||||||
|
|| echo.error "failed to build/install '${name}'" \
|
||||||
|
;
|
||||||
|
;;
|
||||||
|
( unknown )
|
||||||
|
echo.warning 'could not detect supported installation method'
|
||||||
|
echo.reminder 'complete manual installation in the directory below:'
|
||||||
|
echo.reminder "${package_dir}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#####################################################################
|
||||||
|
|
||||||
|
setup.packages.installer.apt-get.update-repositories() { sudo apt-get update && sudo apt-get upgrade; }
|
||||||
|
|
||||||
|
setup.packages.installer.apt-get.list-installed() { dpkg-query -W -f='${Package}\n' 2>/dev/null; }
|
||||||
|
|
||||||
|
setup.packages.installer.apt-get.install-batch() { sudo apt-get install --yes "${@}"; }
|
||||||
|
|
||||||
|
setup.packages.installer.apt-get.install-managed() {
|
||||||
|
local target="${1}"
|
||||||
|
echo.status "checking / installing '${target}'"
|
||||||
|
sudo apt-get install --yes "${target}" \
|
||||||
|
&& echo.success "'${target}' installed" \
|
||||||
|
|| echo.error "failed to install ${target}" \
|
||||||
|
;
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
#####################################################################
|
||||||
|
|
||||||
|
setup.packages.installer.brew.setup-package-manager() {
|
||||||
|
command -v brew &>/dev/null && return 0
|
||||||
|
|
||||||
|
# an already-installed homebrew still isn't on PATH in a fresh login
|
||||||
|
# shell, so adopt it before concluding it needs installing
|
||||||
|
local brew_path
|
||||||
|
for brew_path in /opt/homebrew/bin/brew /usr/local/bin/brew
|
||||||
|
do
|
||||||
|
[[ -x "${brew_path}" ]] || continue
|
||||||
|
eval "$("${brew_path}" shellenv)"
|
||||||
|
return 0
|
||||||
|
done
|
||||||
|
unset brew_path
|
||||||
|
|
||||||
|
: \
|
||||||
|
&& /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" \
|
||||||
|
&& eval "$(/opt/homebrew/bin/brew shellenv 2>/dev/null || /usr/local/bin/brew shellenv 2>/dev/null)" \
|
||||||
|
|| echo.error 'failed to install homebrew' \
|
||||||
|
|| return 1 \
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
setup.packages.installer.brew.update-repositories() { brew update && brew upgrade; }
|
||||||
|
|
||||||
|
setup.packages.installer.brew.list-installed() { # targets needing "brew install --cask" are carried through this whole pipeline as "cask:name"
|
||||||
|
brew list --formula 2>/dev/null
|
||||||
|
brew list --cask 2>/dev/null | sed 's/^/cask:/'
|
||||||
|
}
|
||||||
|
|
||||||
|
setup.packages.installer.brew.install-batch() {
|
||||||
|
local -a formulae casks
|
||||||
|
local target
|
||||||
|
for target in "${@}"
|
||||||
|
do
|
||||||
|
case "${target}" in
|
||||||
|
( cask:* ) casks+=("${target#cask:}") ;;
|
||||||
|
( * ) formulae+=("${target}") ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
unset target
|
||||||
|
|
||||||
|
if [[ "${#formulae[@]}" -gt 0 ]]
|
||||||
|
then
|
||||||
|
yes | brew install "${formulae[@]}" || return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${#casks[@]}" -gt 0 ]]
|
||||||
|
then
|
||||||
|
yes | brew install --cask "${casks[@]}" || return 2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
setup.packages.installer.brew.install-managed() {
|
||||||
|
local target="${1}"
|
||||||
|
local -a cask_flag
|
||||||
|
if [[ "${target}" == cask:* ]]
|
||||||
|
then
|
||||||
|
target="${target#cask:}"
|
||||||
|
cask_flag=(--cask)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if brew list "${cask_flag[@]}" --versions "${target}" &>/dev/null
|
||||||
|
then
|
||||||
|
echo.success "found '${target}'"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
: \
|
||||||
|
&& echo.status "installing '${target}'" \
|
||||||
|
&& yes | brew install "${cask_flag[@]}" "${target}" \
|
||||||
|
&& echo.success "'${target}' installed" \
|
||||||
|
|| echo.error "failed to install '${target}'" \
|
||||||
|
;
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#####################################################################
|
||||||
|
|
||||||
|
setup.packages.installer.dnf.update-repositories() {
|
||||||
|
: \
|
||||||
|
&& sudo dnf update \
|
||||||
|
&& sudo dnf upgrade \
|
||||||
|
&& sudo dnf install -y dnf-plugins-core \
|
||||||
|
&& sudo dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/fedora/docker-ce.repo \
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
setup.packages.installer.dnf.list-installed() { rpm -qa --qf '%{NAME}\n' 2>/dev/null; }
|
||||||
|
|
||||||
|
setup.packages.installer.dnf.install-batch() { sudo dnf install -y "${@}"; }
|
||||||
|
|
||||||
|
setup.packages.installer.dnf.install-managed() {
|
||||||
|
local target="${1}"
|
||||||
|
echo.status "checking / installing '${target}'"
|
||||||
|
sudo dnf install -y "${target}" \
|
||||||
|
&& echo.success "'${target}' installed" \
|
||||||
|
|| echo.error "failed to install ${target}" \
|
||||||
|
;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#####################################################################
|
||||||
|
|
||||||
|
setup.packages.installer.generic.install-managed() {
|
||||||
|
local target="${1}"
|
||||||
|
command -v "${target}" &>/dev/null \
|
||||||
|
|| echo.error "could not find '${target}'; it's up to you to install this one!"
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#####################################################################
|
||||||
|
|
||||||
|
setup.packages.installer.yay.setup-package-manager() {
|
||||||
|
command -v yay &>/dev/null && return 0
|
||||||
|
setup.packages.install-from-source 'https://aur.archlinux.org/yay.git' 'yay'
|
||||||
|
}
|
||||||
|
|
||||||
|
setup.packages.installer.yay.update-repositories() { yay -Syu; }
|
||||||
|
setup.packages.installer.yay.list-installed() { yay -Qq 2>/dev/null; }
|
||||||
|
setup.packages.installer.yay.install-batch() { yay -Syu --noconfirm "${@}"; }
|
||||||
|
|
||||||
|
setup.packages.installer.yay.install-managed() {
|
||||||
|
local target="${1}"
|
||||||
|
local installed_target="$(setup.packages.installer.yay.list-installed | grep "^${target}$\|^${target}-git$")"
|
||||||
|
|
||||||
|
[[ "${installed_target}" ]] \
|
||||||
|
&& echo.success "found '${installed_target}'" \
|
||||||
|
&& return 0
|
||||||
|
|
||||||
|
: \
|
||||||
|
&& echo.status "installing '${target}'" \
|
||||||
|
&& yay -Syu --noconfirm "${target}" \
|
||||||
|
&& : \
|
||||||
|
&& echo.success "successfully installed '${target}'" \
|
||||||
|
|| echo.error "failed to install '${target}'" \
|
||||||
|
;
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#####################################################################
|
||||||
|
|
||||||
|
for setup_library in "${0:a:h}"/*.zsh
|
||||||
|
do
|
||||||
|
case "${setup_library:t}" in
|
||||||
|
( packages.module.zsh | dependency.manifest.zsh ) ;; # self; manifest
|
||||||
|
( * ) source "${setup_library}" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
unset setup_library
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
setup.packages() {
|
||||||
|
local INSTALLER="$(setup.packages.get-installer)"
|
||||||
|
[[ "${INSTALLER}" ]] || return 1
|
||||||
|
|
||||||
|
case "${INSTALLER}" in
|
||||||
|
( brew | generic ) ;; # homebrew refuses to run as root; generic installs nothing
|
||||||
|
( * ) utils.io.getsudo ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if (( ${+functions[setup.packages.installer.${INSTALLER}.setup-package-manager]} ))
|
||||||
|
then
|
||||||
|
"setup.packages.installer.${INSTALLER}.setup-package-manager" || return 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
setup.packages.install-dependencies || return 3
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
#
|
||||||
|
# this file is used exclusively by setup/run; our objectives are:
|
||||||
|
#
|
||||||
|
# 1. to source scwrypts:zsh/utils.module.zsh
|
||||||
|
# (this contains all our echo.+debug+safety fundamentals for zsh)
|
||||||
|
#
|
||||||
|
# 2. to create setup.scwrypts()
|
||||||
|
# (explicitly uses the source scwrypts in .wryn/zsh during setup)
|
||||||
|
#
|
||||||
|
# 3. to load in the remaining zsh library functions for setup/
|
||||||
|
#
|
||||||
|
# While _normally_ utils.module.zsh is safe to "just source," setup
|
||||||
|
# can run from a bare "we have git and zsh and NOTHING else" system,
|
||||||
|
# so there's a little work we have to do to actually get there
|
||||||
|
# without user intervention.
|
||||||
|
#
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
setup.prepare-zsh-utilities._.error() {
|
||||||
|
echo "ERROR::${*}" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
[[ "${EUID}" -ne 0 ]] || [[ "${DOTWRYN_SETUP__FORCE_ROOT}" == true ]] \
|
||||||
|
|| setup.prepare-zsh-utilities._.error 'setup cannot be run as root' \
|
||||||
|
|| return 1
|
||||||
|
|
||||||
|
|
||||||
|
# normally "DOTWRYN" which is not available during first setup
|
||||||
|
export DOTWRYN_SETUP__DOTWRYN="${DOTWRYN_SETUP__SETUP_DIR:h}"
|
||||||
|
[[ -d "${DOTWRYN_SETUP__DOTWRYN}/setup" ]] \
|
||||||
|
|| setup.prepare-zsh-utilities._.error "'${DOTWRYN_SETUP__SETUP_DIR}' is not the .wryn setup directory; run 'setup/run'" \
|
||||||
|
|| return 2
|
||||||
|
|
||||||
|
export DOTWRYN_SETUP__STATE_DIR="${XDG_STATE_HOME:-${HOME}/.local/state}/dotwryn"
|
||||||
|
mkdir -p -- "${DOTWRYN_SETUP__STATE_DIR}"
|
||||||
|
|
||||||
|
printf 'initializing required submodules...' >&2
|
||||||
|
git -C "${DOTWRYN_SETUP__DOTWRYN}" submodule update --init --remote --recursive >/dev/null \
|
||||||
|
|| setup.prepare-zsh-utilities._.error 'unable to initialize required submodules' \
|
||||||
|
|| return 3
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
DEPENDENCIES+=(zsh)
|
||||||
|
REQUIRED_ENV+=()
|
||||||
|
|
||||||
|
command -v fzf &>/dev/null || fzf() { head -n1; }
|
||||||
|
command -v jo &>/dev/null || jo() { :; }
|
||||||
|
command -v jq &>/dev/null || jq() { :; }
|
||||||
|
|
||||||
|
source "${DOTWRYN_SETUP__DOTWRYN}/zsh/plugins/scwrypts/zsh/utils/utils.module.zsh" \
|
||||||
|
|| setup.prepare-zsh-utilities._.error 'unable to load the scwrypts utils' \
|
||||||
|
|| return 4
|
||||||
|
|
||||||
|
unset -f fzf &>/dev/null
|
||||||
|
unset -f jo &>/dev/null
|
||||||
|
unset -f jq &>/dev/null
|
||||||
|
unset -f setup.prepare-zsh-utilities._.error # echo.error takes over from here
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
setup.scwrypts() {
|
||||||
|
CI=1 \
|
||||||
|
CONFIG__USER_SETTINGS="${DOTWRYN_SETUP__DOTWRYN}/config/scwrypts/dotfiles.zsh" \
|
||||||
|
DOTWRYN="${DOTWRYN_SETUP__DOTWRYN}" \
|
||||||
|
"${DOTWRYN_SETUP__DOTWRYN}/zsh/plugins/scwrypts/scwrypts" -n "${@}"
|
||||||
|
}
|
||||||
|
|
||||||
|
##########################################
|
||||||
|
|
||||||
|
# >>> scwrypts bug! <<<
|
||||||
|
# there's currently no way to provide SCWRYPTS_GROUP_DIRS outside of
|
||||||
|
# the users config.zsh; this is a temporary measure to register the
|
||||||
|
# `dotwryn` scwrypts group for a first-time setup run
|
||||||
|
|
||||||
|
scwrypts_user_config="${XDG_CONFIG_HOME:-${HOME}/.config}/scwrypts/config.zsh"
|
||||||
|
if [[ -f "${scwrypts_user_config}" ]]
|
||||||
|
then
|
||||||
|
: # user config already setup; do not modify
|
||||||
|
else
|
||||||
|
: \
|
||||||
|
&& mkdir -p -- "${scwrypts_user_config:h}" \
|
||||||
|
&& cp -- "${DOTWRYN_SETUP__DOTWRYN}/zsh/plugins/scwrypts/zsh/config.user.zsh" "${scwrypts_user_config}" \
|
||||||
|
&& echo "SCWRYPTS_GROUP_DIRS+=(\"${DOTWRYN_SETUP__DOTWRYN}/scwrypts\")" >> "${scwrypts_user_config}" \
|
||||||
|
;
|
||||||
|
fi
|
||||||
|
unset scwrypts_user_config
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
: \
|
||||||
|
&& source "${DOTWRYN_SETUP__DOTWRYN}/setup/filesystem/filesystem.module.zsh" \
|
||||||
|
&& source "${DOTWRYN_SETUP__DOTWRYN}/setup/packages/packages.module.zsh" \
|
||||||
|
&& source "${DOTWRYN_SETUP__DOTWRYN}/setup/config/config.module.zsh" \
|
||||||
|
&& : \
|
||||||
|
|| echo.error 'something went wrong during setup library imports (see above)' \
|
||||||
|
|| return 5 \
|
||||||
|
;
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# shhh don't worry about it
|
||||||
|
[[ "${CI}" == true ]] || [[ -f "${welcome_marker:=${DOTWRYN_SETUP__STATE_DIR}/hush-setup-welcome}" ]] || {clear;C=$((){B(){base64 -d};A="$(cat "$2")";for _ in {1..$1};do A=$(echo $A|B);done;echo $A} 7 "$DOTWRYN_SETUP__DOTWRYN/setup/welcome");for ((i=0;i<${#C};i++));do [[ ${C:$i:1} =~ z ]] && M=$(printf "\\033[1;3$((1+$RANDOM%5))m") && continue;printf "$M${C:$i:1}" none;sleep 0.01;done;echo;unset C M;touch "${welcome_marker}";}
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
[[ "${EUID}" -eq 0 ]] && [[ "${FORCE_ROOT}" != true ]] \
|
|
||||||
&& { echo 'ERROR::Setup cannot be run as root'; exit 1; }
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
# normally "DOTWRYN", but uses "DOTWRYN_PATH" to avoid conflict during setup
|
|
||||||
cd "${0:a:h}"
|
|
||||||
export DOTWRYN_PATH="$(git rev-parse --show-toplevel)"
|
|
||||||
cd "${DOTWRYN_PATH}"
|
|
||||||
|
|
||||||
printf 'initializing required submodules...' >&2
|
|
||||||
git submodule update --init --remote --recursive >/dev/null 2>&1 || {
|
|
||||||
echo 'failed!' >&2
|
|
||||||
echo 'unable to initialize required submodules' >&2
|
|
||||||
exit 2
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
DEPENDENCIES+=(zsh)
|
|
||||||
REQUIRED_ENV+=()
|
|
||||||
|
|
||||||
command -v fzf &>/dev/null || fzf() { head -n1; }
|
|
||||||
command -v jo &>/dev/null || jo() { :; }
|
|
||||||
command -v jq &>/dev/null || jq() { :; }
|
|
||||||
|
|
||||||
source "${DOTWRYN_PATH}/zsh/plugins/scwrypts/zsh/utils/utils.module.zsh" || exit 3
|
|
||||||
|
|
||||||
unset -f fzf &>/dev/null
|
|
||||||
unset -f jo &>/dev/null
|
|
||||||
unset -f jq &>/dev/null
|
|
||||||
|
|
||||||
# register the '.wryn' dotwryn scwrypts group; scwrypts only discovers groups
|
|
||||||
# listed in SCWRYPTS_GROUP_DIRS inside this file, and this file doesn't exist
|
|
||||||
# yet on a fresh machine
|
|
||||||
scwrypts_user_config_dir="${XDG_CONFIG_HOME:-${HOME}/.config}/scwrypts"
|
|
||||||
scwrypts_user_config="${scwrypts_user_config_dir}/config.zsh"
|
|
||||||
mkdir -p "${scwrypts_user_config_dir}"
|
|
||||||
[ -f "${scwrypts_user_config}" ] \
|
|
||||||
|| cp "${DOTWRYN_PATH}/zsh/plugins/scwrypts/zsh/config.user.zsh" "${scwrypts_user_config}"
|
|
||||||
|
|
||||||
grep -qF "${DOTWRYN_PATH}/scwrypts" "${scwrypts_user_config}" \
|
|
||||||
|| echo "SCWRYPTS_GROUP_DIRS+=(\"${DOTWRYN_PATH}/scwrypts\")" >> "${scwrypts_user_config}"
|
|
||||||
unset scwrypts_user_config_dir scwrypts_user_config
|
|
||||||
|
|
||||||
SCWRYPTS() {
|
|
||||||
CI=1 \
|
|
||||||
CONFIG__USER_SETTINGS="${DOTWRYN_PATH}/config/scwrypts/dotfiles.zsh" \
|
|
||||||
DOTWRYN="${DOTWRYN_PATH}" \
|
|
||||||
"${DOTWRYN_PATH}/zsh/plugins/scwrypts/scwrypts" -n "${@}"
|
|
||||||
}
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
source "${DOTWRYN_PATH}/setup/os.zsh"
|
|
||||||
source "${DOTWRYN_PATH}/setup/git.zsh"
|
|
||||||
source "${DOTWRYN_PATH}/setup/config.zsh"
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
clear
|
|
||||||
|
|
||||||
# shhh don't worry about it
|
|
||||||
[[ "${CI}" == true ]] || {C=$((){B(){base64 -d};A="$(cat "$2")";for _ in {1..$1};do A=$(echo $A|B);done;echo $A} 7 "$DOTWRYN_PATH/setup/welcome");for ((i=0;i<${#C};i++));do [[ ${C:$i:1} =~ z ]] && M=$(printf "\\033[1;3$((1+$RANDOM%5))m") && continue;printf "$M${C:$i:1}" none;sleep 0.01;done;echo;unset C M;}
|
|
||||||
@@ -1,48 +1,191 @@
|
|||||||
#!/bin/zsh
|
#!/usr/bin/env zsh
|
||||||
cd "${0:a:h}"
|
DOTWRYN_SETUP__SETUP_DIR="${0:a:h}"
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
FORCE_ROOT=false
|
DOTWRYN_SETUP__FORCE_ROOT=false
|
||||||
CI=false
|
DOTWRYN_SETUP__OVERWRITE_EXISTING=false
|
||||||
OVERWRITE_EXISTING=false
|
DOTWRYN_SETUP__USE_LOGFILE=true
|
||||||
COMPILE_DMENU=true
|
DOTWRYN_SETUP__STRICT=false
|
||||||
MIN=false
|
DOTWRYN_SETUP__INSTALLATION_PROFILE=default
|
||||||
|
DOTWRYN_SETUP__EXCLUDE=()
|
||||||
|
DOTWRYN_SETUP__STEPS=(filesystem packages config)
|
||||||
|
|
||||||
while [[ "${#}" -gt 0 ]]
|
|
||||||
do
|
|
||||||
case "${1}" in
|
|
||||||
( --force-root ) FORCE_ROOT=true ;;
|
|
||||||
( --ci ) export CI=true ;;
|
|
||||||
|
|
||||||
( --overwrite ) OVERWRITE_EXISTING=true ;;
|
setup.run._.usage() {
|
||||||
|
local run_file="${DOTWRYN_SETUP__SETUP_DIR}/run"
|
||||||
|
local line flags description
|
||||||
|
|
||||||
( --no-compile-dmenu ) COMPILE_DMENU=false ;;
|
local found_function=false
|
||||||
|
while read -r line
|
||||||
( --min )
|
do
|
||||||
MIN=true
|
case "${found_function}" in
|
||||||
COMPILE_DMENU=false
|
( false ) [[ "${line}" == '() {' ]] && found_function=true ;;
|
||||||
|
( true )
|
||||||
|
[[ "${line}" =~ '^[[:space:]]*#[[:space:]]?(.*)$' ]] || break
|
||||||
|
echo "${match[1]}"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
shift 1
|
done < "${run_file}"
|
||||||
done
|
|
||||||
source ./requirements.zsh || exit 1
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
logfile="${HOME}/dotwryn-install.txt"
|
echo
|
||||||
|
echo 'options:'
|
||||||
|
|
||||||
echo.status "installation start : $(date)" 2>> "${logfile}"
|
while read -r line
|
||||||
{
|
do
|
||||||
setup.os || utils.fail 1 'failed to set up os-dependencies (see above)'
|
[[ "${line}" =~ '^[[:space:]]*\([[:space:]]*(-[^)]*)\)[^#]*#[[:space:]]*(.*)$' ]] || continue
|
||||||
setup.git || utils.fail 2 'failed to set up git (see above)'
|
|
||||||
setup.config || utils.fail 3 'failed to set up program configuration (see above)'
|
|
||||||
} 2>&1 | tee -a "${logfile}"
|
|
||||||
|
|
||||||
echo.status "installation complete: $(date)" 2>> "${logfile}"
|
flags="${(j: :)${(z)match[1]}}"
|
||||||
|
flags="${flags// | /, }"
|
||||||
|
description="${match[2]}"
|
||||||
|
|
||||||
################################################################################
|
[[ "${description}" =~ '^(<[^>]*>)[[:space:]]+(.*)$' ]] \
|
||||||
|
&& flags="${flags} ${match[1]}" \
|
||||||
|
&& description="${match[2]}"
|
||||||
|
|
||||||
[[ "${ERRORS}" -eq 0 ]] || {
|
printf ' %-38s %s\n' "${flags}" "${description}"
|
||||||
utils.yN 'keep logfile?' \
|
done < "${run_file}"
|
||||||
|| { rm "${logfile}" || echo.error "unable to remove '${logfile}'" }
|
|
||||||
|
echo
|
||||||
|
echo "steps: ${(j:, :)DOTWRYN_SETUP__STEPS}"
|
||||||
|
echo
|
||||||
}
|
}
|
||||||
|
|
||||||
echo.success "\n.wryn setup complete; have a nice day :)\n "
|
#####################################################################
|
||||||
|
|
||||||
|
() {
|
||||||
|
# set up this machine from the .wryn dotfiles repository
|
||||||
|
#
|
||||||
|
# usage: setup/run [...options...]
|
||||||
|
local -a skip_steps only_steps
|
||||||
|
|
||||||
|
setup.run._.error() { echo "ERROR::${*}" >&2; return 1; }
|
||||||
|
|
||||||
|
local _s
|
||||||
|
while [[ "${#}" -gt 0 ]]
|
||||||
|
do
|
||||||
|
_s=1
|
||||||
|
case "${1}" in
|
||||||
|
( -h | --help ) # display this message and exit
|
||||||
|
setup.run._.usage
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
|
||||||
|
( -p | --installation-profile ) _s=2 # <profile> only install dependencies belonging to <profile>
|
||||||
|
DOTWRYN_SETUP__INSTALLATION_PROFILE="${2}"
|
||||||
|
;;
|
||||||
|
|
||||||
|
( --min ) # shorthand for '--installation-profile min'
|
||||||
|
DOTWRYN_SETUP__INSTALLATION_PROFILE=min
|
||||||
|
;;
|
||||||
|
|
||||||
|
( --skip ) _s=2 # <step> don't run <step>; repeatable, incompatible with --only
|
||||||
|
skip_steps+=("${2}")
|
||||||
|
;;
|
||||||
|
|
||||||
|
( --only ) _s=2 # <step> only run <step>; repeatable, incompatible with --skip
|
||||||
|
only_steps+=("${2}")
|
||||||
|
;;
|
||||||
|
|
||||||
|
( --exclude ) _s=2 # <dependencies> comma-separated dependencies to neither install nor verify; repeatable
|
||||||
|
DOTWRYN_SETUP__EXCLUDE+=("${(s:,:)2}")
|
||||||
|
;;
|
||||||
|
|
||||||
|
( --overwrite ) # replace existing local configuration
|
||||||
|
DOTWRYN_SETUP__OVERWRITE_EXISTING=true
|
||||||
|
;;
|
||||||
|
|
||||||
|
( --force-root ) # allow setup to run as root
|
||||||
|
DOTWRYN_SETUP__FORCE_ROOT=true
|
||||||
|
;;
|
||||||
|
|
||||||
|
( --ci ) # automation mode; never prompts (pair with '--skip packages' to also skip installs)
|
||||||
|
export CI=true
|
||||||
|
;;
|
||||||
|
|
||||||
|
( --no-logfile ) # don't write a logfile for this run
|
||||||
|
DOTWRYN_SETUP__USE_LOGFILE=false
|
||||||
|
;;
|
||||||
|
|
||||||
|
( --strict ) # treat unresolved dependencies as a failure instead of prompting
|
||||||
|
DOTWRYN_SETUP__STRICT=true
|
||||||
|
;;
|
||||||
|
|
||||||
|
( * )
|
||||||
|
setup.run._.error "unknown option '${1}'; try '--help'"
|
||||||
|
return 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift "${_s}"
|
||||||
|
done
|
||||||
|
unset _s
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
[[ "${#skip_steps[@]}" -eq 0 ]] || [[ "${#only_steps[@]}" -eq 0 ]] \
|
||||||
|
|| setup.run._.error "'--skip' and '--only' cannot be used together" \
|
||||||
|
|| return 2
|
||||||
|
|
||||||
|
local named_step
|
||||||
|
for named_step in "${skip_steps[@]}" "${only_steps[@]}"
|
||||||
|
do
|
||||||
|
(( ${DOTWRYN_SETUP__STEPS[(Ie)${named_step}]} )) \
|
||||||
|
|| setup.run._.error "no such setup step '${named_step}' (steps: ${(j:, :)DOTWRYN_SETUP__STEPS})" \
|
||||||
|
|| return 2
|
||||||
|
done
|
||||||
|
unset named_step
|
||||||
|
|
||||||
|
local -a steps
|
||||||
|
local step
|
||||||
|
for step in "${DOTWRYN_SETUP__STEPS[@]}"
|
||||||
|
do
|
||||||
|
case "${#only_steps[@]}" in
|
||||||
|
( 0 ) (( ${skip_steps[(Ie)${step}]} )) && continue ;;
|
||||||
|
( * ) (( ${only_steps[(Ie)${step}]} )) || continue ;;
|
||||||
|
esac
|
||||||
|
steps+=("${step}")
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ "${#steps[@]}" -gt 0 ]] \
|
||||||
|
|| setup.run._.error 'every setup step was excluded; nothing to do' \
|
||||||
|
|| return 2
|
||||||
|
|
||||||
|
unset -f setup.run._.error
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
source "${DOTWRYN_SETUP__SETUP_DIR}/prepare-zsh-utilities.zsh" || return 1
|
||||||
|
|
||||||
|
local -a installation_profiles
|
||||||
|
installation_profiles=("${(f)$(setup.packages.list-installation-profiles)}")
|
||||||
|
(( ${installation_profiles[(Ie)${DOTWRYN_SETUP__INSTALLATION_PROFILE}]} )) \
|
||||||
|
|| echo.error "no such installation profile '${DOTWRYN_SETUP__INSTALLATION_PROFILE}' (available: ${(j:, :)installation_profiles})" \
|
||||||
|
|| return 2
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
local ERRORS=0
|
||||||
|
local logfile
|
||||||
|
case "${DOTWRYN_SETUP__USE_LOGFILE}" in
|
||||||
|
( true ) logfile="${DOTWRYN_SETUP__STATE_DIR}/setup.$(date +%Y-%m-%dT%H%M%S).log" ;;
|
||||||
|
( false ) logfile=/dev/null ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo.status "installation start : $(date)" 2>> "${logfile}"
|
||||||
|
echo.status "setup steps : ${(j:, :)steps}"
|
||||||
|
|
||||||
|
for step in "${steps[@]}"
|
||||||
|
do
|
||||||
|
setup.${step} > >(tee -a "${logfile}") 2>&1 \
|
||||||
|
|| echo.error "failed during ${step} setup (see above)" \
|
||||||
|
|| return ${ERRORS}
|
||||||
|
done
|
||||||
|
|
||||||
|
echo.status "installation complete: $(date)" 2>> "${logfile}"
|
||||||
|
|
||||||
|
[[ "${logfile}" == /dev/null ]] \
|
||||||
|
|| echo.reminder "logfile can be found at:\n\t${logfile}"
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
echo.success "\n.wryn setup complete; have a nice day :)\n "
|
||||||
|
} "${@}"
|
||||||
|
|||||||
Reference in New Issue
Block a user