diff options
-rw-r--r-- | examples/emacs | 37 | ||||
-rw-r--r-- | examples/golang | 2 | ||||
-rw-r--r-- | examples/keepassxc | 27 | ||||
-rw-r--r-- | examples/lieer | 21 | ||||
-rw-r--r-- | examples/notmuch | 8 | ||||
-rw-r--r-- | examples/tree-sitter | 4 | ||||
-rwxr-xr-x | misc | 277 |
7 files changed, 376 insertions, 0 deletions
diff --git a/examples/emacs b/examples/emacs new file mode 100644 index 0000000..e7348db --- /dev/null +++ b/examples/emacs | |||
@@ -0,0 +1,37 @@ | |||
1 | # misc :: Emacs -*- bash-ts -*- | ||
2 | |||
3 | # Variables | ||
4 | |||
5 | SOURCE=git://git.sv.gnu.org/emacs.git | ||
6 | CHECKOUT=emacs-29 | ||
7 | |||
8 | CONFIGURE_ARGS=( | ||
9 | --prefix="$MISC_INSTALL_PREFIX" | ||
10 | --with-cairo | ||
11 | --with-file-notification=inotify | ||
12 | --with-imagemagick | ||
13 | --with-json | ||
14 | --with-native-compilation=aot # Emacs 29 | ||
15 | --with-tree-sitter=yes # requires tree-sitter | ||
16 | --with-x | ||
17 | --with-x-toolkit=lucid | ||
18 | --with-xinput2 | ||
19 | --with-xml2 | ||
20 | # --with-xwidgets # requires gtk3 | ||
21 | --without-gconf | ||
22 | --without-gsettings | ||
23 | ) | ||
24 | |||
25 | MISC_DEPENDENCIES=( | ||
26 | tree-sitter | ||
27 | ) | ||
28 | |||
29 | # Plan | ||
30 | |||
31 | install_deps | ||
32 | repo_pull | ||
33 | repo_ready extraclean | ||
34 | |||
35 | with_repo ./autogen.sh | ||
36 | configure | ||
37 | make_install bootstrap | ||
diff --git a/examples/golang b/examples/golang new file mode 100644 index 0000000..65265be --- /dev/null +++ b/examples/golang | |||
@@ -0,0 +1,2 @@ | |||
1 | # golang -*- bash-ts -*- | ||
2 | |||
diff --git a/examples/keepassxc b/examples/keepassxc new file mode 100644 index 0000000..cd3cf42 --- /dev/null +++ b/examples/keepassxc | |||
@@ -0,0 +1,27 @@ | |||
1 | # keepassxc -*- bash-ts -*- | ||
2 | |||
3 | SOURCE=https://github.com/keepassxreboot/keepassxc.git | ||
4 | |||
5 | # This is a cmake program | ||
6 | |||
7 | CMAKE_ARGS=( | ||
8 | -DCMAKE_INSTALL_PREFIX="$MISC_INSTALL_PREFIX" | ||
9 | -DCMAKE_BUILD_TYPE="Release" | ||
10 | # Features | ||
11 | -DWITH_XC_AUTOTYPE="ON" # Auto-Type | ||
12 | -DWITH_XC_YUBIKEY="OFF" # YubiKey HMAC-SHA1 authentication support | ||
13 | -DWITH_XC_BROWSER="ON" # KeePassXC-Browser extension support | ||
14 | -DWITH_XC_NETWORKING="ON" # Networking support | ||
15 | -DWITH_XC_SSHAGENT="ON" # SSHAgent support | ||
16 | -DWITH_XC_FDOSECRETS="ON" # Freedesktop.org Secrets Service support | ||
17 | -DWITH_XC_KEESHARE="OFF" # KeeShare group synchronization extension | ||
18 | -DWITH_XC_UPDATECHECK="OFF" # Enable/Disable automatic updating checking | ||
19 | ) | ||
20 | |||
21 | # Plan | ||
22 | |||
23 | repo_pull latest | ||
24 | repo_ready | ||
25 | |||
26 | with_repo '{ mkdir build; cd build; cmake "${CMAKE_ARGS[@]}" ..; }' | ||
27 | _make install | ||
diff --git a/examples/lieer b/examples/lieer new file mode 100644 index 0000000..6c90e64 --- /dev/null +++ b/examples/lieer | |||
@@ -0,0 +1,21 @@ | |||
1 | # lieer -*- bash-ts -*- | ||
2 | |||
3 | SOURCE=https://github.com/gauteh/lieer | ||
4 | |||
5 | APT_DEPENDENCIES=( | ||
6 | python3 | ||
7 | libnotmuch-dev | ||
8 | # hopefully pip will install the rest | ||
9 | ) | ||
10 | |||
11 | # Don't error when we don't have a virtualenv. | ||
12 | export PIP_REQUIRE_VIRTUALENV=false | ||
13 | |||
14 | # Plan | ||
15 | |||
16 | install_deps | ||
17 | repo_pull | ||
18 | repo_ready | ||
19 | |||
20 | with_repo pip3 install --user . | ||
21 | |||
diff --git a/examples/notmuch b/examples/notmuch new file mode 100644 index 0000000..00db730 --- /dev/null +++ b/examples/notmuch | |||
@@ -0,0 +1,8 @@ | |||
1 | # notmuch -*- bash-ts -*- | ||
2 | |||
3 | SOURCE=https://git.notmuchmail.org/git/notmuch | ||
4 | |||
5 | CONFIGURE_ARGS=( | ||
6 | --prefix="$MISC_INSTALL_PREFIX" | ||
7 | ) | ||
8 | |||
diff --git a/examples/tree-sitter b/examples/tree-sitter new file mode 100644 index 0000000..55c723e --- /dev/null +++ b/examples/tree-sitter | |||
@@ -0,0 +1,4 @@ | |||
1 | # Tree-sitter -*- bash-ts -*- | ||
2 | |||
3 | SOURCE="https://github.com/tree-sitter/tree-sitter.git" | ||
4 | |||
diff --git a/misc b/misc new file mode 100755 index 0000000..f9aae4c --- /dev/null +++ b/misc | |||
@@ -0,0 +1,277 @@ | |||
1 | #!/usr/bin/env bash | ||
2 | # Manually Installed and Source-Compiled | ||
3 | |||
4 | usage() { | ||
5 | cat >&2 <<EOF | ||
6 | misc: install programs from source | ||
7 | --- Usage: | ||
8 | misc -h | ||
9 | misc [-d] [-n] [-r DIR] [-p DIR] REPO ... | ||
10 | --- Parameters: | ||
11 | REPO A program to pull from upstream, build, and install locally. | ||
12 | --- Flags: | ||
13 | -h Show this help and exit. | ||
14 | -d DRY RUN: Don't do anything, just print what would happen. | ||
15 | -n NUKE: Delete REPO, then re-download and build. | ||
16 | --- Options: | ||
17 | -r DIR Change the misc repo directory to DIR | ||
18 | (default: $MISC_REPO_ROOT). | ||
19 | -p DIR Change the directory to search for install plans | ||
20 | (default: $MISC_PLAN_ROOT). | ||
21 | -i DIR Change the PREFIX to use when installing programs | ||
22 | (default: $MISC_INSTALL_PREFIX). | ||
23 | EOF | ||
24 | } | ||
25 | |||
26 | ## Entry point | ||
27 | |||
28 | main() { | ||
29 | config "$@" | ||
30 | shift $((OPTIND - 1)) | ||
31 | |||
32 | (($# > 0)) || usage 1 | ||
33 | |||
34 | [[ "$DEBUG" ]] && set -x | ||
35 | |||
36 | # Variables | ||
37 | MISC_PLAN="$1" | ||
38 | shift | ||
39 | |||
40 | MISC_FULL_PLAN="$MISC_PLAN_ROOT/$MISC_PLAN" | ||
41 | MISC_REPO="$MISC_REPO_ROOT/$MISC_PLAN" | ||
42 | MISC_DONE= | ||
43 | |||
44 | SOURCE= | ||
45 | CHECKOUT=master | ||
46 | CONFIGURE_ARGS=() | ||
47 | MISC_DEPENDENCIES=() | ||
48 | APT_DEPENDENCIES=( | ||
49 | build-essential | ||
50 | git | ||
51 | ) | ||
52 | |||
53 | export LD_LIBRARY_PATH="$MISC_INSTALL_PREFIX/lib:$LD_LIBRARY_PATH" | ||
54 | export PKG_CONFIG_PATH="$MISC_INSTALL_PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH" | ||
55 | |||
56 | # Check that plan exists | ||
57 | [[ -r "$MISC_FULL_PLAN" ]] || | ||
58 | die 2 "Plan not found: \"$MISC_PLAN\"" | ||
59 | |||
60 | _MISC_PREVIOUS_DIR="$PWD" | ||
61 | trap finish EXIT INT | ||
62 | |||
63 | if [[ ! "$PWD" == "$MISC_REPO_ROOT" ]]; then | ||
64 | mkdir -p "$MISC_REPO_ROOT" | ||
65 | run cd "$MISC_REPO_ROOT" | ||
66 | fi | ||
67 | |||
68 | . "$MISC_FULL_PLAN" || | ||
69 | die "$?" "Error executing plan: \"$MISC_PLAN\"" | ||
70 | |||
71 | # If the recipe is just variables, run the default plan | ||
72 | if [[ -z "$MISC_DONE" ]]; then | ||
73 | install_deps | ||
74 | repo_pull | ||
75 | repo_ready | ||
76 | configure || true # Not always have configure | ||
77 | make install | ||
78 | fi | ||
79 | } | ||
80 | |||
81 | config() { | ||
82 | MISC_CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}/misc/misc.sh" | ||
83 | [[ -f "$MISC_CONFIG" ]] && . "$MISC_CONFIG" | ||
84 | |||
85 | MISC_REPO_ROOT="${MISC_ROOT:-$XDG_DATA_HOME/misc}" | ||
86 | MISC_PLAN_ROOT="${MISC_PLAN_ROOT:-$XDG_CONFIG_HOME/misc}" | ||
87 | MISC_INSTALL_PREFIX="${MISC_INSTALL_PREFIX:-$HOME/.local}" | ||
88 | _ARGS=() | ||
89 | _DRY_RUN=false | ||
90 | _NUKE=false | ||
91 | DEBUG= | ||
92 | while getopts :hdnvr:p:i: opt; do | ||
93 | case "$opt" in | ||
94 | h) usage ;; | ||
95 | n) | ||
96 | _NUKE=true | ||
97 | _ARGS+=(-n) | ||
98 | ;; | ||
99 | d) | ||
100 | _DRY_RUN=true | ||
101 | _ARGS+=(-d) | ||
102 | ;; | ||
103 | v) | ||
104 | DEBUG=true | ||
105 | _ARGS+=(-v) | ||
106 | ;; | ||
107 | r) | ||
108 | MISC_REPO_ROOT="$OPTARG" | ||
109 | _ARGS+=(-r "$OPTARG") | ||
110 | ;; | ||
111 | p) | ||
112 | MISC_PLAN_ROOT="$OPTARG" | ||
113 | _ARGS+=(-p "$OPTARG") | ||
114 | ;; | ||
115 | i) | ||
116 | MISC_INSTALL_PREFIX="$OPTARG" | ||
117 | _ARGS+=(-i "$OPTARG") | ||
118 | ;; | ||
119 | \?) | ||
120 | log "Unknown flag \"-$OPTARG\"" | ||
121 | usage 1 | ||
122 | ;; | ||
123 | esac | ||
124 | done | ||
125 | } | ||
126 | |||
127 | finish() { | ||
128 | cd "$_MISC_PREVIOUS_DIR" | ||
129 | } | ||
130 | |||
131 | ## Utilities | ||
132 | |||
133 | say() { # say WORD ... | ||
134 | printf '%s\n' "$*" | ||
135 | } | ||
136 | |||
137 | log() { # log WORD ... | ||
138 | say "$@" >&2 | ||
139 | } | ||
140 | |||
141 | die() { # die CODE WORD ... | ||
142 | code="$1" | ||
143 | shift | ||
144 | log "$@" | ||
145 | exit "$code" | ||
146 | } | ||
147 | |||
148 | run() { # run COMMAND ... | ||
149 | log "$@" | ||
150 | if ! "$_DRY_RUN"; then | ||
151 | eval "$@" | ||
152 | fi | ||
153 | } | ||
154 | |||
155 | cmd() { # cmd COMMAND ... | ||
156 | log "$@" | ||
157 | if ! "$_DRY_RUN"; then | ||
158 | command "$@" | ||
159 | fi | ||
160 | } | ||
161 | |||
162 | with_repo() { # with_repo COMMAND ... | ||
163 | ## Run COMMAND in $MISC_REPO. | ||
164 | run cd "$MISC_REPO" || die 4 "No such directory \"$MISC_REPO\"" | ||
165 | run "$@" | ||
166 | } | ||
167 | |||
168 | ## Library | ||
169 | |||
170 | install_deps() { # install_deps | ||
171 | for dep in "${MISC_DEPENDENCIES[@]}"; do | ||
172 | misc "${_ARGS[@]}" "$dep" || | ||
173 | die 60 "Error installing dependency: \"$dep\"" | ||
174 | done | ||
175 | if command -v apt >/dev/null 2>&1; then | ||
176 | for dep in "${APT_DEPENDENCIES[@]}"; do | ||
177 | # XXX: I don't like how hacky this is. | ||
178 | if [[ "$(apt list --installed "$dep" 2>/dev/null | wc -l)" -lt 2 ]]; then | ||
179 | sudo apt install "$dep" || | ||
180 | die 65 "Error installing dependency: \"$dep\"" | ||
181 | fi | ||
182 | done | ||
183 | fi | ||
184 | } | ||
185 | |||
186 | repo_pull() { # repo_pull [CHECKOUT] | ||
187 | ## Pull the latest CHECKOUT from $REPO. | ||
188 | MISC_DONE=1 | ||
189 | local source checkout | ||
190 | checkout="${1:-$CHECKOUT}" | ||
191 | |||
192 | { [[ -n "$SOURCE" ]] || "$_DRY_RUN"; } || | ||
193 | die 10 "No source specified for \"$MISC_PLAN\"" | ||
194 | |||
195 | if [[ -d "$MISC_REPO" ]]; then | ||
196 | git pull origin "$checkout" || | ||
197 | die "$?" "Error running 'git pull'" | ||
198 | git checkout "$checkout" || | ||
199 | die "$?" "Error running 'git checkout'" | ||
200 | else | ||
201 | _git clone -b "$checkout" "$SOURCE" "$MISC_REPO" || | ||
202 | die "$?" "Error running 'git clone'" | ||
203 | fi | ||
204 | } | ||
205 | |||
206 | repo_download_extract() { # repo_download_extract | ||
207 | run 'curl -RL "$SOURCE" | tar -zxf-' | ||
208 | } | ||
209 | |||
210 | repo_ready() { # repo_ready [TARGET ...] | ||
211 | ## Ready $MISC_ for building. | ||
212 | ## If TARGET ... is specified, they're passed to make; otherwise `make | ||
213 | ## clean` is run in the repo directory. | ||
214 | MISC_DONE=1 | ||
215 | { [[ -d "$MISC_REPO" ]] || "$_DRY_RUN"; } || | ||
216 | die 20 "No directory for \"$MISC_PLAN\"" | ||
217 | make "${@:-clean}" | ||
218 | if git status >/dev/null 2>&1; then | ||
219 | git clean -dxf | ||
220 | fi | ||
221 | } | ||
222 | |||
223 | repo_nuke() { # repo_nuke | ||
224 | ## Fully remove $MISC_FULL_PLAN | ||
225 | { [[ -n "$MISC_REPO" ]] || "$_DRY_RUN"; } || | ||
226 | die 40 "No directory to remove" | ||
227 | run rm -rf "$MISC_REPO" | ||
228 | } | ||
229 | |||
230 | ## Commands (with arguments) | ||
231 | |||
232 | make() { | ||
233 | MISC_DONE=1 | ||
234 | cmd make \ | ||
235 | -C "$MISC_REPO" \ | ||
236 | PREFIX="$MISC_INSTALL_PREFIX" \ | ||
237 | "$@" | ||
238 | } | ||
239 | _make() { cmd make "$@"; } | ||
240 | |||
241 | make_install() { | ||
242 | MISC_DONE=1 | ||
243 | if make "$@"; then | ||
244 | make install | ||
245 | else | ||
246 | die 23 "Make error in \"$MISC_PLAN\": $@" | ||
247 | fi | ||
248 | } | ||
249 | |||
250 | configure() { | ||
251 | MISC_DONE=1 | ||
252 | if (($# == 0)); then | ||
253 | with_repo ./configure "${CONFIGURE_ARGS[@]}" | ||
254 | else | ||
255 | with_repo ./configure "$@" | ||
256 | fi | ||
257 | } | ||
258 | |||
259 | git() { | ||
260 | cmd git \ | ||
261 | -C "$MISC_REPO" \ | ||
262 | "$@" | ||
263 | } | ||
264 | _git() { cmd git "$@"; } | ||
265 | |||
266 | tar() { | ||
267 | cmd tar \ | ||
268 | -C "$MISC_REPO" \ | ||
269 | "$@" | ||
270 | } | ||
271 | _tar() { cmd tar "$@"; } | ||
272 | |||
273 | ## Finally ... | ||
274 | |||
275 | if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then | ||
276 | main "$@" | ||
277 | fi | ||