about summary refs log tree commit diff stats
path: root/common/init
blob: 8d8a2d07f13c49ba95b50febdfb4280997f2cda4 (plain) (blame)
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
#!/usr/bin/env sh

self_dir="$(realpath "$(dirname "$0")")"
self="$(realpath "$0")"

# shellcheck source=/dev/null
. "$self_dir/shell_line_editor.sh"

replacement_file="$(mktemp)"

trap cleanup INT
trap "cleanup; remove_self" EXIT
cleanup() {
    rm "$replacement_file"
}
avoid_cleanup="false"
remove_self() {
    if [ "$avoid_cleanup" = "false" ]; then
        rm "$(realpath "$0")"
        rm "$(realpath "$(dirname "$0")")/shell_line_editor.sh"
        [ -f "$(realpath "$(dirname "$0")")/init.local" ] && rm "$(realpath "$(dirname "$0")")/init.local"
    fi
}
require() {
    program="$1"
    if ! command -v "$program" >/dev/null; then
        avoid_cleanup="true"
        echo "Please install '$program' for this init script to work." 1>&2
        exit 1
    fi
}
die() {
    printf "init: ERROR: %s\n" "$1"
    exit 1
}
quotify() {
    python -c "
import sys
if len(sys.argv) > 1:
    text =''.join(sys.argv[1:])
else:
    text = sys.stdin.read()
quoted_text = text.replace(\"'\", \"'\\\\''\")
print(f\"'{quoted_text}'\", end='')" "$@"
}

# Prompt the user for a specific variable.
# ## Args:
# [1]: Name of the variable to populate the answer to
# [2]: An optional description
# [3]: An optionally suggested answer
# [4]: If this is set, the user is not even asked.
prompt() {
    pr_variable_upper="$(echo "$1" | sed 's/\([a-z]\)/\U\1/')"
    pr_description="$2"
    pr_suggested_answer="$3"
    pr_ask="$4"

    if [ -n "$pr_ask" ]; then
        REPLY="$pr_suggested_answer"
    else
        printf "\033[94;1mEnter %s\033[0m" "$pr_variable_upper"
        if [ -n "$pr_description" ]; then
            printf " (\033[93;1m%s\033[0m):\n" "$pr_description"
        else
            printf ":\n"
        fi

        # LE "> " 0 " " "$pr_suggested_answer" "yes_please_produce_debug_output"
        LE "> " 0 " " "$pr_suggested_answer" ""
    fi

    pr_new_variable="$(printf '%s=%s' "$pr_variable_upper" "$(quotify "$REPLY")")"

    eval "$pr_new_variable"
    printf "%s\n" "$pr_new_variable" >>"$replacement_file"
}

require git

require jq
require curl

require fd
require mv
require sed
require chmod

require python

# necessary meta data
prompt APPLICATION_NAME "The name of the application" "$(basename "$PWD")"
prompt APPLICATION_NAME_STYLIZED "The stylized name of the application (for documentation)" "$(echo "$APPLICATION_NAME" | sed 's/[_-]/ /g' | sed 's/^\(\w\)/\U\1/g' | sed 's/ \(\w\)/ \U\1/g')"
prompt APPLICATION_NAME_CAPITALIZED_MAN_PART "The capitalized name of the application (for documentation also with a man section part)" "$(echo "$APPLICATION_NAME" | sed 's/_/-/g' | sed 's/\(.*\)/\U\1(1)/')" "dont_ask"
prompt APPLICATION_VERSION "The version of this program, without the prefix" "0.1.0"

prompt AUTHOR_NAME "The name of the author (or authors)" "$(git config --get user.name)"
prompt AUTHOR_EMAIL "The email of the author (or authors)" "$(git config --get user.email)"

# cog change-log variables
prompt REMOTE "The remote, this project will be pushed to" "git.vhack.eu"
prompt REPOSITORY "The path of the repository on the remote" "$APPLICATION_NAME"

owner1="$(printf "%.1s" "$AUTHOR_NAME")"
owner2="${AUTHOR_NAME#* }"
if [ "$owner2" = "$AUTHOR_NAME" ]; then
    owner_build="$(echo "$AUTHOR_NAME" | tr '[:upper:]' '[:lower:]')"
else
    owner_build="$(echo "$owner1$owner2" | tr '[:upper:]' '[:lower:]')"
fi
prompt OWNER "The name of owner of the repository" "$owner_build"

# nice meta data
prompt DESCRIPTION "The description of this project" ""
prompt CURRENT_DATE "The stylized version of the current date" "$(date +'%b %Y')"
prompt YEAR "The year the work on this has begun (for copyright reasons)" "$(date +'%Y')"
prompt APPLICATION_SOURCE_CODE_REPOSITORY "The package's source code repository URL" "https://$REMOTE/$OWNER/$REPOSITORY"
prompt HOME_PAGE "The home page URL of the project" "https://$REPOSITORY.org/"
prompt BUG_URL "The URL people should report bugs to" "$APPLICATION_SOURCE_CODE_REPOSITORY/issues"

# git stuff
prompt PUSH_URL "The url used to push this project" "git@$REMOTE:$OWNER/$REPOSITORY.git"
prompt CLONE_URL "The url used to clone this project" "git@$REMOTE:$OWNER/$REPOSITORY.git"
prompt MAIN_BRANCH "The name of the main branch" "$(git config init.defaultbranch)"

if [ -e ./watch.sh ]; then
    # Use a different default license in latex projects.
    init_default_license="CC-BY-SA-4.0"
else
    init_default_license="AGPL-3.0-or-later"
fi
prompt SPDX_LICENSE_IDENTIFIER "THE SPDX identifer of your choosen license" "$init_default_license"

default_license_url="$(curl --silent --show-error "https://spdx.org/licenses/$SPDX_LICENSE_IDENTIFIER.json" | jq --raw-output '.seeAlso[0]')"

# Prefer possible text versions of the license
if curl --fail --silent --show-error "$default_license_url.txt" >/dev/null; then
    default_license_url="$default_license_url.txt"
fi
prompt LICENSE_URL "The url of the license" "$default_license_url"

if [ -e ./.reuse/templates/default.jinja2 ]; then
    if [ -n "$DESCRIPTION" ]; then
        description_str=" - $DESCRIPTION"
    else
        description_str=""
    fi

    cat <<EOF | fmt --uniform-spacing --width=85 --split-only >./.reuse/templates/default.jinja2
{% for copyright_line in copyright_lines %}
{{ copyright_line }}
{% endfor %}
{% for contributor_line in contributor_lines %}
SPDX-FileContributor: {{ contributor_line }}
{% endfor %}
{% for expression in spdx_expressions %}
SPDX-License-Identifier: {{ expression }}
{% endfor %}

This file is part of $APPLICATION_NAME_STYLIZED$description_str.

You should have received a copy of the License along with this program.
If not, see <$LICENSE_URL>.
EOF
fi

# Allow templates to add template specific prompts
[ -e init.local ] && . ./init.local

git init --initial-branch "$MAIN_BRANCH" --template="./git_template"
rm --recursive ./git_template

while read -r var; do
    var_name="${var%=*}"
    var_value="${var#*=\"}"
    var_value="${var_value%\"}"

    fd . --hidden --type file --exec sed --in-place "s|%\bINIT_$var_name\b|$var_value|g"

    # Replace the variable in file paths
    fd "%INIT_$var_name" . --hidden | while read -r file_path; do
        new_file_path="$(echo "$file_path" | sed "s|%INIT_$var_name|$var_value|g")"
        mv "$file_path" "$new_file_path"
    done
done <"$replacement_file"

if [ "$(rg "%INIT_" --files-with-matches --glob="!/init" | wc -l)" -ne 0 ]; then
    echo "Following init variables were not replaced. This is a bug."
    rg "%INIT_" --glob="!/init"
fi

# HACK: Re-add the executable permissions to files, which the nix template has somehow
# removed <2024-04-02>
chmod +x scripts/*
chmod +x update.sh
[ -f ./build.sh ] && chmod +x build.sh
[ -f ./watch.sh ] && chmod +x build.sh

# Do the first run of reuse annotate
reuse="$(nix build nixpkgs#reuse.out --no-link --print-out-paths)/bin/reuse"
[ "$(echo "$reuse" | wc -l)" -ne 1 ] && die "Something is wrong with the nixpkgs#reuse derivation"

git add .

cp "$replacement_file" ".git/init_variables_$(date --iso-8601=date)"

git diff --name-only --cached |
    xargs -I {} "$reuse" annotate \
        --copyright "$AUTHOR_NAME <$AUTHOR_EMAIL>" \
        --copyright-style string-c \
        --template default \
        --license "$SPDX_LICENSE_IDENTIFIER" "{}"

# vim: ft=sh