1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
|
# KISS Package Manager
Some extra information which isn't available on <https://kisslinux.github.io/wiki/package-manager>.
## [%[0.0]] Index
- [1.0](#1.0) Interesting Features
- [1.1](#1.1) Runtime dependency detector built around 'ldd'
- [1.2](#1.2) Fully dynamic (and automatic) alternatives system
- [1.3](#1.3) 3-way handshake for files in /etc/
- [2.0](#2.0) Repositories
- [2.1](#2.1) What is a repository?
- [2.2](#2.2) Enabling a remote repository
- [2.3](#2.3) Preventing a package from receiving updates
- [2.4](#2.4) Package fallbacks
- [2.5](#2.5) Bypassing KISS\_PATH
- [3.0](#3.0) Hook examples
- [3.1](#3.1) Logging build duration
- [3.2](#3.2) Setting the terminal title
- [3.3](#3.3) Drop into shell on build fail
- [4.0](#4.0) Tips and Tricks
- [4.1](#4.1) Swap grep implementations for a major speed up
- [4.2](#4.2) Shallow cloning
## [%[1.0]] Interesting Features
### [%[1.1]] Runtime dependency detector built around 'ldd'
Dynamic dependencies brought in by build systems (which are missing from the
package's dependency list) are fixed on-the-fly by checking which libraries link
to the package's files.
This prevents an incomplete dependency list from causing system breakage as the
package manager is able to complete the list.
A lot of packages make use of this "implicit" to "explicit" dependency list
"conversion" to provide optional dependencies.
Example output:
-> libXmu Checking for missing dependencies
--- /home/dylan/conf/cache/kiss/build-4477/depends
+++ depends
@@ -1,3 +1,8 @@
+libX11
+libXau
libXext
libXt
+libxcb
xorg-util-macros make
### [%[1.2]] Fully dynamic (and automatic) alternatives system
Any file conflicts between two packages automatically become choices in the
alternatives system.
This allows one to swap providers of files without needing to explicitly
tell the package manager that two packages conflict, provide the same
utilities, etc.
In other words, no changes need to be made to packages. In fact, nothing
needs to be done at all. It's entirely automatic.
List available alternatives ('a' is an alias to 'alternatives'):
$ kiss a
gnugrep /usr/bin/grep
ncurses /usr/bin/clear
Swap to GNU grep:
$ kiss a gnugrep /usr/bin/grep
-> Swapping '/usr/bin/grep' from busybox to gnugrep
Swap back to busybox grep:
$ kiss a busybox /usr/bin/grep
-> Swapping '/usr/bin/grep' from gnugrep to busybox
Swap to all alternatives for a given package (sbase for example):
$ kiss a | grep ^sbase | kiss a -
-> Swapping '/usr/bin/cat' from busybox to sbase
-> Swapping '/usr/bin/cut' from busybox to sbase
-> Swapping '/usr/bin/yes' from busybox to sbase
...
The above command works as the output of the alternatives listing is
directly usable as input to 'kiss a'.
### [%[1.3]] 3-way handshake for files in /etc/
Files in /etc/ are handled differently to those elsewhere on the system. A
reinstallation or update to a package will not always overwrite these files.
Instead, a 3-way handshake happens during installation to determine how the
new /etc/ file should be handled.
If the user has made modifications to the file and those modifications
differ to the to-be-installed package's file, the file is installed with the
suffix '.new'.
If the user hasn't touched the file, it will be automatically overwritten by
the package manager as it will contain updated/new contents..
If the user has touched the file but the file has not changed between
package versions, it will simply be skipped over.
## [%[2.0]] Repositories
Repository management in KISS is very simple. Repositories are configurable via
an environment variable. This environment variable can be set system-wide,
per-user, conditionally (via a script or program), for a single invocation, etc.
The environment variable is called `KISS_PATH` and is functionally identical to
the `$PATH` variable. A colon separated list of paths, in other words.
For example,
$ KISS_PATH=/var/db/kiss/repo/core:/var/db/kiss/repo/extra
In the above example, two repositories are enabled (Core and Extra). The package
manager will search this list for packages in the order it is written.
Repositories can live anywhere on the system. In your `$HOME` directory,
somewhere system-wide in '/', etc. The only requirement is that a full path be
used.
### [%[2.1]] What is a repository?
A KISS repository is simply a directory of directories. The quickest way to
get started is as follows.
Create the repository:
$ mkdir -p repo
$ cd repo
Let's "fork" a few packages into our new repository.
$ kiss fork curl
$ kiss fork xz
$ kiss fork zlib
This is now a fully usable repository and it can be added to your `KISS_PATH`.
### [%[2.2]] Enabling a remote repository
Let's assume that our `KISS_PATH` matches the above example (Core and Extra).
As an example, we'll be enabling the Community repository. First, clone it:
# This can live anywhere on the system.
$ git clone https://codeberg.org/kiss-community/community
Now, enable the repository:
$ export KISS_PATH=$KISS_PATH:/path/to/community/community
### [%[2.3]] Preventing a package from receiving updates
Preventing a package from receiving updates can be accomplished in a myriad
of different ways. The easiest method is to leverage a user repository.
Create a new repository:
$ mkdir -p no_updates
$ cd no_updates
Copy the package to the new repository:
$ cp -r /var/db/kiss/installed/PKG_NAME /path/to/no_updates
Add the new repository to the **START** of your `KISS_PATH`:
$ export KISS_PATH=/path/to/no_updates:$KISS_PATH
The package manager will search `KISS_PATH` in order. It will see that the
no\_updates repository provides PKG\_NAME and the version matches that which
is installed. No updates will again happen for the package.
### [%[2.4]] Package fallbacks
If you would like to package something in your own repository but would
like the package manager to prefer other repositories before yours, simply
add your repository to the end of `KISS_PATH`.
The moment that your package is available elsewhere, the package manager
will prefer the new location to yours. The list is searched (in order) and
the first match is picked.
### [%[2.5]] Bypassing KISS\_PATH
There is a special case where one can bypass the regular KISS\_PATH for a
single invocation of the package manager. This has been called "CRUX-like
usage" by users.
$ cd /path/to/myrepo/firefox
$ kiss b
$ kiss i
As seen above, various package manager commands will work without arguments,
so long as you are in a package's repository directory. This will prepend
the current directory to '$KISS\_PATH' _only_ for this invocation.
## [%[3.0]] Hook examples
### [%[3.1]] Logging build duration
This hook adds a new message post-build with the total build duration in a
human readable format (00h 00m). Similar code is used in the boot process
of the system to calculate boot time.
PKG="$2"
case $1 in
pre-build)
cat /proc/uptime > "${KISS_TMPDIR:-/tmp}/_kiss_start"
;;
post-build)
IFS=. read -r _start _ < "${KISS_TMPDIR:-/tmp}/_kiss_start"
IFS=. read -r _end _ < /proc/uptime
rm -f "${KISS_TMPDIR:-/tmp}/_kiss_start"
(
_s=$((_end - _start))
_h=$((_s / 60 / 60 % 24))
_m=$((_s / 60 % 60))
[ "$_h" = 0 ] || _u="${_u}${_h}h "
[ "$_m" = 0 ] || _u="${_u}${_m}m "
printf "-> %s %s\n" "$PKG" "Build finished in ${_u:-${_s}s}"
)
;;
esac
### [%[3.2]] Setting the terminal title
This hook uses the Xterm escape sequence to change the terminal title, which
is supported by most modern terminal emulators. The title will include the
name of the package currently being build, the position in the batch and the
total amount of packages to be built. That way it's easy to keep track of
build progress, without having to scroll past a wall of compiler output.
case $1 in
queue-status|queue)
[ -t 2 ] && {
printf '\033]0;kiss: %s (%d/%d)\a' \
"$2" "${3:-?}" "${4:-?}" >&2
}
;;
esac
### [%[3.3]] Drop into shell on build fail
case $1 in
build-fail)
printf "-> %s %s\a\n" "$2" "Dropped into shell"
sh >/dev/tty
;;
esac
## [%[4.0]] Tips and Tricks
A lot of the package manager's features are hard to discover or otherwise
non-obvious to its users. This section will document these features, how to use
them and the benefits they bring.
### [%[4.1]] Swap grep implementations for a major speed up
The default grep implementation in KISS is busybox grep. This version of
grep works very well and supports a large number of features. The one issue
is that it is painfully slow when compared to other popular implementations.
A fairly major speedup can be attained by swapping to a different grep via
the alternatives system. The fastest grep implementation around is GNU grep
which is available in Community as 'gnugrep'.
$ kiss b gnugrep && kiss i gnugrep
$ kiss a gnugrep /usr/bin/grep
### [%[4.2]] Shallow cloning
By default, the package manager performs a shallow clone of the remote
repository, branch, or commit whenever possible. This is to speedup cloning,
and for most packages does not alter the package building process. This
shallow cloning is done in a way which still allows `git describe`.
For packages which require submodules, add `git submodule update --init` to
pull in the required submodules.
|