-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·148 lines (133 loc) · 6.68 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·148 lines (133 loc) · 6.68 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
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
#!/usr/bin/env bash
# mainstreamos.org/install.sh — verbatim mirror of dots-hyprland/install.sh, so the
# short install URL works: bash <(curl -fsSL https://mainstreamos.org/install.sh)
# Keep in sync with:
# https://github.com/MainstreamOS/dots-hyprland/blob/mainstream/install.sh
#
# Mainstream OS dotfiles bootstrap.
#
# One-line install:
# bash <(curl -fsSL https://raw.githubusercontent.com/MainstreamOS/dots-hyprland/mainstream/install.sh)
#
# Installs the newest numbered release — the same one the ISO ships and
# Settings -> Update tracks. Pass --edge to install the mainstream branch as it
# stands instead, ahead of any release:
# bash <(curl -fsSL ...) --edge
#
# Override defaults via env (export before running):
# MS_REPO_URL, MS_REPO_BRANCH, MS_CLONE_DIR
#
# Anything passed after a `--` is forwarded to ./setup install, e.g.:
# bash <(curl -fsSL ...) -- --verbose
# bash <(curl -fsSL ...) --edge -- --console
set -euo pipefail
REPO_URL="${MS_REPO_URL:-https://github.com/MainstreamOS/dots-hyprland.git}"
REPO_BRANCH="${MS_REPO_BRANCH:-mainstream}"
CLONE_DIR="${MS_CLONE_DIR:-$HOME/.cache/dots-hyprland}"
# The same 1-2 digit major cap updatems uses, so the installer and the updater
# can never disagree about which tag is newest, and the retired date tags
# (2026.05.11) can't sort above a real release.
TAG_REGEX='^[0-9]{1,2}\.[0-9]+\.[0-9]+$'
TAG_GLOB='[0-9]*.[0-9]*.[0-9]*'
MARKER="$CLONE_DIR/.updatems-applied-tag"
EDGE=0
SETUP_ARGS=()
while [[ $# -gt 0 ]]; do
case "$1" in
--edge) EDGE=1; shift ;;
--) shift; SETUP_ARGS=("$@"); break ;;
*) printf 'Unknown option: %s\n' "$1" >&2
printf 'Flags for the installer itself go after a "--" separator.\n' >&2
exit 1 ;;
esac
done
# --- pretty output ----------------------------------------------------------
_c_blue=$'\e[38;5;80m'; _c_green=$'\e[38;5;79m'; _c_red=$'\e[38;5;203m'; _c_rst=$'\e[0m'
say() { printf '%s==>%s %s\n' "$_c_blue" "$_c_rst" "$*"; }
ok() { printf '%s✓%s %s\n' "$_c_green" "$_c_rst" "$*"; }
die() { printf '%s✗ %s%s\n' "$_c_red" "$*" "$_c_rst" >&2; exit 1; }
# --- preflight --------------------------------------------------------------
[[ $EUID -ne 0 ]] || die "Don't run as root — Mainstream installs into your user account."
if ! command -v pacman >/dev/null 2>&1; then
die "pacman not found. Mainstream OS targets Arch Linux / Arch-based distros."
fi
if ! command -v git >/dev/null 2>&1; then
say "git not found, installing via pacman..."
sudo pacman -Sy --needed --noconfirm git
fi
if ! command -v sudo >/dev/null 2>&1; then
die "sudo is required for the installer."
fi
# --- fetch the dotfiles -----------------------------------------------------
if [[ $EDGE -eq 1 ]]; then CHANNEL="edge ($REPO_BRANCH branch)"; else CHANNEL="release"; fi
say "Mainstream OS dotfiles bootstrap"
printf " repo: %s\n" "$REPO_URL"
printf " channel: %s\n" "$CHANNEL"
printf " target: %s\n\n" "$CLONE_DIR"
if [[ -d "$CLONE_DIR/.git" ]]; then
say "Existing clone at $CLONE_DIR — fetching latest $REPO_BRANCH..."
# A clone that has lost an object cannot be fetched into, and this script
# reuses whatever is already at $CLONE_DIR, so one damaged object made a
# fresh install fail the same way updatems and repair had just failed. The
# clone is a cache. When the fetch fails with the signature of a damaged
# repository, set it aside and clone again, carrying the applied-tag marker
# across so the desktop still knows which release it has. Anything else
# that makes the fetch fail, a dropped connection say, still stops here.
if ! _fetch_out=$(git -C "$CLONE_DIR" fetch --tags --force origin "$REPO_BRANCH" 2>&1); then
printf '%s\n' "$_fetch_out" >&2
if grep -qE 'is empty|bad object|did not send all necessary objects|corrupt|unable to read|could not read' <<<"$_fetch_out"; then
_aside="${CLONE_DIR}.corrupt-$(date +%Y%m%d-%H%M%S)"
_saved_marker=""
[[ -f "$MARKER" ]] && _saved_marker=$(<"$MARKER")
say "The clone at $CLONE_DIR is damaged. Setting it aside as $_aside and cloning again."
mv "$CLONE_DIR" "$_aside"
git clone --branch "$REPO_BRANCH" "$REPO_URL" "$CLONE_DIR"
[[ -n "$_saved_marker" ]] && printf '%s\n' "$_saved_marker" > "$MARKER"
git -C "$CLONE_DIR" fetch --tags --force origin "$REPO_BRANCH"
say "Fresh clone in place. Any local edits are still in $_aside."
else
die "git fetch failed"
fi
fi
# If the user has local changes, fail loud rather than blow them away.
if ! git -C "$CLONE_DIR" diff --quiet || ! git -C "$CLONE_DIR" diff --cached --quiet; then
die "Local changes in $CLONE_DIR. Commit/stash them or set MS_CLONE_DIR to a fresh path."
fi
else
say "Cloning $REPO_URL ($REPO_BRANCH) → $CLONE_DIR..."
mkdir -p "$(dirname "$CLONE_DIR")"
git clone --branch "$REPO_BRANCH" "$REPO_URL" "$CLONE_DIR"
fi
# Both channels land on a branch rather than a detached HEAD: setup's branch
# detection tries to bounce a detached HEAD back to main/master, and neither
# exists in this clone.
if [[ $EDGE -eq 1 ]]; then
git -C "$CLONE_DIR" checkout "$REPO_BRANCH"
git -C "$CLONE_DIR" reset --hard "origin/$REPO_BRANCH"
# Named for the release it descends from, so the desktop still has a
# version to show and updatems doesn't treat the install as unversioned.
MARKER_TAG=$(git -C "$CLONE_DIR" describe --tags --abbrev=0 --match "$TAG_GLOB" 2>/dev/null || true)
say "Branch tip: $(git -C "$CLONE_DIR" rev-parse --short HEAD) (after ${MARKER_TAG:-no release tag})"
else
MARKER_TAG=$(git -C "$CLONE_DIR" tag --list --format='%(refname:strip=2)' \
| grep -E "$TAG_REGEX" | sort -V | tail -n1 || true)
[[ -n "$MARKER_TAG" ]] \
|| die "No release tag found in $REPO_URL. Pass --edge to install the $REPO_BRANCH branch instead."
say "Newest release: $MARKER_TAG"
git -C "$CLONE_DIR" checkout -B "$REPO_BRANCH" "refs/tags/$MARKER_TAG"
fi
ok "Sources ready."
# --- run the installer ------------------------------------------------------
cd "$CLONE_DIR"
say "Launching ./setup install ${SETUP_ARGS[*]:-}"
RC=0
./setup install "${SETUP_ARGS[@]}" || RC=$?
[[ $RC -eq 0 ]] || die "./setup install exited with rc=$RC"
# Both the desktop's release indicator and updatems read this marker to learn
# which release is installed. Without it they see an unversioned install: the
# indicator stays silent, and the next updatems run resets the clone to the
# newest tag rather than recognising it is already there.
if [[ -n "$MARKER_TAG" ]]; then
printf '%s\n' "$MARKER_TAG" > "$MARKER"
ok "Installed. Marked as $MARKER_TAG."
fi