v0.2.0: WSL desktop, branding, GRUB theme, CI, installer, fonts, voice architecture
SamiOS CI / lint-and-test (push) Successful in 14s
Major update adding full desktop environment support, complete branding suite, and project infrastructure: Desktop (WSL): - KDE Plasma + SDDM + Dolphin/Konsole/Kate/Firefox setup script - Windows 11 dark/light color schemes - PipeWire audio stack - WSLg-compatible launch script - SamiOS CLI tool (v0.2.0) with desktop command Branding: - Logos: face-on-pyramid with and without text (500px) - Icons: square + launcher (256/512/1024px) + SVG vector - Wallpapers: 1920x1080, 4K, clean variant (PIL-generated) - GRUB theme: full cobalt blue (#1424CE) theme with pyramid background - SDDM theme: SamiOS login screen configuration - Branding README with palette, typography, usage guidelines Fonts: - Sami Grotesk (Helvetica-like) as default system/UI font - Sami Sans as secondary - Full Sami font family support (excluding 7777 personal branding) - fontconfig rules mapping Helvetica/Arial → Sami Grotesk - Font policy enforcement in samios CLI Infrastructure: - Automated installer (samios-installer.sh): partition, format, pacstrap, bootloader - PKGBUILD for samios-branding package - Test suite: shell tests for profiledef, packages, pacman.conf, CLI, font policy - Makefile: test, lint, check, build, clean targets - Gitea Actions CI workflow - Voice integration architecture document (SamiType × SamiOS) - Updated roadmap reflecting completed phases
@@ -0,0 +1,103 @@
|
||||
name: SamiOS CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master, main]
|
||||
pull_request:
|
||||
branches: [master, main]
|
||||
|
||||
jobs:
|
||||
lint-and-test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install shellcheck
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -y -qq shellcheck
|
||||
|
||||
- name: Install Make
|
||||
run: |
|
||||
if ! command -v make >/dev/null 2>&1; then
|
||||
sudo apt-get install -y -qq make
|
||||
fi
|
||||
|
||||
# ── Shellcheck ───────────────────────────────────────────────────
|
||||
- name: Run shellcheck on all shell scripts
|
||||
run: make lint
|
||||
|
||||
# ── Profile structure validation ─────────────────────────────────
|
||||
- name: Validate archiso profile structure
|
||||
run: |
|
||||
set -e
|
||||
PROFILE_DIR="packaging/archiso"
|
||||
echo "Validating profile structure..."
|
||||
|
||||
# Required files
|
||||
for f in profiledef.sh packages.x86_64 pacman.conf; do
|
||||
if [ ! -f "$PROFILE_DIR/$f" ]; then
|
||||
echo "ERROR: Missing required file: $PROFILE_DIR/$f"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Found: $PROFILE_DIR/$f"
|
||||
done
|
||||
|
||||
# profiledef.sh must have valid bash syntax
|
||||
if ! bash -n "$PROFILE_DIR/profiledef.sh"; then
|
||||
echo "ERROR: profiledef.sh has syntax errors"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ profiledef.sh syntax OK"
|
||||
|
||||
# packages.x86_64 must have at least one non-comment line
|
||||
pkg_count=$(grep -vE '^\s*#|^\s*$' "$PROFILE_DIR/packages.x86_64" | wc -l)
|
||||
if [ "$pkg_count" -lt 1 ]; then
|
||||
echo "ERROR: packages.x86_64 has no packages listed"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ packages.x86_64 has $pkg_count package(s)"
|
||||
|
||||
# pacman.conf must have [options] and at least one repo section
|
||||
if ! grep -q '\[options\]' "$PROFILE_DIR/pacman.conf"; then
|
||||
echo "ERROR: pacman.conf missing [options] section"
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -qE '^\[(core|extra)\]' "$PROFILE_DIR/pacman.conf"; then
|
||||
echo "ERROR: pacman.conf missing [core] or [extra] section"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ pacman.conf structure OK"
|
||||
|
||||
# Required airootfs files
|
||||
for f in airootfs/usr/local/bin/samios; do
|
||||
if [ ! -f "$PROFILE_DIR/$f" ]; then
|
||||
echo "ERROR: Missing: $PROFILE_DIR/$f"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Found: $PROFILE_DIR/$f"
|
||||
done
|
||||
|
||||
# samios CLI must be executable
|
||||
if [ ! -x "$PROFILE_DIR/airootfs/usr/local/bin/samios" ]; then
|
||||
echo "ERROR: samios CLI is not executable"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ samios CLI is executable"
|
||||
|
||||
# Boot mode configs
|
||||
for f in grub/grub.cfg syslinux/syslinux.cfg efiboot/loader/loader.conf; do
|
||||
if [ ! -f "$PROFILE_DIR/$f" ]; then
|
||||
echo "WARNING: Missing optional boot config: $PROFILE_DIR/$f"
|
||||
else
|
||||
echo " ✓ Found: $PROFILE_DIR/$f"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Profile structure validation PASSED ✓"
|
||||
|
||||
# ── Test suite ───────────────────────────────────────────────────
|
||||
- name: Run test suite
|
||||
run: make test
|
||||
@@ -0,0 +1,60 @@
|
||||
.PHONY: test lint check build clean help
|
||||
|
||||
# ── Paths ──────────────────────────────────────────────────────────────
|
||||
REPO_ROOT := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
PROFILE_DIR := $(REPO_ROOT)/packaging/archiso
|
||||
SCRIPTS_DIR := $(REPO_ROOT)/packaging/scripts
|
||||
TESTS_DIR := $(REPO_ROOT)/tests
|
||||
|
||||
# Shell scripts to lint with shellcheck
|
||||
SHELL_SCRIPTS := \
|
||||
$(PROFILE_DIR)/profiledef.sh \
|
||||
$(PROFILE_DIR)/build.sh \
|
||||
$(PROFILE_DIR)/airootfs/usr/local/bin/samios \
|
||||
$(PROFILE_DIR)/airootfs/usr/local/bin/choose-mirror \
|
||||
$(PROFILE_DIR)/airootfs/root/.automated_script.sh \
|
||||
$(SCRIPTS_DIR)/samios-desktop-setup.sh \
|
||||
$(TESTS_DIR)/test_helper.sh \
|
||||
$(TESTS_DIR)/test_profiledef.sh \
|
||||
$(TESTS_DIR)/test_packages.sh \
|
||||
$(TESTS_DIR)/test_pacman_conf.sh \
|
||||
$(TESTS_DIR)/test_samios_cli.sh \
|
||||
$(TESTS_DIR)/test_font_policy.sh \
|
||||
$(TESTS_DIR)/run_tests.sh
|
||||
|
||||
SHELLCHECK ?= shellcheck
|
||||
SHELLCHECK_OPTS := --severity=warning
|
||||
# SC2034 (unused var) is expected in profile definitions and CLI stubs
|
||||
SHELLCHECK_EXCLUDE := --exclude=SC2034
|
||||
|
||||
# ── Targets ────────────────────────────────────────────────────────────
|
||||
|
||||
help: ## Show this help
|
||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
|
||||
awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-12s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
test: ## Run the test suite
|
||||
@echo "Running SamiOS test suite..."
|
||||
@bash $(TESTS_DIR)/run_tests.sh --verbose
|
||||
|
||||
lint: ## Run shellcheck on all shell scripts
|
||||
@echo "Running shellcheck..."
|
||||
@for script in $(SHELL_SCRIPTS); do \
|
||||
if [ -f "$$script" ]; then \
|
||||
echo " shellcheck $$script"; \
|
||||
$(SHELLCHECK) $(SHELLCHECK_OPTS) $(SHELLCHECK_EXCLUDE) "$$script" || exit 1; \
|
||||
fi \
|
||||
done
|
||||
@echo "shellcheck passed ✓"
|
||||
|
||||
check: lint test ## Run lint + test (CI entry point)
|
||||
|
||||
build: ## Build the SamiOS ISO (requires archiso + root)
|
||||
@echo "Building SamiOS ISO..."
|
||||
@cd $(PROFILE_DIR) && sudo ./build.sh
|
||||
|
||||
clean: ## Remove build artifacts
|
||||
@echo "Cleaning build artifacts..."
|
||||
@rm -rf /tmp/samios-build
|
||||
@rm -rf $(PROFILE_DIR)/out
|
||||
@echo "Clean complete"
|
||||
@@ -0,0 +1,94 @@
|
||||
# SamiOS Branding
|
||||
|
||||
Official visual identity assets for **SamiOS** — the Arch-based custom Linux distribution.
|
||||
|
||||
## Brand Mark
|
||||
|
||||
The SamiOS mark is a stylized blue pyramid (hex `#1424CE`, cobalt blue with slight violet tint)
|
||||
combined with a Simpsons-style cartoon face. The pyramid represents the foundational geometric
|
||||
base of the OS; the face is the personal signature of the project's creator.
|
||||
|
||||
## Directory Layout
|
||||
|
||||
```
|
||||
branding/
|
||||
├── README.md ← this file
|
||||
├── icons/ ← square and launcher icons (no face — pyramid only)
|
||||
├── logos/ ← full lockups (face + pyramid, with and without text)
|
||||
├── themes/ ← GTK / Qt / display-manager themes (TBD)
|
||||
└── wallpapers/ ← desktop wallpapers (TBD)
|
||||
```
|
||||
|
||||
## Assets
|
||||
|
||||
### Icons (`icons/`)
|
||||
|
||||
Square pyramid-only icons, used for window decoration, file-type associations, and anywhere
|
||||
the face is too detailed at small sizes.
|
||||
|
||||
| File | Size | Use |
|
||||
| --------------------------------- | --------- | ---------------------------------------------------- |
|
||||
| `samios-icon-256.png` | 256×256 | Small UI icons, favicons |
|
||||
| `samios-icon-512.png` | 512×512 | Standard app icon size |
|
||||
| `samios-icon-1024.png` | 1024×1024 | High-DPI / source master |
|
||||
| `samios-icon-launcher-256.png` | 256×256 | Mobile / desktop launcher (rounded square) |
|
||||
| `samios-icon-launcher-512.png` | 512×512 | Standard launcher size |
|
||||
| `samios-icon-launcher-1024.png` | 1024×1024 | High-DPI launcher source |
|
||||
| `samios-icon.svg` | vector | Scalable source — renders at any size, no quality loss |
|
||||
|
||||
**Launcher icons** use a 22.3% corner-radius ratio (matches Apple iOS/macOS Big Sur+ aesthetic).
|
||||
|
||||
### Logos (`logos/`)
|
||||
|
||||
Full lockups with the cartoon face. Use these on websites, documentation, and splash screens.
|
||||
|
||||
| File | Size | Description |
|
||||
| ----------------------------- | --------- | -------------------------------------------- |
|
||||
| `samios-logo.png` | 500×500 | Face on pyramid, no text |
|
||||
| `samios-logo-text.png` | 500×500 | Face on pyramid, with "SamiOS" wordmark |
|
||||
|
||||
## Color Palette
|
||||
|
||||
| Role | Hex | Usage |
|
||||
| ------------------- | --------- | -------------------------------- |
|
||||
| **Primary Blue** | `#1424CE` | Pyramid fill (shadow face) |
|
||||
| **Primary Lit** | `#3B4ED8` | Pyramid lit face (light side) |
|
||||
| **Face Yellow** | `#FFD90F` | Cartoon skin tone |
|
||||
| **Hair / Outlines** | `#3A3A3A` | Cartoon outlines |
|
||||
|
||||
## Typography
|
||||
|
||||
The "SamiOS" wordmark uses the **samiahmed7777** font family. This font is part of the creator's
|
||||
personal brand and is intentionally **not** bundled with the OS — only the rendered wordmark
|
||||
image is distributed as a logo asset. (See project font policy.)
|
||||
|
||||
## Usage Guidelines
|
||||
|
||||
- **Do** keep the cobalt blue (`#1424CE`) consistent across all derivatives.
|
||||
- **Do** preserve the lit/shadow face split on the pyramid — it gives the mark dimensionality.
|
||||
- **Don't** add drop shadows, gradients, or filters on top of the mark.
|
||||
- **Don't** stretch the pyramid non-uniformly; always preserve its aspect ratio.
|
||||
- **Don't** use the face-only or pyramid-only marks as separate brand identities — they are
|
||||
companion assets, not standalone logos.
|
||||
|
||||
## Source / Provenance
|
||||
|
||||
- Pyramid geometry: AI-generated from text prompt, then refined to `#1424CE` color spec.
|
||||
- Face illustration: creator's hand-authored Simpsons-style portrait.
|
||||
- SVG (`samios-icon.svg`): hand-traced from the rasterized pyramid using detected peak
|
||||
coordinates (peak at `x=518, y=244`; base from `x=144` to `x=874`; base center at `y=668`,
|
||||
in a 1024×1024 reference canvas).
|
||||
|
||||
## File Manifest
|
||||
|
||||
```
|
||||
icons/samios-icon.svg 756 B
|
||||
icons/samios-icon-256.png 43,643 B
|
||||
icons/samios-icon-512.png 129,757 B
|
||||
icons/samios-icon-1024.png 303,023 B
|
||||
icons/samios-icon-launcher-256.png 47,229 B
|
||||
icons/samios-icon-launcher-512.png 136,239 B
|
||||
icons/samios-icon-launcher-1024.png 300,798 B
|
||||
logos/samios-logo.png 70,137 B
|
||||
logos/samios-logo-text.png 73,959 B
|
||||
```
|
||||
@@ -0,0 +1,56 @@
|
||||
# SamiOS GRUB Theme
|
||||
|
||||
Cobalt blue (#1424CE) themed GRUB bootloader with pyramid branding.
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
grub-theme/
|
||||
├── theme.txt # GRUB theme definition
|
||||
├── background.png # 1024×768 dark navy gradient + pyramid
|
||||
├── build_theme.py # Regenerate all assets
|
||||
├── README.md # This file
|
||||
├── fonts/
|
||||
│ ├── SamiOS-Regular-12.pf2
|
||||
│ ├── SamiOS-Regular-16.pf2
|
||||
│ ├── SamiOS-Bold-14.pf2
|
||||
│ └── SamiOS-Bold-16.pf2
|
||||
├── icons/
|
||||
│ ├── samios_16.png
|
||||
│ ├── samios_24.png
|
||||
│ ├── samios_32.png
|
||||
│ └── samios_48.png
|
||||
├── samios_select_*.png # Selected menu item 9-patch
|
||||
├── scrollbar_thumb_*.png # Scrollbar thumb 9-patch
|
||||
└── terminal_box_*.png # Terminal console box 9-patch
|
||||
```
|
||||
|
||||
## Brand Colors
|
||||
|
||||
| Token | Hex | Usage |
|
||||
|---------|-----------|-------|
|
||||
| Primary | `#1424CE` | Cobalt blue — pyramid shadow face, progress bar, selection |
|
||||
| Secondary | `#3B4ED8` | Lighter blue — pyramid lit face, borders |
|
||||
| Dark BG | `#050A1F` | Very dark navy background base |
|
||||
| Text | `#CCD4F5` | Lavender-white — titles, selected items |
|
||||
|
||||
## Installation
|
||||
|
||||
The theme is referenced by `packaging/archiso/grub/grub.cfg`:
|
||||
```
|
||||
set theme=/boot/grub/themes/samios/theme.txt
|
||||
```
|
||||
|
||||
During ISO build, this directory should be copied to:
|
||||
```
|
||||
<iso-root>/boot/grub/themes/samios/
|
||||
```
|
||||
|
||||
## Regenerating Assets
|
||||
|
||||
```bash
|
||||
cd branding/grub-theme
|
||||
python3 build_theme.py
|
||||
```
|
||||
|
||||
Requires: PIL/Pillow, grub-mkfont, DejaVu Sans fonts.
|
||||
|
After Width: | Height: | Size: 25 KiB |
@@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate SamiOS GRUB theme assets:
|
||||
- background.png (1024×768 dark navy gradient + centered pyramid + "SamiOS" label)
|
||||
- icons/*.png (pyramid boot-selection icons)
|
||||
- fonts/*.pf2 (GRUB PFF2 font via grub-mkfont)
|
||||
"""
|
||||
import os
|
||||
from PIL import Image, ImageDraw, ImageFilter, ImageFont
|
||||
import subprocess
|
||||
|
||||
THEME_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
ICONS_DIR = os.path.join(THEME_DIR, "icons")
|
||||
FONTS_DIR = os.path.join(THEME_DIR, "fonts")
|
||||
for d in (ICONS_DIR, FONTS_DIR):
|
||||
os.makedirs(d, exist_ok=True)
|
||||
|
||||
# ── Brand colors
|
||||
COBALT = (0x14, 0x24, 0xCE) # #1424CE primary
|
||||
LIGHT = (0x3B, 0x4E, 0xD8) # #3B4ED8 secondary
|
||||
DARK_BG = (0x05, 0x0A, 0x1F) # very dark navy
|
||||
DARK_BG2 = (0x0A, 0x14, 0x3A) # slightly lighter navy
|
||||
TEXT_COL = (0xCC, 0xD4, 0xF5) # soft lavender-white for "SamiOS" label
|
||||
|
||||
import glob
|
||||
def _find_font(name):
|
||||
for pat in (f"/usr/share/fonts/TTF/{name}",
|
||||
f"/usr/share/fonts/truetype/dejavu/{name}"):
|
||||
hits = glob.glob(pat)
|
||||
if hits:
|
||||
return hits[0]
|
||||
raise FileNotFoundError(f"Cannot find font: {name}")
|
||||
|
||||
DEJAVU_REG = _find_font("DejaVuSans.ttf")
|
||||
DEJAVU_BOLD = _find_font("DejaVuSans-Bold.ttf")
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
# 1. Background image
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
def make_background():
|
||||
W, H = 1024, 768
|
||||
# Build vertical gradient
|
||||
bg = Image.new("RGB", (W, H))
|
||||
for y in range(H):
|
||||
t = y / (H - 1)
|
||||
r = int(DARK_BG[0] + (DARK_BG2[0] - DARK_BG[0]) * t)
|
||||
g = int(DARK_BG[1] + (DARK_BG2[1] - DARK_BG[1]) * t)
|
||||
b = int(DARK_BG[2] + (DARK_BG2[2] - DARK_BG[2]) * t)
|
||||
for x in range(W):
|
||||
bg.putpixel((x, y), (r, g, b))
|
||||
|
||||
# Soft radial glow behind pyramid
|
||||
glow = Image.new("RGBA", (W, H), (0, 0, 0, 0))
|
||||
gd = ImageDraw.Draw(glow)
|
||||
gd.ellipse([512 - 280, 160, 512 + 280, 560], fill=LIGHT + (30,))
|
||||
glow = glow.filter(ImageFilter.GaussianBlur(100))
|
||||
bg = Image.alpha_composite(bg.convert("RGBA"), glow)
|
||||
|
||||
draw = ImageDraw.Draw(bg, "RGBA")
|
||||
|
||||
# Pyramid geometry
|
||||
cx, peak_y = 512, 210
|
||||
base_y = 510
|
||||
half_w = 210
|
||||
left_x = cx - half_w
|
||||
right_x = cx + half_w
|
||||
|
||||
# Ground shadow (stacked semi-transparent ellipses for soft falloff)
|
||||
sw = int(half_w * 1.3)
|
||||
for i in range(14):
|
||||
a = int(30 * (1 - i / 14))
|
||||
draw.ellipse([cx - sw, base_y + 6 - i, cx + sw, base_y + 14 - i],
|
||||
fill=COBALT + (a,))
|
||||
|
||||
# Right (shadow) face
|
||||
draw.polygon([(cx, peak_y), (right_x, base_y), (cx, base_y)],
|
||||
fill=COBALT + (255,))
|
||||
# Left (lit) face
|
||||
draw.polygon([(cx, peak_y), (cx, base_y), (left_x, base_y)],
|
||||
fill=LIGHT + (255,))
|
||||
|
||||
# "SamiOS" text
|
||||
font = ImageFont.truetype(DEJAVU_BOLD, 52)
|
||||
text = "SamiOS"
|
||||
bbox = draw.textbbox((0, 0), text, font=font)
|
||||
tw = bbox[2] - bbox[0]
|
||||
draw.text(((W - tw) // 2 - bbox[0], base_y + 40), text,
|
||||
fill=TEXT_COL, font=font)
|
||||
|
||||
out = os.path.join(THEME_DIR, "background.png")
|
||||
bg.convert("RGB").save(out)
|
||||
print(f" ✓ background.png ({W}×{H})")
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
# 2. Icons (pyramid silhouettes at multiple sizes)
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
def make_icons():
|
||||
for sz in (16, 24, 32, 48):
|
||||
img = Image.new("RGBA", (sz, sz), (0, 0, 0, 0))
|
||||
d = ImageDraw.Draw(img)
|
||||
cx = sz // 2
|
||||
peak = int(sz * 0.18)
|
||||
base = int(sz * 0.80)
|
||||
hw = int(sz * 0.34)
|
||||
d.polygon([(cx, peak), (cx + hw, base), (cx, base)], fill=COBALT + (255,))
|
||||
d.polygon([(cx, peak), (cx, base), (cx - hw, base)], fill=LIGHT + (255,))
|
||||
img.save(os.path.join(ICONS_DIR, f"samios_{sz}.png"))
|
||||
print(" ✓ icons/samios_{{16,24,32,48}}.png")
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
# 3. Fonts (PFF2 via grub-mkfont)
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
def make_fonts():
|
||||
specs = [
|
||||
# (ttf source, output name, size)
|
||||
(DEJAVU_REG, "SamiOS-Regular-16", 16),
|
||||
(DEJAVU_BOLD, "SamiOS-Bold-16", 16),
|
||||
(DEJAVU_REG, "SamiOS-Regular-12", 12),
|
||||
(DEJAVU_BOLD, "SamiOS-Bold-14", 14),
|
||||
]
|
||||
for ttf, name, size in specs:
|
||||
out = os.path.join(FONTS_DIR, f"{name}.pf2")
|
||||
subprocess.run(
|
||||
["grub-mkfont",
|
||||
"--output", out,
|
||||
"--size", str(size),
|
||||
"--range", "0x0-0x7F",
|
||||
"--name", name,
|
||||
ttf],
|
||||
check=True
|
||||
)
|
||||
print(f" ✓ fonts/{name}.pf2")
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("Building SamiOS GRUB theme assets...")
|
||||
make_background()
|
||||
make_icons()
|
||||
make_fonts()
|
||||
print("Done.")
|
||||
|
After Width: | Height: | Size: 122 B |
|
After Width: | Height: | Size: 154 B |
|
After Width: | Height: | Size: 180 B |
|
After Width: | Height: | Size: 236 B |
|
After Width: | Height: | Size: 100 B |
|
After Width: | Height: | Size: 107 B |
|
After Width: | Height: | Size: 110 B |
|
After Width: | Height: | Size: 116 B |
|
After Width: | Height: | Size: 112 B |
|
After Width: | Height: | Size: 108 B |
|
After Width: | Height: | Size: 114 B |
|
After Width: | Height: | Size: 117 B |
|
After Width: | Height: | Size: 107 B |
|
After Width: | Height: | Size: 83 B |
|
After Width: | Height: | Size: 83 B |
|
After Width: | Height: | Size: 83 B |
|
After Width: | Height: | Size: 83 B |
|
After Width: | Height: | Size: 83 B |
|
After Width: | Height: | Size: 83 B |
|
After Width: | Height: | Size: 83 B |
|
After Width: | Height: | Size: 83 B |
|
After Width: | Height: | Size: 83 B |
|
After Width: | Height: | Size: 96 B |
|
After Width: | Height: | Size: 104 B |
|
After Width: | Height: | Size: 106 B |
|
After Width: | Height: | Size: 112 B |
|
After Width: | Height: | Size: 108 B |
|
After Width: | Height: | Size: 105 B |
|
After Width: | Height: | Size: 111 B |
|
After Width: | Height: | Size: 114 B |
|
After Width: | Height: | Size: 103 B |
@@ -0,0 +1,96 @@
|
||||
# ─────────────────────────────────────────────────────────
|
||||
# SamiOS GRUB Theme
|
||||
# Brand colors: #1424CE (cobalt blue) / #3B4ED8 (light blue)
|
||||
# ─────────────────────────────────────────────────────────
|
||||
|
||||
# Background image
|
||||
desktop-image: "background.png"
|
||||
|
||||
# ── Colors ──
|
||||
title-color: "#CCD4F5"
|
||||
title-text-color: "#CCD4F5"
|
||||
message-color: "#A0A8D0"
|
||||
message-bg-color: "#050A1F"
|
||||
terminal-box: "terminal_box_c"
|
||||
terminal-border: "1"
|
||||
terminal-title-color: "#CCD4F5"
|
||||
|
||||
# ── Global font ──
|
||||
title-font: "SamiOS Bold Bold 16"
|
||||
font: "SamiOS Regular Regular 16"
|
||||
|
||||
# ── Title (top banner) ──
|
||||
+title {
|
||||
top = 5%
|
||||
left = 0%
|
||||
width = 100%
|
||||
height = 40
|
||||
text = "SamiOS Boot Menu"
|
||||
align = "center"
|
||||
color = "#CCD4F5"
|
||||
font = "SamiOS Bold Bold 16"
|
||||
}
|
||||
|
||||
# ── Boot entry list ──
|
||||
+boot_menu {
|
||||
top = 35%
|
||||
left = 25%
|
||||
width = 50%
|
||||
height = 40%
|
||||
|
||||
# Normal (unselected) entry
|
||||
item_font = "SamiOS Regular Regular 16"
|
||||
item_color = "#A0A8D0"
|
||||
# Selected entry
|
||||
selected_item_font = "SamiOS Bold Bold 16"
|
||||
selected_item_color = "#FFFFFF"
|
||||
selected_item_pixmap_style = "samios_select_c"
|
||||
|
||||
# Number of lines visible
|
||||
item_height = 28
|
||||
item_padding = 4
|
||||
item_spacing = 4
|
||||
|
||||
icon_width = 24
|
||||
icon_height = 24
|
||||
item_icon_space = 8
|
||||
|
||||
# Scrollbar
|
||||
scrollbar = true
|
||||
scrollbar_width = 8
|
||||
scrollbar_thumb = "scrollbar_thumb_c"
|
||||
scrollbar_frame = 0
|
||||
}
|
||||
|
||||
# ── Help text at bottom ──
|
||||
+hbox {
|
||||
left = 5%
|
||||
top = 90%
|
||||
width = 90%
|
||||
height = 30
|
||||
|
||||
+vbox {
|
||||
+label {
|
||||
text = "↑↓ Select · Enter Boot · e Edit · c Console · Esc Back"
|
||||
align = "center"
|
||||
color = "#6878A8"
|
||||
font = "SamiOS Regular Regular 12"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ── Progress bar area ──
|
||||
+progress_bar {
|
||||
id = "__timeout__"
|
||||
text = "@TIMEOUT_NOTIFICATION_SHORT@"
|
||||
left = 25%
|
||||
width = 50%
|
||||
top = 85%
|
||||
height = 16
|
||||
|
||||
font = "SamiOS Regular Regular 12"
|
||||
text_color = "#6878A8"
|
||||
fg_color = "#1424CE"
|
||||
bg_color = "#0A143A"
|
||||
border_color = "#3B4ED8"
|
||||
}
|
||||
|
After Width: | Height: | Size: 296 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 127 KiB |
|
After Width: | Height: | Size: 294 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 133 KiB |
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1024" height="1024">
|
||||
<title>SamiOS Pyramid Icon</title>
|
||||
<desc>Stylized blue (#1424CE) pyramid icon — lit left face, shadowed right face, soft ground shadow.</desc>
|
||||
|
||||
<!-- Ground shadow ellipse -->
|
||||
<ellipse cx="518" cy="728" rx="306.59999999999997" ry="20"
|
||||
fill="#1424CE" opacity="0.18"/>
|
||||
|
||||
<!-- Pyramid: two triangular faces -->
|
||||
<!-- Right (shadow) face: peak -> base_right_corner -> center_bottom -->
|
||||
<polygon points="518,244 874,668 518,668"
|
||||
fill="#1424CE"/>
|
||||
<!-- Left (lit) face: peak -> center_bottom -> base_left_corner -->
|
||||
<polygon points="518,244 518,668 144,668"
|
||||
fill="#3B4ED8"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 756 B |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 68 KiB |
@@ -0,0 +1,25 @@
|
||||
# SamiOS SDDM Theme
|
||||
|
||||
A custom SDDM login screen theme for SamiOS with the cobalt blue (#1424CE) color scheme.
|
||||
|
||||
## Files
|
||||
|
||||
- `theme.conf` — SDDM theme configuration
|
||||
- `background.png` — SamiOS wallpaper (cobalt pyramid on navy gradient)
|
||||
- `metadata.desktop` — Theme metadata
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
sudo cp -r samios-sddm-theme /usr/share/sddm/themes/samios
|
||||
echo -e "[Theme]\nCurrent=samios" | sudo tee /etc/sddm.conf.d/theme.conf
|
||||
```
|
||||
|
||||
## Colors
|
||||
|
||||
| Role | Hex |
|
||||
|------|-----|
|
||||
| Primary | `#1424CE` |
|
||||
| Secondary | `#3B4ED8` |
|
||||
| Background | `#0A0E27` |
|
||||
| Text | `#FFFFFF` |
|
||||
@@ -0,0 +1,10 @@
|
||||
[SddmGreeterTheme]
|
||||
Name=SamiOS
|
||||
Description=SamiOS login screen — cobalt blue pyramid theme
|
||||
Author=SamiOS
|
||||
Copyright=(c) 2026 Sami Ahmed
|
||||
License=GPL-3.0
|
||||
Type=sddm-theme
|
||||
Version=0.2.0
|
||||
Website=https://sami-ahmed.net
|
||||
Screenshot=background.png
|
||||
@@ -0,0 +1,37 @@
|
||||
[SamiOS SDDM Theme]
|
||||
|
||||
[General]
|
||||
Background=samios-wallpaper-clean-1920x1080.png
|
||||
|
||||
[ColorEffects:Disabled]
|
||||
Color=56,56,56
|
||||
ColorAmount=0
|
||||
ContrastAmount=0.65
|
||||
Enabled=false
|
||||
IntensityAmount=0.1
|
||||
|
||||
[Colors:Button]
|
||||
BackgroundNormal=32,32,32
|
||||
ForegroundNormal=255,255,255
|
||||
DecorationFocus=20,36,206
|
||||
DecorationHover=59,78,216
|
||||
|
||||
[Colors:View]
|
||||
BackgroundNormal=24,24,36
|
||||
ForegroundNormal=255,255,255
|
||||
DecorationFocus=20,36,206
|
||||
DecorationHover=59,78,216
|
||||
|
||||
[Colors:Window]
|
||||
BackgroundNormal=10,14,39
|
||||
ForegroundNormal=255,255,255
|
||||
|
||||
[Colors:Selection]
|
||||
BackgroundNormal=20,36,206
|
||||
ForegroundNormal=255,255,255
|
||||
|
||||
[General]
|
||||
ColorScheme=Win11Dark
|
||||
|
||||
[KDE]
|
||||
widgetStyle=Lightly
|
||||
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 10 KiB |
@@ -1,67 +1,94 @@
|
||||
# SamiOS Roadmap
|
||||
|
||||
## Phase 1: Foundation (Current)
|
||||
## Phase 1: Foundation ✅
|
||||
- [x] Basic archiso profile
|
||||
- [x] CLI tool (`samios`)
|
||||
- [x] Boot configuration (BIOS + UEFI)
|
||||
- [x] System configuration files
|
||||
- [ ] Automated installer
|
||||
- [ ] Font management system
|
||||
- [ ] Build automation
|
||||
- [x] Automated installer (`samios-installer.sh`)
|
||||
- [x] Font management system (fontconfig + policy enforcement)
|
||||
- [x] SamiOS branding package (logos, icons, wallpapers)
|
||||
- [x] GRUB theme (#1424CE cobalt blue)
|
||||
- [x] SDDM theme
|
||||
- [ ] Build automation CI pipeline (in progress)
|
||||
- [ ] Test suite (in progress)
|
||||
|
||||
## Phase 2: Desktop Environment
|
||||
- [ ] KDE Plasma integration
|
||||
- [ ] Display manager (SDDM)
|
||||
- [ ] Graphics drivers (NVIDIA/AMD/Intel)
|
||||
- [ ] Audio setup (PipeWire)
|
||||
- [ ] Network management GUI
|
||||
- [ ] System settings GUI
|
||||
## Phase 2: Desktop Environment ✅ (WSL)
|
||||
- [x] KDE Plasma integration (WSL on SAMI-PC)
|
||||
- [x] Display manager config (SDDM)
|
||||
- [x] Graphics via WSLg
|
||||
- [x] Audio setup (PipeWire)
|
||||
- [x] Network management (NetworkManager)
|
||||
- [x] Windows 11 theme (color schemes, window borders)
|
||||
- [x] Sami Grotesk as default system font
|
||||
- [x] Sami Sans as secondary font
|
||||
- [x] Sami font family installed (excluding 7777 branding fonts)
|
||||
- [x] SamiOS wallpapers (1920×1080, 4K, clean variant)
|
||||
- [ ] KDE panel configuration (bottom taskbar, Win11 start menu style)
|
||||
- [ ] Full system settings GUI
|
||||
|
||||
## Phase 3: Applications
|
||||
- [ ] Web browser (Firefox/Chromium)
|
||||
- [ ] File manager (Dolphin)
|
||||
- [ ] Terminal emulator (Konsole)
|
||||
- [ ] Text editor (Kate)
|
||||
## Phase 3: Applications (Next)
|
||||
- [ ] Web browser (Firefox) ✅ installed
|
||||
- [ ] File manager (Dolphin) ✅ installed
|
||||
- [ ] Terminal emulator (Konsole) ✅ installed
|
||||
- [ ] Text editor (Kate) ✅ installed
|
||||
- [ ] Office suite (LibreOffice)
|
||||
- [ ] Media player (VLC)
|
||||
- [ ] Image viewer (Gwenview)
|
||||
|
||||
## Phase 4: System Tools
|
||||
- [ ] Package manager GUI (Pamac)
|
||||
- [ ] Email client (Thunderbird/KMail)
|
||||
|
||||
## Phase 4: SamiType Voice Integration
|
||||
- [ ] SamiType STT service (systemd, always-on)
|
||||
- [ ] Wake word detection ("Computer")
|
||||
- [ ] Command router (intent classification)
|
||||
- [ ] KDE/WM control via voice
|
||||
- [ ] Web navigation via voice
|
||||
- [ ] System control via voice (volume, brightness, screenshots)
|
||||
- [ ] TTS voice feedback
|
||||
- [ ] Push-to-talk mode (keyboard shortcut)
|
||||
- [ ] Dictation mode (SamiType → any text field)
|
||||
- See: `docs/voice-integration-architecture.md`
|
||||
|
||||
## Phase 5: System Tools
|
||||
- [ ] System monitor
|
||||
- [ ] Backup tool
|
||||
- [ ] Backup tool (Btrfs snapshots)
|
||||
- [ ] Firewall configuration
|
||||
- [ ] User management GUI
|
||||
- [ ] System update GUI
|
||||
|
||||
## Phase 5: Polish
|
||||
- [ ] Custom themes
|
||||
- [ ] SamiOS branding
|
||||
- [ ] Documentation
|
||||
- [ ] Testing suite
|
||||
- [ ] Release automation
|
||||
## Phase 6: Polish
|
||||
- [x] Custom themes (Win11 dark/light color schemes)
|
||||
- [x] SamiOS branding (logos, wallpapers, boot screens)
|
||||
- [x] Documentation (installation, voice architecture)
|
||||
- [ ] Testing suite (shell tests, CI)
|
||||
- [ ] Release automation (ISO build pipeline)
|
||||
|
||||
## Phase 6: Advanced Features
|
||||
- [ ] Dual-boot setup tool
|
||||
## Phase 7: Advanced Features
|
||||
- [ ] Dual-boot setup tool (Windows → SamiOS migration)
|
||||
- [ ] System recovery tools
|
||||
- [ ] Snapshot/rollback (Btrfs)
|
||||
- [ ] Container support (Docker/Podman)
|
||||
- [ ] Virtual machine support
|
||||
- [ ] Custom kernel with optimizations
|
||||
|
||||
## Long-term Goals
|
||||
- [ ] Custom kernel with optimizations
|
||||
- [ ] SamiOS-specific packages
|
||||
- [ ] Custom kernel with SamiType hardware acceleration
|
||||
- [ ] SamiOS-specific packages (voice-native apps)
|
||||
- [ ] Community repository
|
||||
- [ ] Hardware certification
|
||||
- [ ] Enterprise features
|
||||
|
||||
## Timeline
|
||||
- Phase 1: Q4 2024
|
||||
- Phase 2: Q1 2025
|
||||
- Phase 3: Q2 2025
|
||||
- Phase 4-6: Ongoing
|
||||
- Phase 1: ✅ Complete
|
||||
- Phase 2: ✅ Complete (WSL), bare-metal pending
|
||||
- Phase 3: Q3 2026
|
||||
- Phase 4: Q4 2026 (SamiType integration begins)
|
||||
- Phase 5-7: 2027+
|
||||
|
||||
## Notes
|
||||
- Prioritize stability over features
|
||||
- Keep system lightweight
|
||||
- Maintain Arch compatibility
|
||||
- Focus on daily-driver usability
|
||||
- Voice-first interaction is the north star
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
# SamiType × SamiOS Voice Integration Architecture
|
||||
|
||||
## Vision
|
||||
|
||||
Voice-first OS control — "Computer, open Firefox", "Computer, go to youtube.com",
|
||||
"Computer, volume up" — Star Trek computer style, powered by SamiType (Sami's
|
||||
custom speech-to-text engine).
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ SamiOS Desktop │
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │
|
||||
│ │ Audio │──▶│ SamiType │──▶│ Command │ │
|
||||
│ │ Capture │ │ STT │ │ Router │ │
|
||||
│ └──────────┘ └──────────┘ └──────┬──────┘ │
|
||||
│ │ │
|
||||
│ ┌──────────────────┼─────┐ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ ┌──────────┐ ┌──────┐ ┌──────┐ │
|
||||
│ │ KDE/WM │ │ Web │ │ Sys │ │
|
||||
│ │ Control │ │ Nav │ │ Ctrl │ │
|
||||
│ └──────────┘ └──────┘ └──────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────┐ │
|
||||
│ │ SamiType TTS (Voice Response) │ │
|
||||
│ └──────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Components
|
||||
|
||||
### 1. Wake Word Engine
|
||||
- **Trigger:** "Computer" (configurable)
|
||||
- **Implementation:** Porcupine or openWakeWord (offline, low-latency)
|
||||
- **Always listening** via systemd service, minimal CPU (< 2%)
|
||||
- Push-to-talk fallback (keyboard shortcut or dedicated button)
|
||||
|
||||
### 2. SamiType STT (Speech-to-Text)
|
||||
- Sami's existing speech-to-text engine
|
||||
- **Offline-first** — models run locally, no cloud dependency
|
||||
- **Streaming mode** — starts transcribing before user finishes speaking
|
||||
- Outputs text + confidence score
|
||||
|
||||
### 3. Command Router
|
||||
- Parses SamiType transcription → structured command
|
||||
- Intent classification:
|
||||
- **Navigation:** "go to [website]", "open [app]", "search for [query]"
|
||||
- **System:** "volume [up/down/mute]", "brightness [N]", "screenshot", "lock screen"
|
||||
- **Window:** "minimize", "maximize", "close window", "switch to [app]"
|
||||
- **File:** "open [file]", "create folder [name]", "move [file] to [location]"
|
||||
- **Query:** "what time is it", "what's the weather", "system status"
|
||||
- **Fallback:** If no command match → pass to web search or LLM
|
||||
|
||||
### 4. Execution Layer
|
||||
- **KDE/WM Control:** kdialog, qdbus, kstart, wmctrl, xdotool
|
||||
- **Web Navigation:** xdg-open, firefox --new-tab [url]
|
||||
- **System Control:** pactl (volume), brightnessctl, systemctl, loginctl
|
||||
|
||||
### 5. Voice Response (TTS)
|
||||
- SamiType TTS engine for spoken confirmations
|
||||
- "Opening Firefox", "Volume set to 50%", "Screenshot saved"
|
||||
- Subtle — not chatty, only speaks when action confirmed or error
|
||||
|
||||
## Command Examples
|
||||
|
||||
| Voice Input | Action |
|
||||
|-------------|--------|
|
||||
| "Computer, open Firefox" | Launch Firefox |
|
||||
| "Computer, go to youtube.com" | Open youtube.com in default browser |
|
||||
| "Computer, volume up" | Increase volume by 10% |
|
||||
| "Computer, mute" | Mute audio |
|
||||
| "Computer, take a screenshot" | spectacle -f (fullscreen capture) |
|
||||
| "Computer, lock screen" | loginctl lock-session |
|
||||
| "Computer, what time is it" | TTS: "It's 3:42 PM" |
|
||||
| "Computer, minimize all windows" | Show desktop (Meta+D) |
|
||||
| "Computer, switch to Firefox" | Activate Firefox window |
|
||||
| "Computer, check for updates" | Run pacman -Syu, TTS result |
|
||||
|
||||
## Integration Points
|
||||
|
||||
### SamiType → SamiOS
|
||||
```
|
||||
samiType.onTranscription(text, confidence) {
|
||||
if (confidence < 0.6) return; // ignore low-confidence
|
||||
|
||||
command = CommandRouter.parse(text);
|
||||
if (command) {
|
||||
result = command.execute();
|
||||
if (result.shouldSpeak) {
|
||||
samiTypeTTS.speak(result.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### systemd Service
|
||||
```ini
|
||||
[Unit]
|
||||
Description=SamiOS Voice Assistant (SamiType)
|
||||
After=pipewire.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/samios-voice
|
||||
Restart=always
|
||||
User=sami
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
```
|
||||
|
||||
## Phased Rollout
|
||||
|
||||
### Phase 1: Foundation (MVP)
|
||||
- [ ] SamiType running as systemd service in SamiOS
|
||||
- [ ] Push-to-talk activation (keyboard shortcut)
|
||||
- [ ] Basic command set: open apps, web nav, volume
|
||||
- [ ] Text output in notification (no TTS yet)
|
||||
|
||||
### Phase 2: Always-On Wake Word
|
||||
- [ ] Wake word "Computer" detection
|
||||
- [ ] Expanded command set: window management, screenshots
|
||||
- [ ] TTS voice feedback
|
||||
|
||||
### Phase 3: Natural Language
|
||||
- [ ] LLM-powered intent parsing for complex commands
|
||||
- [ ] "Computer, find all PDFs from last week and move them to Documents"
|
||||
- [ ] Context awareness (current app, current selection)
|
||||
|
||||
### Phase 4: Full Voice OS
|
||||
- [ ] Voice-controlled settings (display, network, bluetooth)
|
||||
- [ ] Dictation mode (SamiType → any text field)
|
||||
- [ ] Custom command creation ("Computer, when I say X, do Y")
|
||||
- [ ] Multi-turn voice interactions
|
||||
|
||||
## Dependencies
|
||||
- SamiType (STT + TTS)
|
||||
- pipewire (audio capture/playback)
|
||||
- KDE Plasma (window/desktop control via qdbus)
|
||||
- wmctrl / xdotool (X11 window manipulation)
|
||||
- Optional: openWakeWord or Porcupine (wake word detection)
|
||||
|
||||
## Security Considerations
|
||||
- All processing is local (no cloud, no data leaves the machine)
|
||||
- Microphone indicator (notification when listening)
|
||||
- Manual disable switch (system tray toggle)
|
||||
- No voice data stored unless explicitly saved by user
|
||||
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<!--
|
||||
SamiOS System Font Configuration
|
||||
Sets Sami Grotesk as the default sans-serif (Helvetica-like) system font.
|
||||
Sami Sans as secondary sans-serif.
|
||||
All other Sami font families available but not default.
|
||||
Fonts with "7777" in the name are explicitly excluded (personal branding).
|
||||
-->
|
||||
<fontconfig>
|
||||
|
||||
<!-- === Exclude 7777 fonts (personal branding policy) === -->
|
||||
<selectfont>
|
||||
<rejectfont>
|
||||
<pattern>
|
||||
<patelt name="family"><string>samiahmed7777</string></patelt>
|
||||
</pattern>
|
||||
</rejectfont>
|
||||
</selectfont>
|
||||
|
||||
<!-- === Default sans-serif → Sami Grotesk === -->
|
||||
<match target="font">
|
||||
<test name="family"><string>sans-serif</string></test>
|
||||
<edit name="family" mode="assign" binding="strong">
|
||||
<string>Sami Grotesk</string>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
<!-- === Default serif → Sami Serif === -->
|
||||
<match target="font">
|
||||
<test name="family"><string>serif</string></test>
|
||||
<edit name="family" mode="assign" binding="strong">
|
||||
<string>Sami Serif</string>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
<!-- === Default monospace → keep system default === -->
|
||||
|
||||
<!-- === Helvetica/Arial alias → Sami Grotesk === -->
|
||||
<match target="font">
|
||||
<test name="family"><string>Helvetica</string></test>
|
||||
<edit name="family" mode="assign" binding="strong">
|
||||
<string>Sami Grotesk</string>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
<match target="font">
|
||||
<test name="family"><string>Arial</string></test>
|
||||
<edit name="family" mode="assign" binding="strong">
|
||||
<string>Sami Grotesk</string>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
<!-- === Sami Grotesk as primary system font === -->
|
||||
<match target="pattern">
|
||||
<test name="family"><string>system-ui</string></test>
|
||||
<edit name="family" mode="assign" binding="strong">
|
||||
<string>Sami Grotesk</string>
|
||||
</edit>
|
||||
</match>
|
||||
|
||||
</fontconfig>
|
||||
@@ -0,0 +1,25 @@
|
||||
# SamiOS locale.gen
|
||||
# Uncomment the locales you need, then run `locale-gen`.
|
||||
# SamiOS defaults to en_US.UTF-8 (see /etc/locale.conf).
|
||||
|
||||
en_US.UTF-8 UTF-8
|
||||
#en_US ISO-8859-1
|
||||
|
||||
# Additional locales — uncomment as needed:
|
||||
#en_GB.UTF-8 UTF-8
|
||||
#de_DE.UTF-8 UTF-8
|
||||
#fr_FR.UTF-8 UTF-8
|
||||
#es_ES.UTF-8 UTF-8
|
||||
#it_IT.UTF-8 UTF-8
|
||||
#pt_BR.UTF-8 UTF-8
|
||||
#ru_RU.UTF-8 UTF-8
|
||||
#ja_JP.UTF-8 UTF-8
|
||||
#ko_KR.UTF-8 UTF-8
|
||||
#zh_CN.UTF-8 UTF-8
|
||||
#zh_TW.UTF-8 UTF-8
|
||||
#ar_SA.UTF-8 UTF-8
|
||||
#hi_IN.UTF-8 UTF-8
|
||||
#tr_TR.UTF-8 UTF-8
|
||||
#pl_PL.UTF-8 UTF-8
|
||||
#nl_NL.UTF-8 UTF-8
|
||||
#sv_SE.UTF-8 UTF-8
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/bin/bash
|
||||
# ~/.bashrc — SamiOS root shell configuration
|
||||
# Loaded by Bash for interactive shells
|
||||
|
||||
# ============================================================
|
||||
# History
|
||||
# ============================================================
|
||||
HISTSIZE=1000
|
||||
HISTFILESIZE=2000
|
||||
shopt -s histappend
|
||||
|
||||
# ============================================================
|
||||
# Shell options
|
||||
# ============================================================
|
||||
shopt -s checkwinsize
|
||||
shopt -s cdable_vars
|
||||
|
||||
# ============================================================
|
||||
# Aliases
|
||||
# ============================================================
|
||||
alias ls='ls --color=auto'
|
||||
alias ll='ls -lah'
|
||||
alias la='ls -A'
|
||||
alias l='ls -CF'
|
||||
alias grep='grep --color=auto'
|
||||
alias ..='cd ..'
|
||||
alias ...='cd ../..'
|
||||
alias df='df -h'
|
||||
alias free='free -h'
|
||||
|
||||
# SamiOS-specific aliases
|
||||
alias samios-status='samios status'
|
||||
alias samios-help='samios help'
|
||||
|
||||
# ============================================================
|
||||
# Prompt — SamiOS branded
|
||||
# ============================================================
|
||||
# Blue pyramid color matches brand primary (#1424CE)
|
||||
PS1='\[\e[1;34m\]▲ SamiOS\[\e[0m\] \[\e[32m\]\u@\h\[\e[0m\] \w \$ '
|
||||
|
||||
# ============================================================
|
||||
# Welcome message — printed once per interactive login shell
|
||||
# ============================================================
|
||||
if shopt -q login_shell; then
|
||||
SAMIOS_VER=$(cat /usr/share/samios/version 2>/dev/null | tail -1 || echo "0.1.0")
|
||||
echo ""
|
||||
echo -e " \033[1;34m ▲\033[0m \033[1;34mSamiOS\033[0m \033[0;37m${SAMIOS_VER}\033[0m"
|
||||
echo -e " \033[0;37m |\\\\ Arch-based Linux by Sami Ahmed\033[0m"
|
||||
echo -e " \033[0;37m | \\\\ https://sami-ahmed.net\033[0m"
|
||||
echo ""
|
||||
echo -e " \033[0;37mCommands:\033[0m \033[1;msamios help\033[0m · \033[1;msamios status\033[0m · \033[1;msamios fonts\033[0m"
|
||||
echo ""
|
||||
fi
|
||||
@@ -0,0 +1,67 @@
|
||||
#!/bin/zsh
|
||||
# ~/.zshrc — SamiOS root shell configuration
|
||||
# Loaded by Zsh for interactive shells (SamiOS default shell)
|
||||
|
||||
# ============================================================
|
||||
# History
|
||||
# ============================================================
|
||||
HISTFILE=~/.zsh_history
|
||||
HISTSIZE=1000
|
||||
SAVEHIST=1000
|
||||
setopt appendhistory
|
||||
setopt sharehistory
|
||||
setopt incappendhistory
|
||||
|
||||
# ============================================================
|
||||
# Shell options
|
||||
# ============================================================
|
||||
setopt auto_cd # cd by typing directory name
|
||||
setopt interactive_comments
|
||||
|
||||
# ============================================================
|
||||
# Key bindings (vi-style for line editing)
|
||||
# ============================================================
|
||||
bindkey -e # emacs-style bindings (more familiar default)
|
||||
|
||||
# ============================================================
|
||||
# Aliases
|
||||
# ============================================================
|
||||
alias ls='ls --color=auto'
|
||||
alias ll='ls -lah'
|
||||
alias la='ls -A'
|
||||
alias l='ls -CF'
|
||||
alias grep='grep --color=auto'
|
||||
alias ..='cd ..'
|
||||
alias ...='cd ../..'
|
||||
alias df='df -h'
|
||||
alias free='free -h'
|
||||
|
||||
# SamiOS-specific aliases
|
||||
alias samios-status='samios status'
|
||||
alias samios-help='samios help'
|
||||
|
||||
# ============================================================
|
||||
# Prompt — SamiOS branded
|
||||
# ============================================================
|
||||
# Blue pyramid color matches brand primary (#1424CE)
|
||||
autoload -Uz colors && colors
|
||||
PROMPT='%{$fg_bold[blue]%}▲ SamiOS%{$reset_color%} %{$fg[green]%}%n@%m%{$reset_color%} %~ %# '
|
||||
|
||||
# ============================================================
|
||||
# Completion
|
||||
# ============================================================
|
||||
autoload -Uz compinit && compinit
|
||||
zstyle ':completion:*' menu select
|
||||
|
||||
# ============================================================
|
||||
# Welcome message — printed once per interactive login shell
|
||||
# ============================================================
|
||||
if [[ -o login ]]; then
|
||||
echo ""
|
||||
echo " \033[1;34m ▲\033[0m \033[1;34mSamiOS\033[0m \033[0;37m$(cat /usr/share/samios/version 2>/dev/null | tail -1 || echo '0.1.0')\033[0m"
|
||||
echo " \033[0;37m |\\\ Arch-based Linux by Sami Ahmed\033[0m"
|
||||
echo " \033[0;37m | \\ https://sami-ahmed.net\033[0m"
|
||||
echo ""
|
||||
echo " \033[0;37mCommands:\033[0m \033[1;msamios help\033[0m · \033[1;msamios status\033[0m · \033[1;msamios fonts\033[0m"
|
||||
echo ""
|
||||
fi
|
||||
@@ -3,6 +3,19 @@
|
||||
set default=0
|
||||
set timeout=5
|
||||
|
||||
# ── Load SamiOS theme ──
|
||||
insmod all_video
|
||||
insmod gfxterm
|
||||
insmod png
|
||||
insmod ext2
|
||||
set gfxmode=1024x768
|
||||
set gfxpayload=keep
|
||||
terminal_output gfxterm
|
||||
|
||||
# Theme path (relative to GRUB root at boot; also set during ISO build)
|
||||
set theme=/boot/grub/themes/samios/theme.txt
|
||||
export theme
|
||||
|
||||
menuentry "SamiOS Live" {
|
||||
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL%
|
||||
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
|
||||
|
||||
@@ -16,6 +16,20 @@ filesystem
|
||||
util-linux
|
||||
shadow
|
||||
sudo
|
||||
nano
|
||||
vi
|
||||
less
|
||||
diffutils
|
||||
tar
|
||||
man-db
|
||||
man-pages
|
||||
|
||||
# Fonts (base sans-serif coverage)
|
||||
ttf-dejavu
|
||||
ttf-liberation
|
||||
|
||||
# User directories
|
||||
xdg-user-dirs
|
||||
|
||||
# Networking
|
||||
networkmanager
|
||||
@@ -35,8 +49,14 @@ systemd-sysvcompat
|
||||
arch-install-scripts
|
||||
pacman-contrib
|
||||
|
||||
# SamiOS branding
|
||||
samios-branding
|
||||
# Mirror management
|
||||
reflector
|
||||
|
||||
# SamiOS branding is NOT installed via pacman — it is baked into the
|
||||
# ISO through the airootfs overlay (see airootfs/usr/share/samios/
|
||||
# and airootfs/etc/samios/). The standalone PKGBUILD at
|
||||
# packaging/packages/samios-branding/ can also be built for
|
||||
# post-install use on a running system.
|
||||
|
||||
# Excluded: fonts with 7777 in name (personal branding)
|
||||
# Excluded: desktop environment (CLI-only for now)
|
||||
|
||||
@@ -22,6 +22,8 @@ file_permissions=(
|
||||
["/etc/gshadow"]="0:0:400"
|
||||
["/root"]="0:0:750"
|
||||
["/root/.automated_script.sh"]="0:0:755"
|
||||
["/root/.zshrc"]="0:0:644"
|
||||
["/root/.bashrc"]="0:0:644"
|
||||
["/root/.gnupg"]="0:0:700"
|
||||
["/usr/local/bin/choose-mirror"]="0:0:755"
|
||||
["/usr/local/bin/samios"]="0:0:755"
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
# Maintainer: Sami Ahmed <sami@sami-ahmed.net>
|
||||
# SamiOS branding package — logos, icons, boot themes, default configs
|
||||
#
|
||||
# Build: Copy the branding assets into this directory alongside the PKGBUILD,
|
||||
# then run `makepkg -f` from within it. Alternatively run the build helper
|
||||
# packaging/packages/samios-branding/fetch-assets.sh to pull them in from
|
||||
# the repo branding/ tree.
|
||||
|
||||
pkgname=samios-branding
|
||||
pkgver=0.1.0
|
||||
pkgrel=1
|
||||
pkgdesc="SamiOS branding assets — logos, icons, GRUB theme, and default configuration"
|
||||
arch=('any')
|
||||
url="https://sami-ahmed.net"
|
||||
license=('GPL3')
|
||||
depends=('filesystem')
|
||||
optdepends=('grub: for GRUB theme files')
|
||||
install=samios-branding.install
|
||||
|
||||
# Source assets — these files live alongside the PKGBUILD in this directory.
|
||||
# Run fetch-assets.sh to copy them from ../../branding/ before building.
|
||||
source=(
|
||||
"samios-logo.png"
|
||||
"samios-logo-text.png"
|
||||
"samios-icon-256.png"
|
||||
"samios-icon-512.png"
|
||||
"samios-icon-1024.png"
|
||||
"samios-icon-launcher-256.png"
|
||||
"samios-icon-launcher-512.png"
|
||||
"samios-icon-launcher-1024.png"
|
||||
"samios-icon.svg"
|
||||
)
|
||||
sha256sums=(
|
||||
'd5fdf1dcfbba1f1b1e56d0325963ef540e7da3c0f6824672105a0480ba02b26d' # samios-logo.png
|
||||
'45238639444b666c824e7abacb18bc69d4d1c6cc01b7a30d75862c2a52f82343' # samios-logo-text.png
|
||||
'e8781728b5dad6c6047e360bd6f7189599d5e058097c980b5a26c2e3d7a00fd0' # samios-icon-256.png
|
||||
'841be1020c53a7ef67d5807c67e484f29a1db4b92ced3b08082866dab8b6ebb2' # samios-icon-512.png
|
||||
'13b4231b144e0bbedc4d8ab052d5dbcc2d5aab69c2854a9e681b75140715a72d' # samios-icon-1024.png
|
||||
'39a02a848db661a3b2de29643802d781e9745bd209c9c067d4d62495c4f32954' # samios-icon-launcher-256.png
|
||||
'cd3a73c8106e92abf7082638ee2d3193f40b0454b289e75292a3793ba04666b1' # samios-icon-launcher-512.png
|
||||
'77234f406e6077b751a900a26c17eda280ef3345e56a4b6230efefa997416618' # samios-icon-launcher-1024.png
|
||||
'011bece75f08db7795858052a2999e5acbf7196b79702cda087cbbbe205843f7' # samios-icon.svg
|
||||
)
|
||||
|
||||
package() {
|
||||
# === Directory structure ===
|
||||
install -d "${pkgdir}/usr/share/samios"
|
||||
install -d "${pkgdir}/usr/share/samios/logos"
|
||||
install -d "${pkgdir}/usr/share/samios/icons"
|
||||
install -d "${pkgdir}/usr/share/icons/hicolor/256x256/apps"
|
||||
install -d "${pkgdir}/usr/share/icons/hicolor/512x512/apps"
|
||||
install -d "${pkgdir}/usr/share/icons/hicolor/1024x1024/apps"
|
||||
install -d "${pkgdir}/usr/share/icons/hicolor/scalable/apps"
|
||||
install -d "${pkgdir}/usr/share/pixmaps"
|
||||
install -d "${pkgdir}/etc/samios"
|
||||
|
||||
# === Logos (full lockups with face) ===
|
||||
install -m644 "${srcdir}/samios-logo.png" "${pkgdir}/usr/share/samios/logos/samios-logo.png"
|
||||
install -m644 "${srcdir}/samios-logo-text.png" "${pkgdir}/usr/share/samios/logos/samios-logo-text.png"
|
||||
|
||||
# Copy logo to pixmaps for legacy lookups
|
||||
install -m644 "${srcdir}/samios-logo.png" "${pkgdir}/usr/share/pixmaps/samios-logo.png"
|
||||
|
||||
# === Icons (pyramid-only, no face) ===
|
||||
# Square icons in hicolor theme
|
||||
install -m644 "${srcdir}/samios-icon-256.png" "${pkgdir}/usr/share/icons/hicolor/256x256/apps/samios.png"
|
||||
install -m644 "${srcdir}/samios-icon-512.png" "${pkgdir}/usr/share/icons/hicolor/512x512/apps/samios.png"
|
||||
install -m644 "${srcdir}/samios-icon-1024.png" "${pkgdir}/usr/share/icons/hicolor/1024x1024/apps/samios.png"
|
||||
|
||||
# Scalable SVG icon
|
||||
install -m644 "${srcdir}/samios-icon.svg" "${pkgdir}/usr/share/icons/hicolor/scalable/apps/samios.svg"
|
||||
|
||||
# Launcher icons (rounded-square variant) stored under samios assets
|
||||
install -m644 "${srcdir}/samios-icon-launcher-256.png" "${pkgdir}/usr/share/samios/icons/samios-icon-launcher-256.png"
|
||||
install -m644 "${srcdir}/samios-icon-launcher-512.png" "${pkgdir}/usr/share/samios/icons/samios-icon-launcher-512.png"
|
||||
install -m644 "${srcdir}/samios-icon-launcher-1024.png" "${pkgdir}/usr/share/samios/icons/samios-icon-launcher-1024.png"
|
||||
|
||||
# Also store source PNG icons in samios assets directory
|
||||
install -m644 "${srcdir}/samios-icon-256.png" "${pkgdir}/usr/share/samios/icons/samios-icon-256.png"
|
||||
install -m644 "${srcdir}/samios-icon-512.png" "${pkgdir}/usr/share/samios/icons/samios-icon-512.png"
|
||||
install -m644 "${srcdir}/samios-icon-1024.png" "${pkgdir}/usr/share/samios/icons/samios-icon-1024.png"
|
||||
install -m644 "${srcdir}/samios-icon.svg" "${pkgdir}/usr/share/samios/icons/samios-icon.svg"
|
||||
|
||||
# === Branding metadata ===
|
||||
cat > "${pkgdir}/usr/share/samios/version" <<EOF
|
||||
SamiOS ${pkgver}
|
||||
EOF
|
||||
|
||||
cat > "${pkgdir}/usr/share/samios/branding.json" <<EOF
|
||||
{
|
||||
"name": "SamiOS",
|
||||
"version": "${pkgver}",
|
||||
"color_primary": "#1424CE",
|
||||
"color_secondary": "#3B4ED8",
|
||||
"publisher": "Sami Ahmed",
|
||||
"website": "https://sami-ahmed.net"
|
||||
}
|
||||
EOF
|
||||
|
||||
# === Default configuration ===
|
||||
cat > "${pkgdir}/etc/samios/samios.conf" <<EOF
|
||||
# SamiOS configuration
|
||||
SAMIOS_VERSION=${pkgver}
|
||||
SAMIOS_COLOR_PRIMARY=#1424CE
|
||||
SAMIOS_COLOR_SECONDARY=#3B4ED8
|
||||
# Font policy: exclude fonts with 7777 in the name (personal branding)
|
||||
SAMIOS_FONT_EXCLUDE_PATTERN=7777
|
||||
EOF
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
# fetch-assets.sh — copy branding assets from the repo branding/ tree
|
||||
# into this directory so makepkg can find them as local sources.
|
||||
#
|
||||
# Usage: cd into this directory and run ./fetch-assets.sh
|
||||
set -euo pipefail
|
||||
|
||||
# Resolve the repo root (../../.. from packaging/packages/samios-branding/)
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
||||
BRANDING_DIR="$REPO_ROOT/branding"
|
||||
|
||||
if [ ! -d "$BRANDING_DIR" ]; then
|
||||
echo "ERROR: branding directory not found at $BRANDING_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Copying branding assets from $BRANDING_DIR ..."
|
||||
|
||||
# Logos
|
||||
cp "$BRANDING_DIR/logos/samios-logo.png" "$SCRIPT_DIR/samios-logo.png"
|
||||
cp "$BRANDING_DIR/logos/samios-logo-text.png" "$SCRIPT_DIR/samios-logo-text.png"
|
||||
|
||||
# Square icons
|
||||
cp "$BRANDING_DIR/icons/samios-icon-256.png" "$SCRIPT_DIR/samios-icon-256.png"
|
||||
cp "$BRANDING_DIR/icons/samios-icon-512.png" "$SCRIPT_DIR/samios-icon-512.png"
|
||||
cp "$BRANDING_DIR/icons/samios-icon-1024.png" "$SCRIPT_DIR/samios-icon-1024.png"
|
||||
|
||||
# Launcher icons
|
||||
cp "$BRANDING_DIR/icons/samios-icon-launcher-256.png" "$SCRIPT_DIR/samios-icon-launcher-256.png"
|
||||
cp "$BRANDING_DIR/icons/samios-icon-launcher-512.png" "$SCRIPT_DIR/samios-icon-launcher-512.png"
|
||||
cp "$BRANDING_DIR/icons/samios-icon-launcher-1024.png" "$SCRIPT_DIR/samios-icon-launcher-1024.png"
|
||||
|
||||
# SVG
|
||||
cp "$BRANDING_DIR/icons/samios-icon.svg" "$SCRIPT_DIR/samios-icon.svg"
|
||||
|
||||
echo "Done. You can now run: makepkg -f"
|
||||
@@ -0,0 +1,24 @@
|
||||
# samios-branding install hooks
|
||||
# Updates the icon cache after install/upgrade so hicolor icons are registered.
|
||||
|
||||
post_install() {
|
||||
echo ":: SamiOS branding assets installed"
|
||||
echo " Logos: /usr/share/samios/logos/"
|
||||
echo " Icons: /usr/share/icons/hicolor/*/apps/samios.*"
|
||||
echo " Config: /etc/samios/samios.conf"
|
||||
|
||||
if command -v gtk-update-icon-cache >/dev/null 2>&1; then
|
||||
gtk-update-icon-cache -f -t /usr/share/icons/hicolor 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
post_upgrade() {
|
||||
post_install "$@"
|
||||
}
|
||||
|
||||
post_remove() {
|
||||
if command -v gtk-update-icon-cache >/dev/null 2>&1; then
|
||||
gtk-update-icon-cache -f -t /usr/share/icons/hicolor 2>/dev/null || true
|
||||
fi
|
||||
echo ":: SamiOS branding assets removed"
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
[General]
|
||||
ColorScheme=Win11Dark
|
||||
|
||||
[KDE]
|
||||
widgetStyle=Lightly
|
||||
|
||||
[Icons]
|
||||
Theme=breeze
|
||||
|
||||
[General]
|
||||
font=Sami Grotesk,10,-1,5,50,0,0,0,0,0
|
||||
fixed=Monospace,10,-1,5,50,0,0,0,0,0
|
||||
toolbarFont=Sami Grotesk,10,-1,5,50,0,0,0,0,0
|
||||
menuFont=Sami Grotesk,10,-1,5,50,0,0,0,0,0
|
||||
smallestReadableFont=Sami Grotesk,8,-1,5,50,0,0,0,0,0
|
||||
desktopFont=Sami Grotesk,10,-1,5,50,0,0,0,0,0
|
||||
taskbarFont=Sami Grotesk,10,-1,5,50,0,0,0,0,0
|
||||
@@ -0,0 +1,495 @@
|
||||
#!/bin/bash
|
||||
# SamiOS WSL Desktop Setup - Complete automated build script
|
||||
# Runs inside Arch WSL as root
|
||||
# Installs: KDE Plasma desktop, Windows 11 theme, SamiOS branding, fonts
|
||||
set -ex
|
||||
|
||||
LOG="/var/log/samios-setup.log"
|
||||
exec > >(tee -a "$LOG") 2>&1
|
||||
echo "=== SamiOS Desktop Setup started $(date) ==="
|
||||
|
||||
# ============================================================
|
||||
# PHASE 1: Unregister old Arch, import fresh with 100GB VHD
|
||||
# ============================================================
|
||||
# This script assumes it runs AFTER the export/import is done
|
||||
# If running standalone, skip to Phase 2
|
||||
|
||||
# ============================================================
|
||||
# PHASE 2: Base system prep
|
||||
# ============================================================
|
||||
echo "--- Phase 2: Base system prep ---"
|
||||
|
||||
# Ensure sudo installed
|
||||
pacman -S --noconfirm --needed sudo
|
||||
|
||||
# Ensure user sami exists with sudo
|
||||
if ! id sami &>/dev/null; then
|
||||
useradd -m -G wheel -s /bin/bash sami
|
||||
fi
|
||||
echo 'sami ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/sami
|
||||
chmod 440 /etc/sudoers.d/sami
|
||||
|
||||
# wsl.conf
|
||||
cat > /etc/wsl.conf << 'EOF'
|
||||
[boot]
|
||||
systemd=true
|
||||
|
||||
[automount]
|
||||
enabled=true
|
||||
mountFsTab=true
|
||||
|
||||
[user]
|
||||
default=sami
|
||||
EOF
|
||||
|
||||
# Locale
|
||||
sed -i 's/^#en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen
|
||||
locale-gen
|
||||
echo 'LANG=en_US.UTF-8' > /etc/locale.conf
|
||||
|
||||
# Hostname
|
||||
echo samios > /etc/hostname
|
||||
|
||||
# ============================================================
|
||||
# PHASE 3: Install desktop packages
|
||||
# ============================================================
|
||||
echo "--- Phase 3: Installing desktop packages ---"
|
||||
|
||||
# Refresh mirrors
|
||||
reflector --country "United States" --age 12 --protocol https --sort rate --save /etc/pacman.d/mirrorlist 2>/dev/null || true
|
||||
|
||||
# Remove conflicting jack2 first
|
||||
pacman -R --noconfirm jack2 2>/dev/null || true
|
||||
|
||||
pacman -Syu --noconfirm --needed \
|
||||
xorg-server xorg-xinit \
|
||||
pipewire pipewire-pulse pipewire-alsa pipewire-jack wireplumber \
|
||||
dbus \
|
||||
polkit \
|
||||
mesa \
|
||||
plasma-desktop plasma-workspace plasma-pa plasma-nm \
|
||||
sddm \
|
||||
dolphin konsole kate kfind \
|
||||
firefox \
|
||||
ark \
|
||||
spectacle \
|
||||
ttf-dejavu ttf-liberation noto-fonts \
|
||||
kvantum \
|
||||
git \
|
||||
base-devel
|
||||
|
||||
echo "--- Phase 3 complete ---"
|
||||
|
||||
# ============================================================
|
||||
# PHASE 4: Windows 11 Theme
|
||||
# ============================================================
|
||||
echo "--- Phase 4: Windows 11 Theme ---"
|
||||
|
||||
# Install Lightly (Windows 11 style window decoration for KDE)
|
||||
# We'll use the lightly-git package from AUR
|
||||
sudo -u sami bash -c '
|
||||
cd /tmp
|
||||
git clone https://aur.archlinux.org/lightly-git.git 2>/dev/null || true
|
||||
cd lightly-git
|
||||
makepkg -si --noconfirm --skippgpcheck 2>&1 | tail -10
|
||||
' || echo "Lightly install failed (non-critical)"
|
||||
|
||||
# Download Windows 11 color scheme for KDE
|
||||
mkdir -p /usr/share/color-schemes
|
||||
cat > /usr/share/color-schemes/Win11Dark.colors << 'SCHEME'
|
||||
[Desktop Entry]
|
||||
Name=Windows 11 Dark
|
||||
X-KDE-PluginInfo-Author=SamiOS
|
||||
X-KDE-PluginInfo-Name=Win11Dark
|
||||
X-KDE-PluginInfo-License=GPL
|
||||
|
||||
[ColorEffects:Disabled]
|
||||
Color=56,56,56
|
||||
ColorAmount=0
|
||||
ColorAmount=0.1
|
||||
ContrastAmount=0.65
|
||||
ContrastAmount=0.65
|
||||
Enabled=false
|
||||
IntensityAmount=0.1
|
||||
IntensityAmount=0.1
|
||||
|
||||
[Colors:Button]
|
||||
BackgroundAlternate=30,30,30
|
||||
BackgroundNormal=32,32,32
|
||||
DecorationFocus=0,120,212
|
||||
DecorationHover=0,120,212
|
||||
ForegroundActive=0,120,212
|
||||
ForegroundInactive=160,160,160
|
||||
ForegroundLink=0,120,212
|
||||
ForegroundNegative=240,71,71
|
||||
ForegroundNeutral=255,196,0
|
||||
ForegroundNormal=255,255,255
|
||||
ForegroundPositive=0,200,83
|
||||
ForegroundVisited=0,90,158
|
||||
|
||||
[Colors:Selection]
|
||||
BackgroundAlternate=0,120,212
|
||||
BackgroundNormal=0,120,212
|
||||
DecorationFocus=0,120,212
|
||||
DecorationHover=0,120,212
|
||||
ForegroundNormal=255,255,255
|
||||
|
||||
[Colors:View]
|
||||
BackgroundAlternate=37,37,37
|
||||
BackgroundNormal=32,32,32
|
||||
DecorationFocus=0,120,212
|
||||
DecorationHover=0,120,212
|
||||
ForegroundActive=0,120,212
|
||||
ForegroundInactive=160,160,160
|
||||
ForegroundLink=0,120,212
|
||||
ForegroundNegative=240,71,71
|
||||
ForegroundNeutral=255,196,0
|
||||
ForegroundNormal=255,255,255
|
||||
ForegroundPositive=0,200,83
|
||||
ForegroundVisited=0,90,158
|
||||
|
||||
[Colors:Window]
|
||||
BackgroundAlternate=30,30,30
|
||||
BackgroundNormal=32,32,32
|
||||
DecorationFocus=0,120,212
|
||||
DecorationHover=0,120,212
|
||||
ForegroundActive=0,120,212
|
||||
ForegroundInactive=160,160,160
|
||||
ForegroundLink=0,120,212
|
||||
ForegroundNegative=240,71,71
|
||||
ForegroundNeutral=255,196,0
|
||||
ForegroundNormal=255,255,255
|
||||
ForegroundPositive=0,200,83
|
||||
ForegroundVisited=0,90,158
|
||||
|
||||
[General]
|
||||
ColorScheme=Win11Dark
|
||||
Name=Windows 11 Dark
|
||||
shadeSortColumn=true
|
||||
|
||||
[KDE]
|
||||
contrast=4
|
||||
widgetStyle=Lightly
|
||||
|
||||
[WM]
|
||||
activeBackground=32,32,32
|
||||
activeBlend=32,32,32
|
||||
activeForeground=255,255,255
|
||||
inactiveBackground=24,24,24
|
||||
inactiveBlend=24,24,24
|
||||
inactiveForeground=160,160,160
|
||||
SCHEME
|
||||
|
||||
# Win11 Light scheme
|
||||
cat > /usr/share/color-schemes/Win11Light.colors << 'SCHEME2'
|
||||
[Desktop Entry]
|
||||
Name=Windows 11 Light
|
||||
X-KDE-PluginInfo-Author=SamiOS
|
||||
X-KDE-PluginInfo-Name=Win11Light
|
||||
X-KDE-PluginInfo-License=GPL
|
||||
|
||||
[Colors:View]
|
||||
BackgroundNormal=249,249,249
|
||||
ForegroundNormal=0,0,0
|
||||
DecorationFocus=0,120,212
|
||||
DecorationHover=0,120,212
|
||||
|
||||
[Colors:Window]
|
||||
BackgroundNormal=243,243,243
|
||||
ForegroundNormal=0,0,0
|
||||
|
||||
[Colors:Selection]
|
||||
BackgroundNormal=0,120,212
|
||||
ForegroundNormal=255,255,255
|
||||
|
||||
[Colors:Button]
|
||||
BackgroundNormal=255,255,255
|
||||
ForegroundNormal=0,0,0
|
||||
|
||||
[General]
|
||||
ColorScheme=Win11Light
|
||||
Name=Windows 11 Light
|
||||
|
||||
[KDE]
|
||||
widgetStyle=Lightly
|
||||
SCHEME2
|
||||
|
||||
echo "--- Phase 4 complete ---"
|
||||
|
||||
# ============================================================
|
||||
# PHASE 5: KDE Configuration for Windows-like experience
|
||||
# ============================================================
|
||||
echo "--- Phase 5: KDE Configuration ---"
|
||||
|
||||
# Create sami's KDE config directory
|
||||
SAMHOME=$(getent passwd sami | cut -d: -f6)
|
||||
KDEDIR="$SAMHOME/.config"
|
||||
mkdir -p "$KDEDIR"
|
||||
|
||||
# Plasma Shell config — bottom panel, Win11 style
|
||||
cat > "$KDEDIR/plasma-localerc" << 'EOF'
|
||||
[Formats]
|
||||
LANG=en_US.UTF-8
|
||||
EOF
|
||||
|
||||
# Window Management — like Windows
|
||||
cat > "$KDEDIR/kdeglobals" << 'EOF'
|
||||
[General]
|
||||
ColorScheme=Win11Dark
|
||||
|
||||
[KDE]
|
||||
widgetStyle=Lightly
|
||||
|
||||
[Icons]
|
||||
Theme=breeze
|
||||
EOF
|
||||
|
||||
# KWin config — Windows-like window behavior
|
||||
cat > "$KDEDIR/kwinrc" << 'EOF'
|
||||
[Windows]
|
||||
BorderlessMaximizedWindows=false
|
||||
TitlebarDoubleClick=Maximize
|
||||
ClickRaise=true
|
||||
FocusPolicy=ClickFocus
|
||||
|
||||
[org.kde.kdecoration2]
|
||||
library=org.kde.lightly
|
||||
theme=
|
||||
|
||||
[TabBox]
|
||||
LayoutName=covers
|
||||
EOF
|
||||
|
||||
# SDDM config
|
||||
mkdir -p /etc/sddm.conf.d
|
||||
cat > /etc/sddm.conf.d/samios.conf << 'EOF'
|
||||
[Theme]
|
||||
Current=breeze
|
||||
CursorTheme=breeze_cursors
|
||||
EOF
|
||||
|
||||
echo "--- Phase 5 complete ---"
|
||||
|
||||
# ============================================================
|
||||
# PHASE 6: SamiOS Branding
|
||||
# ============================================================
|
||||
echo "--- Phase 6: SamiOS Branding ---"
|
||||
|
||||
mkdir -p /usr/share/samios /usr/share/wallpapers/SamiOS
|
||||
|
||||
# Copy branding from C:\SamiOS\branding if available
|
||||
if [ -d /mnt/c/SamiOS/branding ]; then
|
||||
cp /mnt/c/SamiOS/branding/* /usr/share/samios/ 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Version file
|
||||
echo "SamiOS 0.2.0 (WSL Desktop)" > /usr/share/samios/version
|
||||
|
||||
# SDDM theme override
|
||||
mkdir -p /usr/share/sddm/themes/breeze
|
||||
cat > /usr/share/sddm/themes/breeze/theme.conf << 'EOF'
|
||||
[General]
|
||||
background=/usr/share/wallpapers/SamiOS/samios-wallpaper.png
|
||||
EOF
|
||||
|
||||
echo "--- Phase 6 complete ---"
|
||||
|
||||
# ============================================================
|
||||
# PHASE 7: Font Management
|
||||
# ============================================================
|
||||
echo "--- Phase 7: Fonts ---"
|
||||
|
||||
mkdir -p /usr/share/fonts/samios
|
||||
|
||||
# Copy Sami's fonts from Windows (exclude any with 7777 in name)
|
||||
if [ -d /mnt/c/Windows/Fonts ]; then
|
||||
find /mnt/c/Windows/Fonts -type f \( -iname "*.ttf" -o -iname "*.otf" -o -iname "*.ttc" \) \
|
||||
! -iname "*7777*" \
|
||||
-exec cp {} /usr/share/fonts/samios/ \; 2>/dev/null
|
||||
echo "Copied Windows fonts (excluding 7777)"
|
||||
fi
|
||||
|
||||
# Also check C:\SamiOS\fonts
|
||||
if [ -d /mnt/c/SamiOS/fonts ]; then
|
||||
find /mnt/c/SamiOS/fonts -type f \( -iname "*.ttf" -o -iname "*.otf" \) \
|
||||
! -iname "*7777*" \
|
||||
-exec cp {} /usr/share/fonts/samios/ \; 2>/dev/null
|
||||
echo "Copied C:\\SamiOS\\fonts (excluding 7777)"
|
||||
fi
|
||||
|
||||
# Rebuild font cache
|
||||
fc-cache -f
|
||||
FONT_COUNT=$(fc-list | wc -l)
|
||||
echo "Total fonts installed: $FONT_COUNT"
|
||||
|
||||
# Verify no 7777 fonts
|
||||
if fc-list | grep -i "7777"; then
|
||||
echo "WARNING: 7777 fonts detected!"
|
||||
else
|
||||
echo "OK: No 7777 fonts present"
|
||||
fi
|
||||
|
||||
echo "--- Phase 7 complete ---"
|
||||
|
||||
# ============================================================
|
||||
# PHASE 8: WSLg + Plasma launch script
|
||||
# ============================================================
|
||||
echo "--- Phase 8: Launch script ---"
|
||||
|
||||
mkdir -p /usr/local/bin
|
||||
cat > /usr/local/bin/start-samios << 'EOF'
|
||||
#!/bin/bash
|
||||
# Start SamiOS Plasma desktop in WSLg
|
||||
export DISPLAY=:0
|
||||
export WAYLAND_DISPLAY=wayland-0
|
||||
export XDG_RUNTIME_DIR=/mnt/wslg/runtime-dir
|
||||
export PULSE_SERVER=/mnt/wslg/PulseServer
|
||||
export XDG_SESSION_TYPE=x11
|
||||
export XDG_CURRENT_DESKTOP=KDE
|
||||
|
||||
# Start dbus
|
||||
if ! pgrep -x dbus-daemon >/dev/null; then
|
||||
dbus-launch --sh-syntax > /tmp/dbus-env
|
||||
source /tmp/dbus-env
|
||||
fi
|
||||
|
||||
# Start pipewire
|
||||
if ! pgrep -x pipewire >/dev/null; then
|
||||
pipewire &
|
||||
pipewire-pulse &
|
||||
wireplumber &
|
||||
fi
|
||||
|
||||
echo "Starting KDE Plasma..."
|
||||
startplasma-x11 2>/tmp/plasma.log &
|
||||
echo "Plasma started. Check /tmp/plasma.log for errors."
|
||||
EOF
|
||||
chmod +x /usr/local/bin/start-samios
|
||||
|
||||
# Create a Windows-side shortcut script
|
||||
cat > /mnt/c/SamiOS/start-samios.bat << 'EOF'
|
||||
@echo off
|
||||
echo Starting SamiOS Desktop...
|
||||
wsl -d Arch -u sami -- /usr/local/bin/start-samios
|
||||
EOF
|
||||
|
||||
echo "--- Phase 8 complete ---"
|
||||
|
||||
# ============================================================
|
||||
# PHASE 9: SamiOS CLI tool
|
||||
# ============================================================
|
||||
echo "--- Phase 9: SamiOS CLI ---"
|
||||
|
||||
cat > /usr/local/bin/samios << 'EOF'
|
||||
#!/bin/bash
|
||||
set -e
|
||||
VERSION="0.2.0"
|
||||
|
||||
cmd_help() {
|
||||
cat << HELPEOF
|
||||
SamiOS CLI v${VERSION}
|
||||
|
||||
Commands:
|
||||
version Show version
|
||||
status Show system status
|
||||
desktop Start KDE Plasma desktop
|
||||
update Update system packages
|
||||
install <pkg> Install a package
|
||||
remove <pkg> Remove a package
|
||||
fonts Check fonts and policy
|
||||
help Show this help
|
||||
HELPEOF
|
||||
}
|
||||
|
||||
cmd_version() {
|
||||
echo "SamiOS v${VERSION}"
|
||||
echo "Kernel: $(uname -r)"
|
||||
echo "Desktop: KDE Plasma on WSLg"
|
||||
}
|
||||
|
||||
cmd_status() {
|
||||
echo "=== SamiOS System Status ==="
|
||||
echo "Version: ${VERSION}"
|
||||
echo "Hostname: $(hostname)"
|
||||
echo "Kernel: $(uname -r)"
|
||||
echo "Uptime: $(uptime -p)"
|
||||
echo
|
||||
echo "=== Disk ==="
|
||||
df -h / | tail -1
|
||||
echo
|
||||
echo "=== Memory ==="
|
||||
free -h | grep "Mem:"
|
||||
echo
|
||||
echo "=== Network ==="
|
||||
ip -br addr show 2>/dev/null | grep -v "lo" || echo "no interfaces"
|
||||
}
|
||||
|
||||
cmd_desktop() {
|
||||
/usr/local/bin/start-samios
|
||||
}
|
||||
|
||||
cmd_update() {
|
||||
sudo pacman -Syu --noconfirm
|
||||
}
|
||||
|
||||
cmd_install() {
|
||||
[ -z "$1" ] && echo "Usage: samios install <package>" && exit 1
|
||||
sudo pacman -S --noconfirm "$1"
|
||||
}
|
||||
|
||||
cmd_remove() {
|
||||
[ -z "$1" ] && echo "Usage: samios remove <package>" && exit 1
|
||||
sudo pacman -R --noconfirm "$1"
|
||||
}
|
||||
|
||||
cmd_fonts() {
|
||||
echo "=== Installed Fonts ==="
|
||||
fc-list | wc -l
|
||||
echo "fonts installed"
|
||||
echo
|
||||
echo "=== Font Policy ==="
|
||||
echo "Excluded: fonts with '7777' in name (personal branding)"
|
||||
echo
|
||||
if fc-list | grep -iq "7777"; then
|
||||
echo "WARNING: Found fonts with '7777' in name:"
|
||||
fc-list | grep -i "7777"
|
||||
else
|
||||
echo "OK: No forbidden fonts detected"
|
||||
fi
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
version) cmd_version ;;
|
||||
status) cmd_status ;;
|
||||
desktop) cmd_desktop ;;
|
||||
update) cmd_update ;;
|
||||
install) shift; cmd_install "$@" ;;
|
||||
remove) shift; cmd_remove "$@" ;;
|
||||
fonts) cmd_fonts ;;
|
||||
help|--help|-h|"") cmd_help ;;
|
||||
*) echo "Unknown command: $1"; echo "Run 'samios help'"; exit 1 ;;
|
||||
esac
|
||||
EOF
|
||||
chmod +x /usr/local/bin/samios
|
||||
|
||||
echo "--- Phase 9 complete ---"
|
||||
|
||||
# ============================================================
|
||||
# PHASE 10: Fix ownership
|
||||
# ============================================================
|
||||
echo "--- Phase 10: Fix ownership ---"
|
||||
chown -R sami:sami "$SAMHOME/.config" 2>/dev/null || true
|
||||
echo "--- Phase 10 complete ---"
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo "=== SamiOS Desktop Setup COMPLETE ==="
|
||||
echo "============================================"
|
||||
echo ""
|
||||
echo "To start the desktop:"
|
||||
echo " 1. Open Command Prompt or Terminal"
|
||||
echo " 2. Run: C:\\SamiOS\\start-samios.bat"
|
||||
echo " Or inside WSL: samios desktop"
|
||||
echo ""
|
||||
echo "To check system status: samios status"
|
||||
echo ""
|
||||
@@ -0,0 +1,445 @@
|
||||
#!/bin/bash
|
||||
# SamiOS Automated Installer
|
||||
# Partitions disk, formats, pacstraps base system, installs bootloader, creates user
|
||||
# Usage: samios install [options]
|
||||
set -e
|
||||
|
||||
VERSION="0.2.0"
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
log() { echo -e "${BLUE}[SamiOS]${NC} $*"; }
|
||||
ok() { echo -e "${GREEN}✓${NC} $*"; }
|
||||
warn() { echo -e "${YELLOW}⚠${NC} $*"; }
|
||||
err() { echo -e "${RED}✗${NC} $*" >&2; }
|
||||
|
||||
# ============================================================
|
||||
# Pre-flight checks
|
||||
# ============================================================
|
||||
check_root() {
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
err "This script must be run as root"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_uefi() {
|
||||
if [ -d /sys/firmware/efi/efivars ]; then
|
||||
UEFI=true
|
||||
ok "UEFI mode detected"
|
||||
else
|
||||
UEFI=false
|
||||
ok "BIOS mode detected"
|
||||
fi
|
||||
}
|
||||
|
||||
detect_disks() {
|
||||
log "Detecting available disks..."
|
||||
mapfile -t DISKS < <(lsblk -d -n -p -o NAME | grep -v "loop\|sr\|fd")
|
||||
|
||||
echo ""
|
||||
echo "Available disks:"
|
||||
for i in "${!DISKS[@]}"; do
|
||||
SIZE=$(lsblk -d -n -o SIZE "${DISKS[$i]}" 2>/dev/null)
|
||||
MODEL=$(lsblk -d -n -o MODEL "${DISKS[$i]}" 2>/dev/null)
|
||||
echo " [$i] ${DISKS[$i]} - ${SIZE} ${MODEL}"
|
||||
done
|
||||
echo ""
|
||||
}
|
||||
|
||||
select_disk() {
|
||||
if [ -n "$TARGET_DISK" ]; then
|
||||
return
|
||||
fi
|
||||
read -p "Select target disk [0-$(( ${#DISKS[@]} - 1 ))]: " DISK_IDX
|
||||
TARGET_DISK="${DISKS[$DISK_IDX]}"
|
||||
|
||||
echo ""
|
||||
warn "WARNING: This will ERASE ALL DATA on ${TARGET_DISK}"
|
||||
read -p "Type 'YES' to confirm: " CONFIRM
|
||||
if [ "$CONFIRM" != "YES" ]; then
|
||||
err "Installation cancelled"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
# Partitioning
|
||||
# ============================================================
|
||||
partition_disk() {
|
||||
log "Partitioning ${TARGET_DISK}..."
|
||||
|
||||
# Wipe all partition tables
|
||||
sgdisk --zap-all "$TARGET_DISK"
|
||||
|
||||
if [ "$UEFI" = true ]; then
|
||||
# UEFI: GPT with EFI System Partition + root
|
||||
sgdisk -n 1:0:+1G -t 1:ef00 -c 1:"EFI System" "$TARGET_DISK"
|
||||
sgdisk -n 2:0:0 -t 2:8300 -c 2:"SamiOS Root" "$TARGET_DISK"
|
||||
partprobe "$TARGET_DISK"
|
||||
sleep 2
|
||||
|
||||
# Determine partition names
|
||||
if [[ "$TARGET_DISK" == *"nvme"* ]] || [[ "$TARGET_DISK" == *"mmcblk"* ]]; then
|
||||
EFI_PART="${TARGET_DISK}p1"
|
||||
ROOT_PART="${TARGET_DISK}p2"
|
||||
else
|
||||
EFI_PART="${TARGET_DISK}1"
|
||||
ROOT_PART="${TARGET_DISK}2"
|
||||
fi
|
||||
|
||||
# Format
|
||||
mkfs.fat -F32 "$EFI_PART"
|
||||
mkfs.ext4 -F -L samios "$ROOT_PART"
|
||||
|
||||
ok "UEFI partitions created"
|
||||
else
|
||||
# BIOS: MBR with single root + boot
|
||||
sgdisk -n 1:0:0 -t 1:8300 -c 1:"SamiOS" "$TARGET_DISK"
|
||||
partprobe "$TARGET_DISK"
|
||||
sleep 2
|
||||
|
||||
if [[ "$TARGET_DISK" == *"nvme"* ]] || [[ "$TARGET_DISK" == *"mmcblk"* ]]; then
|
||||
ROOT_PART="${TARGET_DISK}p1"
|
||||
else
|
||||
ROOT_PART="${TARGET_DISK}1"
|
||||
fi
|
||||
|
||||
mkfs.ext4 -F -L samios "$ROOT_PART"
|
||||
ok "BIOS partition created"
|
||||
fi
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
# Mount and pacstrap
|
||||
# ============================================================
|
||||
mount_and_install() {
|
||||
log "Mounting filesystems..."
|
||||
|
||||
MOUNT_POINT="/mnt"
|
||||
mount "$ROOT_PART" "$MOUNT_POINT"
|
||||
|
||||
if [ "$UEFI" = true ]; then
|
||||
mkdir -p "$MOUNT_POINT/boot/efi"
|
||||
mount "$EFI_PART" "$MOUNT_POINT/boot/efi"
|
||||
fi
|
||||
|
||||
log "Installing base system (this takes a few minutes)..."
|
||||
|
||||
# Install base system
|
||||
pacstrap "$MOUNT_POINT" base base-devel linux linux-firmware
|
||||
|
||||
# Generate fstab
|
||||
genfstab -U "$MOUNT_POINT" > "$MOUNT_POINT/etc/fstab"
|
||||
|
||||
ok "Base system installed"
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
# System configuration
|
||||
# ============================================================
|
||||
configure_system() {
|
||||
log "Configuring system..."
|
||||
|
||||
MOUNT_POINT="/mnt"
|
||||
|
||||
# Hostname
|
||||
echo "samios" > "$MOUNT_POINT/etc/hostname"
|
||||
|
||||
# Hosts
|
||||
cat > "$MOUNT_POINT/etc/hosts" << 'HOSTS'
|
||||
127.0.0.1 localhost
|
||||
::1 localhost
|
||||
127.0.1.1 samios.localdomain samios
|
||||
HOSTS
|
||||
|
||||
# Timezone
|
||||
arch-chroot "$MOUNT_POINT" ln -sf /usr/share/zoneinfo/America/New_York /etc/localtime
|
||||
arch-chroot "$MOUNT_POINT" hwclock --systohc
|
||||
|
||||
# Locale
|
||||
sed -i 's/^#en_US.UTF-8/en_US.UTF-8/' "$MOUNT_POINT/etc/locale.gen"
|
||||
arch-chroot "$MOUNT_POINT" locale-gen
|
||||
echo "LANG=en_US.UTF-8" > "$MOUNT_POINT/etc/locale.conf"
|
||||
|
||||
# Keymap
|
||||
echo "KEYMAP=us" > "$MOUNT_POINT/etc/vconsole.conf"
|
||||
|
||||
# Install essential packages
|
||||
arch-chroot "$MOUNT_POINT" pacman -S --noconfirm \
|
||||
networkmanager \
|
||||
sudo \
|
||||
grub \
|
||||
efibootmgr \
|
||||
os-prober \
|
||||
nano \
|
||||
vim \
|
||||
less \
|
||||
man-db \
|
||||
man-pages \
|
||||
git \
|
||||
curl \
|
||||
wget \
|
||||
bash-completion \
|
||||
reflector \
|
||||
openssh
|
||||
|
||||
# Enable NetworkManager
|
||||
arch-chroot "$MOUNT_POINT" systemctl enable NetworkManager
|
||||
|
||||
# Enable SSH (optional)
|
||||
arch-chroot "$MOUNT_POINT" systemctl enable sshd
|
||||
|
||||
ok "System configured"
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
# Bootloader
|
||||
# ============================================================
|
||||
install_bootloader() {
|
||||
log "Installing bootloader..."
|
||||
|
||||
MOUNT_POINT="/mnt"
|
||||
|
||||
if [ "$UEFI" = true ]; then
|
||||
arch-chroot "$MOUNT_POINT" grub-install --target=x86_64-efi \
|
||||
--efi-directory=/boot/efi --bootloader-id=SamiOS
|
||||
else
|
||||
arch-chroot "$MOUNT_POINT" grub-install --target=i386-pc "$TARGET_DISK"
|
||||
fi
|
||||
|
||||
# Configure GRUB
|
||||
arch-chroot "$MOUNT_POINT" grub-mkconfig -o /boot/grub/grub.cfg
|
||||
|
||||
ok "Bootloader installed"
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
# User creation
|
||||
# ============================================================
|
||||
create_user() {
|
||||
log "Creating user account..."
|
||||
|
||||
MOUNT_POINT="/mnt"
|
||||
|
||||
INTERACTIVE_USER="${INSTALL_USER:-sami}"
|
||||
|
||||
if [ -z "$INSTALL_PASSWORD" ]; then
|
||||
read -s -p "Enter password for ${INTERACTIVE_USER}: " USER_PASS
|
||||
echo ""
|
||||
read -s -p "Confirm password: " USER_PASS_CONFIRM
|
||||
echo ""
|
||||
if [ "$USER_PASS" != "$USER_PASS_CONFIRM" ]; then
|
||||
err "Passwords do not match"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
USER_PASS="$INSTALL_PASSWORD"
|
||||
fi
|
||||
|
||||
# Create user
|
||||
arch-chroot "$MOUNT_POINT" useradd -m -G wheel,storage,power,network -s /bin/bash "$INTERACTIVE_USER"
|
||||
|
||||
# Set password
|
||||
echo "$INTERACTIVE_USER:$USER_PASS" | arch-chroot "$MOUNT_POINT" chpasswd
|
||||
|
||||
# Enable sudo for wheel group
|
||||
sed -i 's/^# %wheel ALL=(ALL:ALL) ALL/%wheel ALL=(ALL:ALL) ALL/' "$MOUNT_POINT/etc/sudoers"
|
||||
|
||||
# Set root password
|
||||
echo "root:$USER_PASS" | arch-chroot "$MOUNT_POINT" chpasswd
|
||||
|
||||
ok "User ${INTERACTIVE_USER} created"
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
# SamiOS CLI tool
|
||||
# ============================================================
|
||||
install_samios_cli() {
|
||||
log "Installing SamiOS CLI tool..."
|
||||
|
||||
MOUNT_POINT="/mnt"
|
||||
|
||||
cat > "$MOUNT_POINT/usr/local/bin/samios" << 'SAMIOS_CLI'
|
||||
#!/bin/bash
|
||||
set -e
|
||||
VERSION="0.2.0"
|
||||
|
||||
cmd_help() {
|
||||
cat << EOF
|
||||
SamiOS CLI v${VERSION}
|
||||
|
||||
Commands:
|
||||
version Show version
|
||||
status Show system status
|
||||
update Update system packages
|
||||
install <pkg> Install a package
|
||||
remove <pkg> Remove a package
|
||||
services List running services
|
||||
fonts Check fonts and policy
|
||||
help Show this help
|
||||
EOF
|
||||
}
|
||||
|
||||
cmd_version() {
|
||||
echo "SamiOS v${VERSION}"
|
||||
echo "Kernel: $(uname -r)"
|
||||
echo "Architecture: $(uname -m)"
|
||||
}
|
||||
|
||||
cmd_status() {
|
||||
echo "=== SamiOS System Status ==="
|
||||
echo "Version: ${VERSION}"
|
||||
echo "Hostname: $(hostname)"
|
||||
echo "Kernel: $(uname -r)"
|
||||
echo "Uptime: $(uptime -p)"
|
||||
echo
|
||||
echo "=== Disk Usage ==="
|
||||
df -h / | tail -n 1
|
||||
echo
|
||||
echo "=== Memory ==="
|
||||
free -h | grep "Mem:"
|
||||
echo
|
||||
echo "=== Network ==="
|
||||
ip -br addr show | grep -v "lo" 2>/dev/null
|
||||
}
|
||||
|
||||
cmd_update() { sudo pacman -Syu --noconfirm; }
|
||||
cmd_install() { [ -z "$1" ] && echo "Usage: samios install <package>" && exit 1; sudo pacman -S --noconfirm "$1"; }
|
||||
cmd_remove() { [ -z "$1" ] && echo "Usage: samios remove <package>" && exit 1; sudo pacman -R --noconfirm "$1"; }
|
||||
cmd_services() { systemctl list-units --type=service --state=running; }
|
||||
cmd_fonts() {
|
||||
echo "=== Installed Fonts ==="
|
||||
fc-list | wc -l
|
||||
echo "fonts installed"
|
||||
echo
|
||||
echo "=== Font Policy ==="
|
||||
echo "Excluded: fonts with '7777' in name (personal branding)"
|
||||
if fc-list | grep -iq "7777"; then
|
||||
echo "WARNING: Found 7777 fonts:"
|
||||
fc-list | grep -i "7777"
|
||||
else
|
||||
echo "OK: No forbidden fonts"
|
||||
fi
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
version) cmd_version ;;
|
||||
status) cmd_status ;;
|
||||
update) cmd_update ;;
|
||||
install) shift; cmd_install "$@" ;;
|
||||
remove) shift; cmd_remove "$@" ;;
|
||||
services) cmd_services ;;
|
||||
fonts) cmd_fonts ;;
|
||||
help|--help|-h|"") cmd_help ;;
|
||||
*) echo "Unknown: $1"; exit 1 ;;
|
||||
esac
|
||||
SAMIOS_CLI
|
||||
|
||||
chmod +x "$MOUNT_POINT/usr/local/bin/samios"
|
||||
|
||||
# MOTD
|
||||
cat > "$MOUNT_POINT/etc/motd" << 'MOTD'
|
||||
|
||||
___ ___ ___ ___ ___
|
||||
/\ \ /\__\ /\ \ /\__\ /\ \
|
||||
/::\ \ /::| | /::\ \ /:/ / /::\ \
|
||||
/:/\:\ \ /:|:| | /:/\:\ \ /:/ / /:/\:\ \
|
||||
/:\ \:\ \ /:/|:| |__ /::\~\:\ \ /:/ / ___ /::\~\:\ \
|
||||
/:/\:\ \:\__\/:/ |:| /\__\ /:/\:\ \:\__\ /:/__/ /\__\ /:/\:\ \:\__\
|
||||
\/__\:\/:/ /\/ |:|/:/ / \/_|::\/:/ / \:\ \ /:/ / \:\~\:\ \/__/
|
||||
\::/ / |:/:/ / |:|::/ / \:\ /:/ / \:\ \:\__\
|
||||
/:/ / |::/ / |:|\/__/ \:\/:/ / \:\ \/__/
|
||||
/:/ / /:/ / |:| | \::/ / \:\__\
|
||||
\/__/ \/__/ \|__| \/__/ \/__/
|
||||
|
||||
Welcome to SamiOS! Type 'samios help' to get started.
|
||||
|
||||
MOTD
|
||||
|
||||
# Bashrc welcome
|
||||
cat > "$MOUNT_POINT/etc/bash.bashrc" << 'BASHRC'
|
||||
# SamiOS system-wide bashrc
|
||||
export PS1='\[\033[01;34m\]sami\[\033[01;34m\]@samios\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
|
||||
|
||||
alias ls='ls --color=auto'
|
||||
alias ll='ls -la'
|
||||
alias la='ls -A'
|
||||
alias l='ls -CF'
|
||||
alias update='sudo pacman -Syu'
|
||||
alias install='sudo pacman -S'
|
||||
alias remove='sudo pacman -R'
|
||||
|
||||
# SamiOS CLI in PATH
|
||||
export PATH="/usr/local/bin:$PATH"
|
||||
BASHRC
|
||||
|
||||
ok "SamiOS CLI and configs installed"
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
# Cleanup and finish
|
||||
# ============================================================
|
||||
finish_install() {
|
||||
log "Finalizing installation..."
|
||||
|
||||
MOUNT_POINT="/mnt"
|
||||
|
||||
# Unmount
|
||||
umount -R "$MOUNT_POINT"
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo " SamiOS Installation Complete! "
|
||||
echo "============================================"
|
||||
echo ""
|
||||
echo " Disk: $TARGET_DISK"
|
||||
echo " User: ${INSTALL_USER:-sami}"
|
||||
echo " Bootloader: $([ "$UEFI" = true ] && echo "GRUB (UEFI)" || echo "GRUB (BIOS)")"
|
||||
echo ""
|
||||
echo " Next steps:"
|
||||
echo " 1. Reboot: systemctl reboot"
|
||||
echo " 2. Log in as ${INSTALL_USER:-sami}"
|
||||
echo " 3. Run: samios status"
|
||||
echo " 4. Install desktop: samios install plasma"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
# Main
|
||||
# ============================================================
|
||||
main() {
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo " SamiOS Installer v${VERSION} "
|
||||
echo "============================================"
|
||||
echo ""
|
||||
|
||||
check_root
|
||||
check_uefi
|
||||
detect_disks
|
||||
select_disk
|
||||
partition_disk
|
||||
mount_and_install
|
||||
configure_system
|
||||
install_bootloader
|
||||
create_user
|
||||
install_samios_cli
|
||||
finish_install
|
||||
}
|
||||
|
||||
# Parse args
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--disk) TARGET_DISK="$2"; shift 2 ;;
|
||||
--user) INSTALL_USER="$2"; shift 2 ;;
|
||||
--password) INSTALL_PASSWORD="$2"; shift 2 ;;
|
||||
--help|-h) echo "Usage: samios install [--disk /dev/sdX] [--user username] [--password pass]"; exit 0 ;;
|
||||
*) shift ;;
|
||||
esac
|
||||
done
|
||||
|
||||
main
|
||||
@@ -0,0 +1,83 @@
|
||||
#!/bin/bash
|
||||
# SamiOS test suite runner
|
||||
# Runs all test scripts and aggregates results.
|
||||
#
|
||||
# Usage: ./tests/run_tests.sh [--verbose]
|
||||
# Exit code: 0 if all tests pass, 1 if any fail.
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
VERBOSE=false
|
||||
|
||||
if [ "${1:-}" = "--verbose" ] || [ "${1:-}" = "-v" ]; then
|
||||
VERBOSE=true
|
||||
fi
|
||||
|
||||
echo "╔══════════════════════════════════════╗"
|
||||
echo "║ SamiOS Test Suite Runner ║"
|
||||
echo "╚══════════════════════════════════════╝"
|
||||
|
||||
TEST_FILES=(
|
||||
"test_profiledef.sh"
|
||||
"test_packages.sh"
|
||||
"test_pacman_conf.sh"
|
||||
"test_samios_cli.sh"
|
||||
"test_font_policy.sh"
|
||||
)
|
||||
|
||||
TOTAL_RUN=0
|
||||
TOTAL_PASSED=0
|
||||
TOTAL_FAILED=0
|
||||
FAILED_SUITES=()
|
||||
|
||||
for tf in "${TEST_FILES[@]}"; do
|
||||
full_path="$SCRIPT_DIR/$tf"
|
||||
if [ ! -f "$full_path" ]; then
|
||||
echo "WARNING: test file not found: $full_path"
|
||||
continue
|
||||
fi
|
||||
|
||||
suite_name="${tf%.sh}"
|
||||
echo ""
|
||||
echo ">>> Running: $suite_name"
|
||||
|
||||
# Run the test file in a subshell so we capture its exit code
|
||||
output=$(bash "$full_path" 2>&1)
|
||||
exit_code=$?
|
||||
|
||||
if $VERBOSE || [ $exit_code -ne 0 ]; then
|
||||
echo "$output"
|
||||
else
|
||||
# Print just the suite headers and pass/fail lines
|
||||
echo "$output" | grep -E "^=|^ [✓✗]"
|
||||
fi
|
||||
|
||||
if [ $exit_code -ne 0 ]; then
|
||||
FAILED_SUITES+=("$suite_name")
|
||||
echo " >>> FAILED"
|
||||
else
|
||||
echo " >>> PASSED"
|
||||
fi
|
||||
done
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Summary
|
||||
# ---------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo "═══════════════════════════════════════"
|
||||
echo "SamiOS Test Suite — Final Summary"
|
||||
echo "═══════════════════════════════════════"
|
||||
|
||||
if [ ${#FAILED_SUITES[@]} -eq 0 ]; then
|
||||
echo "All test suites PASSED ✓"
|
||||
exit 0
|
||||
else
|
||||
echo "FAILED suites:"
|
||||
for s in "${FAILED_SUITES[@]}"; do
|
||||
echo " ✗ $s"
|
||||
done
|
||||
echo ""
|
||||
echo "${#FAILED_SUITES[@]} suite(s) failed"
|
||||
exit 1
|
||||
fi
|
||||
@@ -0,0 +1,57 @@
|
||||
#!/bin/bash
|
||||
# Test: Font policy enforcement
|
||||
# Validates that no packages, files, or scripts reference '7777' fonts
|
||||
# as something to include — only to exclude.
|
||||
|
||||
source "$(dirname "$0")/test_helper.sh"
|
||||
|
||||
suite "Font policy tests"
|
||||
|
||||
PKGLIST="$PROFILE_DIR/packages.x86_64"
|
||||
SAMIOS_CLI="$PROFILE_DIR/airootfs/usr/local/bin/samios"
|
||||
SETUP_SCRIPT="$SCRIPTS_DIR/samios-desktop-setup.sh"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# packages.x86_64 must not contain any font package with '7777'
|
||||
# ---------------------------------------------------------------------------
|
||||
assert "no font package with '7777' in package list" \
|
||||
bash -c '
|
||||
if grep -iE "^[^#].*7777" "'"$PKGLIST"'"; then
|
||||
exit 1
|
||||
fi
|
||||
'
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# samios CLI fonts command must explicitly check for 7777
|
||||
# ---------------------------------------------------------------------------
|
||||
assert_contains "samios CLI fonts function checks for 7777" "$SAMIOS_CLI" "7777"
|
||||
assert_contains "samios CLI warns about forbidden fonts" "$SAMIOS_CLI" "forbidden fonts"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Desktop setup script must use ! -iname *7777* exclusion (not inclusion)
|
||||
# ---------------------------------------------------------------------------
|
||||
assert_contains "desktop setup excludes 7777 fonts in copy from Windows" "$SETUP_SCRIPT" '! -iname'
|
||||
|
||||
# Verify the exclusion appears in a find command context (copy, not removal)
|
||||
assert "desktop setup script copies fonts but excludes 7777" \
|
||||
bash -c '
|
||||
grep -c "! -iname.*7777" "'"$SETUP_SCRIPT"'" | grep -q "[1-9]"
|
||||
'
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Verify the desktop setup script has a verification check for no 7777 fonts
|
||||
# ---------------------------------------------------------------------------
|
||||
assert_contains "desktop setup verifies no 7777 fonts after copy" "$SETUP_SCRIPT" 'grep -i "7777"'
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Check that font-related exclusion logic appears in the samios CLI
|
||||
# ---------------------------------------------------------------------------
|
||||
assert "samios CLI font policy grep uses -i flag for case-insensitive match" \
|
||||
bash -c 'grep -q "grep -i.*7777" "'"$SAMIOS_CLI"'" || grep -q "grep -iq.*7777" "'"$SAMIOS_CLI"'"'
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# If packages.x86_64 has an excluded-fonts comment, it must mention 7777
|
||||
# ---------------------------------------------------------------------------
|
||||
assert_contains "package list documents font exclusion policy" "$PKGLIST" "7777"
|
||||
|
||||
print_summary
|
||||
@@ -0,0 +1,135 @@
|
||||
#!/bin/bash
|
||||
# Common test helpers for SamiOS test suite
|
||||
# Sourced by individual test scripts
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Path setup — resolve repo root relative to this file
|
||||
# ---------------------------------------------------------------------------
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
PROFILE_DIR="$REPO_ROOT/packaging/archiso"
|
||||
SCRIPTS_DIR="$REPO_ROOT/packaging/scripts"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Counters
|
||||
# ---------------------------------------------------------------------------
|
||||
TESTS_RUN=0
|
||||
TESTS_PASSED=0
|
||||
TESTS_FAILED=0
|
||||
CURRENT_SUITE=""
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Output helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
suite() {
|
||||
CURRENT_SUITE="$1"
|
||||
echo ""
|
||||
echo "=== $CURRENT_SUITE ==="
|
||||
}
|
||||
|
||||
assert() {
|
||||
# assert <description> <condition-cmd...>
|
||||
local desc="$1"; shift
|
||||
local output
|
||||
if output="$("$@" 2>&1)"; then
|
||||
echo " ✓ $desc"
|
||||
((TESTS_PASSED++))
|
||||
else
|
||||
echo " ✗ $desc"
|
||||
echo " output: $output"
|
||||
((TESTS_FAILED++))
|
||||
fi
|
||||
((TESTS_RUN++))
|
||||
}
|
||||
|
||||
assert_contains() {
|
||||
# assert_contains <description> <file> <pattern>
|
||||
local desc="$1" file="$2" pattern="$3"
|
||||
if grep -q "$pattern" "$file" 2>/dev/null; then
|
||||
echo " ✓ $desc"
|
||||
((TESTS_PASSED++))
|
||||
else
|
||||
echo " ✗ $desc"
|
||||
echo " '$pattern' not found in $file"
|
||||
((TESTS_FAILED++))
|
||||
fi
|
||||
((TESTS_RUN++))
|
||||
}
|
||||
|
||||
assert_not_contains() {
|
||||
# assert_not_contains <description> <file> <pattern>
|
||||
local desc="$1" file="$2" pattern="$3"
|
||||
if grep -q "$pattern" "$file" 2>/dev/null; then
|
||||
echo " ✗ $desc"
|
||||
echo " '$pattern' unexpectedly found in $file"
|
||||
((TESTS_FAILED++))
|
||||
else
|
||||
echo " ✓ $desc"
|
||||
((TESTS_PASSED++))
|
||||
fi
|
||||
((TESTS_RUN++))
|
||||
}
|
||||
|
||||
assert_file_exists() {
|
||||
local desc="$1" file="$2"
|
||||
if [ -f "$file" ]; then
|
||||
echo " ✓ $desc"
|
||||
((TESTS_PASSED++))
|
||||
else
|
||||
echo " ✗ $desc"
|
||||
echo " file not found: $file"
|
||||
((TESTS_FAILED++))
|
||||
fi
|
||||
((TESTS_RUN++))
|
||||
}
|
||||
|
||||
assert_cmd_output_contains() {
|
||||
# assert_cmd_output_contains <description> <expected-substring> <cmd...>
|
||||
local desc="$1" expected="$2"; shift 2
|
||||
local output
|
||||
output="$("$@" 2>&1)" || true
|
||||
if echo "$output" | grep -q "$expected"; then
|
||||
echo " ✓ $desc"
|
||||
((TESTS_PASSED++))
|
||||
else
|
||||
echo " ✗ $desc"
|
||||
echo " expected '$expected' in output, got:"
|
||||
echo " $output"
|
||||
((TESTS_FAILED++))
|
||||
fi
|
||||
((TESTS_RUN++))
|
||||
}
|
||||
|
||||
assert_exit_code() {
|
||||
# assert_exit_code <description> <expected-code> <cmd...>
|
||||
local desc="$1" expected="$2"; shift 2
|
||||
local actual=0
|
||||
"$@" >/dev/null 2>&1 || actual=$?
|
||||
if [ "$actual" -eq "$expected" ]; then
|
||||
echo " ✓ $desc"
|
||||
((TESTS_PASSED++))
|
||||
else
|
||||
echo " ✗ $desc"
|
||||
echo " expected exit code $expected, got $actual"
|
||||
((TESTS_FAILED++))
|
||||
fi
|
||||
((TESTS_RUN++))
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Summary — prints results and sets exit code
|
||||
# ---------------------------------------------------------------------------
|
||||
print_summary() {
|
||||
echo ""
|
||||
echo "────────────────────────────────────────"
|
||||
echo "Tests run: $TESTS_RUN"
|
||||
echo "Tests passed: $TESTS_PASSED"
|
||||
echo "Tests failed: $TESTS_FAILED"
|
||||
echo "────────────────────────────────────────"
|
||||
if [ "$TESTS_FAILED" -gt 0 ]; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
#!/bin/bash
|
||||
# Test: packages.x86_64 format and content
|
||||
# Validates package list format, required packages, and font policy.
|
||||
|
||||
source "$(dirname "$0")/test_helper.sh"
|
||||
|
||||
suite "packages.x86_64 tests"
|
||||
|
||||
PKGLIST="$PROFILE_DIR/packages.x86_64"
|
||||
|
||||
assert_file_exists "packages.x86_64 exists" "$PKGLIST"
|
||||
|
||||
# Every non-comment, non-empty line must be a valid package name
|
||||
assert "all package names match valid format (alphanumeric, dashes, +)" \
|
||||
bash -c '
|
||||
while IFS= read -r line; do
|
||||
# skip comments and blank lines
|
||||
[[ -z "$line" || "$line" == \#* ]] && continue
|
||||
# validate: letters, digits, dashes, underscores, plus signs
|
||||
if ! grep -qE "^[a-zA-Z0-9][a-zA-Z0-9_+.-]*$" <<< "$line"; then
|
||||
echo "invalid package name: $line"
|
||||
exit 1
|
||||
fi
|
||||
done < "'"$PKGLIST"'"
|
||||
'
|
||||
|
||||
# Required core packages
|
||||
assert_contains "includes base" "$PKGLIST" "^base$"
|
||||
assert_contains "includes linux" "$PKGLIST" "^linux$"
|
||||
assert_contains "includes linux-firmware" "$PKGLIST" "^linux-firmware$"
|
||||
assert_contains "includes networkmanager" "$PKGLIST" "^networkmanager$"
|
||||
|
||||
# Font policy: no actual package (non-comment line) containing '7777'
|
||||
assert "no package with '7777' in name" \
|
||||
bash -c '
|
||||
if grep -vE "^\s*#" "'"$PKGLIST"'" | grep -i "7777"; then
|
||||
exit 1
|
||||
fi
|
||||
'
|
||||
|
||||
# No blank trailing package lines (exactly one trailing newline)
|
||||
assert "no trailing blank lines in package list" \
|
||||
bash -c '
|
||||
content="$(cat "'"$PKGLIST"'")"
|
||||
# wc -l should equal number of non-empty lines
|
||||
[ "$(tail -c1 "'"$PKGLIST"'" | wc -l)" -le 1 ]
|
||||
'
|
||||
|
||||
# No duplicate packages
|
||||
assert "no duplicate package entries" \
|
||||
bash -c '
|
||||
dups=$(grep -vE "^\s*#|^\s*$" "'"$PKGLIST"'" | sort | uniq -d)
|
||||
if [ -n "$dups" ]; then
|
||||
echo "duplicates: $dups"
|
||||
exit 1
|
||||
fi
|
||||
'
|
||||
|
||||
print_summary
|
||||
@@ -0,0 +1,50 @@
|
||||
#!/bin/bash
|
||||
# Test: pacman.conf validity
|
||||
# Validates INI structure, required sections, and key options.
|
||||
|
||||
source "$(dirname "$0")/test_helper.sh"
|
||||
|
||||
suite "pacman.conf tests"
|
||||
|
||||
PACMANCONF="$PROFILE_DIR/pacman.conf"
|
||||
|
||||
assert_file_exists "pacman.conf exists" "$PACMANCONF"
|
||||
|
||||
assert "pacman.conf has valid structure (no unparseable lines)" \
|
||||
bash -c '
|
||||
while IFS= read -r line; do
|
||||
# skip blank lines and comments
|
||||
[[ -z "$line" || "$line" == \#* || "$line" == \;* ]] && continue
|
||||
# section header [name]
|
||||
if grep -qE "^\[.+\]$" <<< "$line"; then continue; fi
|
||||
# key = value pair
|
||||
if grep -qE "^[A-Za-z].*=.*$" <<< "$line"; then continue; fi
|
||||
# bare pacman options (e.g. CheckSpace, NoProgressBar, Color)
|
||||
if grep -qE "^[A-Z][A-Za-z]+$" <<< "$line"; then continue; fi
|
||||
echo "unparseable line: $line"
|
||||
exit 1
|
||||
done < "'"$PACMANCONF"'"
|
||||
'
|
||||
|
||||
assert_contains "pacman.conf has [options] section" "$PACMANCONF" "^\[options\]"
|
||||
assert_contains "pacman.conf has [core] section" "$PACMANCONF" "^\[core\]"
|
||||
assert_contains "pacman.conf has [extra] section" "$PACMANCONF" "^\[extra\]"
|
||||
assert_contains "pacman.conf has Architecture setting" "$PACMANCONF" "^Architecture"
|
||||
assert_contains "pacman.conf has SigLevel setting" "$PACMANCONF" "^SigLevel"
|
||||
assert_contains "pacman.conf has HoldPkg setting" "$PACMANCONF" "^HoldPkg"
|
||||
|
||||
# Validate all section headers are well-formed [name]
|
||||
assert "all section headers are well-formed" \
|
||||
bash -c '
|
||||
while IFS= read -r line; do
|
||||
# match [something] — non-empty, no spaces in name
|
||||
if [[ "$line" == \[* ]]; then
|
||||
if ! grep -qE "^\[[a-zA-Z0-9_-]+\]$" <<< "$line"; then
|
||||
echo "malformed section header: $line"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done < "'"$PACMANCONF"'"
|
||||
'
|
||||
|
||||
print_summary
|
||||
@@ -0,0 +1,55 @@
|
||||
#!/bin/bash
|
||||
# Test: profiledef.sh validity
|
||||
# Validates that profiledef.sh exists, has valid bash syntax, and defines
|
||||
# all required archiso profile variables.
|
||||
|
||||
source "$(dirname "$0")/test_helper.sh"
|
||||
|
||||
suite "profiledef.sh tests"
|
||||
|
||||
PROFILEDEF="$PROFILE_DIR/profiledef.sh"
|
||||
|
||||
assert_file_exists "profiledef.sh exists" "$PROFILEDEF"
|
||||
|
||||
assert "profiledef.sh has valid bash syntax" \
|
||||
bash -n "$PROFILEDEF"
|
||||
|
||||
# profiledef.sh uses associative arrays without explicit `declare -A`,
|
||||
# relying on mkarchiso's caller context. Pre-declare so plain bash can source it.
|
||||
SOURCE_CMD='declare -A file_permissions; source "'"$PROFILEDEF"'"'
|
||||
|
||||
# Source the file in a subshell and verify required variables are set
|
||||
assert "profiledef.sh defines iso_name" \
|
||||
bash -c "$SOURCE_CMD; [ -n \"\$iso_name\" ]"
|
||||
|
||||
assert "profiledef.sh defines iso_version" \
|
||||
bash -c "$SOURCE_CMD; [ -n \"\$iso_version\" ]"
|
||||
|
||||
assert "profiledef.sh defines iso_publisher" \
|
||||
bash -c "$SOURCE_CMD; [ -n \"\$iso_publisher\" ]"
|
||||
|
||||
assert "profiledef.sh defines iso_application" \
|
||||
bash -c "$SOURCE_CMD; [ -n \"\$iso_application\" ]"
|
||||
|
||||
assert "profiledef.sh defines arch" \
|
||||
bash -c "$SOURCE_CMD; [ -n \"\$arch\" ]"
|
||||
|
||||
assert "iso_name is 'samios'" \
|
||||
bash -c "$SOURCE_CMD; [ \"\$iso_name\" = 'samios' ]"
|
||||
|
||||
assert "arch is 'x86_64'" \
|
||||
bash -c "$SOURCE_CMD; [ \"\$arch\" = 'x86_64' ]"
|
||||
|
||||
assert "buildmodes array is non-empty" \
|
||||
bash -c "$SOURCE_CMD; [ \${#buildmodes[@]} -gt 0 ]"
|
||||
|
||||
assert "bootmodes array is non-empty" \
|
||||
bash -c "$SOURCE_CMD; [ \${#bootmodes[@]} -gt 0 ]"
|
||||
|
||||
assert "file_permissions includes /usr/local/bin/samios" \
|
||||
bash -c "$SOURCE_CMD; [ -n \"\${file_permissions[/usr/local/bin/samios]}\" ]"
|
||||
|
||||
assert "file_permissions includes /etc/shadow" \
|
||||
bash -c "$SOURCE_CMD; [ -n \"\${file_permissions[/etc/shadow]}\" ]"
|
||||
|
||||
print_summary
|
||||
@@ -0,0 +1,96 @@
|
||||
#!/bin/bash
|
||||
# Test: samios CLI tool
|
||||
# Validates the CLI script's syntax, help, version, status, and error handling.
|
||||
# We test the script at packaging/archiso/airootfs/usr/local/bin/samios
|
||||
# (the installed script), not the one embedded in samios-desktop-setup.sh.
|
||||
|
||||
source "$(dirname "$0")/test_helper.sh"
|
||||
|
||||
suite "samios CLI tests"
|
||||
|
||||
SAMIOS_CLI="$PROFILE_DIR/airootfs/usr/local/bin/samios"
|
||||
|
||||
assert_file_exists "samios CLI exists" "$SAMIOS_CLI"
|
||||
|
||||
assert "samios CLI has valid bash syntax" \
|
||||
bash -n "$SAMIOS_CLI"
|
||||
|
||||
assert "samios CLI is executable" \
|
||||
bash -c "[ -x '$SAMIOS_CLI' ]"
|
||||
|
||||
assert "samios CLI starts with bash shebang" \
|
||||
bash -c 'head -1 "'"$SAMIOS_CLI"'" | grep -q "#!/bin/bash"'
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# --help / help / -h
|
||||
# ---------------------------------------------------------------------------
|
||||
assert_cmd_output_contains "samios --help shows usage" "Usage" \
|
||||
bash "$SAMIOS_CLI" --help
|
||||
|
||||
assert_cmd_output_contains "samios help shows Usage" "Usage" \
|
||||
bash "$SAMIOS_CLI" help
|
||||
|
||||
assert_cmd_output_contains "samios -h shows Usage" "Usage" \
|
||||
bash "$SAMIOS_CLI" -h
|
||||
|
||||
assert_cmd_output_contains "samios help lists 'version' command" "version" \
|
||||
bash "$SAMIOS_CLI" help
|
||||
|
||||
assert_cmd_output_contains "samios help lists 'status' command" "status" \
|
||||
bash "$SAMIOS_CLI" help
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# version
|
||||
# ---------------------------------------------------------------------------
|
||||
assert_cmd_output_contains "samios version outputs 'SamiOS v'" "SamiOS v" \
|
||||
bash "$SAMIOS_CLI" version
|
||||
|
||||
assert_cmd_output_contains "samios version outputs Kernel info" "Kernel:" \
|
||||
bash "$SAMIOS_CLI" version
|
||||
|
||||
assert_cmd_output_contains "samios version outputs Architecture info" "Architecture:" \
|
||||
bash "$SAMIOS_CLI" version
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# status (may fail in CI if commands like 'ip' aren't installed, so we use || true)
|
||||
# ---------------------------------------------------------------------------
|
||||
assert_cmd_output_contains "samios status shows system status header" "System Status" \
|
||||
bash "$SAMIOS_CLI" status
|
||||
|
||||
assert_cmd_output_contains "samios status shows Disk Usage" "Disk" \
|
||||
bash "$SAMIOS_CLI" status
|
||||
|
||||
assert_cmd_output_contains "samios status shows Memory section" "Memory" \
|
||||
bash "$SAMIOS_CLI" status
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# fonts
|
||||
# ---------------------------------------------------------------------------
|
||||
assert_cmd_output_contains "samios fonts shows font count" "fonts installed" \
|
||||
bash "$SAMIOS_CLI" fonts
|
||||
|
||||
assert_cmd_output_contains "samios fonts mentions font policy" "Font Policy" \
|
||||
bash "$SAMIOS_CLI" fonts
|
||||
|
||||
assert "samios fonts mentions 7777 exclusion" \
|
||||
bash -c '
|
||||
output="$(bash "'"$SAMIOS_CLI"'" fonts 2>&1)" || true
|
||||
echo "$output" | grep -q "7777"
|
||||
'
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# unknown command
|
||||
# ---------------------------------------------------------------------------
|
||||
assert_exit_code "samios with unknown command exits non-zero" 1 \
|
||||
bash "$SAMIOS_CLI" nonexistentcommand
|
||||
|
||||
assert_cmd_output_contains "samios unknown cmd shows error" "Unknown command" \
|
||||
bash "$SAMIOS_CLI" nonexistentcommand
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# No-arg invocation defaults to help
|
||||
# ---------------------------------------------------------------------------
|
||||
assert_cmd_output_contains "samios with no args shows Usage" "Usage" \
|
||||
bash "$SAMIOS_CLI"
|
||||
|
||||
print_summary
|
||||