aboutsummaryrefslogtreecommitdiff
path: root/kiss-new
blob: 2667553d50ae9045cf37afaa5f8888b82a324620 (plain)
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
#!/bin/sh -e
#
# This is a simple package manager written in POSIX 'sh' for
# KISS Linux utlizing the core unix utilites where needed.
#
# The script runs with 'set -e' enabled. It will exit on any
# non-zero return code. This ensures that no function continues
# if it fails at any point.
#
# Keep in mind that this involves extra code in the case where
# an error is optional or required.
#
# Where possible the package manager should "error first".
# Check things first, die is necessary and continue if all is well.
#
# The code below conforms to shellcheck's rules. However, some
# lint errors *are* disabled as they relate to unexpected
# behavior (which we do expect).
#
# KISS is available under the MIT license.
#
# - Dylan Araps.

die() {
    # Print a message and exit with '1' (error).
    printf '\033[31m!>\033[m %s\n' "$@" >&2
    exit 1
}

log() {
    # Print a message with a colorful arrow to distinguish
    # from other output.
    printf '\033[32m=>\033[m %s\n' "$@"
}

pkg_search() {
    # Figure out which repository a package belongs to by
    # searching for directories matching the package name
    # in $KISS_PATH/*.
    [ "$KISS_PATH" ] || \
        die "\$KISS_PATH needs to be set." \
            "Example: KISS_PATH=/packages/core:/packages/extra:/packages/xorg" \
            "Repositories will be searched in the configured order." \
            "The variable should work just like \$PATH."

    # Disable globbing with 'set -f' to ensure that the unquoted
    # variable doesn't expand into anything nasty.
    # shellcheck disable=2086,2046
    {
        set -f
        set -- "$1" $(IFS=:; find $KISS_PATH -maxdepth 1 -name "$1")
        set +f
    }

    # A package may also not be found due to a repository not being
    # readable by the current user. Either way, we need to die here.
    [ -z "$2" ] && die "Package '$1' not in any repository."

    printf '%s\n' "$2"
}

pkg_list() {
    # List installed packages. As the format is files and
    # diectories, this just involves a simple for loop and
    # file read.

    # Changing directories is similar to storing the full
    # full path in a variable, only there is no variable as
    # you can access children relatively.
    cd "$KISS_ROOT/var/db/kiss" || \
        die "KISS database doesn't exist or is inaccessible."

    # Optional arguments can be passed to check for specific
    # packages. If no arguments are passed, list all. As we
    # loop over '$@', if there aren't any arguments we can
    # just set the directory contents to the argument list.
    [ "$1" ] || set -- *

    # Loop over each version file and warn if one doesn't exist.
    # Also warn if a package is missing its version file.
    for pkg; do
        [ -d "$pkg" ] || {
            log "Package '$pkg' is not installed."
            return 1
        }

        [ -f "$pkg/version" ] || {
            log "Warning: Package '$pkg' has no version file."
            return
        }

        read -r version release < "$pkg/version" &&
            printf '%s\n' "${pkg%/*} $version-$release"
    done
}

args() {
    # Parse script arguments manually. POSIX 'sh' has no 'getopts'
    # or equivalent built in. This is rather easy to do in our case
    # since the first argument is always an "action" and the arguments
    # that follow are all package names.

    # Actions can be abbreviated to their first letter. This saves
    # keystrokes once you memorize themand it also has the side-effect
    # of "correcting" spelling mistakes assuming the first letter is
    # right.
    while [ "${1:-?}" ]; do
        case $1 in
            # Build the list of packages.
            b*)

            ;;

            # List installed packages.
            l*)
                shift
                pkg_list "$@"
                exit
            ;;

            # Print version and exit.
            v*)
                log "$kiss 0.1.10"
                exit
            ;;

            # Catch all invalid arguments as well as
            # any help related flags (-h, --help, help).
            *)
                log "$kiss [b|c|i|l|r|u] [pkg]" \
                    "build:     Build a package." \
                    "checksum:  Generate checksums." \
                    "install:   Install a package (Runs build if needed)." \
                    "list:      List packages." \
                    "remove:    Remove a package." \
                    "update:    Check for updates."
                exit
            ;;
        esac
    done
}

main() {
    kiss=${0##*/}

    args "$@"
}

main "$@"