200920.2 · 92db3c9339d8035befe4c045dc68fce75956071c
system: re-arrange system configuration structure
Basically, for system configuration, we want to check all of that into source control. Until now, I had just been sporadically maintaining system configuration on each machine, but this has become unwieldy. It also guarantees that I will forget to copy something whenever I wipe a machine.
Given that my Archlinux install on my laptop is FUBAR, I'm trying to start this process right. The general scheme is:
$HOME/etc/path/to/config-file-as-directory/{default,krusty,...}
Where `/etc/path/to/config-file-as-directory` is a directory that refers to a concrete file path in the /etc directory. Inside this directory is an optional file named `default`, along with other optional files named by hostname, e.g., `krusty`. If a hostname file is present, then that file is symlinked to the corresponding config file location. Otherwise the `default` file is. If no files are present, then no symlinks are created.
This simple scheme permits per-system configuration without losing track of anything.
reading declarations
bin/rust/setup-system-links/.gitignore
@@ -0,0 +1 @@+/target
bin/rust/setup-system-links/Cargo.lock
@@ -0,0 +1,139 @@+# This file is automatically @generated by Cargo.+# It is not intended for manual editing.+[[package]]+name = "anyhow"+version = "1.0.32"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "6b602bfe940d21c130f3895acd65221e8a61270debe89d628b9cb4e3ccb8569b"++[[package]]+name = "bitflags"+version = "1.2.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"++[[package]]+name = "bstr"+version = "0.2.13"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "31accafdb70df7871592c058eca3985b71104e15ac32f64706022c58867da931"+dependencies = [+ "lazy_static",+ "memchr",+ "regex-automata",+]++[[package]]+name = "byteorder"+version = "1.3.4"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"++[[package]]+name = "clap"+version = "2.33.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"+dependencies = [+ "bitflags",+ "textwrap",+ "unicode-width",+]++[[package]]+name = "lazy_static"+version = "1.4.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"++[[package]]+name = "memchr"+version = "2.3.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"++[[package]]+name = "regex-automata"+version = "0.1.9"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4"+dependencies = [+ "byteorder",+]++[[package]]+name = "same-file"+version = "1.0.6"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"+dependencies = [+ "winapi-util",+]++[[package]]+name = "setup-system-links"+version = "0.0.1"+dependencies = [+ "anyhow",+ "bstr",+ "clap",+ "same-file",+ "walkdir",+]++[[package]]+name = "textwrap"+version = "0.11.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"+dependencies = [+ "unicode-width",+]++[[package]]+name = "unicode-width"+version = "0.1.8"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"++[[package]]+name = "walkdir"+version = "2.3.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"+dependencies = [+ "same-file",+ "winapi",+ "winapi-util",+]++[[package]]+name = "winapi"+version = "0.3.9"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"+dependencies = [+ "winapi-i686-pc-windows-gnu",+ "winapi-x86_64-pc-windows-gnu",+]++[[package]]+name = "winapi-i686-pc-windows-gnu"+version = "0.4.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"++[[package]]+name = "winapi-util"+version = "0.1.5"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"+dependencies = [+ "winapi",+]++[[package]]+name = "winapi-x86_64-pc-windows-gnu"+version = "0.4.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
bin/rust/setup-system-links/Cargo.toml
@@ -0,0 +1,12 @@+[package]+name = "setup-system-links"+version = "0.0.1"+authors = ["Andrew Gallant <jamslam@gmail.com>"]+edition = "2018"++[dependencies]+anyhow = "1.0.32"+bstr = "0.2.13"+clap = { version = "2.33.0", default-features = false }+same-file = "1.0.6"+walkdir = "2.3.1"
bin/rust/setup-system-links/rustfmt.toml
@@ -0,0 +1,2 @@+max_width = 79+use_small_heuristics = "max"
bin/rust/setup-system-links/src/main.rs
@@ -0,0 +1,376 @@+#[cfg(not(unix))]+compile_error!("setup-system-links only works on Unix systems");++use std::collections::{BTreeMap, BTreeSet};+use std::env;+use std::ffi::{OsStr, OsString};+use std::io::{self, Write};+#[cfg(unix)]+use std::os::unix;+use std::path::{Path, PathBuf};++use anyhow::Context;+use bstr::{BString, ByteSlice, ByteVec};+use walkdir::WalkDir;++fn main() -> anyhow::Result<()> {+ let args = Args::parse()?;+ let mut links = Links::discover(&args.system, &args.hostname)?;+ if let Some(ref backup_dir) = args.backup {+ links.backup(backup_dir.to_owned());+ }+ if args.dry_run {+ links.dry_run(std::io::stdout())?;+ } else {+ links.run(std::io::stdout())?;+ }+ Ok(())+}++/// Represents a collection of links derived from this machine's ~/system+/// directory.+#[derive(Debug)]+struct Links {+ links: Vec<Link>,+ backup: Option<PathBuf>,+}++impl Links {+ /// Determine the full set of system config links for this machine given+ /// the system configuration directory and this machine's hostname.+ fn discover(system: &Path, hostname: &str) -> anyhow::Result<Links> {+ // Collect all leaf files in ~/system, creating a map, e.g.,+ // etc/default/grub |--> {default, krusty, frink, ...}+ // Note that the key lack the leading slash. We add that below.+ let mut all: BTreeMap<PathBuf, BTreeSet<String>> = BTreeMap::new();+ for result in WalkDir::new(system) {+ let dent = result.with_context(|| {+ format!("{}: failed to walk directory", system.display())+ })?;+ if !dent.file_type().is_file() {+ continue;+ }++ let machine_config_name = dent+ .file_name()+ .to_str()+ .with_context(|| {+ format!("{} is not valid UTF-8", dent.path().display())+ })?+ .to_string();+ // Should never fail since 'system' is our root and is guaranteed+ // to be non-empty.+ let dst = dent+ .path()+ .strip_prefix(system)+ .unwrap()+ .parent()+ .unwrap()+ .to_path_buf();+ if dst.as_os_str().is_empty() {+ // These are files directly in ~/system/ like+ // ~/system/README.md and are not part of our config.+ continue;+ }+ all.entry(dst)+ .or_insert_with(|| BTreeSet::new())+ .insert(machine_config_name);+ }+ // Now organize them into links by choosing the appropriate specific+ // config for this machine.+ let mut links = vec![];+ for (relative_dst, configs) in all {+ let dst = Path::new("/").join(&relative_dst);+ for &attempt in &[hostname, "default"] {+ if configs.contains(attempt) {+ let src = system.join(relative_dst).join(attempt);+ links.push(Link { src, dst });+ break;+ }+ }+ }+ Ok(Links { links, backup: None })+ }++ /// Indicates that the destination of each link should be backed up+ /// first.+ fn backup(&mut self, dir: PathBuf) {+ self.backup = Some(dir);+ }++ /// Create the links that do not yet exist.+ ///+ /// When backup is enabled (the default), then all config files will be+ /// backed up before attempting any link. If any backup fails, then no+ /// link will be created.+ ///+ /// The equivalent Unix command to each operation will be written to the+ /// given writer (like during a dry run).+ fn run<W: Write>(&self, mut wtr: W) -> anyhow::Result<()> {+ let mut to_link = vec![];+ for link in &self.links {+ if link.exists()? {+ continue;+ }+ to_link.push(link);+ }+ if let Some(ref backup_dir) = self.backup {+ for link in &to_link {+ link.backup(&mut wtr, backup_dir)?;+ }+ }+ for link in to_link {+ link.link(&mut wtr)?;+ }+ Ok(())+ }++ /// Print the equivalent Unix commands that this would execute if we were+ /// running for real, but make no changes to the file system.+ fn dry_run<W: Write>(&self, mut wtr: W) -> anyhow::Result<()> {+ let mut to_link = vec![];+ for link in &self.links {+ if link.exists()? {+ continue;+ }+ to_link.push(link);+ }+ if let Some(ref backup_dir) = self.backup {+ for link in &to_link {+ link.dry_backup(&mut wtr, backup_dir)?;+ }+ }+ for link in to_link {+ link.dry_link(&mut wtr)?;+ }+ Ok(())+ }+}++/// Represents a link between a file in ~/system and an actual system+/// configuration path on the system. e.g., ~/system/etc/default/grub/krusty+/// will link to /etc/default/grub on my 'krusty' laptop.+#[derive(Debug)]+struct Link {+ /// The ~/system/ path to this machine's config.+ src: PathBuf,+ /// The path to where this config lives on the system.+ dst: PathBuf,+}++impl Link {+ /// Write the equivalent Unix command we would execute if we were running+ /// for real.+ fn dry_link<W: Write>(&self, mut wtr: W) -> io::Result<()> {+ writeln!(+ wtr,+ "ln \"{}\" \"{}\"",+ self.src.display(),+ self.dst.display()+ )+ }++ /// Write the equivalent Unix command we would execute to backup the config+ /// file if we were running for real.+ fn dry_backup<W: Write>(&self, mut wtr: W, dir: &Path) -> io::Result<()> {+ let backup_dst = dir.join(self.relative_dst());+ // OK since self.dst is guaranteed to be non-empty.+ let parent = backup_dst.parent().unwrap();+ writeln!(wtr, "mkdir -p \"{}\"", parent.display(),)?;+ writeln!(+ wtr,+ "cp \"{}\" \"{}\"",+ self.dst.display(),+ backup_dst.display()+ )+ }++ /// Link the source to the destination, overwriting the destination if it+ /// exists. Callers should ensure that the destination is backed up before+ /// executing.+ fn link<W: Write>(&self, wtr: W) -> anyhow::Result<()> {+ if self.dst.exists() {+ std::fs::remove_file(&self.dst).with_context(|| {+ format!(+ "failed to delete {} before creating symlink from {}",+ self.dst.display(),+ self.src.display()+ )+ })?;+ }+ unix::fs::symlink(&self.src, &self.dst).with_context(|| {+ format!(+ "failed to link {} to {}",+ self.src.display(),+ self.dst.display()+ )+ })?;+ self.dry_link(wtr)?;+ Ok(())+ }++ /// Backup the destination to the directory given.+ fn backup<W: Write>(&self, wtr: W, dir: &Path) -> anyhow::Result<()> {+ let backup_dst = dir.join(self.relative_dst());+ // OK since self.dst is guaranteed to be non-empty.+ let parent = backup_dst.parent().unwrap();+ std::fs::create_dir_all(parent).with_context(|| {+ format!(+ "failed to create parent directory {} for backup",+ parent.display()+ )+ })?;+ std::fs::copy(&self.dst, &backup_dst).with_context(|| {+ format!(+ "failed to backup {} to {}",+ self.dst.display(),+ backup_dst.display()+ )+ })?;+ self.dry_backup(wtr, dir)?;+ Ok(())+ }++ /// Returns true if and only if this link already exists in the file+ /// system. That is, when the src and dst refer to the same underlying+ /// file.+ fn exists(&self) -> anyhow::Result<bool> {+ if !self.dst.exists() {+ return Ok(false);+ }+ same_file::is_same_file(&self.src, &self.dst).with_context(|| {+ format!(+ "failed to determine if {} == {}",+ self.src.display(),+ self.dst.display(),+ )+ })+ }++ /// Returns the destination path without its leading /.+ fn relative_dst(&self) -> &Path {+ // OK because dst is always absolute, by construction.+ self.dst.strip_prefix("/").unwrap()+ }+}++#[derive(Debug)]+struct Args {+ /// The directory in which to copy the contents of system configuration+ /// files before removing them and putting a symlink in its place.+ backup: Option<PathBuf>,+ /// When true, make no changes to the file system and instead print what+ /// we would do instead.+ dry_run: bool,+ /// The hostname of this machine (possibly derived from ~/.myhostname).+ hostname: String,+ /// The path to the directory containing this machine's system+ /// configuration. This is currently hard-coded to ~/system.+ system: PathBuf,+}++impl Args {+ fn parse() -> anyhow::Result<Args> {+ use clap::{crate_authors, crate_version, App, Arg};++ let parsed = App::new("Install system configuration symlinks.")+ .author(crate_authors!())+ .version(crate_version!())+ .max_term_width(80)+ .arg(Arg::with_name("no-backup").long("no-backup"))+ .arg(Arg::with_name("dry-run").long("dry-run"))+ .get_matches();++ let home = match env::var_os("HOME") {+ None => anyhow::bail!("HOME environment variable not set"),+ Some(home) => PathBuf::from(home),+ };+ let system = home.join("system");+ if !system.is_dir() {+ anyhow::bail!(+ "{}: system directory does not exist",+ system.display()+ );+ }++ let dry_run = parsed.is_present("dry-run");+ let hostname = runcmd(&["myhostname"])?;+ let backup = if parsed.is_present("no-backup") {+ None+ } else if dry_run {+ let parent = home.join("tmp").join("setup-system-links-backup");+ Some(parent.join("backup-{timestamp}"))+ } else {+ let parent = home.join("tmp").join("setup-system-links-backup");+ Some(+ create_unique_dir_in(parent, "backup")+ .context("failed to create backup directory")?,+ )+ };+ Ok(Args { backup, dry_run, hostname, system })+ }+}++fn runcmd<A: AsRef<OsStr>>(+ argv: impl IntoIterator<Item = A>,+) -> anyhow::Result<String> {+ let args: Vec<OsString> =+ argv.into_iter().map(|a| a.as_ref().to_os_string()).collect();+ let output = std::process::Command::new(&args[0])+ .args(&args[1..])+ .output()+ .context("failed to run 'myhostname'")?;+ if !output.status.success() {+ let stderr = BString::from(output.stderr.trim().to_vec());+ let args: Vec<Vec<u8>> = args+ .into_iter()+ .map(|a| Vec::from_os_str_lossy(&a).into_owned())+ .collect();+ let mut command = BString::from(bstr::join(" ", args));+ if let Some(code) = output.status.code() {+ command =+ BString::from(format!("`{}` (exit code {})", command, code));+ } else {+ command = BString::from(format!("`{}`", command));+ }+ anyhow::bail!("failed to run {}, stderr:\n\n{}", command, stderr)+ }++ let stdout = output+ .stdout+ .to_str()+ .context("hostname is not valid UTF-8")?+ .trim()+ .to_string();+ Ok(stdout)+}++fn create_unique_dir_in<P: AsRef<Path>, S: AsRef<str>>(+ parent: P,+ prefix: S,+) -> anyhow::Result<PathBuf> {+ use std::time::{Duration, SystemTime};++ let parent = parent.as_ref();+ let prefix = prefix.as_ref();+ std::fs::create_dir_all(&parent).with_context(|| {+ format!("{}: failed to create parent directory", parent.display())+ })?;+ for _ in 0..100 {+ let ts = SystemTime::now()+ .duration_since(SystemTime::UNIX_EPOCH)+ .context("system time is borked")?;+ let name =+ format!("{}-{}-{}", prefix, ts.as_secs(), ts.subsec_nanos());+ let dir = parent.join(name);+ if std::fs::create_dir(&dir).is_err() {+ std::thread::sleep(Duration::from_secs(1));+ continue;+ }+ return Ok(dir);+ }+ anyhow::bail!(+ "failed to create unique directory inside of {}",+ parent.display()+ );+}
etc/libinput/local-overrides.quirks
@@ -1,6 +0,0 @@-[Touchpad pressure override]-MatchUdevType=touchpad-MatchName=*SynPS/2 Synaptics TouchPad-MatchDMIModalias=dmi:*svnSystem76*pvrdarp6*-AttrPressureRange=45:44-AttrPalmPressureThreshold=75
@@ -0,0 +1,22 @@+This directory contains machine specific system wide configuration files. The+directory hierarchy follows a convention that permits easily symlinking the+right config file to the right location. Before this scheme, I had just been+maintaining system configuration on an ad hoc basis (and sometimes via+~/bin/arch-install), but this was error prone and inefficient. Namely, I would+frequently need to copy configs from other machines, or worse, would forget+about a config before wiping a machine.++The general scheme is:++ $HOME/etc/path/to/config-file-as-directory/{default,krusty,...}++Where `/etc/path/to/config-file-as-directory` is a directory that refers to a+concrete file path in the /etc directory. Inside this directory is an optional+file named `default`, along with other optional files named by hostname, e.g.,+`krusty`. If a hostname file is present, then that file is symlinked to the+corresponding config file location. Otherwise the `default` file is. If no+files are present, then no symlinks are created. Thus, if you want to keep a+configuration checked into git but disable it, then rename it from `{name}` to+`{name}.disable`.++symlinks are created by ~/bin/setup-system-links.
system/etc/X11/xorg.conf.d/20-intel.conf/krusty
@@ -0,0 +1,14 @@+Section "Device"+ Identifier "Intel Graphics"+ Driver "intel"++ Option "AccelMethod" "sna"+ Option "TearFree" "true"+ Option "DRI" "2"++# Option "DRI" "2" +# Option "VSync" "false"+# Option "SwapbuffersWait" "true"+# Option "NoAccel" "true"+# Option "DRI" "false"+EndSection
system/etc/default/grub/krusty
@@ -0,0 +1,55 @@+# GRUB boot loader configuration++GRUB_DEFAULT=0+GRUB_TIMEOUT=0+GRUB_DISTRIBUTOR="Arch"+# GRUB_CMDLINE_LINUX_DEFAULT="quiet loglevel=0 audit=0 ec_sys.write_support=1 cryptdevice=UUID=82fb86df-0215-48c2-a05c-3f92b240a2c7:cryptroot root=/dev/mapper/cryptroot splash rd.udev.log_priority=0 rd.systemd.show_status=0 vt.global_cursor_default=0"+GRUB_CMDLINE_LINUX_DEFAULT="loglevel=0 audit=0 ec_sys.write_support=1 cryptdevice=UUID=82fb86df-0215-48c2-a05c-3f92b240a2c7:cryptroot root=/dev/mapper/cryptroot rd.udev.log_priority=0 rd.systemd.show_status=0 vt.global_cursor_default=0"+GRUB_CMDLINE_LINUX=""++# Preload both GPT and MBR modules so that they are not missed+GRUB_PRELOAD_MODULES="part_gpt part_msdos"++# Uncomment to enable booting from LUKS encrypted devices+#GRUB_ENABLE_CRYPTODISK=y++# Set to 'countdown' or 'hidden' to change timeout behavior,+# press ESC key to display menu.+GRUB_TIMEOUT_STYLE=menu++# Uncomment to use basic console+GRUB_TERMINAL_INPUT=console++# Uncomment to disable graphical terminal+#GRUB_TERMINAL_OUTPUT=console++# The resolution used on graphical terminal+# note that you can use only modes which your graphic card supports via VBE+# you can see them in real GRUB with the command `vbeinfo'+GRUB_GFXMODE=auto++# Uncomment to allow the kernel use the same resolution used by grub+GRUB_GFXPAYLOAD_LINUX=keep++# Uncomment if you want GRUB to pass to the Linux kernel the old parameter+# format "root=/dev/xxx" instead of "root=/dev/disk/by-uuid/xxx"+#GRUB_DISABLE_LINUX_UUID=true++# Uncomment to disable generation of recovery mode menu entries+GRUB_DISABLE_RECOVERY=true++# Uncomment and set to the desired menu colors. Used by normal and wallpaper+# modes only. Entries specified as foreground/background.+#GRUB_COLOR_NORMAL="light-blue/black"+#GRUB_COLOR_HIGHLIGHT="light-cyan/blue"++# Uncomment one of them for the gfx desired, a image background or a gfxtheme+#GRUB_BACKGROUND="/path/to/wallpaper"+#GRUB_THEME="/path/to/gfxtheme"++# Uncomment to get a beep at GRUB start+#GRUB_INIT_TUNE="480 440 1"++# Uncomment to make GRUB remember the last selection. This requires+# setting 'GRUB_DEFAULT=saved' above.+#GRUB_SAVEDEFAULT="true"
@@ -0,0 +1,17 @@+# The file /etc/fuse.conf allows for the following parameters:+#+# user_allow_other - Using the allow_other mount option works fine as root, in+# order to have it work as user you need user_allow_other in /etc/fuse.conf as+# well. (This option allows users to use the allow_other option.) You need+# allow_other if you want users other than the owner to access a mounted fuse.+# This option must appear on a line by itself. There is no value, just the+# presence of the option.++user_allow_other+++# mount_max = n - this option sets the maximum number of mounts.+# Currently (2014) it must be typed exactly as shown+# (with a single space before and after the equals sign).++#mount_max = 1000
system/etc/libinput/local-overrides.quirks/krusty.disable
@@ -0,0 +1,6 @@+[Touchpad pressure override]+MatchUdevType=touchpad+MatchName=*SynPS/2 Synaptics TouchPad+MatchDMIModalias=dmi:*svnSystem76*pvrdarp6*+AttrPressureRange=45:44+AttrPalmPressureThreshold=75
system/etc/makepkg.conf/default
@@ -0,0 +1,148 @@+#!/hint/bash+#+# /etc/makepkg.conf+#++#########################################################################+# SOURCE ACQUISITION+#########################################################################+#+#-- The download utilities that makepkg should use to acquire sources+# Format: 'protocol::agent'+DLAGENTS=('file::/usr/bin/curl -gqC - -o %o %u'+ 'ftp::/usr/bin/curl -gqfC - --ftp-pasv --retry 3 --retry-delay 3 -o %o %u'+ 'http::/usr/bin/curl -gqb "" -fLC - --retry 3 --retry-delay 3 -o %o %u'+ 'https::/usr/bin/curl -gqb "" -fLC - --retry 3 --retry-delay 3 -o %o %u'+ 'rsync::/usr/bin/rsync --no-motd -z %u %o'+ 'scp::/usr/bin/scp -C %u %o')++# Other common tools:+# /usr/bin/snarf+# /usr/bin/lftpget -c+# /usr/bin/wget++#-- The package required by makepkg to download VCS sources+# Format: 'protocol::package'+VCSCLIENTS=('bzr::bzr'+ 'git::git'+ 'hg::mercurial'+ 'svn::subversion')++#########################################################################+# ARCHITECTURE, COMPILE FLAGS+#########################################################################+#+CARCH="x86_64"+CHOST="x86_64-pc-linux-gnu"++#-- Compiler and Linker Flags+CPPFLAGS="-D_FORTIFY_SOURCE=2"+CFLAGS="-march=x86-64 -mtune=generic -O2 -pipe -fno-plt"+CXXFLAGS="-march=x86-64 -mtune=generic -O2 -pipe -fno-plt"+LDFLAGS="-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now"+#RUSTFLAGS="-C opt-level=2"+#-- Make Flags: change this for DistCC/SMP systems+#MAKEFLAGS="-j2"+#-- Debugging flags+DEBUG_CFLAGS="-g -fvar-tracking-assignments"+DEBUG_CXXFLAGS="-g -fvar-tracking-assignments"+#DEBUG_RUSTFLAGS="-C debuginfo=2"++#########################################################################+# BUILD ENVIRONMENT+#########################################################################+#+# Defaults: BUILDENV=(!distcc !color !ccache check !sign)+# A negated environment option will do the opposite of the comments below.+#+#-- distcc: Use the Distributed C/C++/ObjC compiler+#-- color: Colorize output messages+#-- ccache: Use ccache to cache compilation+#-- check: Run the check() function if present in the PKGBUILD+#-- sign: Generate PGP signature file+#+BUILDENV=(!distcc color !ccache check !sign)+#+#-- If using DistCC, your MAKEFLAGS will also need modification. In addition,+#-- specify a space-delimited list of hosts running in the DistCC cluster.+#DISTCC_HOSTS=""+#+#-- Specify a directory for package building.+#BUILDDIR=/tmp/makepkg++#########################################################################+# GLOBAL PACKAGE OPTIONS+# These are default values for the options=() settings+#########################################################################+#+# Default: OPTIONS=(!strip docs libtool staticlibs emptydirs !zipman !purge !debug)+# A negated option will do the opposite of the comments below.+#+#-- strip: Strip symbols from binaries/libraries+#-- docs: Save doc directories specified by DOC_DIRS+#-- libtool: Leave libtool (.la) files in packages+#-- staticlibs: Leave static library (.a) files in packages+#-- emptydirs: Leave empty directories in packages+#-- zipman: Compress manual (man and info) pages in MAN_DIRS with gzip+#-- purge: Remove files specified by PURGE_TARGETS+#-- debug: Add debugging flags as specified in DEBUG_* variables+#+OPTIONS=(strip docs !libtool !staticlibs emptydirs zipman purge !debug)++#-- File integrity checks to use. Valid: md5, sha1, sha224, sha256, sha384, sha512, b2+INTEGRITY_CHECK=(md5)+#-- Options to be used when stripping binaries. See `man strip' for details.+STRIP_BINARIES="--strip-all"+#-- Options to be used when stripping shared libraries. See `man strip' for details.+STRIP_SHARED="--strip-unneeded"+#-- Options to be used when stripping static libraries. See `man strip' for details.+STRIP_STATIC="--strip-debug"+#-- Manual (man and info) directories to compress (if zipman is specified)+MAN_DIRS=({usr{,/local}{,/share},opt/*}/{man,info})+#-- Doc directories to remove (if !docs is specified)+DOC_DIRS=(usr/{,local/}{,share/}{doc,gtk-doc} opt/*/{doc,gtk-doc})+#-- Files to be removed from all packages (if purge is specified)+PURGE_TARGETS=(usr/{,share}/info/dir .packlist *.pod)+#-- Directory to store source code in for debug packages+DBGSRCDIR="/usr/src/debug"++#########################################################################+# PACKAGE OUTPUT+#########################################################################+#+# Default: put built package and cached source in build directory+#+#-- Destination: specify a fixed directory where all packages will be placed+#PKGDEST=/home/packages+#-- Source cache: specify a fixed directory where source files will be cached+#SRCDEST=/home/sources+#-- Source packages: specify a fixed directory where all src packages will be placed+#SRCPKGDEST=/home/srcpackages+#-- Log files: specify a fixed directory where all log files will be placed+#LOGDEST=/home/makepkglogs+#-- Packager: name/email of the person or organization building packages+#PACKAGER="John Doe <john@doe.com>"+#-- Specify a key to use for package signing+#GPGKEY=""++#########################################################################+# COMPRESSION DEFAULTS+#########################################################################+#+COMPRESSGZ=(gzip -c -f -n)+COMPRESSBZ2=(bzip2 -c -f)+COMPRESSXZ=(xz -c -z -)+COMPRESSZST=(zstd -c -z -q -)+COMPRESSLRZ=(lrzip -q)+COMPRESSLZO=(lzop -q)+COMPRESSZ=(compress -c -f)+COMPRESSLZ4=(lz4 -q)+COMPRESSLZ=(lzip -c -f)++#########################################################################+# EXTENSION DEFAULTS+#########################################################################+#+PKGEXT='.pkg.tar.zst'+SRCEXT='.src.tar.gz'+COMPRESSXZ=(xz -c -z -0 -)
system/etc/mkinitcpio.conf/krusty
@@ -0,0 +1,67 @@+# vim:set ft=sh+# MODULES+# The following modules are loaded before any boot hooks are+# run. Advanced users may wish to specify all system modules+# in this array. For instance:+# MODULES=(piix ide_disk reiserfs)+MODULES=(i915)++# BINARIES+# This setting includes any additional binaries a given user may+# wish into the CPIO image. This is run last, so it may be used to+# override the actual binaries included by a given hook+# BINARIES are dependency parsed, so you may safely ignore libraries+BINARIES=()++# FILES+# This setting is similar to BINARIES above, however, files are added+# as-is and are not parsed in any way. This is useful for config files.+FILES=()++# HOOKS+# This is the most important setting in this file. The HOOKS control the+# modules and scripts added to the image, and what happens at boot time.+# Order is important, and it is recommended that you do not change the+# order in which HOOKS are added. Run 'mkinitcpio -H <hook name>' for+# help on a given hook.+# 'base' is _required_ unless you know precisely what you are doing.+# 'udev' is _required_ in order to automatically load modules+# 'filesystems' is _required_ unless you specify your fs modules in MODULES+# Examples:+## This setup specifies all modules in the MODULES setting above.+## No raid, lvm2, or encrypted root is needed.+# HOOKS=(base)+#+## This setup will autodetect all modules for your system and should+## work as a sane default+# HOOKS=(base udev autodetect block filesystems)+#+## This setup will generate a 'full' image which supports most systems.+## No autodetection is done.+# HOOKS=(base udev block filesystems)+#+## This setup assembles a pata mdadm array with an encrypted root FS.+## Note: See 'mkinitcpio -H mdadm' for more information on raid devices.+# HOOKS=(base udev block mdadm encrypt filesystems)+#+## This setup loads an lvm2 volume group on a usb device.+# HOOKS=(base udev block lvm2 filesystems)+#+## NOTE: If you have /usr on a separate partition, you MUST include the+# usr, fsck and shutdown hooks.+# HOOKS=(base udev plymouth autodetect modconf block plymouth-encrypt filesystems keyboard fsck)+HOOKS=(base udev autodetect modconf block encrypt filesystems keyboard fsck)++# COMPRESSION+# Use this to compress the initramfs image. By default, gzip compression+# is used. Use 'cat' to create an uncompressed image.+#COMPRESSION="gzip"+#COMPRESSION="bzip2"+#COMPRESSION="lzma"+#COMPRESSION="xz"+#COMPRESSION="lzop"+#COMPRESSION="lz4"++# COMPRESSION_OPTIONS+# Additional options for the compressor+#COMPRESSION_OPTIONS=()
system/etc/modprobe.d/blacklist.conf/krusty
@@ -0,0 +1 @@+blacklist thunderbolt
system/etc/modprobe.d/system76-alsa-base.conf/krusty
@@ -0,0 +1 @@+options snd-hda-intel model=headset-mode-no-hp-mic patch=system76-audio-patch
system/etc/systemd/system.conf/default
@@ -0,0 +1,71 @@+# This file is part of systemd.+#+# systemd is free software; you can redistribute it and/or modify it+# under the terms of the GNU Lesser General Public License as published by+# the Free Software Foundation; either version 2.1 of the License, or+# (at your option) any later version.+#+# Entries in this file show the compile time defaults.+# You can change settings by editing this file.+# Defaults can be restored by simply deleting this file.+#+# See systemd-system.conf(5) for details.++[Manager]+#LogLevel=info+#LogTarget=journal-or-kmsg+#LogColor=yes+#LogLocation=no+#LogTime=no+#DumpCore=yes+#ShowStatus=yes+#CrashChangeVT=no+#CrashShell=no+#CrashReboot=no+#CtrlAltDelBurstAction=reboot-force+#CPUAffinity=1 2+#NUMAPolicy=default+#NUMAMask=+#RuntimeWatchdogSec=0+#RebootWatchdogSec=10min+#ShutdownWatchdogSec=10min+#KExecWatchdogSec=0+#WatchdogDevice=+#CapabilityBoundingSet=+#NoNewPrivileges=no+#SystemCallArchitectures=+#TimerSlackNSec=+#StatusUnitFormat=description+#DefaultTimerAccuracySec=1min+#DefaultStandardOutput=journal+#DefaultStandardError=inherit+#DefaultTimeoutStartSec=90s+DefaultTimeoutStopSec=5s+#DefaultTimeoutAbortSec=+#DefaultRestartSec=100ms+#DefaultStartLimitIntervalSec=10s+#DefaultStartLimitBurst=5+#DefaultEnvironment=+#DefaultCPUAccounting=no+#DefaultIOAccounting=no+#DefaultIPAccounting=no+#DefaultBlockIOAccounting=no+#DefaultMemoryAccounting=yes+#DefaultTasksAccounting=yes+#DefaultTasksMax=15%+#DefaultLimitCPU=+#DefaultLimitFSIZE=+#DefaultLimitDATA=+#DefaultLimitSTACK=+#DefaultLimitCORE=+#DefaultLimitRSS=+DefaultLimitNOFILE=524288+#DefaultLimitAS=+#DefaultLimitNPROC=+#DefaultLimitMEMLOCK=+#DefaultLimitLOCKS=+#DefaultLimitSIGPENDING=+#DefaultLimitMSGQUEUE=+#DefaultLimitNICE=+#DefaultLimitRTPRIO=+#DefaultLimitRTTIME=
system/usr/lib/systemd/system-sleep/system76-darter-hook-sleep/krusty
@@ -0,0 +1,23 @@+#!/bin/sh++# This is a systemd hook script that is run whenever+# suspend/resume takes place. It should be symlinked into+# /usr/lib/systemd/system-sleep.++# To see logs from this script, use:+#+# journalctl -b -u systemd-suspend.service++# $1 is 'pre' (going to sleep) or 'post' (waking up)+# $2 is 'suspend', 'hibernate' or 'hybrid-sleep'+case "$1/$2" in+ pre/*)+ if lsmod | grep -q thunderbolt; then+ sudo rmmod thunderbolt+ fi+ ;;+ post/*)+ /home/andrew/bin/system76-darter-set-kbd-backlight+ sudo modprobe thunderbolt+ ;;+esac