-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbootstrap.sh
More file actions
86 lines (76 loc) · 4.25 KB
/
Copy pathbootstrap.sh
File metadata and controls
86 lines (76 loc) · 4.25 KB
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
#!/usr/bin/env bash
# Clone/update CustomPiOS into ./CustomPiOS (gitignored).
#
# CUSTOMPIOS_REF pins the upstream revision. Prefer a full 40-char commit
# SHA: upstream's tags are lightweight and can be force-moved, a SHA cannot.
# Branch names and tags are accepted too, but they float by definition.
#
# Why this script is more than a `git clone`: `git clone --branch` rejects a
# bare SHA, and a `git fetch <tag>` on a shallow clone writes only FETCH_HEAD
# without creating a local ref - so the naive `fetch && checkout <ref>` pair
# silently keeps the OLD tree. That is exactly how CI sat frozen on CustomPiOS
# 1.5.0 for 20 months while claiming to track master. We therefore fetch the
# ref explicitly, check out FETCH_HEAD, and verify the resulting HEAD.
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CUSTOMPIOS_DIR="$ROOT/CustomPiOS"
CUSTOMPIOS_URL="${CUSTOMPIOS_URL:-https://github.com/guysoft/CustomPiOS.git}"
# CustomPiOS 2.0.0. Moving this ref is a deliberate act: v2 requires the
# python3-git / python3-yaml host packages installed by the CI workflow.
CUSTOMPIOS_REF="${CUSTOMPIOS_REF:-d293309aac2f606c609645b441962c8f02b6e8c3}"
# A 40-char hex string is a commit SHA; anything else is a branch or tag name.
# Case-insensitive: git accepts an uppercase SHA, so we must too - otherwise
# an uppercase pin would silently skip both the short-circuit and the drift check.
is_sha() { [[ "$1" =~ ^[0-9a-fA-F]{40}$ ]]; }
# git always reports lowercase, so compare against a normalised copy -
# otherwise an uppercase pin would fail the drift check against itself.
REF_LC="$(printf '%s' "$CUSTOMPIOS_REF" | tr '[:upper:]' '[:lower:]')"
# CustomPiOS ships no .gitattributes, so a host with a global
# core.autocrlf=true (every default Git for Windows install) checks out
# src/common.sh and src/custompios with CRLF. Both are sourced inside the
# build container, where a trailing ^M is not whitespace - `unpack` and the
# module scripts then fail in ways that look like anything but line endings.
# Pin the setting on this repo instead of trusting the host's global config.
if [[ -d "$CUSTOMPIOS_DIR/.git" ]]; then
git -C "$CUSTOMPIOS_DIR" config core.autocrlf false
git -C "$CUSTOMPIOS_DIR" config core.eol lf
# A tree checked out before that setting existed is still CRLF on disk.
# With autocrlf off those files no longer match their blobs, so a forced
# checkout restores them. Without this the cache-hit path below would
# short-circuit on a corrupted tree forever - it never re-checks out.
if [[ -n "$(git -C "$CUSTOMPIOS_DIR" status --porcelain 2>/dev/null)" ]]; then
echo "[bootstrap] normalising CustomPiOS line endings"
git -C "$CUSTOMPIOS_DIR" checkout -q -f -- .
fi
fi
# Already at the requested revision? Nothing to do. This is the cache-hit
# path and must stay cheap - no network round-trip.
if [[ -d "$CUSTOMPIOS_DIR/.git" ]] \
&& is_sha "$CUSTOMPIOS_REF" \
&& [[ "$(git -C "$CUSTOMPIOS_DIR" rev-parse HEAD 2>/dev/null || true)" == "$REF_LC" ]]; then
echo "[bootstrap] CustomPiOS already at $CUSTOMPIOS_REF"
exit 0
fi
if [[ ! -d "$CUSTOMPIOS_DIR/.git" ]]; then
echo "[bootstrap] initialising CustomPiOS from $CUSTOMPIOS_URL"
rm -rf "$CUSTOMPIOS_DIR"
git init -q "$CUSTOMPIOS_DIR"
# Before the first fetch, so the initial checkout is LF on every host.
git -C "$CUSTOMPIOS_DIR" config core.autocrlf false
git -C "$CUSTOMPIOS_DIR" config core.eol lf
git -C "$CUSTOMPIOS_DIR" remote add origin "$CUSTOMPIOS_URL"
fi
echo "[bootstrap] fetching $CUSTOMPIOS_REF"
# GitHub serves arbitrary reachable SHAs (uploadpack.allowAnySHA1InWant), so a
# depth-1 fetch of an exact commit works. For a branch/tag name the same call
# resolves it server-side; either way the result lands in FETCH_HEAD.
git -C "$CUSTOMPIOS_DIR" fetch --depth 1 --quiet origin "$CUSTOMPIOS_REF"
git -C "$CUSTOMPIOS_DIR" checkout -q -f FETCH_HEAD
HEAD_SHA="$(git -C "$CUSTOMPIOS_DIR" rev-parse HEAD)"
# Fail loudly on drift. The previous version ended in `|| true`, which is how
# a broken update went unnoticed for 20 months.
if is_sha "$CUSTOMPIOS_REF" && [[ "$HEAD_SHA" != "$REF_LC" ]]; then
echo "[bootstrap] ERROR: HEAD is $HEAD_SHA but $CUSTOMPIOS_REF was requested" >&2
exit 1
fi
echo "[bootstrap] CustomPiOS HEAD: $HEAD_SHA"