Compare commits

...

143 commits

Author SHA1 Message Date
Manuel Thalmann 9bad19a2e4 Add scripts for backing up and restoring LGHub 2024-08-28 05:05:55 +02:00
Manuel Thalmann 986e73ea2d Allow users to restore a backup 2024-08-28 04:40:32 +02:00
Manuel Thalmann ce74c501d1 Add scripts for backing up and restoring personal files 2024-08-28 04:40:00 +02:00
Manuel Thalmann f2c0d935c7 Fix non-functioning profile script 2024-08-28 04:39:15 +02:00
Manuel Thalmann 76692b7a39 Ensure 7z is installed for backups 2024-08-28 04:38:56 +02:00
Manuel Thalmann ee6ba04e98 Streamline restoration of directories 2024-08-28 04:38:30 +02:00
Manuel Thalmann aa1e89fc64 Set a default path for backup artifacts 2024-08-28 00:38:20 +02:00
Manuel Thalmann 5126193ea6 Add capabilities to back up apps 2024-08-28 00:37:04 +02:00
Manuel Thalmann 369d49304f Allow specifying a backup action 2024-08-28 00:29:33 +02:00
Manuel Thalmann 0ef3d8d3b1 Ignore unspecified backup archives 2024-08-28 00:22:38 +02:00
Manuel Thalmann 1275d50503 Ignore inexistent backup artifacts 2024-08-28 00:21:06 +02:00
Manuel Thalmann ecaf8608db Make the install script action agnostic 2024-08-28 00:03:28 +02:00
Manuel Thalmann 00a4e82e66 Rename the Windows installer script 2024-08-27 23:35:56 +02:00
Manuel Thalmann ecf47a34bc Rename outdated archive 2024-08-27 23:08:41 +02:00
Manuel Thalmann 8918215bf8 Silence errors concerning empty aliae configurations 2024-08-27 22:35:31 +02:00
Manuel Thalmann 011611432b Make Operations script cross platform 2024-08-27 22:27:44 +02:00
Manuel Thalmann 9ab422d784 Handle OneShot tasks only on Windows 2024-08-27 21:32:49 +02:00
Manuel Thalmann 95fe616bab Add a script for managing backups 2024-08-27 21:05:51 +02:00
Manuel Thalmann 6a888fc3ad Add tools for managing aliae 2024-08-27 18:58:33 +02:00
Manuel Thalmann 1573bfb32e Fix non-functioning aliae installation 2024-08-27 18:55:12 +02:00
Manuel Thalmann fd1686bb16 Create dedicated script for creating users 2024-08-27 17:04:17 +02:00
Manuel Thalmann 36bc594910 Create dedicated script for installing software 2024-08-27 16:41:08 +02:00
Manuel Thalmann 13b10928d8 Prevent reading nix config multiple times 2024-08-27 14:35:04 +02:00
Manuel Thalmann 26956e7ba2 Ensure only one user is enabled at once 2024-08-27 14:11:31 +02:00
Manuel Thalmann 5b8ac0b4be Prevent unnecessary file creation 2024-08-27 14:06:56 +02:00
Manuel Thalmann 2c3629c5aa Execute OneShot tasks in any operation 2024-08-27 14:05:16 +02:00
Manuel Thalmann d7b9bc1373 Use /mnt as mount directory 2024-08-27 04:30:12 +02:00
Manuel Thalmann f5a075aaad Force the use of the managed distribution 2024-08-27 04:26:25 +02:00
Manuel Thalmann ac0a654048 Initialize operation for all users 2024-08-27 04:24:29 +02:00
Manuel Thalmann 903859efe0 Handle initialization in operation code 2024-08-27 04:15:37 +02:00
Manuel Thalmann e9d056aa5a Execute script non-interactive during OneShot tasks 2024-08-27 03:50:08 +02:00
Manuel Thalmann fbea744ab4 Exit script after running OneShot task 2024-08-27 03:45:44 +02:00
Manuel Thalmann 4edcc24b1c Modify user after first login 2024-08-27 03:27:54 +02:00
Manuel Thalmann c5507ed4c4 Rearm Windows Activation before creating MSAcc 2024-08-27 03:25:19 +02:00
Manuel Thalmann ba9cdf9a09 Register MSAcc logon script early 2024-08-27 03:24:37 +02:00
Manuel Thalmann cdc499a76c Allow rebooting without registering setup 2024-08-27 03:11:35 +02:00
Manuel Thalmann cb3707f8a0 Prevent reboots during installation 2024-08-27 02:18:01 +02:00
Manuel Thalmann 594e495e47 Fix non-functioning NoProfile argument 2024-08-27 02:09:04 +02:00
Manuel Thalmann 35ece24b36 Prevent unnecessary installation actions 2024-08-27 01:57:46 +02:00
Manuel Thalmann 4a932d9b49 Only install PowerShell module if necessary 2024-08-27 01:25:32 +02:00
Manuel Thalmann 1236b2b69f Streamline PowerShell installation 2024-08-27 00:45:46 +02:00
Manuel Thalmann 5130bc5e72 Add further functionality to the WSL script 2024-08-27 00:38:46 +02:00
Manuel Thalmann 6fe336ddc2 Create a separate script for WSL interaction 2024-08-26 23:33:46 +02:00
Manuel Thalmann 8e98984285 Fix recursive configuration 2024-08-25 03:58:28 +02:00
Manuel Thalmann 5ca16910f5 Fix malformed module 2024-08-24 18:35:43 +02:00
Manuel Thalmann ccce13fad0 Keep Windows fixes separate 2024-08-24 16:56:29 +02:00
Manuel Thalmann 42e4d8ea6a Remove WSL after operation 2024-08-24 16:52:41 +02:00
Manuel Thalmann d20c450e7a Make distribution name unique 2024-08-24 16:41:05 +02:00
Manuel Thalmann 1770ddc683 Streamline WSL distribution name 2024-08-24 16:27:34 +02:00
Manuel Thalmann 0f99dcbc50 Remove unused resources after user setup 2024-08-24 16:15:10 +02:00
Manuel Thalmann 3ca505a14f Print update logs properly 2024-08-24 14:47:51 +02:00
Manuel Thalmann a57f1e822d Allow overriding Windows settings 2024-08-24 14:20:22 +02:00
Manuel Thalmann 481b379e16 Update incorrect path 2024-08-24 14:11:38 +02:00
Manuel Thalmann 4c67628540 Simplify osu!lazer installation 2024-08-24 14:10:02 +02:00
Manuel Thalmann 24ac9cfff4 Determine name of setup user properly 2024-08-24 14:01:05 +02:00
Manuel Thalmann 963dcdc826 Make OMP configuration platform independent 2024-08-24 13:27:48 +02:00
Manuel Thalmann f52d730a96 Fix incorrect character in OMP theme 2024-08-24 13:27:35 +02:00
Manuel Thalmann 61776ddd47 Remove unnecessary code 2024-08-24 04:25:07 +02:00
Manuel Thalmann 2b2f013daf Remove unnecessary loop 2024-08-24 04:24:55 +02:00
Manuel Thalmann 1105276e34 Add missing module 2024-08-24 04:24:37 +02:00
Manuel Thalmann 035c5081be Add nextcloud to the module list 2024-08-24 04:18:57 +02:00
Manuel Thalmann 14d0f4cf11 Add a function for creating shortcuts 2024-08-24 04:18:33 +02:00
Manuel Thalmann ff42d74d69 Configure nextcloud syncs 2024-08-24 04:07:47 +02:00
Manuel Thalmann 67907e3a53 Allow configuring nextcloud syncs 2024-08-24 04:07:35 +02:00
Manuel Thalmann 06206c454f Create separate option holding win users 2024-08-24 03:25:28 +02:00
Manuel Thalmann e33c65d2a6 Rename Nextcloud installer 2024-08-24 01:50:07 +02:00
Manuel Thalmann 5765d6beef Add file system driver for dual boot 2024-08-24 01:41:09 +02:00
Manuel Thalmann 70c61c931b Prevent unnecessary config evaluation 2024-08-24 01:31:39 +02:00
Manuel Thalmann f809dbdf37 Fix non-functioning installer 2024-08-24 01:27:26 +02:00
Manuel Thalmann 9653e88a2f Install vscode extensions by default 2024-08-24 01:16:56 +02:00
Manuel Thalmann e65ddef92f Load theme file from WSL properly 2024-08-24 00:59:59 +02:00
Manuel Thalmann 58d380880e Update aliae configuration script 2024-08-24 00:42:57 +02:00
Manuel Thalmann 8c1e572725 Strip duplicate variables and aliases 2024-08-24 00:08:58 +02:00
Manuel Thalmann b068386bb1 Install posh theme automatically 2024-08-23 23:53:48 +02:00
Manuel Thalmann 79a4f44b18 Export missing function 2024-08-23 23:50:13 +02:00
Manuel Thalmann db84dbe961 Install aliae by default 2024-08-23 23:46:23 +02:00
Manuel Thalmann 5f59d70927 Add scripts for changing aliae config 2024-08-23 23:44:51 +02:00
Manuel Thalmann 1ca843bfe3 Fix compatibility with mixed new line characters 2024-08-23 23:44:23 +02:00
Manuel Thalmann 6c206346bd Add a script for installing aliae 2024-08-23 22:38:28 +02:00
Manuel Thalmann 94fb3d5768 Add desired posh theme 2024-08-23 19:43:06 +02:00
Manuel Thalmann 02084c159d Make option names more clear 2024-08-23 19:42:27 +02:00
Manuel Thalmann 1cae378395 Allow configuring oh-my-posh 2024-08-23 19:39:18 +02:00
Manuel Thalmann 30f8adc042 Fetch config from proper section 2024-08-23 19:24:49 +02:00
Manuel Thalmann 43ebf1ac5f Adjust configuration accordingly 2024-08-23 19:14:09 +02:00
Manuel Thalmann de8f7cc9f0 Refactor option descriptions 2024-08-23 19:02:06 +02:00
Manuel Thalmann 0396b9f6a3 Clean up the Windows configuration 2024-08-23 18:59:49 +02:00
Manuel Thalmann 1cdca091b4 Clean up the users.nix file 2024-08-23 18:51:54 +02:00
Manuel Thalmann 9f72c505f0 Create dedicated rclone module 2024-08-23 18:48:30 +02:00
Manuel Thalmann de27bfcc56 Move git module to separate directory 2024-08-23 18:42:16 +02:00
Manuel Thalmann 29cb72c91b Move git options to separate module 2024-08-23 18:40:24 +02:00
Manuel Thalmann 7830735e74 Fix inheritance of user config 2024-08-23 18:28:20 +02:00
Manuel Thalmann 46d2fcf5b4 Allow OS specific settings 2024-08-23 18:11:48 +02:00
Manuel Thalmann 8e231dbc7b Update archiso 2024-08-23 14:19:56 +02:00
Manuel Thalmann 94f94348f4 Set user info during git setup 2024-08-23 02:01:16 +02:00
Manuel Thalmann 3ad0d50987 Make all config scripts platform independent 2024-08-23 01:57:53 +02:00
Manuel Thalmann d2fb783429 Allow leaving aliases unspecified 2024-08-23 01:52:25 +02:00
Manuel Thalmann 9724f49491 Make scripts platform independent 2024-08-23 01:52:04 +02:00
Manuel Thalmann fe11cc7608 Add scripts for configuring git 2024-08-23 01:43:26 +02:00
Manuel Thalmann 46f1567df1 Configure software implicitly 2024-08-23 01:41:32 +02:00
Manuel Thalmann 377941bc68 Skip profile creation for PinnedItem 2024-08-22 23:55:41 +02:00
Manuel Thalmann 38c68fb7f4 Allow skipping powershell module registration 2024-08-22 23:55:00 +02:00
Manuel Thalmann 9c6fcd9253 Add profiles to the flake 2024-08-22 23:37:53 +02:00
Manuel Thalmann 46126290e8 Remove user profile of OneShot user 2024-08-22 23:12:11 +02:00
Manuel Thalmann 6afb6310f2 Add missing OneShotTask declaration 2024-08-22 20:41:30 +02:00
Manuel Thalmann 8eefa29dc5 Fix infinite loop 2024-08-22 20:41:17 +02:00
Manuel Thalmann 55a03d245d Fix incorrect variable name 2024-08-22 20:34:16 +02:00
Manuel Thalmann a3ffafa624 Fix handling empty error messages 2024-08-22 20:12:18 +02:00
Manuel Thalmann f4c26f1ad5 Add choco to the profile of the setup user 2024-08-22 13:46:55 +02:00
Manuel Thalmann 6e58c8a587 Fix incorrect typings 2024-08-22 11:11:12 +02:00
Manuel Thalmann 696be84757 Fix permission issues when enabling Win hack 2024-08-22 11:11:00 +02:00
Manuel Thalmann 867e7a0786 Register setup script as admin 2024-08-22 11:10:39 +02:00
Manuel Thalmann 5aa93b5aaa Execute the entire installer using live scripts 2024-08-21 23:21:32 +02:00
Manuel Thalmann f2251fc63b Streamline the creation of users 2024-08-21 18:34:18 +02:00
Manuel Thalmann 1ecd94a418 Replace osk with cmd during debugging 2024-08-21 18:33:41 +02:00
Manuel Thalmann 7f82f950e6 Prevent pauses in OneShot tasks 2024-08-21 18:28:50 +02:00
Manuel Thalmann cc04d9ec8a Print commands in debug mode 2024-08-21 18:28:08 +02:00
Manuel Thalmann 5747a5a044 Run OneShot tasks with dedicated user 2024-08-21 18:27:47 +02:00
Manuel Thalmann c7ec156504 Add function for generating startup command 2024-08-21 18:26:58 +02:00
Manuel Thalmann 67485175e7 Allow registering startup script for the default user 2024-08-21 18:20:11 +02:00
Manuel Thalmann dbae964196 Prevent unnecessary errors during WSL execution 2024-08-21 14:08:26 +02:00
Manuel Thalmann 7a27cb5e21 Register WSL before running OneShot tasks 2024-08-21 03:37:44 +02:00
Manuel Thalmann 2f068c4aba Overwrite broken module 2024-08-21 03:20:37 +02:00
Manuel Thalmann 561c3f947f Prevent initialization of nested operations 2024-08-21 03:18:31 +02:00
Manuel Thalmann 363a91a030 Improve log messages of OneShot tasks 2024-08-21 02:02:30 +02:00
Manuel Thalmann 1e8a06cd88 Retry Linux path conversion for errors 2024-08-20 00:20:33 +02:00
Manuel Thalmann 464370880a Fix typo 2024-08-20 00:20:07 +02:00
Manuel Thalmann db0e94c4a7 Fix broken signature of Restart-Intermediate 2024-08-19 12:07:26 +02:00
Manuel Thalmann 3155355a20 Report unexpected path conversions 2024-08-19 02:50:41 +02:00
Manuel Thalmann c322b4a842 Load missing path 2024-08-19 02:50:19 +02:00
Manuel Thalmann 9c22599d2b Ensure error file can be read from 2024-08-19 02:24:45 +02:00
Manuel Thalmann 083b708a86 Streamline OneShot task handler 2024-08-19 02:24:30 +02:00
Manuel Thalmann a85836768e Simplify script registration 2024-08-19 02:24:13 +02:00
Manuel Thalmann 0be35dbb78 Fix broken regedit paths 2024-08-19 01:38:25 +02:00
Manuel Thalmann e29999f7a0 Allow registering reboots for users 2024-08-19 01:37:14 +02:00
Manuel Thalmann c2d0b21e84 Prevent users from being excluded 2024-08-19 01:10:29 +02:00
Manuel Thalmann 448c62eadb Force copying of Linux users to Windows 2024-08-19 00:54:13 +02:00
Manuel Thalmann d038881be1 Improve log messages of updates 2024-08-18 12:20:21 +02:00
Manuel Thalmann 809a50e74e Remove unnecessary command 2024-08-18 10:24:15 +02:00
Manuel Thalmann 72d14602ba Fix time for QEMU VMs 2024-08-18 09:35:16 +02:00
Manuel Thalmann fe9111da66 Remove unnecessary desktop icons 2024-08-18 09:25:23 +02:00
Manuel Thalmann bbc9d3e6d7 Add a timeout for the reWASD downloader 2024-08-18 09:05:04 +02:00
Manuel Thalmann 5d1920b209 Allow setting a timeout for clicking download buttons 2024-08-18 09:04:42 +02:00
Manuel Thalmann ecbd16ad52 Emit errors concerning WSL commands 2024-08-17 13:51:10 +02:00
79 changed files with 3078 additions and 1290 deletions

View file

@ -23,7 +23,7 @@ automated_script() {
sleep 1 sleep 1
done done
printf '%s: downloading %s\n' "$0" "${script}" printf '%s: downloading %s\n' "$0" "${script}"
curl "${script}" --location --retry-connrefused --retry 10 -s -o /tmp/startup_script curl "${script}" --location --retry-connrefused --retry 10 --fail -s -o /tmp/startup_script
rt=$? rt=$?
else else
cp "${script}" /tmp/startup_script cp "${script}" /tmp/startup_script

View file

@ -1,8 +1,8 @@
diff --git a/airootfs/root/.zlogin b/airootfs/root/.zlogin diff --git a/airootfs/root/.zlogin b/airootfs/root/.zlogin
index bf6bc8f..76e5893 100755 index bf6bc8f..a0dae7b 100755
--- a/airootfs/root/.zlogin --- a/airootfs/root/.zlogin
+++ b/airootfs/root/.zlogin +++ b/airootfs/root/.zlogin
@@ -4,3 +4,18 @@ if grep -Fqa 'accessibility=' /proc/cmdline &> /dev/null; then @@ -4,3 +4,19 @@ if grep -Fqa 'accessibility=' /proc/cmdline &> /dev/null; then
fi fi
~/.automated_script.sh ~/.automated_script.sh
@ -16,13 +16,14 @@ index bf6bc8f..76e5893 100755
+ +
+git diff -p -R --no-ext-diff --no-color --diff-filter=M \ +git diff -p -R --no-ext-diff --no-color --diff-filter=M \
+ | grep -E "^(diff|(old|new) mode)" --color=never \ + | grep -E "^(diff|(old|new) mode)" --color=never \
+ | sed "/^diff/{ x; d; }; x; /./{ p; z; }; x;" \
+ | git apply + | git apply
+ +
+popd > /dev/null +popd > /dev/null
+ +
+loadkeys de_CH-latin1 +loadkeys de_CH-latin1
diff --git a/packages.x86_64 b/packages.x86_64 diff --git a/packages.x86_64 b/packages.x86_64
index 9e876e7..b89ab30 100755 index 9e876e7..c5db92a 100755
--- a/packages.x86_64 --- a/packages.x86_64
+++ b/packages.x86_64 +++ b/packages.x86_64
@@ -30,8 +30,10 @@ ethtool @@ -30,8 +30,10 @@ ethtool
@ -36,7 +37,15 @@ index 9e876e7..b89ab30 100755
gnu-netcat gnu-netcat
gpart gpart
gpm gpm
@@ -75,6 +77,7 @@ nbd @@ -45,6 +47,7 @@ irssi
iw
iwd
jfsutils
+jq
kitty-terminfo
ldns
less
@@ -75,6 +78,7 @@ nbd
ndisc6 ndisc6
nfs-utils nfs-utils
nilfs-utils nilfs-utils

View file

@ -6,7 +6,7 @@
flake-utils.url = "github:numtide/flake-utils?ref=b1d9ab70662946ef0850d488da1c9019f3a9752a"; flake-utils.url = "github:numtide/flake-utils?ref=b1d9ab70662946ef0850d488da1c9019f3a9752a";
}; };
outputs = { self, flake-utils, nixpkgs }: flake-utils.lib.eachDefaultSystem ( outputs = { self, flake-utils, nixpkgs }: (flake-utils.lib.eachDefaultSystem (
system: system:
let let
pkgs = import nixpkgs { pkgs = import nixpkgs {
@ -32,5 +32,11 @@
packages = { packages = {
archiso = pkgs.archiso; archiso = pkgs.archiso;
}; };
}); })) // {
valhalla = {
"DerGeret Windows" = import ./profiles/DerGeret/config.nix;
"der-geret Arch Linux" = import ./profiles/DerGeret/Arch/config.nix;
"manu-surface Arch Linux" = import ./profiles/ManuSurface/Arch/config.nix;
};
};
} }

View file

@ -1,7 +0,0 @@
{ lib, ... }: {
options = {
valhalla = {
git = (import ./git/options.nix) { inherit lib; };
};
};
}

View file

@ -1,33 +0,0 @@
{ lib, ... }:
let
inherit (lib)
mkOption
types
;
in {
defaultBranch = mkOption {
type = types.nullOr types.str;
description = "The name of the default branch in git.";
default = null;
};
flow = {
mainBranch = mkOption {
type = types.nullOr types.str;
description = "The name of the stable branch in git flow.";
default = null;
};
devBranch = mkOption {
type = types.nullOr types.str;
description = "The name of the development branch in git flow.";
default = null;
};
};
aliases = mkOption {
type = types.attrsOf types.str;
description = "Git command aliases to install.";
default = {};
};
}

52
lib/modules/os.nix Normal file
View file

@ -0,0 +1,52 @@
{ lib, ... }:
let
inherit (lib)
mkOption
types
;
in {
options = {
valhalla = mkOption {
type = types.submodule (
{ extendModules, ... }:
let
osVariant = extendModules {
modules = [
({ config, ... }: {
options = {
config = mkOption {
type = types.attrs;
description = "The configuration of the Operating System.";
default = builtins.removeAttrs config ["_module" "config" "linux" "windows"];
visible = false;
};
};
})
];
};
linuxVariant = osVariant.extendModules { };
windowsVariant = osVariant.extendModules { };
in {
options = {
linux = mkOption {
inherit (linuxVariant) type;
description = "The options for setting up Linux.";
default = {};
visible = "shallow";
};
windows = mkOption {
inherit (windowsVariant) type;
description = "The options for setting up Windows.";
default = {};
visible = "shallow";
};
};
});
description = "Configuration for PortValhalla.";
default = {};
};
};
}

View file

@ -0,0 +1,59 @@
{ lib, ... }:
let
inherit (lib)
mkOption
types
;
gitType = types.submodule (
{ ... }: {
options = {
defaultBranch = mkOption {
type = types.nullOr types.str;
description = "The name of the default branch in newly created repositories.";
default = null;
};
flow = {
mainBranch = mkOption {
type = types.nullOr types.str;
description = "The name of the stable branch in git flow.";
default = null;
};
devBranch = mkOption {
type = types.nullOr types.str;
description = "The name of the development branch in git flow.";
default = null;
};
};
aliases = mkOption {
type = types.attrsOf types.str;
description = "The git command aliases to install.";
default = {};
};
};
});
gitOption = mkOption {
type = gitType;
description = "The git related options.";
default = {};
};
in {
options = {
valhalla = {
git = gitOption;
users = mkOption {
type = types.attrsOf (types.submodule (
{ ... }: {
options = {
git = gitOption;
};
}));
};
};
};
}

View file

@ -0,0 +1,44 @@
{ lib, ... }:
let
inherit (lib)
mkEnableOption
mkOption
types
;
syncType = types.submodule (
{ ... }: {
options = {
remotePath = mkOption {
type = types.str;
description = "The path to the folder on the cloud to sync.";
};
localPath = mkOption {
type = types.str;
description = "The path to sync the cloud content to.";
};
virtualFiles = (mkEnableOption "virtual file support") // {
default = true;
};
};
});
in {
options = {
valhalla.windows.users = mkOption {
type = types.attrsOf (types.submodule (
{ ... }: {
options = {
nextcloud = {
folderSyncs = mkOption {
type = types.listOf syncType;
description = "The folders to synchronize.";
default = [];
};
};
};
}));
};
};
}

View file

@ -0,0 +1,60 @@
{ lib, ... }:
let
inherit (lib)
mkOption
types
;
themeType = types.submodule (
{ config, ... }: {
options = {
source = mkOption {
type = types.nullOr types.path;
description = "The path to the oh-my-posh theme to use.";
default = null;
};
name = mkOption {
type = types.nullOr types.str;
description = "The name of the theme.";
default = if (config.source != null)
then
lib.strings.removeSuffix ".omp" (lib.strings.removeSuffix ".json" (builtins.baseNameOf config.source))
else
null;
};
};
});
ompType = types.submodule (
{ config, ... }: {
options = {
theme = mkOption {
type = types.either types.str themeType;
description = "The default theme.";
default = {};
};
additionalThemes = mkOption {
type = types.listOf themeType;
description = "A set of additional themes to install.";
default = [];
};
};
});
in {
options = {
valhalla.users = mkOption {
type = types.attrsOf (types.submodule (
{ ... }: {
options = {
oh-my-posh = mkOption {
type = ompType;
description = "The Oh My Posh configuration to apply.";
default = {};
};
};
}));
};
};
}

View file

@ -0,0 +1,40 @@
{ lib, ... }:
let
inherit (lib)
mkOption
types
;
syncType = types.submodule (
{ ... }: {
options = {
dirName = mkOption {
type = types.str;
description = "The name of the directory to sync the remote files to.";
};
cacheDuration = mkOption {
type = types.nullOr types.str;
description = "The amount of time to keep cached files.";
default = null;
};
};
});
in {
options = {
valhalla.linux.users = mkOption {
type = types.attrsOf (types.submodule (
{ ... }: {
options = {
rclone = {
configurations = mkOption {
type = types.attrsOf syncType;
description = "The configurations of the rclone mounts.";
default = {};
};
};
};
}));
};
};
}

View file

@ -1,84 +1,56 @@
{ config, lib, ... }: { lib, ... }:
let let
inherit (lib) inherit (lib)
mkOption mkOption
types types
; ;
cfg = config.valhalla;
capitalize = (import ../text.nix { inherit lib; }).capitalize; capitalize = (import ../text.nix { inherit lib; }).capitalize;
linuxOptions = { userType = types.submodule (
defaultShell = mkOption { { ... } : {
type = types.nullOr types.str;
description = "The default shell of the user.";
default = null;
};
rclone = {
configurations = mkOption {
type = types.attrsOf syncType;
description = "The configurations of the rclone mounts.";
default = {};
};
};
};
syncType = types.submodule (
{ ... }: {
options = { options = {
dirName = mkOption { displayName = mkOption {
type = types.str; type = types.nullOr types.str;
description = "The name of the directory to sync the remote files to."; description = "The human-readable name of the user.";
default = null;
}; };
cacheDuration = mkOption { mailAddress = mkOption {
type = types.nullOr types.str; type = types.nullOr types.str;
description = "The amount of time to keep cached files."; description = "The mail address of the user.";
default = null;
};
groups = mkOption {
type = types.listOf types.str;
description = "The additional groups of the user.";
default = [];
};
};
});
linuxUserType = types.submodule (
{ ... }: {
options = {
defaultShell = mkOption {
type = types.nullOr types.str;
description = "The default shell of the user.";
default = null; default = null;
}; };
}; };
}); });
mkUserType = { options }: ( winUserType = types.submodule (
types.submodule ( { ... }: {
{ ... }: { options = {
options = { microsoftAccount = mkOption {
displayName = mkOption { type = types.bool;
type = types.nullOr types.str; description = "A value indicating whether this user is a Microsoft Account.";
description = "The human-readable name of the user."; default = false;
default = null; };
};
mailAddress = mkOption {
type = types.nullOr types.str;
description = "The mail address of the user.";
default = null;
};
groups = mkOption {
type = types.listOf types.str;
description = "The additional groups of the user.";
default = [];
};
git = (import ./git/options.nix) { inherit lib; };
} // options;
}));
userType = mkUserType {
options = linuxOptions;
};
winUserType = mkUserType {
options = {
microsoftAccount = mkOption {
type = types.bool;
description = "A value indicating whether this user is a Microsoft Account.";
default = false;
}; };
}; });
};
in { in {
options = { options = {
valhalla = { valhalla = {
@ -88,25 +60,33 @@
default = {}; default = {};
}; };
windows.users = mkOption { linux.users = mkOption {
type = types.attrsOf winUserType; type = types.attrsOf linuxUserType;
description = "The users to create on the Windows machine."; };
default = (lib.attrsets.concatMapAttrs (
name: options: windows = mkOption {
if builtins.elem name (builtins.attrNames linuxOptions) type = types.submoduleWith {
then {} modules = [
else { ({ config, options, ... }: {
${capitalize name} = (lib.attrsets.concatMapAttrs ( options = {
name: value: users = mkOption {
if builtins.elem name (builtins.attrNames linuxOptions) type = types.attrsOf winUserType;
then {}
else {
${name} = value;
}
) options) // {
groups = [];
}; };
}) cfg.users);
winUsers = mkOption {
type = options.users.type;
description = "Blablabla";
default = (lib.attrsets.concatMapAttrs (
name: options: {
${capitalize name} = options // {
groups = [];
};
}) config.users);
};
};
})
];
};
}; };
}; };
}; };

View file

@ -6,9 +6,13 @@
; ;
in { in {
imports = [ imports = [
./git.nix ./packages/git.nix
./packages/nextcloud.nix
./packages/oh-my-posh.nix
./packages/rclone.nix
./hardware.nix ./hardware.nix
./i18n.nix ./i18n.nix
./os.nix
./partition.nix ./partition.nix
./software.nix ./software.nix
./users.nix ./users.nix

View file

@ -1,24 +1,18 @@
{ lib, config, ... }: { lib, config, ... }:
let let
inherit (lib) inherit (lib)
mkOption mkDefault
mkEnableOption mkEnableOption
mkIf mkIf
mkOption
types types
; ;
setupUser = config.valhalla.setupUser.name;
capitalize = (import ../text.nix { inherit lib; }).capitalize; capitalize = (import ../text.nix { inherit lib; }).capitalize;
in {
winType = types.submodule ( options = {
{ config, ... }: { valhalla = {
options = { windows = {
setupUser = mkOption {
type = types.str;
description = "The name of the user for setting up Windows.";
default = capitalize setupUser;
};
dualboot = { dualboot = {
enable = mkEnableOption "dual boot"; enable = mkEnableOption "dual boot";
@ -41,19 +35,13 @@
dynamicLighting = mkEnableOption "dynamic lighting"; dynamicLighting = mkEnableOption "dynamic lighting";
adware = mkEnableOption "adware"; # Fuck you for displaying ads on an OS I fricking paid for! adware = mkEnableOption "adware"; # Fuck you for displaying ads on an OS I fricking paid for!
}; };
};
};
config = { config = {
dualboot.linuxPercentage = mkIf (!config.dualboot.enable) 0; valhalla.windows = {
}; setupUser.name = mkDefault (capitalize config.valhalla.setupUser.name);
}); dualboot.linuxPercentage = mkIf (!config.valhalla.windows.dualboot.enable) (mkDefault 0);
in {
options = {
valhalla = {
windows = mkOption {
type = winType;
description = "The options for setting up Windows.";
default = {};
};
}; };
}; };
} }

View file

@ -1,7 +1,7 @@
#!/bin/pwsh #!/bin/pwsh
$null = New-Module { $null = New-Module {
. "$PSScriptRoot/../../../scripts/Common/Scripts/Context.ps1"; . "$PSScriptRoot/../../../scripts/Common/Scripts/Context.ps1";
. "$PSScriptRoot/../../../scripts/Windows/OS/Manage.ps1"; . "$PSScriptRoot/../../../scripts/Windows/OS/Legacy.ps1";
Write-Host "Starting Backup of Windows"; Write-Host "Starting Backup of Windows";
$context = [Context]::new(); $context = [Context]::new();

View file

@ -2,7 +2,7 @@
. "$PSScriptRoot/Drivers.ps1"; . "$PSScriptRoot/Drivers.ps1";
. "$PSScriptRoot/../../../scripts/Common/Scripts/Context.ps1"; . "$PSScriptRoot/../../../scripts/Common/Scripts/Context.ps1";
. "$PSScriptRoot/../../../scripts/Windows/Collections/Personal.ps1" . "$PSScriptRoot/../../../scripts/Windows/Collections/Personal.ps1"
. "$PSScriptRoot/../../../scripts/Windows/OS/Install.ps1"; . "$PSScriptRoot/../../../scripts/Windows/OS/Manage.ps1";
function Initialize-Configuration { function Initialize-Configuration {
# Fix synchronization between Linux and Windows clock # Fix synchronization between Linux and Windows clock

View file

@ -11,7 +11,7 @@
linuxPercentage = 30; linuxPercentage = 30;
}; };
users.Manuel = { users.manuel = {
microsoftAccount = true; microsoftAccount = true;
groups = ["Administrators"]; groups = ["Administrators"];
}; };

View file

@ -1,6 +1,6 @@
#!/bin/pwsh #!/bin/pwsh
. "$PSScriptRoot/../../../scripts/Common/Scripts/Context.ps1"; . "$PSScriptRoot/../../../scripts/Common/Scripts/Context.ps1";
. "$PSScriptRoot/../../../scripts/Windows/OS/Install.ps1"; . "$PSScriptRoot/../../../scripts/Windows/OS/Manage.ps1";
. "$PSScriptRoot/../../../scripts/Windows/Collections/Generic.ps1" . "$PSScriptRoot/../../../scripts/Windows/Collections/Generic.ps1"
function Restore-Apps { function Restore-Apps {

View file

@ -3,6 +3,7 @@
fs = import ../../lib/modules/partition/fs.nix; fs = import ../../lib/modules/partition/fs.nix;
in { in {
imports = [ imports = [
../manuel/config.nix
../../lib/modules/valhalla.nix ../../lib/modules/valhalla.nix
]; ];
@ -44,7 +45,10 @@
"wheel" "wheel"
"nix-users" "nix-users"
]; ];
};
};
linux.users.manuel = {
defaultShell = "fish"; defaultShell = "fish";
rclone = { rclone = {
@ -57,6 +61,25 @@
}; };
}; };
}; };
};
windows.users.manuel = {
nextcloud = {
folderSyncs =
let
localPath = "C:/tools/RetroArch-Win64";
remotePath = "/Saved Games/RetroArch";
in [
{
remotePath = "${remotePath}/Saves";
localPath = "${localPath}/saves";
virtualFiles = false;
}
{
remotePath = "${remotePath}/System";
localPath = "${localPath}/system";
}
];
}; };
}; };

View file

@ -0,0 +1,23 @@
{ ... }: {
imports = [
../../lib/modules/valhalla.nix
];
config = {
valhalla = {
users.manuel = {
oh-my-posh = {
theme = {
source = ./manuel.omp.json;
};
};
};
partition = {
os = {
partitions = { };
};
};
};
};
}

View file

@ -0,0 +1,173 @@
{
"$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json",
"version": 2,
"blocks": [
{
"type": "prompt",
"alignment": "left",
"segments": [
{
"type": "os",
"style": "diamond",
"leading_diamond": "\ue0b6",
"trailing_diamond": "\ue0b4",
"background_templates": [
"{{ if eq .OS \"ubuntu\" }}#EA531A{{ end }}",
"{{ if eq .OS \"debian\" }}#D80150{{ end }}",
"{{ if eq .OS \"arch\" }}#1793D1{{ end }}"
],
"foreground": "p:white",
"template": "{{ if ne .OS \"windows\" }}{{ .Icon }} {{ end }}"
},
{
"type": "session",
"style": "diamond",
"leading_diamond": "\ue0b6",
"trailing_diamond": "\ue0b0",
"background": "p:yellow",
"foreground": "p:black",
"properties": {
"display_host": false
},
"template": " {{ if .SSHSession }}\ueb39 {{ end }}{{ .UserName }} "
},
{
"type": "path",
"style": "powerline",
"powerline_symbol": "\ue0b0",
"background": "p:orange",
"foreground": "p:black",
"properties": {
"home_icon": "~",
"style": "folder"
},
"template": " \udb80\ude4b {{ path .Path .Location }} "
},
{
"type": "dotnet",
"style": "powerline",
"powerline_symbol": "\ue0b0",
"foreground": "p:black",
"background": "#00ffff",
"template": " \udb81\ude10 {{ .Full }} "
},
{
"type": "java",
"style": "powerline",
"powerline_symbol": "\ue0b0",
"background": "#4063d8",
"template": " \udb82\udf37 {{ .Full }} "
},
{
"type": "python",
"style": "powerline",
"powerline_symbol": "\ue0b0",
"background": "#906cff",
"template": " \udb80\udf20 {{ .Full }} "
},
{
"type": "git",
"style": "powerline",
"powerline_symbol": "\ue0b0",
"trailing_diamond": "\ue0b4",
"background": "p:green",
"background_templates": [
"{{ if or (.Working.Changed) (.Staging.Changed) }}p:yellow{{ end }}",
"{{ if and (gt .Ahead 0) (gt .Behind 0) }}p:red{{ end }}",
"{{ if gt .Ahead 0 }}#49416D{{ end }}",
"{{ if gt .Behind 0 }}#7A306C{{ end }}"
],
"foreground": "p:black",
"foreground_templates": [
"{{ if or (.Working.Changed) (.Staging.Changed) }}p:black{{ end }}",
"{{ if and (gt .Ahead 0) (gt .Behind 0) }}p:white{{ end }}",
"{{ if gt .Ahead 0 }}p:white{{ end }}"
],
"properties": {
"branch_max_length": 25,
"fetch_stash_count": true,
"fetch_status": true,
"fetch_upstream_icon": true,
"upstream_icons": {
"codeberg.org": "\uf330 ",
"git.nuth.ch": "\uf335",
"git.jonascosta.ch": "\uf339 ",
"git.romhackersworld.eu": "\uf339 ",
"aur.archlinux.org": "\uf303 "
}
},
"templates": [
"{{ if .UpstreamURL }} {{ url .UpstreamIcon .UpstreamURL }}{{ end }}",
" {{ .HEAD }} ",
"{{ if .BranchStatus }}{{ .BranchStatus }} {{ end }}",
"{{ if .Working.Changed }} \uf044 {{ .Working.String }} {{ end }}",
"{{ if and (.Working.Changed) (or (.Staging.Changed) (gt .StashCount 0)) }} | {{ end }}",
"{{ if .Staging.Changed }} \uf046 {{ .Staging.String }} {{ end }}",
"{{ if and (.Staging.Changed) (gt .StashCount 0) }} | {{ end }}",
"{{ if gt .StashCount 0 }} \udb80\udd93 {{ .StashCount }}{{ end }} "
]
},
{
"type": "node",
"style": "powerline",
"powerline_symbol": "\ue0b0",
"background": "#6ca35e",
"foreground": "p:white",
"properties": {
"fetch_version": true
},
"template": " \udb80\udf99 {{ if .PackageManagerIcon }}{{ .PackageManagerIcon }} {{ end }}{{ .Full }} "
},
{
"type": "root",
"style": "powerline",
"powerline_symbol": "\ue0b0",
"background": "p:yellow",
"foreground": "p:white",
"properties": {
"root_icon": "\uf0e7"
}
},
{
"type": "executiontime",
"style": "plain",
"background": "#83769c",
"foreground": "p:white",
"properties": {
"always_enabled": true
},
"template": "<transparent>\ue0b0</> \udb81\udead {{ .FormattedMs }}\u2800"
},
{
"type": "text",
"style": "diamond",
"background": "p:blue",
"trailing_diamond": "\ue0b4",
"background_templates": [
"{{ if gt .Code 0 }}p:red{{ end }}"
],
"foreground": "p:white",
"properties": {
"always_enabled": true
},
"template": "<parentBackground>\ue0b0</> {{ if gt .Code 0 }}\uf00d{{ else }}\uf00c{{ end }} "
}
]
}
],
"transient_prompt": {
"background": "transparent",
"foreground": "p:black",
"template": "<p:yellow,transparent>\ue0b6</><,p:yellow> {{ .Folder }} </><p:yellow,transparent>\ue0b0</> "
},
"final_space": true,
"palette": {
"black": "#262B44",
"blue": "#4B95E9",
"green": "#59C9A5",
"orange": "#F07623",
"red": "#D81E5B",
"white": "#E0DEF4",
"yellow": "#F3AE35"
}
}

View file

@ -127,12 +127,16 @@ $null = New-Module {
.PARAMETER OutDir .PARAMETER OutDir
The directory to download the file to. The directory to download the file to.
.PARAMETER Timeout
The number of seconds to wait before clicking the download button.
#> #>
function Start-BrowserDownload { function Start-BrowserDownload {
param( param(
[string] $URL, [string] $URL,
[string] $ButtonSelector, [string] $ButtonSelector,
[string] $OutDir = $null [string] $OutDir = $null,
[double] $Timeout = 0
) )
Start-CustomBrowserDownload @PSBoundParameters -Action { Start-CustomBrowserDownload @PSBoundParameters -Action {
@ -153,8 +157,12 @@ $null = New-Module {
} }
} }
if ($Timeout -gt 0) {
Start-Sleep $Timeout;
}
if ($element) { if ($element) {
$Browser.FindElement([OpenQA.Selenium.By]::CssSelector($ButtonSelector)).Click(); $Browser.FindElement($selector).Click();
} else { } else {
Write-Error "Unable to find download button!"; Write-Error "Unable to find download button!";
} }

View file

@ -2,19 +2,32 @@ using namespace Microsoft.Win32;
using namespace System.Security.AccessControl; using namespace System.Security.AccessControl;
using namespace System.Security.Principal; using namespace System.Security.Principal;
enum SetupStage { enum WindowsInstallerStage {
Idle
Initialize Initialize
OneShot Run
Completed
}
enum SetupStage {
Configure Configure
Install Install
CreateUser CreateUser
ConfigureUser }
enum UserStage {
Create
Configure
Cleanup
Completed
} }
$null = New-Module { $null = New-Module {
[string] $configRoot = "HKLM:\Software\PortValhalla"; [string] $configRoot = "HKLM:\Software\PortValhalla";
[string] $stageOption = "Stage"; [string] $stageOption = "Stage";
[string] $setupStageOption = "SetupStage";
[string] $userOption = "SetupUser";
[string] $userStageOption = "UserStage";
[string] $accountOption = "MSAccount";
[string] $finishedOption = "Finished"; [string] $finishedOption = "Finished";
[RegistryKey] $key = $null; [RegistryKey] $key = $null;
@ -30,14 +43,36 @@ $null = New-Module {
[string] $Path [string] $Path
) )
$job = Start-Job { & {
$env:Value = Resolve-Path $Using:Path; $ErrorActionPreference = 'Continue';
$env:WSLENV = "Value/p"; $completed = $false;
$result = wsl -- bash -c 'echo "$Value"';
wsl -e printf "%q" "$result";
};
Receive-Job -Wait $job; while (-not $completed) {
$job = Start-Job {
$env:Value = Resolve-Path $Using:Path;
$env:WSLENV = "Value/p";
$result = wsl -- bash -c 'echo "$Value"';
wsl -e printf "%q" "$result";
};
$result = Receive-Job -Wait $job;
if ((Split-Path -Leaf $Path) -ne (Split-Path -Leaf $result)) {
Write-Error "The result of the path conversion of ``$Path`` was unexpected: ``$result``";
continue;
}
if ($job.State -ne ([System.Management.Automation.JobState]::Completed)) {
Write-Error "An error occurred while converting ``$Path`` to a Linux path.`nOutput: ``$result``";
continue;
}
$completed = $true;
}
$result;
};
} }
<# <#
@ -79,19 +114,33 @@ $null = New-Module {
$scriptPath = "$PSScriptRoot/../../Common/Scripts/config.fish"; $scriptPath = "$PSScriptRoot/../../Common/Scripts/config.fish";
if (-not $IsWindows) { if ($env:CONFIG_MODULE) {
$escapedPath = (fish -c 'string escape $argv' "$scriptPath"); $output = & {
fish -c ". $escapedPath; $Script"; if (-not $IsWindows) {
} else { $escapedPath = (fish -c 'string escape $argv' "$scriptPath");
function fish { fish -c ". $escapedPath; $Script";
wsl --shell-type login -- nix --extra-experimental-features "nix-command flakes" run nixpkgs`#fish -- $args } else {
function fish {
wsl --shell-type login -- nix --extra-experimental-features "nix-command flakes" run nixpkgs`#fish -- $args
}
$output = fish -c ". $(ConvertTo-LinuxPath $scriptPath); $Script";
if (-not $?) {
Write-Error "The configuration could not be retrieved!";
} else {
$output;
}
}
} }
fish -c ". $(ConvertTo-LinuxPath $scriptPath); $Script" | ConvertFrom-Json; if (-not ($output -and ($output | Test-Json))) {
} Write-Error "The value ``$output`` is not valid JSON.";
} else {
if (-not $?) { $output | ConvertFrom-Json;
throw "The configuration could not be retrieved!"; }
} else {
$null;
} }
} }
@ -112,6 +161,22 @@ $null = New-Module {
Invoke-ConfigScript "getConfig $Name --json $ArgumentList"; Invoke-ConfigScript "getConfig $Name --json $ArgumentList";
} }
<#
.SYNOPSIS
Gets the name of the config root.
#>
function Get-ConfigRootName {
return "valhalla.$($IsWindows ? "windows" : "linux")";
}
<#
.SYNOPSIS
Gets the name of the user root.
#>
function Get-UserRootName {
return "$(Get-ConfigRootName).$($IsWindows ? "winUsers" : "users")";
};
<# <#
.SYNOPSIS .SYNOPSIS
Gets a user configuration. Gets a user configuration.
@ -124,13 +189,13 @@ $null = New-Module {
#> #>
function Get-UserConfig { function Get-UserConfig {
param( param(
[string] $UserName = $env:UserName, [string] $UserName = ($IsWindows ? $env:UserName : $env:USER),
[Parameter(Mandatory, Position = 0)] [Parameter(Mandatory, Position = 0)]
[string] $Name [string] $Name
) )
if ((Get-Users) -contains $UserName) { if ((Get-Users) -contains $UserName) {
Get-Config "valhalla.windows.users.$UserName.$Name"; Get-Config "$(Get-UserRootName).$UserName.$Name";
} else { } else {
return $null; return $null;
} }
@ -158,7 +223,7 @@ $null = New-Module {
function Get-Users { function Get-Users {
[OutputType([string[]])] [OutputType([string[]])]
param() param()
Get-Attributes "valhalla.windows.users"; Get-Attributes "$(Get-UserRootName)";
} }
<# <#
@ -168,7 +233,7 @@ $null = New-Module {
function Get-SetupUser { function Get-SetupUser {
[OutputType([string])] [OutputType([string])]
param() param()
Get-Config "valhalla.windows.setupUser"; Get-Config "$(Get-ConfigRootName).setupUser.name";
} }
<# <#
@ -214,11 +279,44 @@ $null = New-Module {
<# <#
.SYNOPSIS .SYNOPSIS
Gets the name of the current setup stage. Gets the name of the current stage of the Windows install script action.
#> #>
function Get-Stage { function Get-Stage {
$stage = Get-SetupOption $stageOption; $stage = Get-SetupOption $stageOption;
if ($null -ne $stage) {
$stage = [WindowsInstallerStage]$stage;
}
return $stage;
}
<#
.SYNOPSIS
Sets the name of the current stage of the Windows install script action.
.PARAMETER Name
The name of the stage to set.
#>
function Set-Stage {
param(
$Name
)
if (-not (($null -eq $Name) -or ($Name -is [string]))) {
$Name = ([WindowsInstallerStage]$Name).ToString();
}
$null = Set-SetupOption $stageOption $Name;
}
<#
.SYNOPSIS
Gets the name of the current setup stage.
#>
function Get-SetupStage {
$stage = Get-SetupOption $setupStageOption;
if ($null -ne $stage) { if ($null -ne $stage) {
$stage = [SetupStage]$stage; $stage = [SetupStage]$stage;
} }
@ -233,7 +331,7 @@ $null = New-Module {
.PARAMETER Name .PARAMETER Name
The name to set the current stage to. The name to set the current stage to.
#> #>
function Set-Stage { function Set-SetupStage {
param( param(
$Name $Name
) )
@ -242,7 +340,86 @@ $null = New-Module {
$Name = ([SetupStage]$Name).ToString(); $Name = ([SetupStage]$Name).ToString();
} }
$null = Set-SetupOption $stageOption $Name; $null = Set-SetupOption $setupStageOption $Name;
}
<#
.SYNOPSIS
Gets the current user to set up.
#>
function Get-CurrentUser {
return (Get-SetupOption $userOption) ?? 0;
}
<#
.SYNOPSIS
Sets the index of the current user to set up.
.PARAMETER Value
The index of the user to set up.
#>
function Set-CurrentUser {
param(
[int] $Value
)
Set-SetupOption $userOption $value;
}
<#
.SYNOPSIS
Gets the name of the current stage of the user setup.
#>
function Get-UserStage {
$stage = Get-SetupOption $userStageOption;
if ($null -ne $stage) {
$stage = [UserStage]$stage;
}
return $stage;
}
<#
.SYNOPSIS
Sets the current stage of the user setup.
.PARAMETER Name
The name of the stage to set.
#>
function Set-UserStage {
param(
$Name
)
if (-not (($null -eq $Name) -or ($Name -is [string]))) {
$Name = ([UserStage]$Name).ToString();
}
$null = Set-SetupOption $userStageOption $Name;
}
<#
.SYNOPSIS
Gets the name of the microsoft account to create.
#>
function Get-MSAccountName {
return Get-SetupOption $accountOption;
}
<#
.SYNOPSIS
Sets the name of the microsoft account to create.
.PARAMETER Name
The name of the microsoft account to create.
#>
function Set-MSAccountName {
param(
[string] $Name
)
Set-SetupOption $accountOption $Name;
} }
<# <#
@ -250,7 +427,7 @@ $null = New-Module {
Gets a value indicating whether the setup has finished. Gets a value indicating whether the setup has finished.
#> #>
function Get-IsFinished { function Get-IsFinished {
return [bool] (((Get-Stage) -eq ([SetupStage]::Idle)) -or (Get-SetupOption $finishedOption)); return [bool](Get-SetupOption $finishedOption);
} }
<# <#
@ -277,7 +454,7 @@ $null = New-Module {
[string] $Name [string] $Name
) )
Get-Config "valhalla.software.$Name"; Get-Config "$(Get-ConfigRootName).software.$Name";
} }
<# <#
@ -293,7 +470,7 @@ $null = New-Module {
Checks whether the current user is the setup user. Checks whether the current user is the setup user.
#> #>
function Test-SetupUser { function Test-SetupUser {
$env:UserName -eq (Get-Config "valhalla.windows.setupUser"); ($IsWindows ? $env:UserName : $env:USER) -eq (Get-SetupUser);
} }
<# <#

View file

@ -1,10 +1,16 @@
. "$PSScriptRoot/Config.ps1"; using namespace System.Management.Automation.Host;
. "$PSScriptRoot/../Types/OneShotTask.ps1"; . "$PSScriptRoot/../Types/OneShotTask.ps1";
. "$PSScriptRoot/../../Windows/Scripts/PowerManagement.ps1";
. "$PSScriptRoot/../../Windows/Scripts/Registry.ps1";
$null = New-Module { $null = New-Module {
. "$PSScriptRoot/Config.ps1";
. "$PSScriptRoot/../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../Types/OneShotTask.ps1"; . "$PSScriptRoot/../Types/OneShotTask.ps1";
. "$PSScriptRoot/../../Windows/Scripts/Hooks.ps1";
. "$PSScriptRoot/../../Windows/Scripts/PowerManagement.ps1";
. "$PSScriptRoot/../../Windows/Scripts/Registry.ps1";
. "$PSScriptRoot/../../Windows/Scripts/Security.ps1";
. "$PSScriptRoot/../../Windows/Scripts/WSL.ps1";
$oneShotTaskName = "PortValhalla OneShot"; $oneShotTaskName = "PortValhalla OneShot";
$logName = "Application"; $logName = "Application";
$oneShotTrigger = 1337; $oneShotTrigger = 1337;
@ -12,6 +18,10 @@ $null = New-Module {
# ToDo: Store "ProgramData/PortValhalla" path somewhere as const # ToDo: Store "ProgramData/PortValhalla" path somewhere as const
$errorPath = "$env:ProgramData/PortValhalla/error.txt"; $errorPath = "$env:ProgramData/PortValhalla/error.txt";
$getUserName = {
"$(Get-SetupUser)OneShot";
};
$taskSetter = { $taskSetter = {
param([OneShotTask] $Task) param([OneShotTask] $Task)
Set-SetupOption $taskOption ([string]$Task); Set-SetupOption $taskOption ([string]$Task);
@ -19,22 +29,237 @@ $null = New-Module {
function Start-Operation { function Start-Operation {
param( param(
[switch] $NonInteractive,
[switch] $NoImplicitCleanup,
[scriptblock] $Action [scriptblock] $Action
) )
$Global:ErrorActionPreference = 'Inquire'; $cleanup = { };
$env:WSLENV = "CONFIG_MODULE/p";
if ($env:CONFIG_MODULE) { if ($IsWindows -and ($null -ne (Get-OneShotTask))) {
$env:CONFIG_MODULE = Resolve-Path $env:CONFIG_MODULE; $taskPending = $true;
[switch] $NonInteractive = $true;
} }
if (Test-Admin) { if (-not $Global:InOperation) {
Disable-WindowsUpdateAutoRestart; if ($env:DEBUG) {
Set-PSDebug -Trace 1;
}
$Global:InOperation = $true;
$Global:ErrorActionPreference = $NonInteractive.IsPresent ? 'Continue' : 'Inquire';
if ($IsWindows) {
$env:WSLENV = "CONFIG_MODULE/p";
if ($env:CONFIG_MODULE) {
$env:CONFIG_MODULE = Resolve-Path $env:CONFIG_MODULE;
}
if (Test-Admin) {
Disable-WindowsUpdateAutoRestart;
}
New-Alias -Force "sudo" gsudo;
}
if (-not $NoImplicitCleanup.IsPresent) {
$cleanup = {
Clear-OperationResources;
};
}
& {
$initialized = $false;
while (-not $initialized) {
if ($IsWindows) {
if (-not ((Test-Command "choco") -and (Test-Command "refreshenv"))) {
Invoke-Hook "Install-Chocolatey" -Fallback {
# Install chocolatey
New-Item -Force $PROFILE;
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;
Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'));
Import-Module $env:ChocolateyInstall/helpers/chocolateyProfile.psm1;
refreshenv;
};
continue;
}
if (-not (Test-ChocoPackage "powershell-core")) {
Invoke-Hook "Install-PowerShellCore" -Fallback {
choco install -y powershell-core --install-arguments='"ADD_FILE_CONTEXT_MENU_RUNPOWERSHELL=1 ADD_EXPLORER_CONTEXT_MENU_OPENPOWERSHELL=1 REGISTER_MANIFEST=1 USER_MU=1 ENABLE_MU=1"';
};
Restart-Intermediate;
return;
}
if ($env:PWSH_PATH -and (Test-Path $env:PWSH_PATH)) {
attrib "-R" "$env:PWSH_PATH\*" /S /D;
Remove-Item -Recurse -Force $env:PWSH_PATH;
continue;
}
if ($env:DEBUG) {
if (
(Get-Item $env:INSTALLER_SCRIPT).IsReadOnly -and
(Test-Qemu) -and
($Host.UI.PromptForChoice(
"Confirm",
"Do you wish to swap to live scripts?",
[ChoiceDescription[]]@(
[ChoiceDescription]::new("&No", "Use scripts stored in the virtual machine"),
[ChoiceDescription]::new("&Yes", "Use live scripts stored on the host")),
0) -eq 1)) {
Install-ChocoPackage winfsp qemu-guest-agent;
Get-Service VirtioFsSvc | Start-Service -PassThru | Set-Service -StartupType Automatic;
while (-not (Test-Path Z:\)) {
Start-Sleep 0.1;
}
foreach ($name in @("CONFIG_MODULE", "INSTALLER_SCRIPT")) {
$variable = Get-Item "Env:\$name";
$path = Join-Path `
"Z:\Repositories\PortValhalla" `
([System.IO.Path]::GetRelativePath("$PSScriptRoot/../../..", $variable.Value));
Set-Item "Env:\$name" $path;
Write-Host "The new value of ``$name`` is ``$path``";
}
Restart-Intermediate;
exit;
}
}
if (-not (Test-Command "gsudo")) {
Install-ChocoPackage gsudo;
refreshenv;
continue;
}
if ($env:DEBUG) {
& {
$sys32 = "$env:WINDIR/System32";
$osk = (Get-Item "$sys32/osk.exe").FullName;
$cmd = (Get-Item "$sys32/cmd.exe").FullName;
if ((Get-FileHash $osk).Hash -ne (Get-FileHash $cmd).Hash) {
Set-MpPreference -ExclusionPath $osk;
gsudo -d --ti move $osk "${osk}_";
gsudo -d -s copy $cmd $osk;
continue;
}
};
}
if (-not (Test-Winget)) {
. "$PSScriptRoot/../Software/winget/Manage.ps1";
continue;
}
if (-not (Test-Command "git")) {
Install-WingetPackage Git.Git;
refreshenv;
continue;
}
if (-not (Test-Command "7z")) {
Install-ChocoPackage 7zip.portable;
refreshenv;
continue;
}
if (-not (Test-Command "yq")) {
Install-ChocoPackage "yq";
refreshenv;
continue;
}
if (-not (Test-Wsl)) {
Install-Wsl;
Restart-Intermediate;
return;
}
if (-not (Test-WslDistribution)) {
if (-not (Test-Path (Get-WslDistributionDisk))) {
Install-WslDistribution;
}
Register-WslDistribution;
continue;
}
if (-not (wsl --shell-type login type -t nix)) {
wsl -- sh `<`(curl -L https://nixos.org/nix/install`) --daemon --yes;
wsl --shutdown;
continue;
}
if (-not (Test-PSPackage Selenium.WebDriver)) {
Write-Host "Installing browser automation tools…";
$null = Install-Package -Force Selenium.WebDriver -RequiredVersion 4.10.0 -SkipDependencies;
continue;
}
Install-ChocoPackage selenium-gecko-driver firefox;
Install-WingetPackage AutoHotkey.AutoHotkey;
. "$PSScriptRoot/../../Windows/Software/PinnedItem/Manage.ps1";
}
Invoke-Hook "Install-PSModules" -Fallback {
$modules = @(
@("PSScriptAnalyzer")
) + (& {
if (-not $IsWindows) {
@()
} else {
@(
@("KnownFolders"),
@("PSWindowsUpdate"),
@("LocalAccounts", $true),
@("NuGet")
)
}
});
foreach ($module in $modules) {
$parameters = @{ };
if ($module -is [string]) {
$module = @($module);
}
if ($module[1]) {
$parameters = @{
allowPrerelease = $true;
};
}
if (-not (Test-PSModule $module[0])) {
Install-Module -Scope AllUsers -AcceptLicense -Force $module[0] @parameters;
Import-Module $module[0];
}
}
};
$initialized = $true;
}
}
} }
New-Alias -Force "sudo" gsudo; if ($taskPending) {
& $Action; Start-OneShot;
} else {
& $Action;
}
& $cleanup;
} }
<# <#
@ -42,7 +267,13 @@ $null = New-Module {
Gets the current OneShot task. Gets the current OneShot task.
#> #>
function Get-OneShotTask { function Get-OneShotTask {
[OneShotTask](Get-SetupOption $taskOption); $task = Get-SetupOption $taskOption;
if ($task) {
return [OneShotTask]$task;
} else {
return $null;
}
} }
<# <#
@ -51,12 +282,23 @@ $null = New-Module {
#> #>
function Enable-OneShotListener { function Enable-OneShotListener {
$tempTask = "PortValhalla Temp"; $tempTask = "PortValhalla Temp";
$action = New-ScheduledTaskAction -Execute "pwsh" -Argument ([string](Get-StartupArguments)); $user = & $getUserName;
$password = [string]([guid]::NewGuid());
$adminGroup = @{
SID = [SecurityIdentifier]::new([WellKnownSidType]::BuiltinAdministratorsSid, $null);
};
$null = New-LocalUser -Name $user -Password (ConvertTo-SecureString -AsPlainText $password);
Add-LocalGroupMember -Member $user @adminGroup;
$path = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList";
$null = New-Item -Force -ErrorAction SilentlyContinue $path;
Set-ItemProperty $path -Name $user -Value 0;
$action = New-ScheduledTaskAction -Execute "pwsh" -Argument "-Command & { $([string](Get-StartupCommand)) } 2>&1 | Tee-Object -FilePath `$env:ProgramData/PortValhalla/OneShotTask.log";
schtasks /Create /SC ONEVENT /EC $logName /MO "*[System[Provider[@Name='$logName'] and EventID=$($oneShotTrigger)]]" /TR cmd.exe /TN $tempTask; schtasks /Create /SC ONEVENT /EC $logName /MO "*[System[Provider[@Name='$logName'] and EventID=$($oneShotTrigger)]]" /TR cmd.exe /TN $tempTask;
$trigger = (Get-ScheduledTask $tempTask).Triggers; $trigger = (Get-ScheduledTask $tempTask).Triggers;
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -RunLevel Highest; $null = Register-ScheduledTask -Force $oneShotTaskName -Action $action -Trigger $trigger -RunLevel Highest -User $user -Password $password;
$task = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger;
$null = Register-ScheduledTask -Force $oneShotTaskName -InputObject $task;
$null = Unregister-ScheduledTask -Confirm:$false $tempTask; $null = Unregister-ScheduledTask -Confirm:$false $tempTask;
} }
@ -66,6 +308,10 @@ $null = New-Module {
#> #>
function Disable-OneShotListener { function Disable-OneShotListener {
Unregister-ScheduledTask -Confirm:$false $oneShotTaskName; Unregister-ScheduledTask -Confirm:$false $oneShotTaskName;
$user = Get-LocalUser (& $getUserName);
[string] $sid = $user.SID;
Remove-LocalUser $user;
Get-CimInstance Win32_UserProfile | Where-Object { $_.SID -eq $sid } | Remove-CimInstance;
} }
<# <#
@ -80,8 +326,6 @@ $null = New-Module {
[OneShotTask] $Task [OneShotTask] $Task
) )
$currentStage = Get-Stage;
Set-Stage ([SetupStage]::OneShot);
& $taskSetter $Task; & $taskSetter $Task;
& { & {
@ -104,16 +348,19 @@ $null = New-Module {
}; };
Write-EventLog -LogName $logName -Source $logName -EventId $oneShotTrigger -Message "Starting OneShot task ``$(Get-OneShotTask)``"; Write-EventLog -LogName $logName -Source $logName -EventId $oneShotTrigger -Message "Starting OneShot task ``$(Get-OneShotTask)``";
Remove-Event -EventIdentifier (Wait-Event -SourceIdentifier $identifier).EventIdentifier;
$null = Wait-Event -SourceIdentifier $identifier;
};
Set-Stage $currentStage; for ($i = 0; $i -lt 2; $i++) {
Remove-Event -EventIdentifier (Wait-Event -SourceIdentifier $identifier).EventIdentifier;
}
};
if (Test-Path $errorPath) { if (Test-Path $errorPath) {
$errorMessage = Get-Content $errorPath; $errorMessage = Get-Content $errorPath;
Remove-Item $errorPath; Remove-Item $errorPath;
Write-Error $errorMessage;
if ($errorMessage) {
Write-Error $errorMessage;
}
} }
} }
@ -124,19 +371,38 @@ $null = New-Module {
Executes the specified action and notifies the OneShot task executor. Executes the specified action and notifies the OneShot task executor.
#> #>
function Start-OneShot { function Start-OneShot {
param(
[scriptblock] $Action
)
try { try {
Start-Operation @PSBoundParameters; Write-Host "Running OneShot task ``$(Get-OneShotTask)``";
Start-Operation {
switch (Get-OneShotTask) {
([OneShotTask]::InitializeMSAccount) {
Initialize-UserCreation;
}
([OneShotTask]::DisableUAC) {
Disable-UAC;
Register-Setup;
}
}
};
} }
catch { catch {
Set-Content -Path $errorPath -Value $Error; Set-Content -Path $errorPath -Value $Error;
Set-UserPermissions $errorPath;
} }
finally { finally {
Set-Stage ([SetupStage]::Idle); & $taskSetter $null;
Write-EventLog -LogName $logName -Source $logName -EventId $oneShotTrigger -Message "The OneShot task ``$(Get-OneShotTask)`` finished."; Write-EventLog -LogName $logName -Source $logName -EventId $oneShotTrigger -Message "The OneShot task ``$(Get-OneShotTask)`` finished.";
} }
} }
<#
.SYNOPSIS
Clears resources allocated during the operation.
#>
function Clear-OperationResources {
if ($IsWindows) {
Uninstall-WslDistribution;
}
}
}; };

View file

@ -51,6 +51,7 @@ function Write-PSScript {
Import-Module PSScriptAnalyzer; Import-Module PSScriptAnalyzer;
$dirName = Split-Path -Parent $FileName; $dirName = Split-Path -Parent $FileName;
$Script = ($Script -split "\r?\n") -join [System.Environment]::NewLine;
$content = Invoke-Formatter -ScriptDefinition $Script; $content = Invoke-Formatter -ScriptDefinition $Script;
$exists = Test-Path -PathType Leaf $FileName; $exists = Test-Path -PathType Leaf $FileName;

View file

@ -197,8 +197,10 @@ $null = New-Module {
function Start-SoftwareInstaller { function Start-SoftwareInstaller {
param( param(
[string] $Name, [string] $Name,
[scriptblock] $Backup = $null,
[scriptblock] $Installer = $null, [scriptblock] $Installer = $null,
[scriptblock] $Configurator = $null, [scriptblock] $Configurator = $null,
[scriptblock] $UserBackup = $null,
[scriptblock] $UserConfigurator = $null, [scriptblock] $UserConfigurator = $null,
[Nullable[InstallerAction]] $Action, [Nullable[InstallerAction]] $Action,
[hashtable] $Arguments [hashtable] $Arguments
@ -236,30 +238,52 @@ $null = New-Module {
arguments = $Arguments; arguments = $Arguments;
}; };
if ($action -eq ([InstallerAction]::Install)) { switch ($Action) {
if ($Installer) { ([InstallerAction]::Backup) {
Write-Host "Installing $Name"; if ($Backup) {
& $Installer @argumentList; Write-Host "Backing up $Name";
} & $Backup @argumentList;
# ToDo: Automatically configure after installation }
} elseif ($Action -eq ([InstallerAction]::Configure)) {
if ($Configurator) {
Write-Host "Configuring $Name";
& $Configurator @argumentList;
} }
([InstallerAction]::Install) {
if ($Installer) {
Write-Host "Installing $Name";
& $Installer @argumentList;
}
if (-not (Test-SetupUser)) { & $installHandler @argumentList -Action ([InstallerAction]::Configure);
$argumentList.Add("action", [InstallerAction]::ConfigureUser);
& $installHandler @argumentList;
}
} elseif ($Action -eq ([InstallerAction]::ConfigureUser)) {
if ((-not $Arguments.ContainsKey($userArgument)) -or (-not $Arguments[$userArgument])) {
$Arguments.Add($userArgument, ($env:UserName));
}
if ($UserConfigurator) { if ($UserConfigurator -and (-not (Test-SetupUser))) {
Write-Host "Configuring $Name for user ``$($Arguments[$userArgument])``"; & $installHandler @argumentList -Action ([InstallerAction]::ConfigureUser);
& $UserConfigurator @argumentList; }
}
([InstallerAction]::Configure) {
if ($Configurator) {
Write-Host "Configuring $Name";
& $Configurator @argumentList;
}
}
default {
if ((-not $Arguments.ContainsKey($userArgument)) -or (-not $Arguments[$userArgument])) {
$Arguments.Add($userArgument, ($IsWindows ? $env:UserName : $env:USER));
}
$user = $Arguments[$userArgument];
switch ($_) {
([InstallerAction]::BackupUser) {
if ($UserBackup) {
Write-Host "Backing up ``$Name`` for user ``$user``";
& $UserBackup @argumentList;
}
}
([InstallerAction]::ConfigureUser) {
if ($UserConfigurator) {
Write-Host "Configuring $Name for user ``$user``";
& $UserConfigurator @argumentList;
}
}
}
} }
} }
}; };

View file

@ -103,3 +103,18 @@ function Test-PSPackage {
[bool] (Get-Package $Name -ErrorAction SilentlyContinue); [bool] (Get-Package $Name -ErrorAction SilentlyContinue);
} }
<#
.SYNOPSIS
Checks whether a module with the specified name is installed.
.PARAMETER Name
The name of the module to check.
#>
function Test-PSModule {
param(
[string] $Name
)
[bool](Get-Module -ListAvailable $Name -ErrorAction SilentlyContinue);
}

View file

@ -30,6 +30,27 @@ function Remove-DesktopIcon {
} }
} }
<#
.SYNOPSIS
Adds a new shortcut to the start menu.
.PARAMETER Name
The name of the icon to create.
.PARAMETER Target
The file to link to.
#>
function Add-StartMenuIcon {
param(
[string] $Name,
[string] $Target
)
Import-Module KnownFolders;
Import-Module "$env:ChocolateyInstall/helpers/chocolateyInstaller.psm1";
Install-ChocolateyShortcut -ShortcutFilePath "$((Get-KnownFolder "Common Programs").Path)/$Name.lnk" -TargetPath ((Get-Item $Target).FullName);
}
<# <#
.SYNOPSIS .SYNOPSIS
Removes icons from the task bar. Removes icons from the task bar.

View file

@ -3,18 +3,12 @@ param (
[hashtable] $Arguments [hashtable] $Arguments
) )
. "$PSScriptRoot/../aliae/Manage.ps1";
. "$PSScriptRoot/../PowerShell/Profile.ps1"; . "$PSScriptRoot/../PowerShell/Profile.ps1";
. "$PSScriptRoot/../../Scripts/Software.ps1"; . "$PSScriptRoot/../../Scripts/Software.ps1";
. "$PSScriptRoot/../../Types/InstallerAction.ps1"; . "$PSScriptRoot/../../Types/InstallerAction.ps1";
Start-SoftwareInstaller @PSBoundParameters ` Start-SoftwareInstaller @PSBoundParameters `
-Installer {
param(
[scriptblock] $Installer
)
& $Installer -Action ([InstallerAction]::Configure);
} `
-Configurator { -Configurator {
Add-PowerShellProfileStatement ` Add-PowerShellProfileStatement `
-System ` -System `
@ -25,4 +19,39 @@ Start-SoftwareInstaller @PSBoundParameters `
(Get-ScriptInitializer "oh-my-posh init pwsh"), (Get-ScriptInitializer "oh-my-posh init pwsh"),
(Get-ScriptInitializer "oh-my-posh completion powershell") (Get-ScriptInitializer "oh-my-posh completion powershell")
) -join [System.Environment]::NewLine) ) -join [System.Environment]::NewLine)
} `
-UserConfigurator {
param(
[hashtable] $Arguments
)
$theme = Get-UserConfig "oh-my-posh.theme";
if ($theme) {
$varName = "POSH_THEME";
if ($theme -isnot [string]) {
$root = "$($IsWindows ? $env:AppData : "~/.config")/oh-my-posh";
$path = Join-Path $root "$($theme.name).omp.json";
$null = New-Item -Force -ItemType Directory $root;
Set-Content $path (
& {
if ($IsWindows) {
wsl cat $theme.source
} else {
cat $theme.source
}
});
$theme = [string] $path;
}
if ($IsWindows) {
[System.Environment]::SetEnvironmentVariable($varName, $path, "User");
} else {
. "$PSScriptRoot/../aliae/Manage.ps1";
Add-EnvironmentVariable -User $Arguments.Name $varName $path;
}
}
}; };

View file

@ -8,13 +8,6 @@ param (
. "$PSScriptRoot/../../Types/InstallerAction.ps1"; . "$PSScriptRoot/../../Types/InstallerAction.ps1";
Start-SoftwareInstaller @PSBoundParameters ` Start-SoftwareInstaller @PSBoundParameters `
-Installer {
param(
[scriptblock] $Installer
)
& $Installer -Action ([InstallerAction]::Configure);
} `
-Configurator { -Configurator {
[string] $globalDir = $null; [string] $globalDir = $null;
$indicator = "# Profile Files"; $indicator = "# Profile Files";

View file

@ -8,11 +8,18 @@ $null = New-Module {
.PARAMETER Name .PARAMETER Name
The name of the module to install. The name of the module to install.
.PARAMETER NativeOnly
A value indicating whether the module is installed in Windows PowerShell only.
.PARAMETER NoProfile
A value indicating whether the module is not added to the profile script of users.
#> #>
function Get-ModuleInstallerComponents { function Get-ModuleInstallerComponents {
param( param(
[string] $Name, [string] $Name,
[switch] $NativeOnly [switch] $NativeOnly,
[switch] $NoProfile
) )
@{ @{
@ -27,7 +34,14 @@ $null = New-Module {
) )
$env:PENDING_MODULE_NAME = $Arguments.Name; $env:PENDING_MODULE_NAME = $Arguments.Name;
$installAction = { Install-Module -Scope AllUsers -Force $env:PENDING_MODULE_NAME @args };
$installAction = {
$module = $env:PENDING_MODULE_NAME;
if (-not (Get-Module -ListAvailable $module -ErrorAction SilentlyContinue)) {
Install-Module -Scope AllUsers -Force $module @args;
}
};
if (-not $Arguments.NativeOnly) { if (-not $Arguments.NativeOnly) {
& $installAction -AcceptLicense; & $installAction -AcceptLicense;
@ -41,7 +55,7 @@ $null = New-Module {
& $Installer -Action ([InstallerAction]::Configure) @PSBoundParameters; & $Installer -Action ([InstallerAction]::Configure) @PSBoundParameters;
}; };
configurator = { configurator = ($NoProfile.IsPresent) ? { } : {
param( param(
[hashtable] $Arguments [hashtable] $Arguments
) )

View file

@ -75,9 +75,11 @@ $null = New-Module {
Push-Location ~; Push-Location ~;
$profiles = $profiles | $profiles = @(
ForEach-Object { [System.IO.Path]::GetRelativePath((Get-Location), $_) } | $profiles |
ForEach-Object { "$HomeDir/$_" }; ForEach-Object { [System.IO.Path]::GetRelativePath((Get-Location), $_) } |
ForEach-Object { "$HomeDir/$_" }
);
Pop-Location; Pop-Location;
} }

View file

@ -0,0 +1,15 @@
<#
.SYNOPSIS
Gets a powershell expression which points to the global `aliae` configuration.
#>
function Get-GlobalConfigExpression {
return "`"$($IsWindows ? "`$env:ProgramData" : "/etc")/aliae/aliae.yml`"";
}
<#
.SYNOPSIS
Gets the path to the global `aliae` configuration.
#>
function Get-GlobalConfigPath {
return & ([scriptblock]::Create((Get-GlobalConfigExpression)));
}

View file

@ -0,0 +1,50 @@
param(
$Action,
[hashtable] $Arguments
)
. "$PSScriptRoot/Constants.ps1";
. "$PSScriptRoot/../PowerShell/Profile.ps1";
. "$PSScriptRoot/../../Scripts/Software.ps1";
Start-SoftwareInstaller @PSBoundParameters `
-Configurator {
. "$PSScriptRoot/Constants.ps1";
$pathExpression = Get-GlobalConfigExpression;
$path = Get-GlobalConfigPath;
$null = New-Item -Force -ItemType Directory (Split-Path -Parent $path);
Copy-Item -Force "$PSScriptRoot/aliae.yml" $path;
Add-PowerShellProfileStatement `
-System `
-Category "aliae" `
-Script (
@(
{
#aliae
},
"`$globalPath = $pathExpression",
{
$userPath = & {
if ($env:ALIAE_CONFIG) {
$env:ALIAE_CONFIG;
} else {
"~/.aliae.yaml";
}
};
if (Test-Path $globalPath) {
$null = & ([scriptblock]::Create((aliae init pwsh --config $globalPath))) *>&1;
}
if (Test-Path $userPath) {
$null = & ([scriptblock]::Create((aliae init pwsh))) *>&1;
}
aliae completion powershell | Out-String | Invoke-Expression;
}
) -join [System.Environment]::NewLine)
} `
-UserConfigurator {
Copy-Item -Force "$PSScriptRoot/aliae.yml" ~/.aliae.yml;
};

View file

@ -0,0 +1,98 @@
$null = New-Module {
. "$PSScriptRoot/Constants.ps1";
<#
.SYNOPSIS
Adds an alias to an existing `aliae` configuration.
.PARAMETER Name
The name of the alias to add.
.PARAMETER Value
The script the alias should point to.
.PARAMETER User
The user to add the alias to.
#>
function Add-Alias {
param(
[string] $Name,
[string] $Value,
[string] $User
)
Edit-Config `
-Variables @{
Name = "$Name";
Value = "$Value";
} `
".alias |= [((. // [])[] | select(.name != env.Name))] + [{ name: env.Name, value: env.Value }]" `
-User $User;
}
<#
.SYNOPSIS
Adds an environment variable to an existing `aliae` configuration.
.PARAMETER Name
The name of the variable to add.
.PARAMETER Value
The value of the variable.
#>
function Add-EnvironmentVariable {
param(
[string] $Name,
[string] $Value,
[string] $User
)
Edit-Config `
-Variables @{
Name = "$Name";
Value = "$Value";
} `
".env |= [((. // [])[] | select(.name != env.Name))] + [{ name: env.Name, value: env.Value }]" `
-User $User;
}
<#
.SYNOPSIS
Edits the underlying `aliae` configuration.
.PARAMETER Script
The yq script to run over the configuration.
.PARAMETER User
The user to edit the configuration for.
#>
function Edit-Config {
param(
[string] $Script,
[hashtable] $Variables,
[string] $User
)
if ($User) {
$path = "$($IsWindows ? "~" : "$(sudo -u $User bash -c "realpath ~")")/.aliae.yaml";
} else {
$path = Get-GlobalConfigPath;
}
Start-Job {
$file = New-TemporaryFile;
$variables = $using:Variables;
foreach ($key in $variables.Keys) {
Set-Item "Env:\$key" $variables[$key];
}
sudo -u $using:User cp $using:path $file;
yq -yi $using:Script $file;
sudo -u $using:User cp $file $using:path;
Remove-Item $file;
} | Receive-Job -Wait;
}
Export-ModuleMember -Function Add-Alias,Add-EnvironmentVariable;
};

View file

@ -1,22 +1,4 @@
alias: alias: []
- name: totsch env: []
value: git
env:
- name: POSH_THEME
value: '{{ if eq .OS "windows" }}{{ .Home }}/Nextcloud/.omp{{ else }}/usr/local/share/oh-my-posh/themes{{ end }}/manuel.omp.json'
path: [] path: []
script: script: []
- value: |
# Profile Files
$profileRoot = Split-Path -Parent $PROFILE;
$profilePaths = @(
"$profileRoot/conf.d/*.ps1",
"{{ if eq .OS "windows" }}$env:ProgramData{{ else }}/etc{{ end }}/powershell/conf.d/*.ps1"
);
foreach ($profilePath in $profilePaths) {
if (Test-Path $profilePath) {
Get-Item $profilePath | ForEach-Object { . $_; };
}
}
if: match .Shell "pwsh"

View file

@ -10,28 +10,35 @@ begin
function configureSW -V dir function configureSW -V dir
source "$dir/../bash/profile.fish" source "$dir/../bash/profile.fish"
source "$dir/../fish/profile.fish" source "$dir/../fish/profile.fish"
set -l file /etc/aliae/aliae.yml set -l file (pwsh -CommandWithArgs '. $args[0]; Get-GlobalConfigPath' "$dir/Constants.ps1");
echo "export ALIAE_CONFIG=$(string escape "$file")" | sudo tee /etc/profile.d/aliae.sh > /dev/null
sudo install -Dm644 "$dir/aliae.yml" "$file" sudo install -Dm644 "$dir/aliae.yml" "$file"
begin begin
printf %s\n \ printf %s\n \
"# aliae" \ "if [ -f $(string escape $file) ]" \
'eval "$(aliae init bash)"' \ 'then' \
" eval \"\$(aliae init bash --config $(string escape $file))\"" \
'fi' \
'' \
'if [ -n "$ALIAE_CONFIG" ] && [ -f "$ALIAE_CONFIG" ] || [ -f ~/.aliae.yaml ]' \
'then' \
' eval "$(aliae init bash)"' \
'fi' \
'' \
'eval "$(aliae completion bash)"' 'eval "$(aliae completion bash)"'
end | installBashProfile "aliae" "aliae" end | installBashProfile "aliae" "aliae"
begin
printf %s\n "" \
"# aliae" \
'eval "$(aliae init bash)"' \
'eval "$(aliae completion bash)"'
end | sudo tee /etc/skel/.bashrc > /dev/null
if type -q fish if type -q fish
begin begin
printf %s\n \ printf %s\n \
"aliae init fish | source" \ "if [ -f $(string escape $file) ]" \
" eval \"\$(aliae init bash --config $(string escape $file))\"" \
'end' \
'' \
'if [ -n "$ALIAE_CONFIG" ] && [ -f "$ALIAE_CONFIG" ] || [ -f ~/.aliae.yaml ]' \
' aliae init fish | source' \
'end' \
'' \
"aliae completion fish | source" "aliae completion fish | source"
end | installFishProfile "aliae" "aliae" end | installFishProfile "aliae" "aliae"
end end

View file

@ -4,15 +4,123 @@ param (
) )
. "$PSScriptRoot/../../Scripts/Software.ps1"; . "$PSScriptRoot/../../Scripts/Software.ps1";
. "$PSScriptRoot/../../Scripts/System.ps1";
. "$PSScriptRoot/../../Types/InstallerAction.ps1"; . "$PSScriptRoot/../../Types/InstallerAction.ps1";
Start-SoftwareInstaller @PSBoundParameters ` $null = New-Module {
-Installer { param(
[hashtable] $Parameters
)
$configure = {
param( param(
[scriptblock] $Installer [string] $User
) )
& $Installer -Action ([InstallerAction]::Configure); $root = "valhalla";
} `
-Configurator { if ($User) {
$root = "$root$($IsWindows ? ".windows" : '').users.$User";
$sudoArgs = @("-u", $User);
$configArgs = @("--global");
} else {
$sudoArgs = @();
$configArgs = @("--system");
}
<#
.SYNOPSIS
Gets the specified git configuration.
.PARAMETER Name
THe name of the configuration to get.
#>
function Get-GitConfig {
param(
[string] $Name
)
Get-Config "$root.git.$Name";
}
<#
.SYNOPSIS
Sets a configuration option in git.
#>
function Set-GitConfig {
sudo @sudoArgs git config @configArgs $args;
}
if ((-not $IsWindows) -or $User) {
$branch = Get-GitConfig "defaultBranch";
if ($branch) {
Set-GitConfig "init.defaultBranch" $branch;
}
}
if ($User) {
$displayName = Get-UserConfig "displayName";
$mailAddress = Get-UserConfig "mailAddress";
if ($displayName) {
Set-GitConfig "user.name" $displayName;
}
if ($mailAddress) {
Set-GitConfig "user.email" $mailAddress;
}
}
# Git Flow
. {
$dir = New-TemporaryDirectory;
$key = "flow";
$mainBranch = Get-GitConfig "$key.mainBranch";
$devBranch = Get-GitConfig "$key.devBranch";
& {
git -C "$dir" init;
git -C "$dir" config user.name "PortValhalla";
git -C "$dir" config user.email "no-reply@valhal.la";
git -C "$dir" commit --allow-empty -m "Initial commit";
git -C "$dir" branch master;
git -C "$dir" branch dev;
git -C "$dir" flow init --defaults;
} | Out-Null;
if ($mainBranch) {
git -C "$dir" branch $mainBranch | Out-Null;;
sudo @sudoArgs git -C "$dir" flow config set @configArgs master $mainBranch;
}
if ($devBranch) {
git -C "$dir" branch $devBranch | Out-Null;
sudo @sudoArgs git -C "$dir" flow config set @configArgs develop $devBranch;
}
Remove-Item -Recurse -Force $dir;
};
# Aliases
[PSCustomObject] $aliases = Get-GitConfig "aliases";
if ($aliases) {
foreach ($alias in ($aliases | Get-Member -MemberType Properties)) {
Set-GitConfig "alias.$($alias.Name)" $aliases.$($alias.Name);
}
}
}; };
Start-SoftwareInstaller @Parameters `
-Configurator {
& $configure @PSBoundParameters;
} `
-UserConfigurator {
param(
[hashtable] $Arguments
)
& $configure -User $Arguments.Name;
};
} $PSBoundParameters;

View file

@ -0,0 +1,26 @@
param(
$Action,
[hashtable] $Arguments
)
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Scripts/SoftwareManagement.ps1";
Start-SoftwareInstaller @PSBoundParameters `
-UserConfigurator {
param(
$Arguments
)
$bins = @("codium", "codium-insiders", "code", "code-insiders");
$extensions = @("zokugun.sync-settings", "zokugun.vsix-manager");
$user = $Arguments.Name;
foreach ($bin in $bins) {
if (Test-Command "$bin") {
foreach ($extension in $extensions) {
sudo -u "$user" "$bin" --install-extension "$extension";
}
}
}
};

View file

@ -2,19 +2,9 @@
begin begin
set -l dir (status dirname) set -l dir (status dirname)
source "$dir/../../Scripts/software.fish" source "$dir/../../Scripts/software.fish"
source "$dir/../../../Common/Software/aliae/main.fish"
function userConfig -a name function userConfig -V dir -a name
set -l bins codium codium-insiders code code-insiders pwsh "$dir/Main.ps1" ConfigureUser;
set -l extensions zokugun.{sync-settings,vsix-manager}
for bin in $bins
if type -q "$bin"
for extension in $extensions
sudo -u "$name" "$bin" --install-extension "$extension"
end
end
end
end end
runInstaller $argv runInstaller $argv

View file

@ -1,5 +1,7 @@
enum InstallerAction { enum InstallerAction {
Backup
Install Install
Configure Configure
BackupUser
ConfigureUser ConfigureUser
} }

View file

@ -1,3 +1,4 @@
enum OneShotTask { enum OneShotTask {
InitializeMSAccount
DisableUAC DisableUAC
} }

View file

@ -1,705 +0,0 @@
#!/bin/pwsh
using namespace System.Management.Automation.Host;
using namespace System.Security.Principal;
. "$PSScriptRoot/../../../scripts/Windows/Scripts/Prerequisites.ps1";
. "$PSScriptRoot/../../Common/Scripts/Context.ps1";
. "$PSScriptRoot/../Scripts/Security.ps1";
. "$PSScriptRoot/../Software/Firefox/Install.ps1";
. "$PSScriptRoot/Manage.ps1";
. "$PSScriptRoot/User/Install.ps1";
$null = New-Module {
. "$PSScriptRoot/../Scripts/Hooks.ps1";
. "$PSScriptRoot/../Scripts/PowerManagement.ps1";
. "$PSScriptRoot/../Scripts/Registry.ps1";
. "$PSScriptRoot/../Scripts/Security.ps1";
. "$PSScriptRoot/../Scripts/Update.ps1";
. "$PSScriptRoot/../Scripts/Users.ps1";
. "$PSScriptRoot/../../Common/Scripts/Config.ps1";
. "$PSScriptRoot/../../Common/Scripts/Operations.ps1";
. "$PSScriptRoot/../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../Common/Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../Common/Types/InstallerAction.ps1";
<#
.SYNOPSIS
Finishes the installation of a running Windows machine.
#>
function Start-WindowsInstallation {
Start-Operation {
Start-InstallationLoop;
};
}
<#
.SYNOPSIS
Starts the installation loop.
#>
function Start-InstallationLoop {
$wslLocation = "$env:ProgramData\PortValhalla\Ubuntu";
while (-not (Get-IsFinished)) {
switch (Get-Stage) {
($null) {
Set-Stage ([SetupStage]::Initialize);
break;
}
([SetupStage]::Initialize) {
if (-not ((Test-Command "choco") -and (Test-Command "refreshenv"))) {
Invoke-Hook "Install-Chocolatey" -Fallback {
# Install chocolatey
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;
Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'));
Import-Module $env:ChocolateyInstall/helpers/chocolateyProfile.psm1;
refreshenv;
};
continue;
}
if (-not (Test-Command "gsudo")) {
Install-ChocoPackage gsudo;
refreshenv;
continue;
}
if (-not (Test-Command "git")) {
Install-ChocoPackage git;
refreshenv;
continue;
}
if (-not (Test-ChocoPackage "powershell-core")) {
Invoke-Hook "Install-PowerShellCore" -Fallback {
choco install -y powershell-core --install-arguments='"ADD_FILE_CONTEXT_MENU_RUNPOWERSHELL=1 ADD_EXPLORER_CONTEXT_MENU_OPENPOWERSHELL=1 REGISTER_MANIFEST=1 USER_MU=1 ENABLE_MU=1"';
};
if ($env:DEBUG) {
if (
(Test-Qemu) -and
($Host.UI.PromptForChoice(
"Confirm",
"Do you wish to swap to live scripts?",
[ChoiceDescription[]]@(
[ChoiceDescription]::new("&No", "Use scripts stored in the virtual machine"),
[ChoiceDescription]::new("&Yes", "Use live scripts stored on the host")),
0) -eq 1)) {
Install-ChocoPackage winfsp qemu-guest-agent;
Get-Service VirtioFsSvc | Start-Service -PassThru | Set-Service -StartupType Automatic;
while (-not (Test-Path Z:\)) {
Start-Sleep 0.1;
}
foreach ($name in @("CONFIG_MODULE", "INSTALLER_SCRIPT")) {
$variable = Get-Item "Env:\$name";
$path = Join-Path `
"Z:\Repositories\PortValhalla" `
([System.IO.Path]::GetRelativePath("$PSScriptRoot/../../..", $variable.Value));
Set-Item "Env:\$name" $path;
Write-Host "The new value of ``$name`` is ``$path``";
}
}
}
Restart-Intermediate;
return;
}
if ($env:PWSH_PATH -and (Test-Path $env:PWSH_PATH)) {
attrib "-R" "$env:PWSH_PATH\*" /S /D;
Remove-Item -Recurse -Force $env:PWSH_PATH;
continue;
}
if (-not (Test-Winget)) {
. "$PSScriptRoot/../Software/winget/Manage.ps1";
continue;
}
if (-not (& { $null = wsl --status; $?; })) {
wsl --install --no-launch;
Restart-Intermediate;
return;
}
if (-not (& { $null = wsl -l; $?; })) {
$wslRoot = Split-Path -Parent $wslLocation;
if (-not (Test-Path $wslRoot)) {
$null = New-Item -ItemType Directory $wslRoot;
}
Copy-Item -Recurse (Get-AppxPackage "*Ubuntu*").InstallLocation $wslLocation;
Set-UserPermissions $wslLocation;
& "$wslLocation\ubuntu.exe" install --root;
continue;
}
if (-not (wsl --shell-type login type -t nix)) {
wsl -- sh `<`(curl -L https://nixos.org/nix/install`) --daemon --yes;
wsl --shutdown;
continue;
}
if (-not (Test-PSPackage Selenium.WebDriver)) {
Write-Host "Installing browser automation tools…";
Install-Module -AcceptLicense -Force NuGet;
Import-Module NuGet;
$null = Install-Package -Force Selenium.WebDriver -RequiredVersion 4.10.0 -SkipDependencies;
continue;
}
Install-ChocoPackage selenium-gecko-driver firefox;
Invoke-Hook "Install-PSModules" -Fallback {
Install-Module -Scope AllUsers -AcceptLicense -Force PSWindowsUpdate;
Install-Module -Scope AllUsers -AcceptLicense -Force PSScriptAnalyzer;
. "$PSScriptRoot/../Software/PinnedItem/Manage.ps1";
};
Install-WingetPackage AutoHotkey.AutoHotkey;
Set-Stage ([SetupStage]::Configure);
break;
}
([SetupStage]::OneShot) {
Write-Host "Running a OneShot task";
Start-OneShot {
Write-Host "task is-a running!";
switch (Get-OneShotTask) {
([OneShotTask]::DisableUAC) {
Disable-UAC;
Register-Setup;
}
}
};
break;
}
default {
if (-not (& { $null = wsl -l; $? })) {
wsl --import-in-place "PortValhalla" "$wslLocation/ext4.vhdx";
wsl --set-default "PortValhalla";
}
if (Test-Admin) {
$null = Import-Module PSWindowsUpdate;
Invoke-Hook "Invoke-WindowsUpdate" -Fallback {
Update-WindowsInstallation;
};
if ((Get-WURebootStatus -Silent)) {
Restart-Intermediate;
return;
}
}
<#
.SYNOPSIS
Deploys an action for each software.
.PARAMETER Action
The action to execute by default.
#>
function Deploy-SoftwareAction {
param(
[Nullable[InstallerAction]] $Action = $null
)
[bool] $install = $null;
$arguments = [hashtable]@{ };
if ($null -ne $Action) {
$install = ($Action -eq ([InstallerAction]::Install));
$null = $arguments.Add("action", $Action);
} else {
$install = $true;
}
# Drivers
& {
$driverPath = "$PSScriptRoot/../Drivers";
$mbPath = "$driverPath/ROG Zenith Extreme Alpha";
if ($install) {
if (Get-Config "valhalla.hardware.elgatoWave") {
if (-not (Test-ChocoPackage wavelink)) {
Install-ChocoPackage wavelink -ArgumentList '--install-arguments="/norestart"';
Remove-DesktopIcon "*Wave Link*";
Restart-Intermediate;
exit;
}
}
}
foreach ($component in (Get-Config "valhalla.hardware.components")) {
switch ($component) {
("ROG Zenith Extreme Alpha") {
& "$mbPath/MarvellEthernet/Manage.ps1" @arguments;
& "$mbPath/IntelWiFi/Manage.ps1" @arguments;
& "$mbPath/IntelBluetooth/Manage.ps1" @arguments;
& "$mbPath/AMDChipsetX399/Manage.ps1" @arguments;
& "$driverPath/AMDChipsetX399/Manage.ps1" @arguments;
}
("Predator Z301C") {
& "$driverPath/Predator Z301C/Manage.ps1" @arguments;
}
}
}
if ($install) {
if (Get-Config "valhalla.hardware.amdCPU") {
Install-ChocoPackage amd-ryzen-master;
# ToDo: backup Ryzen energy saving plan
}
if (Get-Config "valhalla.hardware.nvidiaGPU") {
Install-ChocoPackage geforce-game-ready-driver;
Remove-DesktopIcon "*Geforce*";
}
if (Get-Config "valhalla.hardware.corsairDevice") {
Install-ChocoPackage icue;
}
}
if (Get-Config "valhalla.hardware.eyeX") {
& "$driverPath/Tobii EyeX/Manage.ps1" @arguments;
}
};
& {
# Windows Config
$softwarePath = "$PSScriptRoot/../Software";
$commonSoftware = "$PSScriptRoot/../../Common/Software";
& "$softwarePath/Windows/Manage.ps1" @arguments;
if (Get-Config "valhalla.hardware.logitechG") {
& "$softwarePath/LGHub/Manage.ps1" @arguments;
}
if (Test-Collection "essential") {
# Essentials
& "$softwarePath/OpenSSH/Manage.ps1" @arguments;
& "$softwarePath/PowerShell/Manage.ps1" @arguments;
& "$softwarePath/chocolatey/Manage.ps1" @arguments;
& "$softwarePath/zoxide/Manage.ps1" @arguments;
& "$commonSoftware/posh-git/Manage.ps1" @arguments;
& "$commonSoftware/Terminal-Icons/Manage.ps1" @arguments;
& "$softwarePath/Oh My Posh/Manage.ps1" @arguments;
if ($install) {
Install-ChocoPackage `
procexp `
procmon `
;
Install-WingetPackage `
KDE.KDEConnect `
;
}
}
if (Test-Collection "common") {
# Common Software
& "$softwarePath/WinSCP/Manage.ps1" @arguments;
& "$softwarePath/Thunderbird/Manage.ps1" @arguments;
& "$softwarePath/PuTTY/Manage.ps1" @arguments;
if ($install) {
Install-ChocoPackage `
7zip `
chocolateygui `
DefaultProgramsEditor `
bitwarden `
keepass `
;
Install-WingetPackage `
SomePythonThings.WingetUIStore `
;
}
}
if (Test-Collection "desktopExperience") {
if ($install) {
# Fonts
Install-ChocoPackage nerd-fonts-CascadiaCode;
# Internet Access
Install-WingetPackage Brave.Brave kamranahmedse.pennywise;
Remove-DesktopIcon "*Brave*";
Remove-TaskbarItem "*Brave*";
Remove-DesktopIcon "Pennywise*";
# Tools
Install-SetupPackage -Source "https://github.com/mRemoteNG/mRemoteNG/releases/download/2023.03.03-v1.77.3-nb/mRemoteNG-Installer-1.77.3.nb-1784.msi" -ArgumentList "/Quiet";
Remove-DesktopIcon "mRemoteNG*";
Install-ChocoPackage `
gimp `
gpu-z `
windirstat `
winmerge `
handbrake `
hwmonitor `
qbittorrent `
imgburn `
inkscape `
krita `
MetaX `
obs-studio `
;
Remove-DesktopIcon "GPU-Z*";
Remove-DesktopIcon "WinDirStat*";
Remove-DesktopIcon "*HWMonitor*";
Remove-DesktopIcon "ImgBurn*";
Remove-DesktopIcon "InkScape*";
Remove-DesktopIcon "Krita*";
Remove-DesktopIcon "MetaX*";
Remove-DesktopIcon "OBS Studio*";
Install-WingetPackage `
AntSoftware.AntRenamer `
AppWork.JDownloader;
Remove-DesktopIcon "JDownloader*";
}
# ToDo: Consider hiding behind own config?
& "$softwarePath/Ubiquiti UniFi Controller/Manage.ps1" @arguments;
# Internet Access
& "$softwarePath/Firefox/Manage.ps1" @arguments;
& "$softwarePath/MSEdgeRedirect/Manage.ps1" @arguments;
if (Test-Collection "fileSync") {
& "$softwarePath/Nextcloud/Manage.ps1" @arguments;
}
}
if (Test-Collection "socialMedia") {
if ($install) {
Install-ChocoPackage `
signal `
threema-desktop `
element-desktop `
teamspeak `
;
Remove-DesktopIcon "*Element*";
Remove-DesktopIcon "*TeamSpeak*";
Install-WingetPackage Discord.Discord;
Remove-DesktopIcon "*Discord*";
}
}
if (Test-Collection "media") {
if ($install) {
Install-ChocoPackage `
k-litecodecpackmega `
vlc `
;
Remove-DesktopIcon "VLC*";
Install-ChocoPackage jellyfin-media-player -ArgumentList "--install-args","/norestart"
Install-WingetPackage Ytmdesktop.Ytmdesktop;
Remove-DesktopIcon "Youtube Music*";
}
}
if (Test-Collection "coding") {
if ($install) {
Install-ChocoPackage vscode -ArgumentList "--params","/NoDesktopIcon";
Install-ChocoPackage vscodium -ArgumentList "--params","/NoDesktopIcon /AssociateWithFiles";
Install-ChocoPackage `
gh `
github-desktop `
ida-free `
HxD `
docker-desktop `
imhex `
dotpeek `
;
Remove-DesktopIcon "IDA *";
Remove-DesktopIcon "GitHub*";
Remove-DesktopIcon "Docker*";
}
& "$softwarePath/VisualStudio/Manage.ps1" @arguments;
# Node.js
& "$softwarePath/NVS/Manage.ps1" @arguments;
}
if (Test-Collection "gaming") {
# Gaming
if ($install) {
Install-ChocoPackage `
goggalaxy `
epicgameslauncher `
rayman-controlpanel `
ppsspp `
;
Remove-DesktopIcon "*Epic Games*";
Remove-DesktopIcon "*PPSSPP *-Bit*";
Install-ChocoPackage `
steam `
ubisoft-connect `
-ArgumentList "--ignore-checksums" `
;
Remove-DesktopIcon "*Steam*";
Remove-DesktopIcon "*Ubisoft Connect*";
Install-WingetPackage ElectronicArts.EADesktop;
Remove-DesktopIcon "EA.*";
}
& "$softwarePath/TrackMania Nations Forever/Manage.ps1" @arguments;
& "$softwarePath/TrackMania United Forever/Manage.ps1" @arguments;
& "$softwarePath/ManiaPlanet/Manage.ps1" @arguments;
& "$softwarePath/osu!/Manage.ps1" @arguments;
& "$softwarePath/osu!lazer/Manage.ps1" @arguments;
& "$softwarePath/RetroArch/Manage.ps1" @arguments;
& "$softwarePath/reWASD/Manage.ps1" @arguments;
}
};
}
switch (Get-Stage) {
([SetupStage]::Configure) {
if (Get-Config "valhalla.windows.dualboot.enable") {
# Fix synchronization between Linux and Windows clocks.
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\TimeZoneInformation" -Name "RealTimeIsUniversal" -Value 1 -Type "DWord";
# Force time resynchronization
$timeZoneOption = "Start";
$timeZoneKey = "HKLM:\SYSTEM\CurrentControlSet\Services\tzautoupdate";
$service = Get-Service W32Time;
$autoUpdate = (Get-Item $timeZoneKey).GetValue($timeZoneOption);
$stopped = ($service.Status -eq "Stopped");
$setUpdate = { param([int] $Value) Set-ItemProperty $timeZoneKey -Name $timeZoneOption $Value };
& $setUpdate 3;
Start-Service $service;
w32tm /resync /force;
& $setUpdate $autoUpdate;
if ($stopped) {
Stop-Service $service;
}
}
Set-Stage ([SetupStage]::Install);
}
([SetupStage]::Install) {
Write-Host "Entering install phase";
Deploy-SoftwareAction;
Set-Stage ([SetupStage]::CreateUser);
}
([SetupStage]::CreateUser) {
Start-ValhallaUserSetup;
Set-Stage ([SetupStage]::ConfigureUser);
}
([SetupStage]::ConfigureUser) {
$userOption = "CurrentUser";
function Get-CurrentUser {
(Get-SetupOption $userOption) ?? 0;
}
function Set-CurrentUser {
param([int] $Value)
Set-SetupOption $userOption $Value;
}
[string[]] $users = Get-Users;
$currentUser = Get-CurrentUser;
if (Test-Admin) {
Disable-BootMessage;
}
if ($currentUser -lt $users.Count) {
$user = Get-LocalUser $users[$currentUser];
$msAccount = Get-UserConfig -UserName "$user" -Name "microsoftAccount";
$adminGroup = @{
SID = [SecurityIdentifier]::new([WellKnownSidType]::BuiltinAdministratorsSid, $null);
};
Add-LocalGroupMember `
@adminGroup `
$user `
-ErrorAction SilentlyContinue;
if ($env:UserName -ne "$user") {
Disable-LocalUser $env:UserName;
Enable-LocalUser $user;
if ($msAccount) {
Enable-UAC;
Disable-Autologin;
Enable-OneShotListener;
Set-BootMessage -Caption "Please Log In" -Message "Please log in using your new Microsoft Account ``$user``.";
} else {
Set-AutologinUser "$user";
}
Restart-Intermediate -DefaultUser;
return;
} else {
$configure = {
Deploy-SoftwareAction -Action ([InstallerAction]::ConfigureUser);
Remove-LocalGroupMember -Member "$user" @adminGroup -ErrorAction SilentlyContinue;
foreach ($group in Get-UserConfig "groups") {
Add-LocalGroupMember -Member "$user" -Name "$group";
}
}
if ($msAccount) {
if (-not (Test-Admin)) {
Invoke-OneShot DisableUAC;
Restart-Computer;
return;
} else {
& $configure;
Clear-SetupRegistration;
Disable-OneShotListener;
}
} else {
& $configure;
}
}
Set-CurrentUser ($currentUser + 1);
continue;
}
Set-IsFinished $true;
}
}
}
}
}
}
function Invoke-WindowsInstallation([Context] $context) {
$Global:InformationPreference = "Continue";
$Global:ErrorActionPreference = "Inquire";
$context.UserNames ??= @("Manuel");
Start-OldWindowsInstallationScript $context;
}
function Start-OldWindowsInstallationScript([Context] $context) {
. "$PSScriptRoot/Upgrade.ps1";
$finished = $false;
Remove-Item Env:\POSH_THEME -ErrorAction SilentlyContinue;
$configPath = "$PSScriptRoot/../Config";
$softwarePath = "$PSScriptRoot/../Software";
$initialConfigStage = "InitialConfiguration";
$prerequisitesStage = "InstallationPrerequisites";
$driverStage = "DriverInstallation";
$softwareStage = "MachineWideSoftwareInstallation";
$userStage = "CreatingUser";
$restorationStage = "Restoring";
while (-not $finished) {
switch ($context.GetStage()) {
{ (-not $_) -or ($_ -eq $initialConfigStage) } {
$context.SetStage($initialConfigStage);
if ((Get-Command Initialize-Configuration -ErrorAction SilentlyContinue)) {
Write-Information "Configuration initialization function was found. Running...";
Initialize-Configuration $context;
}
$null = Enable-WindowsOptionalFeature -Online -All -FeatureName "NetFx3";
. "$configPath/Windows/Install.ps1" $context;
. "$configPath/Explorer/Install.ps1" $context;
. "$configPath/OpenSSH/Install.ps1" $context;
. "$configPath/chocolatey/Install.ps1";
$context.RemoveDesktopIcon("*Microsoft Edge*");
$context.SetStage($prerequisitesStage);
break;
}
# Always install updates
default {
Write-Host "Starting Installation and Restoration of Windows";
Update-WindowsInstallation $context;
}
$prerequisitesStage {
Write-Host "Installing prerequisites for installing software";
if (-not $(Get-Command winget)) {
choco install -y winget;
}
Install-Module -AcceptLicense -Force "NuGet";
Import-Module NuGet;
Install-Firefox $context;
choco install -y selenium-gecko-driver;
$null = Install-Package -Force Selenium.WebDriver -RequiredVersion 4.10.0 -SkipDependencies;
winget install --accept-source-agreements --accept-package-agreements -e --id AutoHotkey.AutoHotkey;
$context.SetStage($driverStage);
break;
}
$driverStage {
Write-Host "Installing drivers";
if ((Get-Command Install-PortValhallaDrivers -ErrorAction SilentlyContinue)) {
Write-Information "Driver installation function was found. Starting installation";
Install-PortValhallaDrivers $context;
}
Write-Information "Finished installing drivers";
$context.SetStage($softwareStage);
$context.Reboot();
exit;
}
$softwareStage {
Write-Host "Setting up software with default app associations";
. "$softwarePath/WinSCP/Install.ps1" $context;
. "$softwarePath/Thunderbird/Install.ps1" $context;
Write-Host "Installing default settings for new users";
. "$softwarePath/aliae/Install.ps1" $context;
. "$softwarePath/posh-git/Install.ps1";
. "$softwarePath/Terminal-Icons/Install.ps1";
. "$softwarePath/Oh My Posh/Install.ps1" $context;
$context.SetStage($userStage);
break;
}
$userStage {
Install-PersonalUsers $context;
$context.SetStage($restorationStage);
break;
}
$restorationStage {
Restore-WindowsInstallation $context;
$finished = $true;
break;
}
}
}
}
};

View file

@ -0,0 +1,63 @@
#!/bin/pwsh
. "$PSScriptRoot/../Scripts/PersonalFiles.ps1";
. "$PSScriptRoot/../Software/Firefox/Install.ps1";
. "$PSScriptRoot/../Software/Nextcloud/Install.ps1";
. "$PSScriptRoot/../Collections/Personal.ps1";
. "$PSScriptRoot/../../Common/Scripts/Context.ps1";
function Backup-WindowsInstallation([Context] $context) {
Write-Information "Backing up Windows";
$Global:InformationPreference = "Continue";
$Global:ErrorActionPreference = "Inquire";
. "$PSScriptRoot/../../../scripts/Windows/Scripts/Prerequisites.ps1";
$backupRoot = $context.BackupRoot();
Backup-PersonalFiles $context;
Backup-PersonalApps $context;
$context.Backup($backupRoot, "$backupRoot.7z", @("-sdel"), $false);
$context.Cleanup();
Write-Host "Never forget to store the backup somewhere safe!";
Write-Host "I mean... what kind of a dumbass would ever forget to do so, right?";
}
function Restore-WindowsInstallation([Context] $context) {
Write-Host "Restoring Windows";
choco feature enable -n useEnhancedExitCodes;
function Read-Path()
{
$backupPath = Read-Host -Prompt "Please enter the path to the archive to load the backup from.";
if ($backupPath -and (-not (Test-Path -PathType Leaf $backupPath)))
{
Write-Host "No file could be found at the specified path.";
return Read-Path;
}
else
{
return $backupPath;
}
}
Install-Firefox $context;
Restore-Nextcloud $context;
Write-Information "Determining Backup Archive Path";
$backupPath = Read-Path;
$context.BackupName ??= "PortValhalla";
$context.RootDir = $context.GetTempDirectory();
if ($backupPath)
{
$context.Restore($backupPath, $context.BackupRoot());
}
Copy-UserInternationalSettingsToSystem -WelcomeScreen $True -NewUser $False;
Restore-PersonalFiles $context;
if ((Get-Command Restore-Apps -ErrorAction SilentlyContinue)) {
Restore-Apps $context;
}
Remove-Item -Recurse $context.RootDir;
$context.Cleanup();
}

View file

@ -1,63 +1,248 @@
#!/bin/pwsh #!/bin/pwsh
. "$PSScriptRoot/../Scripts/PersonalFiles.ps1"; using namespace System.Security.Principal;
. "$PSScriptRoot/../Software/Firefox/Install.ps1";
. "$PSScriptRoot/../Software/Nextcloud/Install.ps1"; . "$PSScriptRoot/../../../scripts/Windows/Scripts/Prerequisites.ps1";
. "$PSScriptRoot/../Collections/Personal.ps1"; . "$PSScriptRoot/../../../scripts/Windows/Scripts/WSL.ps1";
. "$PSScriptRoot/../../Common/Scripts/Context.ps1"; . "$PSScriptRoot/../../Common/Scripts/Context.ps1";
. "$PSScriptRoot/../Scripts/Security.ps1";
. "$PSScriptRoot/../Software/Firefox/Install.ps1";
. "$PSScriptRoot/Legacy.ps1";
. "$PSScriptRoot/User/Install.ps1";
function Backup-WindowsInstallation([Context] $context) { $null = New-Module {
Write-Information "Backing up Windows"; . "$PSScriptRoot/../Scripts/Deployment.ps1";
$Global:InformationPreference = "Continue"; . "$PSScriptRoot/../Scripts/Hooks.ps1";
$Global:ErrorActionPreference = "Inquire"; . "$PSScriptRoot/../Scripts/PowerManagement.ps1";
. "$PSScriptRoot/../../../scripts/Windows/Scripts/Prerequisites.ps1"; . "$PSScriptRoot/../Scripts/Registry.ps1";
$backupRoot = $context.BackupRoot(); . "$PSScriptRoot/../Scripts/Security.ps1";
Backup-PersonalFiles $context; . "$PSScriptRoot/../Scripts/Update.ps1";
Backup-PersonalApps $context; . "$PSScriptRoot/../Scripts/Users.ps1";
$context.Backup($backupRoot, "$backupRoot.7z", @("-sdel"), $false); . "$PSScriptRoot/../Types/WindowsInstallerAction.ps1";
$context.Cleanup(); . "$PSScriptRoot/../../Common/Scripts/Config.ps1";
Write-Host "Never forget to store the backup somewhere safe!"; . "$PSScriptRoot/../../Common/Scripts/Operations.ps1";
Write-Host "I mean... what kind of a dumbass would ever forget to do so, right?"; . "$PSScriptRoot/../../Common/Scripts/Software.ps1";
} . "$PSScriptRoot/../../Common/Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../Common/Types/InstallerAction.ps1";
function Restore-WindowsInstallation([Context] $context) { <#
Write-Host "Restoring Windows"; .SYNOPSIS
choco feature enable -n useEnhancedExitCodes; Finishes the installation of a running Windows machine.
#>
function Start-WindowsInstallation {
Start-Operation -NoImplicitCleanup {
Start-InstallationLoop ([WindowsInstallerAction]::Install);
};
}
function Read-Path() <#
{ .SYNOPSIS
$backupPath = Read-Host -Prompt "Please enter the path to the archive to load the backup from."; Starts the installation loop.
#>
function Start-InstallationLoop {
param(
[WindowsInstallerAction] $Action
)
if ($backupPath -and (-not (Test-Path -PathType Leaf $backupPath))) while ((Get-Stage) -ne ([WindowsInstallerStage]::Completed)) {
{ switch (Get-Stage) {
Write-Host "No file could be found at the specified path."; ($null) {
return Read-Path; Set-Stage ([WindowsInstallerStage]::Initialize);
} break;
else }
{ ([WindowsInstallerStage]::Initialize) {
return $backupPath; $env:BACKUP_ARCHIVE = pwsh -Command Write-Host (
Read-Host (
& {
switch ($Action) {
([WindowsInstallerAction]::Backup) {
"Please select the path you wish to store your backup at"
}
([WindowsInstallerAction]::Install) {
"Please select the backup archive you wish to restore from"
}
}
}));
Set-Stage ([WindowsInstallerStage]::Run);
break;
}
([WindowsInstallerStage]::Run) {
switch ($Action) {
([WindowsInstallerAction]::Install) {
while (-not (Get-IsFinished)) {
switch (Get-SetupStage) {
($null) {
Set-SetupStage ([SetupStage]::Configure);
break;
}
default {
if (Test-Admin) {
$null = Import-Module PSWindowsUpdate;
Invoke-Hook "Invoke-WindowsUpdate" -Fallback {
Update-WindowsInstallation;
};
if ((Get-WURebootStatus -Silent)) {
Restart-Intermediate;
return;
}
}
switch ($_) {
([SetupStage]::Configure) {
if (Get-Config "valhalla.windows.dualboot.enable") {
if (-not (Test-Qemu)) {
# Fix synchronization between Linux and Windows clocks.
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\TimeZoneInformation" -Name "RealTimeIsUniversal" -Value 1 -Type "DWord";
}
# Force time resynchronization
$timeZoneOption = "Start";
$timeZoneKey = "HKLM:\SYSTEM\CurrentControlSet\Services\tzautoupdate";
$service = Get-Service W32Time;
$autoUpdate = (Get-Item $timeZoneKey).GetValue($timeZoneOption);
$stopped = ($service.Status -eq "Stopped");
$setUpdate = { param([int] $Value) Set-ItemProperty $timeZoneKey -Name $timeZoneOption $Value };
& $setUpdate 3;
Start-Service $service;
w32tm /resync /force;
& $setUpdate $autoUpdate;
if ($stopped) {
Stop-Service $service;
}
}
Set-SetupStage ([SetupStage]::Install);
}
([SetupStage]::Install) {
Write-Host "Entering install phase";
Deploy-SoftwareAction;
Set-SetupStage ([SetupStage]::CreateUser);
}
([SetupStage]::CreateUser) {
Install-ValhallaUsers;
Set-IsFinished $true;
}
}
}
}
}
}
}
Set-Stage ([WindowsInstallerStage]::Completed);
break;
}
}
} }
} }
Install-Firefox $context; function Invoke-WindowsInstallation([Context] $context) {
Restore-Nextcloud $context; $Global:InformationPreference = "Continue";
$Global:ErrorActionPreference = "Inquire";
Write-Information "Determining Backup Archive Path"; $context.UserNames ??= @("Manuel");
$backupPath = Read-Path; Start-OldWindowsInstallationScript $context;
$context.BackupName ??= "PortValhalla";
$context.RootDir = $context.GetTempDirectory();
if ($backupPath)
{
$context.Restore($backupPath, $context.BackupRoot());
} }
Copy-UserInternationalSettingsToSystem -WelcomeScreen $True -NewUser $False; function Start-OldWindowsInstallationScript([Context] $context) {
Restore-PersonalFiles $context; . "$PSScriptRoot/Upgrade.ps1";
$finished = $false;
Remove-Item Env:\POSH_THEME -ErrorAction SilentlyContinue;
$configPath = "$PSScriptRoot/../Config";
$softwarePath = "$PSScriptRoot/../Software";
$initialConfigStage = "InitialConfiguration";
$prerequisitesStage = "InstallationPrerequisites";
$driverStage = "DriverInstallation";
$softwareStage = "MachineWideSoftwareInstallation";
$userStage = "CreatingUser";
$restorationStage = "Restoring";
if ((Get-Command Restore-Apps -ErrorAction SilentlyContinue)) {
Restore-Apps $context; while (-not $finished) {
switch ($context.GetStage()) {
{ (-not $_) -or ($_ -eq $initialConfigStage) } {
$context.SetStage($initialConfigStage);
if ((Get-Command Initialize-Configuration -ErrorAction SilentlyContinue)) {
Write-Information "Configuration initialization function was found. Running...";
Initialize-Configuration $context;
}
$null = Enable-WindowsOptionalFeature -Online -All -FeatureName "NetFx3";
. "$configPath/Windows/Install.ps1" $context;
. "$configPath/Explorer/Install.ps1" $context;
. "$configPath/OpenSSH/Install.ps1" $context;
. "$configPath/chocolatey/Install.ps1";
$context.RemoveDesktopIcon("*Microsoft Edge*");
$context.SetStage($prerequisitesStage);
break;
}
# Always install updates
default {
Write-Host "Starting Installation and Restoration of Windows";
Update-WindowsInstallation $context;
}
$prerequisitesStage {
Write-Host "Installing prerequisites for installing software";
if (-not $(Get-Command winget)) {
choco install -y winget;
}
Install-Module -AcceptLicense -Force "NuGet";
Import-Module NuGet;
Install-Firefox $context;
choco install -y selenium-gecko-driver;
$null = Install-Package -Force Selenium.WebDriver -RequiredVersion 4.10.0 -SkipDependencies;
winget install --accept-source-agreements --accept-package-agreements -e --id AutoHotkey.AutoHotkey;
$context.SetStage($driverStage);
break;
}
$driverStage {
Write-Host "Installing drivers";
if ((Get-Command Install-PortValhallaDrivers -ErrorAction SilentlyContinue)) {
Write-Information "Driver installation function was found. Starting installation";
Install-PortValhallaDrivers $context;
}
Write-Information "Finished installing drivers";
$context.SetStage($softwareStage);
$context.Reboot();
exit;
}
$softwareStage {
Write-Host "Setting up software with default app associations";
. "$softwarePath/WinSCP/Install.ps1" $context;
. "$softwarePath/Thunderbird/Install.ps1" $context;
Write-Host "Installing default settings for new users";
. "$softwarePath/aliae/Install.ps1" $context;
. "$softwarePath/posh-git/Install.ps1";
. "$softwarePath/Terminal-Icons/Install.ps1";
. "$softwarePath/Oh My Posh/Install.ps1" $context;
$context.SetStage($userStage);
break;
}
$userStage {
Install-PersonalUsers $context;
$context.SetStage($restorationStage);
break;
}
$restorationStage {
Restore-WindowsInstallation $context;
$finished = $true;
break;
}
}
}
} }
};
Remove-Item -Recurse $context.RootDir;
$context.Cleanup();
}

View file

@ -224,7 +224,7 @@ function Start-Setup {
foreach ($xpath in @("./ua:AutoLogon/ua:Username", foreach ($xpath in @("./ua:AutoLogon/ua:Username",
"./ua:UserAccounts/ua:LocalAccounts/ua:LocalAccount/ua:Name", "./ua:UserAccounts/ua:LocalAccounts/ua:LocalAccount/ua:Name",
"./ua:UserAccounts/ua:LocalAccounts/ua:LocalAccount/ua:DisplayName")) { "./ua:UserAccounts/ua:LocalAccounts/ua:LocalAccount/ua:DisplayName")) {
$oobeSettings.SelectSingleNode($xpath, $namespace).InnerText = $valhallaConfig.setupUser; $oobeSettings.SelectSingleNode($xpath, $namespace).InnerText = $valhallaConfig.setupUser.name;
} }
Add-StartupCommand ` Add-StartupCommand `

View file

@ -206,12 +206,6 @@
</SynchronousCommand> --> </SynchronousCommand> -->
<SynchronousCommand wcm:action="add"> <SynchronousCommand wcm:action="add">
<Order>1</Order> <Order>1</Order>
<RequiresUserInput>true</RequiresUserInput>
<CommandLine>cmd /C wmic useraccount where name="Admin" set PasswordExpires=false</CommandLine>
<Description>Password Never Expires</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>2</Order>
<RequiresUserInput>false</RequiresUserInput> <RequiresUserInput>false</RequiresUserInput>
<CommandLine>powershell -Command "Set-ExecutionPolicy -Force Bypass"</CommandLine> <CommandLine>powershell -Command "Set-ExecutionPolicy -Force Bypass"</CommandLine>
<Description>Allow PowerShell scripts from anywhere.</Description> <Description>Allow PowerShell scripts from anywhere.</Description>

View file

@ -0,0 +1,293 @@
. "$PSScriptRoot/../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../Common/Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../Common/Types/InstallerAction.ps1";
<#
.SYNOPSIS
Deploys an action for each software selected for installation.
.PARAMETER
The action to execute.
#>
function Deploy-SoftwareAction {
param(
[System.Nullable[InstallerAction]] $Action = $null
)
[bool] $install = $false;
$arguments = [hashtable]@{ };
if ($null -ne $Action) {
$install = ($Action -eq ([InstallerAction]::Install));
$null = $arguments.Add("action", $Action);
} else {
$install = $true;
}
# Drivers
& {
$driverPath = "$PSScriptRoot/../Drivers";
$mbPath = "$driverPath/ROG Zenith Extreme Alpha";
if ($install) {
if (Get-Config "valhalla.hardware.elgatoWave") {
if (-not (Test-ChocoPackage wavelink)) {
Install-ChocoPackage wavelink -ArgumentList '--install-arguments="/norestart"';
Remove-DesktopIcon "*Wave Link*";
Restart-Intermediate;
exit;
}
}
}
foreach ($component in (Get-Config "valhalla.hardware.components")) {
switcH ($component) {
("ROG Zenith Extreme Alpha") {
& "$mbPath/MarvellEthernet/Manage.ps1" @arguments;
& "$mbPath/IntelWiFi/Manage.ps1" @arguments;
& "$mbPath/IntelBluetooth/Manage.ps1" @arguments;
& "$mbPath/AMDChipsetX399/Manage.ps1" @arguments;
& "$driverPath/AMDChipsetX399/Manage.ps1" @arguments;
}
("Predator Z301C") {
& "$driverPath/Predator Z301C/Manage.ps1" @arguments;
}
}
}
if ($install) {
if (Get-Config "valhalla.hardware.amdCPU") {
Install-ChocoPackage amd-ryzen-master;
# ToDo: backup Ryzen energy saving plan
}
if (Get-Config "valhalla.hardware.nvidiaGPU") {
Install-ChocoPackage geforce-game-ready-driver;
Remove-DesktopIcon "*Geforce*";
}
if (Get-Config "valhalla.hardware.corsairDevice") {
Install-ChocoPackage icue;
}
}
if (Get-Config "valhalla.hardware.eyeX") {
& "$driverPath/Tobii EyeX/Manage.ps1" @arguments;
}
};
& {
$softwarePath = "$PSScriptRoot/../Software";
$commonSoftware = "$PSScriptRoot/../../Common/Software";
# Windows Config
& "$softwarePath/Windows/Manage.ps1" @arguments;
if (Get-Config "valhalla.hardware.logitechG") {
& "$softwarePath/LGHub/Manage.ps1" @arguments;
}
# Essentials
if (Test-Collection "essential") {
& "$softwarePath/aliae/Main.ps1" @arguments;
& "$softwarePath/OpenSSH/Manage.ps1" @arguments;
& "$softwarePath/PowerShell/Manage.ps1" @arguments;
& "$softwarePath/chocolatey/Manage.ps1" @arguments;
& "$softwarePath/zoxide/Manage.ps1" @arguments;
& "$commonSoftware/posh-git/Manage.ps1" @arguments;
& "$commonSoftware/Terminal-Icon/Manage.ps1" @arguments;
& "$softwarePath/Oh My Posh/Manage.ps1" @arguments;
if (Get-Config "valhalla.windows.dualboot") {
& "$softwarePath/Ext4Fsd/Main.ps1" @arguments;
}
if ($install) {
Install-ChocoPackage `
procexp `
procmon `
;
Install-WingetPackage `
KDE.KDEConnect `
;
}
}
# Common Software
if (Test-Collection "common") {
& "$softwarePath/WinSCP/Manage.ps1" @arguments;
& "$softwarePath/Thunderbird/Manage.ps1" @arguments;
& "$softwarePath/PuTTY/Manage.ps1" @arguments;
if ($install) {
Install-ChocoPackage `
7zip `
chocolateygui `
DefaultProgramsEditor `
bitwarden `
keepass `
;
Install-WingetPackage `
SomePythonThings.WingetUIStore `
;
Remove-DesktopIcon "UniGetUI*";
}
}
if (Test-Collection "desktopExperience") {
if ($install) {
# Fonts
Install-ChocoPackage nerd-fonts-CascadiaCode;
# Internet Access
Install-WingetPackage Brave.Brave kamranahmedse.pennywise;
Remove-DesktopIcon "*Brave*";
Remove-TaskbarItem "*Brave*";
Remove-DesktopIcon "Pennywise*";
# Tools
Install-SetupPackage -Source "https://github.com/mRemoteNG/mRemoteNG/releases/download/2023.03.03-v1.77.3-nb/mRemoteNG-Installer-1.77.3.nb-1784.msi" -ArgumentList "/Quiet";
Remove-DesktopIcon "mRemoteNG*";
Install-ChocoPackage `
gimp `
gpu-z `
windirstat `
winmerge `
handbrake `
hwmonitor `
qbittorrent `
imgburn `
inkscape `
krita `
MetaX `
obs-studio `
;
Remove-DesktopIcon "GIMP*";
Remove-DesktopIcon "GPU-Z*";
Remove-DesktopIcon "WinDirStat*";
Remove-DesktopIcon "*HWMonior*";
Remove-DesktopIcon "ImgBurn*";
Remove-DesktopIcon "InkScape*";
Remove-DesktopIcon "Krita*";
Remove-DesktopIcon "MetaX*";
Remove-DesktopIcon "OBS Studio*";
Install-WingetPackage `
AntSoftware.AntRenamer `
AppWork.JDownloader `
;
Remove-DesktopIcon "JDownloader*";
}
# ToDo: Consider hiding behind own config?
& "$softwarePath/Ubiquiti UniFi Controller/Manage.ps1" @arguments;
# Internet Access
& "$softwarePath/Firefox/Manage.ps1" @arguments;
& "$softwarePath/MSEdgeRedirect/Manage.ps1" @arguments;
if (Test-Collection "fileSync") {
& "$softwarePath/Nextcloud/Main.ps1" @arguments;
}
}
if (Test-Collection "socialMedia") {
if ($install) {
Install-ChocoPackage `
signal `
threema-desktop `
element-desktop `
teamspeak `
;
Remove-DesktopIcon "*Element*";
Remove-DesktopIcon "*TeamSpeak*";
Install-WingetPackage Discord.Discord;
Remove-DesktopIcon "*Discord*";
}
}
if (Test-Collection "media") {
if ($install) {
Install-ChocoPackage `
k-litecodecpackmega `
vlc `
;
Remove-DesktopIcon "VLC*";
# When installing Jellyfin Media Player after iCUE, Jellyfin will try to reboot automatically
Install-ChocoPackage jellyfin-media-player -ArgumentList "--install-args","/norestart";
Remove-DesktopIcon "Jellyfin Media Player*";
Install-WingetPackage Ytmdesktop.Ytmdesktop;
Remove-DesktopIcon "Youtube Music*";
}
}
if (Test-Collection "coding") {
if ($install) {
& "$softwarePath/vscode/Main.ps1" @arguments;
Install-ChocoPackage `
gh `
github-desktop `
ida-free `
HxD `
docker-desktop `
imhex `
dotpeek `
;
Remove-DesktopIcon "IDA *";
Remove-DesktopIcon "GitHub*";
Remove-DesktopIcon "Docker*";
}
& "$softwarePath/VisualStudio/Manage.ps1" @arguments;
# Node.js
& "$softwarePath/NVS/Manage.ps1" @arguments;
}
# Gaming
if (Test-Collection "gaming") {
if ($install) {
Install-ChocoPackage `
goggalaxy `
epicgameslauncher `
rayman-controlpanel `
ppsspp `
;
Remove-DesktopIcon "*Epic Games*";
Remove-DesktopIcon "*PPSSPP *-Bit*";
Install-ChocoPackage `
steam `
ubisoft-connect `
-ArgumentList "--ignore-checksums" `
;
Remove-DesktopIcon "*Steam*";
Remove-DesktopIcon "*Ubisoft Connect*";
Install-WingetPackage ElectronicArts.EADesktop;
Remove-DesktopIcon "EA.*";
}
& "$softwarePath/TrackMania Nations Forever/Manage.ps1" @arguments;
& "$softwarePath/TrackMania United Forever/Manage.ps1" @arguments;
& "$softwarePath/ManiaPlanet/Manage.ps1" @arguments;
& "$softwarePath/osu!/Manage.ps1" @arguments;
& "$softwarePath/osu!lazer/Manage.ps1" @arguments;
& "$softwarePath/RetroArch/Manage.ps1" @arguments;
& "$softwarePath/reWASD/Manage.ps1" @arguments;
}
};
}

View file

@ -26,7 +26,7 @@ $null = New-Module {
[string] $path = $null; [string] $path = $null;
if ($UserKey) { if ($UserKey) {
$path = "$($UserKey.PSPath)\$runOncePath"; $path = Join-Path ($UserKey.PSPath) $runOncePath;
} else { } else {
$path = $systemRunOncePath; $path = $systemRunOncePath;
} }
@ -43,17 +43,17 @@ $null = New-Module {
Generates a script for executing the installer. Generates a script for executing the installer.
#> #>
function Get-StartupScript { function Get-StartupScript {
"pwsh " + (Get-StartupArguments); "pwsh -Command " + (Get-StartupCommand);
} }
<# <#
.SYNOPSIS .SYNOPSIS
Generates arguments for running the installer using `pwsh`. Generates a command for running the installer using `pwsh`.
#> #>
function Get-StartupArguments { function Get-StartupCommand {
"-Command " +
($env:PWSH_PATH ? "`$env:PWSH_PATH = $(ConvertTo-Injection $env:PWSH_PATH);" : "") + ($env:PWSH_PATH ? "`$env:PWSH_PATH = $(ConvertTo-Injection $env:PWSH_PATH);" : "") +
($env:DEBUG ? "`$env:DEBUG = $([int]$env:DEBUG);" : "") + ($env:DEBUG ? "`$env:DEBUG = $([int]$env:DEBUG);" : "") +
($env:BACKUP_ARCHIVE ? "`$env:BACKUP_ARCHIVE = $(ConvertTo-Injection (Resolve-Path $env:BACKUP_ARCHIVE));" : "") +
"`$env:INSTALLER_SCRIPT = $(ConvertTo-Injection (Resolve-Path $env:INSTALLER_SCRIPT));" + "`$env:INSTALLER_SCRIPT = $(ConvertTo-Injection (Resolve-Path $env:INSTALLER_SCRIPT));" +
"`$env:CONFIG_MODULE = $(ConvertTo-Injection (Resolve-Path $env:CONFIG_MODULE));" + "`$env:CONFIG_MODULE = $(ConvertTo-Injection (Resolve-Path $env:CONFIG_MODULE));" +
"& `$env:INSTALLER_SCRIPT;"; "& `$env:INSTALLER_SCRIPT;";
@ -70,6 +70,8 @@ $null = New-Module {
param( param(
[Parameter(ParameterSetName="System")] [Parameter(ParameterSetName="System")]
[switch] $System, [switch] $System,
[Parameter(ParameterSetName="DefaultUser", Mandatory)]
[switch] $DefaultUser,
[Parameter(ParameterSetName="User", Mandatory)] [Parameter(ParameterSetName="User", Mandatory)]
[switch] $User, [switch] $User,
[Parameter(ParameterSetName="User")] [Parameter(ParameterSetName="User")]
@ -77,6 +79,18 @@ $null = New-Module {
[RegistryKey] $UserKey [RegistryKey] $UserKey
) )
if ($DefaultUser.IsPresent) {
Edit-DefaultUserKey {
param(
[RegistryKey] $Key
)
Register-Setup -UserKey $Key;
}
return;
}
if ($User.IsPresent -or $UserKey) { if ($User.IsPresent -or $UserKey) {
if (-not $UserKey) { if (-not $UserKey) {
$UserKey = Get-Item "HKCU:\"; $UserKey = Get-Item "HKCU:\";
@ -153,21 +167,22 @@ $null = New-Module {
#> #>
function Restart-Intermediate { function Restart-Intermediate {
param( param(
[switch] $DefaultUser [Parameter(ParameterSetName="None")]
[switch] $NoRegister,
[Parameter(ParameterSetName="Default", Mandatory)]
[switch] $DefaultUser,
[Parameter(ParameterSetName="Current", Mandatory)]
[switch] $CurrentUser
) )
$register = { param($UserKey) Register-Setup @PSBoundParameters; }; if (-not $NoRegister.IsPresent) {
if ($DefaultUser.IsPresent) {
if ($DefaultUser) { Register-Setup -DefaultUser;
Edit-DefaultUserKey { } elseif ($CurrentUser.IsPresent) {
param( Register-Setup -User;
[RegistryKey] $Key } else {
) Register-Setup;
& $register $Key;
} }
} else {
& $register;
} }
Restart-Computer -Force; Restart-Computer -Force;

View file

@ -0,0 +1,171 @@
using namespace System.Collections.Generic;
. "$PSScriptRoot/../../Common/Scripts/System.ps1";
$null = New-Module {
$pathResolver = {
param(
[string] $User,
[string] $Path
)
[string] $result = $null;
if ($User) {
$result = "Users/$User";
} else {
$result = "System";
}
if (-not $Path) {
$Path = "Files";
}
$result = Join-Path $result $Path;
return $result;
};
<#
.SYNOPSIS
Gets the name of the variable holding the path to the backup archive of the current machine.
#>
function Get-ArchiveVariableName {
return "BACKUP_ARCHIVE";
}
<#
.SYNOPSIS
Gets the path to the backup archive of the current machine.
#>
function Get-ValhallaBackupArchive {
(Get-Item "Env:\$(Get-ArchiveVariableName)").Value;
}
<#
.SYNOPSIS
Sets the path to the backup archive of the current machine.
.PARAMETER Path
The path to set.
#>
function Set-ValhallaBackupArchive {
param(
[string] $Path
)
Set-Item "Env:\$(Get-ArchiveVariableName)" $Path;
}
<#
.SYNOPSIS
Adds files to the backup archive.
.PARAMETER User
The user to add the files to.
.PARAMETER Source
The file or directory to add to the backup archive.
.PARAMETER Path
The path to the location to store the file or directory at.
.PARAMETER ArgumentList
The arguments to pass to the `7z` command.
#>
function Add-BackupArtifacts {
param(
[string] $User,
[string] $Source,
[string] $Path,
[string[]] $Include,
[string[]] $Exclude
)
if ($env:BACKUP_ARCHIVE) {
[List[string]] $argumentList = @();
$dir = New-TemporaryDirectory;
$targetPath = & $pathResolver @PSBoundParameters;
$fullPath = Join-Path $dir $targetPath;
$null = New-Item -ItemType Directory -Force (Split-Path -Parent $fullPath);
if (Test-Path -PathType Container $Source) {
$null = New-Item -ItemType Junction $fullPath -Target $Source;
} elseif (Test-Path -PathType Leaf $Source) {
$null = New-Item -ItemType Directory -Force $fullPath;
Copy-Item $Source $fullPath;
}
$options = @(
@("i", $Include),
@("x", $Exclude)
);
foreach ($option in $options) {
$indicator = $option[0];
$list = $option[1];
foreach ($pattern in $list) {
$argumentList.Add("-$indicator!`"$(Join-Path $targetPath $pattern)`"");
}
}
Start-Process `
-NoNewWindow `
-Wait `
-WorkingDirectory $dir `
-FilePath 7z `
-ArgumentList (
@(
"a",
(Get-ValhallaBackupArchive),
"-xr!desktop.ini",
"-xr!thumbs.db",
"-xr!Thumbs.db"
) + $argumentList);
Remove-Item -Recurse -Force $dir;
}
}
<#
.SYNOPSIS
Extracts the specified backup artifacts to the specified target path.
.PARAMETER User
The user to restore the files for.
.PARAMETER Path
The path to restore the files from.
.PARAMETER Target
The path to restore the files to.
.PARAMETER ArgumentList
The arguments to pass to `7z`.
#>
function Expand-BackupArtifacts {
param(
[string] $User,
[string] $Path,
[string] $Target,
[Parameter(ValueFromRemainingArguments)]
[string[]] $ArgumentList
)
if ($env:BACKUP_ARCHIVE) {
$dir = New-TemporaryDirectory;
$sourcePath = & $pathResolver @PSBoundParameters;
$filePath = Join-Path $dir $sourcePath;
7z x "-o$dir" (Get-ValhallaBackupArchive) $sourcePath @ArgumentList;
if (Test-Path $filePath) {
if (Test-Path -PathType Container $filePath) {
$filePath = "$filePath/*";
}
Copy-Item -Recurse $filePath $Target -Force;
}
Remove-Item -Recurse -Force $dir;
}
}
};

View file

@ -55,7 +55,13 @@ $null = New-Module {
[FileSystemAccessRule]::new( [FileSystemAccessRule]::new(
[SecurityIdentifier]::new([WellKnownSidType]::BuiltinUsersSid, $null), [SecurityIdentifier]::new([WellKnownSidType]::BuiltinUsersSid, $null),
[FileSystemRights]::FullControl, [FileSystemRights]::FullControl,
[InheritanceFlags]::ObjectInherit -bor [InheritanceFlags]::ContainerInherit, (& {
if (Test-Path -PathType Container $Path) {
[InheritanceFlags]::ObjectInherit -bor [InheritanceFlags]::ContainerInherit
} else {
0
}
}),
[PropagationFlags]::InheritOnly, [PropagationFlags]::InheritOnly,
[AccessControlType]::Allow)); [AccessControlType]::Allow));

View file

@ -7,12 +7,14 @@ function Update-WindowsInstallation {
Runs the Windows update loop. Runs the Windows update loop.
#> #>
function Start-UpdateLoop { function Start-UpdateLoop {
Write-Host "Preparing for Windows Update";
$null = Import-Module PSWindowsUpdate; $null = Import-Module PSWindowsUpdate;
$hasUpdates = $false;
Write-Host "Searching for updates…";
while (((Get-WindowsUpdate -IgnoreReboot).Count -gt 0)) { while (((Get-WindowsUpdate -IgnoreReboot).Count -gt 0)) {
Write-Host "There are updates available."; Write-Host "There are updates available.";
Write-Host "Installing updates"; Write-Host "Installing updates";
$hasUpdates = $true;
try { try {
$null = Install-WindowsUpdate -AcceptAll -IgnoreReboot -ErrorAction "SilentlyContinue"; $null = Install-WindowsUpdate -AcceptAll -IgnoreReboot -ErrorAction "SilentlyContinue";
@ -20,14 +22,18 @@ function Update-WindowsInstallation {
catch { } catch { }
if ((Get-WURebootStatus -Silent)) { if ((Get-WURebootStatus -Silent)) {
Write-Information "A Reboot is Required!"; Write-Host "A Reboot is Required!";
Write-Information "Windows will reboot now and the installation will be continued automatically."; Write-Host "Windows will reboot now and the installation will be continued automatically.";
return; return;
} else { } else {
Write-Information "Updating Windows finished successfully!"; Write-Host "Updating Windows finished successfully!";
return; return;
} }
} }
if (-not $hasUpdates) {
Write-Host "There are no updates available.";
}
} }
Start-UpdateLoop; Start-UpdateLoop;

View file

@ -1,15 +1,124 @@
using namespace System.Management.Automation.Host; using namespace System.Management.Automation.Host;
using namespace System.Security.Principal;
$null = New-Module { $null = New-Module {
. "$PSScriptRoot/../Scripts/Deployment.ps1";
. "$PSScriptRoot/../../Common/Scripts/Config.ps1"; . "$PSScriptRoot/../../Common/Scripts/Config.ps1";
[string] $userOption = "SetupUser"; . "$PSScriptRoot/../../Common/Scripts/Operations.ps1";
$loggedInUserOption = "LoggedInUser";
<# <#
.SYNOPSIS .SYNOPSIS
Creates the configured users. Installs all pending users to the system.
#> #>
function Start-ValhallaUserSetup { function Install-ValhallaUsers {
[string[]] $users = Get-Users; $users = @(Get-Users);
$i = Get-CurrentUser;
for (; $i -lt $users.Count; $i++) {
Set-CurrentUser $i;
if (Test-Admin) {
Disable-BootMessage;
}
while ((Get-UserStage) -ne ([UserStage]::Completed)) {
switch (Get-UserStage) {
($null) {
Set-UserStage ([UserStage]::Create);
break;
}
([UserStage]::Create) {
$msAccount = Get-UserConfig -UserName $name "microsoftAccount";
if ($env:UserName -ne $name) {
$userInfo = @{
name = $name;
msAccount = $msAccount;
};
New-ValhallaUser @userInfo;
if ($msAccount) {
logoff;
} else {
Restart-Intermediate;
}
exit;
} else {
if ($msAccount) {
if (-not (Test-Admin)) {
Invoke-OneShot DisableUAC;
Restart-Intermediate -NoRegister;
exit;
}
Clear-SetupRegistration;
Disable-OneShotListener;
}
Set-UserStage ([UserStage]::Configure);
}
}
([UserStage]::Configure) {
$displayName = Get-UserConfig -UserName $name "displayName";
$userInfo = @{
name = $name;
};
if ($displayName) {
$userInfo.fullName = $displayName;
}
$adminGroup = @{
SID = [SecurityIdentifier]::new([WellKnownSidType]::BuiltinAdministratorsSid, $null);
};
Set-LocalUser @userInfo;
Deploy-SoftwareAction -Action ConfigureUser;
Remove-LocalGroupMember -Member "$name" @adminGroup -ErrorAction SilentlyContinue;
foreach ($group in Get-UserConfig "groups") {
Add-LocalGroupMember -Member "$name" -Name "$group";
}
Set-UserStage ([UserStage]::Cleanup);
}
([UserStage]::Cleanup) {
$user = Get-SetupUser;
Disable-LocalUser $name;
Enable-LocalUser $user;
Set-AutologinUser $user;
Unregister-WslDistribution;
Set-UserStage ([UserStage]::Completed);
Restart-Intermediate;
}
}
}
}
foreach ($user in $users) {
Enable-LocalUser $user;
}
}
<#
.SYNOPSIS
Creates a new user for the PortValhalla setup.
.PARAMETER Name
The name of the user to create.
.PARAMETER MSAccount
A value indicating whether the user should be created as a Microsoft Account.
#>
function New-ValhallaUser {
param(
[string] $Name,
[switch] $MSAccount
)
function Add-MicrosoftAccount { function Add-MicrosoftAccount {
param( param(
@ -26,7 +135,7 @@ $null = New-Module {
"Thus, you have to do it by yourself.", "Thus, you have to do it by yourself.",
"So sorry…") -join "`n"); "So sorry…") -join "`n");
Write-Host "Create a user for ``$Name`` manually (because Windows is too stupid)"; Write-Host "Create a user for ``$Name`` manually (because Windows is too stupid)";
$null = Read-Host "Hit enter once you're done"; $null = Read-Host "Hit enter once you're done";
$newUsers = @(Get-LocalUser | Where-Object { -not ($currentUsers -contains $_.Name) }); $newUsers = @(Get-LocalUser | Where-Object { -not ($currentUsers -contains $_.Name) });
@ -57,7 +166,6 @@ $null = New-Module {
for ($i = 0; $i -lt $newUsers.Count; $i++) { for ($i = 0; $i -lt $newUsers.Count; $i++) {
$name = "$($newUsers[$i])"; $name = "$($newUsers[$i])";
[ChoiceDescription]::new("&$($i + 1) - ``$name``", "Your user is ``$name``"); [ChoiceDescription]::new("&$($i + 1) - ``$name``", "Your user is ``$name``");
} }
}), 0); }), 0);
@ -74,31 +182,80 @@ $null = New-Module {
} }
}; };
Write-Host "Renaming the new user to ``$Name``"; Set-MSAccountName ([string]$newUser);
Rename-LocalUser $newUser $Name;
} }
for ($i = 0; $i -lt $users.Count; $i++) { if ($MSAccount) {
Set-SetupOption $userOption $i; if (Test-Admin) {
$name = $users[$i]; Write-Host "Preparing environment for creating MS Account";
Write-Host "Creating personal user ``$name``"; Register-Setup -DefaultUser;
$displayName = Get-UserConfig -UserName $name "displayName"; Enable-OneShotListener;
Enable-UAC;
$userArguments = @{ # Reset Windows activation status
name = $name; # Otherwise the login won't work - Windows is fricking frustrating.
}; slmgr /upk;
slmgr /cpky;
if ($displayName) { slmgr /rearm;
$userArguments.fullName = $displayName; Restart-Intermediate -CurrentUser;
exit;
} }
}
if (Get-UserConfig -UserName $name "microsoftAccount") { Write-Host "Creating personal user ``$Name``";
Add-MicrosoftAccount $name;
} else {
New-LocalUser -Disabled -NoPassword @userArguments;
}
Set-LocalUser @userArguments; if ($MSAccount) {
Add-MicrosoftAccount $Name;
Set-SetupOption $loggedInUserOption $env:UserName;
Invoke-OneShot ([OneShotTask]::InitializeMSAccount);
} else {
New-LocalUser -NoPassword @userArguments;
Initialize-UserCreation;
}
}
<#
.SYNOPSIS
Prepares the first login for initializing the current user under configuration.
#>
function Initialize-UserCreation {
$name = (@(Get-Users))[(Get-CurrentUser)];
$msAccount = Get-UserConfig -UserName $name "microsoftAccount";
Write-Host "Initializing user ``$name``";
$userArguments = @{
name = $name;
};
$adminGroup = @{
SID = [SecurityIdentifier]::new([WellKnownSidType]::BuiltinAdministratorsSid, $null);
};
if ($msAccount) {
$accountName = Get-MSAccountName;
Write-Host "Renaming ``$accountName`` to ``$name``"
Rename-LocalUser $accountName $name;
}
Set-LocalUser @userArguments;
if ($msAccount) {
Disable-LocalUser (Get-SetupOption $loggedInUserOption);
} else {
Disable-LocalUser $env:UserName;
}
Add-LocalGroupMember `
@adminGroup `
$name `
-ErrorAction SilentlyContinue;
if ($msAccount) {
Disable-Autologin;
Set-BootMessage -Caption "Please Log In" -Message "Please log in using your new Microsoft Account ``$name``.";
} else {
Set-AutologinUser "$name";
} }
} }
}; };

View file

@ -0,0 +1,115 @@
. "$PSScriptRoot/../Scripts/Security.ps1";
<#
.SYNOPSIS
Gets the name of the WSL distribution used for managing the configuration.
#>
function Get-WslDistributionName {
return "ValhallaUbuntu";
}
<#
.SYNOPSIS
Gets the path to the directory containing the WSL distribution.
#>
function Get-WslDistributionPath {
return "$env:ProgramData/PortValhalla/$(Get-WslDistributionName)";
}
<#
.SYNOPSIS
Gets the path to the virtual hard disk of the WSL distribution.
#>
function Get-WslDistributionDisk {
return "$(Get-WslDistributionPath)/ext4.vhdx";
}
<#
.SYNOPSIS
Checks whether `wsl` is installed properly.
#>
function Test-Wsl {
& { $null = wsl --status; $?; };
}
<#
.SYNOPSIS
Checks whether any WSL distributions are installed for the current user.
#>
function Test-WslDistributions {
& { $null = wsl -l; $?; };
}
<#
.SYNOPSIS
Checks whether the managed distribution is installed.
#>
function Test-WslDistribution {
& { $null = wsl -d (Get-WslDistributionName) -e true; $?; };
}
<#
.SYNOPSIS
Installs `wsl` on the system.
#>
function Install-Wsl {
wsl --install --no-launch;
}
<#
.SYNOPSIS
Installs a Ubuntu distribution to a shared directory.
#>
function Install-WslDistribution {
$dir = Get-WslDistributionPath;
$root = Split-Path -Parent $dir;
$registryPath = "HKCU:/Software/Microsoft/Windows/CurrentVersion/Lxss";
$key = Get-Item $registryPath;
if ($key) {
$key = $key | Rename-Item -NewName "$(Split-Path -Leaf $key)_" -PassThru;
}
if (-not (Test-Path $root)) {
$null = New-Item -ItemType Directory $root;
}
Copy-Item -Recurse (Get-AppxPackage "*Ubuntu*").InstallLocation $dir;
Set-UserPermissions $dir;
& "$dir\ubuntu.exe" install --root;
wsl --shutdown;
Remove-Item -Recurse -Force $registryPath;
if ($key) {
Move-Item $key.PSPath $registryPath;
}
}
<#
.SYNOPSIS
Uninstalls the managed WSL distribution.
#>
function Uninstall-WslDistribution {
wsl --unregister (Get-WslDistributionName);
}
<#
.SYNOPSIS
Registers the managed WSL distribution.
#>
function Register-WslDistribution {
wsl --import-in-place (Get-WslDistributionName) (Get-WslDistributionDisk);
wsl --set-default (Get-WslDistributionName);
}
<#
.SYNOPSIS
Unregisters the managed WSL distribution.
#>
function Unregister-WslDistribution {
$wslDisk = Get-WslDistributionDisk;
wsl --shutdown;
$tempDisk = Rename-Item $wslDisk "ext4_.vhdx" -PassThru;
Uninstall-WslDistribution;
Move-Item $tempDisk $wslDisk;
}

View file

@ -0,0 +1,12 @@
param (
$Action,
[hashtable] $Arguments
)
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1";
Start-SoftwareInstaller @PSBoundParameters `
-Installer {
Install-SetupPackage "https://github.com/bobranten/Ext4Fsd/releases/download/v0.71/Ext2Fsd-0.71-setup.exe";
};

View file

@ -13,7 +13,6 @@ Start-SoftwareInstaller @PSBoundParameters `
) )
Install-ChocoPackage firefox; Install-ChocoPackage firefox;
& $Installer -Action ([InstallerAction]::Configure)
} ` } `
-Configurator { -Configurator {
Write-Host "Making Firefox the default browser…"; Write-Host "Making Firefox the default browser…";

View file

@ -3,13 +3,81 @@ param(
[hashtable] $Arguments [hashtable] $Arguments
) )
. "$PSScriptRoot/../../Scripts/Restoration.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../Scripts/AppAssociations.ps1";
$null = New-Module {
param ($Parameters)
$configPath = "$env:LocalAppData/LGHUB";
Export-ModuleMember -Function @();
<#
.SYNOPSIS
Stops the running Logitech G Hub instance.
#>
function Stop-LGHub {
[OutputType([string])]
param()
$hubName = "lghub_system_tray.exe";
$lghubPath = $(Get-Process | Where-Object { $_.Path -and ((Split-Path -Leaf $_.Path) -eq $hubName) })[0].Path;
$mainProcesses = Get-Process | Where-Object {
$_.Path -and
(@("lghub.exe", "lghub_agent.exe", $hubName) -contains (Split-Path -Leaf $_.Path)) -and
(($_.Parent.ProcessName -eq "explorer") -or ($null -eq $_.Parent))
};
$null = $mainProcesses | ForEach-Object { $_.Kill($true) };
return $lghubPath;
}
<#
.SYNOPSIS
Edits the Logitech G Hub configuration.
#>
function Edit-LGHubConfig {
param(
[scriptblock] $Action
)
Write-Host "Stopping Logitech G Hub";
$path = Stop-LGHub;
& $Action;
if ($path) {
Write-Host "Restarting Logitech G Hub";
Start-Process $path;
}
}
Start-SoftwareInstaller @Parameters `
-Installer {
Install-ChocoPackage lghub;
Remove-DesktopIcon "*G HUB*";
} `
-UserBackup {
param(
[hashtable] $Arguments
)
Edit-LGHubConfig {
Add-BackupArtifacts -User $Arguments.Name -Source $configPath -Path "LGHub" `
-Include @("settings.db", "icon_cache")
};
} `
-UserConfigurator {
param(
[hashtable] $Arguments
)
Edit-LGHubConfig {
Expand-BackupArtifacts -User $Arguments.Name -Path "LGHub" -Target $configPath;
};
};
} $PSBoundParameters;
Start-SoftwareInstaller @PSBoundParameters ` Start-SoftwareInstaller @PSBoundParameters `
-Installer {
Install-ChocoPackage lghub;
Remove-DesktopIcon "*G HUB*";
};
# ToDo: Add restoration # ToDo: Add restoration

View file

@ -12,7 +12,6 @@ Start-SoftwareInstaller @PSBoundParameters `
) )
Install-ChocoPackage MSEdgeRedirect; Install-ChocoPackage MSEdgeRedirect;
& $Installer -Action ([InstallerAction]::Configure);
} ` } `
-Configurator { -Configurator {
$configPath = "HKLM:\SOFTWARE\Robert Maehl Software\MSEdgeRedirect"; $configPath = "HKLM:\SOFTWARE\Robert Maehl Software\MSEdgeRedirect";

View file

@ -22,7 +22,6 @@ Start-SoftwareInstaller @PSBoundParameters `
refreshenv; refreshenv;
Set-UserPermissions $env:NVS_HOME; Set-UserPermissions $env:NVS_HOME;
& $Installer -Action ([InstallerAction]::Configure);
} ` } `
-Configurator { -Configurator {
nvs add latest; nvs add latest;

View file

@ -0,0 +1,125 @@
param(
$Action,
[hashtable] $Arguments
)
. "$PSScriptRoot/../../Scripts/PowerManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
& {
param($Parameters)
<#
.SYNOPSIS
Gets the path to the Nextcloud configuration file.
#>
function Get-ConfigFile {
return "$env:APPDATA/Nextcloud/nextcloud.cfg";
}
<#
.SYNOPSIS
Adds a new nextcloud sync to the current user.
#>
function Add-NextcloudSync {
param(
[string] $RemotePath,
[string] $LocalPath,
[switch] $VirtualFiles
)
Write-Host "Adding a Nextcloud sync";
Write-Host "$RemotePath <=> $LocalPath";
$configName = "Folders";
$virtualName = "WithPlaceholders";
$LocalPath = $LocalPath.Replace("\", "/");
$RemotePath = $RemotePath.Replace("\", "/");
$oldContent = Get-Content (Get-ConfigFile);
$additionalSettings = @();
$pattern = "^\d+\\$configName(?:$virtualName)?\\(\d+)";
$folderID = (
$oldContent | `
Where-Object { $_ -match "$pattern" } | `
ForEach-Object { $_ -replace "$pattern.*$","`$1" } | `
Sort-Object -Unique | `
Measure-Object -Maximum).Maximum + 1;
if ($VirtualFiles.IsPresent) {
$configName += $virtualName;
$additionalSettings = @("0\$configName\$folderID\virtualFilesMode=wincfapi");
}
$newSettings = (
@(
"0\$configName\$folderID\localPath=$LocalPath",
"0\$configName\$folderID\targetPath=$RemotePath"
) + $additionalSettings
) -join "`n";
& {
$accountSectionEntered = $false;
$accountSectionLeft = $false;
for ($i = 0; $i -lt $oldContent.Count; $i++) {
$line = $oldContent[$i];
if ($line -eq "[Accounts]") {
$accountSectionEntered = $true;
}
if ($line -eq "" -and $accountSectionEntered) {
$accountSectionLeft = $true;
$newSettings;
}
$line;
if (
(-not $accountSectionLeft) -and
($i -eq ($oldContent.Count - 1))) {
$newSettings;
}
}
} | Set-Content (Get-ConfigFile);
}
Start-SoftwareInstaller @Parameters `
-Installer {
Install-ChocoPackage nextcloud-client -ArgumentList "-y","--params='/KeepUpdateCheck'";
} `
-UserConfigurator {
param($Arguments)
$user = $Arguments.Name;
& {
$syncs = Get-UserConfig -UserName $user "nextcloud.folderSyncs";
$configExists = { (Test-Path (Get-ConfigFile) ) };
if ($syncs.Count -gt 0) {
if (-not (& $configExists)) {
while (-not (& $configExists)) {
Read-Host "Please log in to the Nextcloud app and hit enter to continue";
if (-not (& $configExists)) {
Write-Error -ErrorAction Continue "The login seems to have failed. Please try again.";
}
}
}
Write-Host "Stopping Nextcloud process";
$nextcloudProcess = Get-Process nextcloud;
$nextcloudPath = [string]$nextcloudProcess[0].Path;
$nextcloudProcess | Stop-Process -Force;
foreach ($sync in $syncs) {
Add-NextcloudSync -LocalPath $sync.localPath -RemotePath $sync.remotePath -VirtualFiles:$sync.virtualFiles;
}
Write-Host "Restarting Nextcloud";
Start-Process $nextcloudPath;
}
};
};
} $PSBoundParameters;

View file

@ -1,32 +0,0 @@
param(
$Action,
[hashtable] $Arguments
)
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
Start-SoftwareInstaller @PSBoundParameters `
-Installer {
Install-ChocoPackage nextcloud-client -ArgumentList "-y","--params='/KeepUpdateCheck'";
} `
-UserConfigurator {
if (-not (Test-Path $context.GetNextcloudConfigFile())) {
Write-Information "Setting up Nextcloud configuration";
Write-Information "Ensuring all Let's Encrypt certificates are cached";
$null = Invoke-WebRequest https://valid-isrgrootx1.letsencrypt.org/;
while (-not (Test-Path $context.GetNextcloudConfigFile())) {
Write-Host "Nextcloud has been installed!";
Read-Host "Please log in in the Nextcloud app and hit enter to continue";
if (-not (Test-Path $context.GetNextcloudConfigFile())) {
Write-Error "The login seems to have failed. Please try again.";
}
}
$context.Reboot();
exit;
}
};

View file

@ -6,16 +6,18 @@ param (
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1"; . "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1";
Start-SoftwareInstaller @PSBoundParameters ` & {
-Installer { param($Parameters)
param( $base = "$PSScriptRoot/../../../Common/Software/Oh My Posh/Manage.ps1";
[scriptblock] $Installer
)
Install-WingetPackage JanDeDobbeleer.OhMyPosh -ArgumentList "--scope","machine"; Start-SoftwareInstaller @Parameters `
& $Installer -Action ([InstallerAction]::Configure); -Installer {
} ` Install-WingetPackage JanDeDobbeleer.OhMyPosh -ArgumentList "--scope","machine";
-Configurator { } `
. "$PSScriptRoot/../../../Common/Software/Oh My Posh/Manage.ps1" ` -Configurator {
-Action ([InstallerAction]::Configure); . $base -Action ([InstallerAction]::Configure);
}; } `
-UserConfigurator {
. $base -Action ([InstallerAction]::ConfigureUser);
};
} $PSBoundParameters;

View file

@ -8,13 +8,6 @@ param(
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
Start-SoftwareInstaller @PSBoundParameters ` Start-SoftwareInstaller @PSBoundParameters `
-Installer {
param(
[scriptblock] $Installer
)
& $Installer -Action ([InstallerAction]::Configure)
} `
-Configurator { -Configurator {
Set-Service ssh-agent -StartupType AutomaticDelayedStart; Set-Service ssh-agent -StartupType AutomaticDelayedStart;
}; };

View file

@ -6,7 +6,7 @@ param (
. "$PSScriptRoot/../../../Common/Software/PowerShell/Module.ps1"; . "$PSScriptRoot/../../../Common/Software/PowerShell/Module.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
$parameters = Get-ModuleInstallerComponents "PinnedItem" -NativeOnly; $parameters = Get-ModuleInstallerComponents "PinnedItem" -NativeOnly -NoProfile;
foreach ($key in $PSBoundParameters.Keys) { foreach ($key in $PSBoundParameters.Keys) {
$parameters.Add($key, $PSBoundParameters.TryGetValue($key)); $parameters.Add($key, $PSBoundParameters.TryGetValue($key));
@ -21,12 +21,15 @@ Start-SoftwareInstaller @parameters -Installer {
[hashtable] $Arguments [hashtable] $Arguments
) )
$feature = "NetFx3"; $module = $Arguments.Name;
if ((Get-WindowsOptionalFeature -Online -FeatureName $feature).State -ne "Enabled") {
Write-Host "Enabling ``$feature`` feature…";
choco install --source windowsFeatures -y $feature;
}
& $Arguments.Installer @PSBoundParameters; & $Arguments.Installer @PSBoundParameters;
if (-not (& { powershell -Command "Import-Module $module"; $?; })) {
$feature = "NetFx3";
if ((Get-WindowsOptionalFeature -Online -NoRestart -FeatureName $feature).State -ne "Enabled") {
Write-Host "Enabling ``$feature`` feature…";
choco install --source windowsFeatures -y $feature;
}
}
} }

View file

@ -7,13 +7,6 @@ param (
. "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1"; . "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1";
Start-SoftwareInstaller @PSBoundParameters ` Start-SoftwareInstaller @PSBoundParameters `
-Installer {
param(
[scriptblock] $Installer
)
& $Installer -Action ([InstallerAction]::Configure);
} `
-Configurator { -Configurator {
. "$PSScriptRoot/../../../Common/Software/PowerShell/Manage.ps1" ` . "$PSScriptRoot/../../../Common/Software/PowerShell/Manage.ps1" `
-Action ([InstallerAction]::Configure); -Action ([InstallerAction]::Configure);

View file

@ -4,12 +4,14 @@ param(
) )
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Scripts/System.ps1";
Start-SoftwareInstaller @PSBoundParameters ` Start-SoftwareInstaller @PSBoundParameters `
-Installer { -Installer {
Install-ChocoPackage retroarch; Install-ChocoPackage retroarch;
# ToDo: Add start menu shortcut } `
# ToDo: Add function for this purpose -Configurator {
Add-StartMenuIcon "RetroArch" "C:\tools\RetroArch-Win64\retroarch.exe";
}; };
# ToDo: Add restoration # ToDo: Add restoration

View file

@ -15,7 +15,6 @@ Start-SoftwareInstaller @PSBoundParameters `
) )
Install-ChocoPackage thunderbird -ArgumentList "--params",'"/NoTaskbarShortcut /NoDesktopShortcut"' Install-ChocoPackage thunderbird -ArgumentList "--params",'"/NoTaskbarShortcut /NoDesktopShortcut"'
& $Installer -Action ([InstallerAction]::Configure)
} ` } `
-Configurator { -Configurator {
Write-Host "Making Thunderbird the default mail program…"; Write-Host "Making Thunderbird the default mail program…";

View file

@ -12,10 +12,10 @@ Start-SoftwareInstaller @PSBoundParameters `
Write-Information "Enabling the ``$feature`` feature…"; Write-Information "Enabling the ``$feature`` feature…";
choco install --source windowsFeatures -y $feature; choco install --source windowsFeatures -y $feature;
} }
Install-WingetPackage Nadeo.TrackManiaNationsForever;
Remove-DesktopIcon "*TmNationsForever*";
} }
Install-WingetPackage Nadeo.TrackManiaNationsForever;
Remove-DesktopIcon "*TmNationsForever*";
}; };
# ToDo: Add restoration # ToDo: Add restoration

View file

@ -11,12 +11,7 @@ param(
Start-SoftwareInstaller @PSBoundParameters ` Start-SoftwareInstaller @PSBoundParameters `
-Installer { -Installer {
param(
[scriptblock] $Installer
)
Install-ChocoPackage winscp; Install-ChocoPackage winscp;
& $Installer -Action ([InstallerAction]::Configure)
} ` } `
-Configurator { -Configurator {
Remove-DesktopIcon "WinSCP*"; Remove-DesktopIcon "WinSCP*";

View file

@ -0,0 +1,37 @@
Pictures/Feedback
Documents/BeamNG.drive
Documents/Default.rdp
Documents/den4b/ReNamer
Documents/Dolphin Emulator
Documents/eFisc
Documents/IISExpress
Documents/KINGDOM HEARTS HD 1.5+2.5 ReMIX
Documents/ManiaPlanet
Documents/MetaX
Documents/MuseScore3
Documents/My Web Sites
Documents/OneNote-Notizbücher
Documents/PCSX2
Documents/PowerShell
Documents/PPSSPP
Documents/PS Vita
Documents/PSV Packages
Documents/PSV Updates
Documents/Repositories
Documents/Rise of the Tomb Raider
Documents/S2
Documents/SEGA
Documents/SEGA Mega Drive Classics
Documents/SQL Server Management Studio
Documents/Square Enix
Documents/TI-Nspire CX
Documents/TmForever
Documents/TrackMania
Documents/UltraVNC
Documents/Visual Studio 2017
Documents/Visual Studio 2019
Documents/Visual Studio 2022
Documents/Viwizard M4V Converter
Documents/WindowsPowerShell
Documents/Zoom
Music/iTunes

View file

@ -5,19 +5,40 @@ param(
[hashtable] $Arguments [hashtable] $Arguments
) )
. "$PSScriptRoot/../../Scripts/Registry.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Config.ps1";
. "$PSScriptRoot/../../../Common/Scripts/System.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1"; . "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1";
Start-SoftwareInstaller @PSBoundParameters ` $null = New-Module {
-Installer { param($Parameters)
param(
[scriptblock] $Installer
)
& $Installer -Action ([InstallerAction]::Configure) . "$PSScriptRoot/../../Scripts/Registry.ps1";
. "$PSScriptRoot/../../Scripts/Restoration.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Config.ps1";
. "$PSScriptRoot/../../../Common/Scripts/System.ps1";
$userFolders = @(
"Pictures",
"Documents",
"Downloads",
"Music",
"Videos"
);
$userExclusions = @(
"Documents/Eigene*",
"Documents/My Games",
"Documents/My Music",
"Documents/My Pictures",
"Documents/My Videos"
);
[string[]] $homeExclusions = Get-Content "$PSScriptRoot/Home.exclude.txt";
Start-SoftwareInstaller @Parameters `
-Backup {
Add-BackupArtifacts -Source "$env:PUBLIC" -Path "Public" `
-Include ($userFolders) `
-Exclude ($userExclusions + @("Documents/Hyper-V", "Documents/reWASD"));
} ` } `
-Configurator { -Configurator {
$dir = New-TemporaryDirectory; $dir = New-TemporaryDirectory;
@ -61,7 +82,7 @@ Start-SoftwareInstaller @PSBoundParameters `
) )
$path = "$($Key.PSPath)\Software\Microsoft\Lighting"; $path = "$($Key.PSPath)\Software\Microsoft\Lighting";
$null = New-Item $path; $null = New-Item $path -ErrorAction SilentlyContinue;
Set-ItemProperty $path -Name "AmbientLightingEnabled" -Value 0 -Type "DWord"; Set-ItemProperty $path -Name "AmbientLightingEnabled" -Value 0 -Type "DWord";
}; };
} }
@ -143,4 +164,20 @@ Start-SoftwareInstaller @PSBoundParameters `
Pop-Location; Pop-Location;
Remove-Item -Recurse $dir; Remove-Item -Recurse $dir;
Expand-BackupArtifacts -Path "Public" -Target $env:PUBLIC;
} `
-UserBackup {
param(
[hashtable] $Arguments
)
Add-BackupArtifacts -User $Arguments.Name -Source $HOME -Path "Home" -Include ($userFolders) -Exclude ($userExclusions + $homeExclusions);
} `
-UserConfigurator {
param(
[hashtable] $Arguments
)
Expand-BackupArtifacts -User $Arguments.Name -Path "Home" -Target $HOME;
}; };
} $PSBoundParameters;

View file

@ -0,0 +1,23 @@
param (
$Action,
[hashtable] $Arguments
)
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1";
& {
param($Parameters)
$base = "$PSScriptRoot/../../../Common/Software/aliae/Manage.ps1";
Start-SoftwareInstaller @Parameters `
-Installer {
Install-WingetPackage JanDeDobbeleer.Aliae;
} `
-Configurator {
. $base -Action ([InstallerAction]::Configure);
} `
-UserConfigurator {
. $base -Action ([InstallerAction]::ConfigureUser);
};
} $PSBoundParameters;

View file

@ -8,13 +8,6 @@ param(
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
Start-SoftwareInstaller @PSBoundParameters ` Start-SoftwareInstaller @PSBoundParameters `
-Installer {
param(
[scriptblock] $Installer
)
& $Installer -Action ([InstallerAction]::Configure)
} `
-Configurator { -Configurator {
[string] $backup = $null; [string] $backup = $null;
$nativeProfile = powershell -c '$PROFILE'; $nativeProfile = powershell -c '$PROFILE';

View file

@ -7,58 +7,33 @@ param (
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Config.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Config.ps1";
$null = New-Module { & {
param( param(
[hashtable] $Parameters [hashtable] $Parameters
) )
. "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1"; . "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1";
$base = "$PSScriptRoot/../../../Common/Software/git/Manage.ps1";
<#
.SYNOPSIS
Gets a configuration value related to git.
.PARAMETER Name
The name of the configuration to get.
.PARAMETER User
The name of the user to get the configuration for.
#>
function Get-GitOption {
param(
[Parameter(Mandatory)]
[string] $Name,
[string] $User
)
$config = "git.$Name";
if ($User) {
Get-UserConfig -UserName $User -Name $config;
} else {
Get-Config $config;
}
}
Start-SoftwareInstaller @Parameters ` Start-SoftwareInstaller @Parameters `
-Installer { -Installer {
param(
[scriptblock] $Installer
)
$params = "/WindowsTerminalProfile"; $params = "/WindowsTerminalProfile";
$defaultBranch = Get-GitOption "defaultBranch"; $defaultBranch = Get-Config "valhalla.git.defaultBranch";
if ($defaultBranch) { if ($defaultBranch) {
$params += " /DefaultBranchName:`"$defaultBranch`""; $params += " /DefaultBranchName:`"$defaultBranch`"";
} }
Install-ChocoPackage git -ArgumentList "--params",$params; Install-ChocoPackage git -ArgumentList "--params",$params;
& $Installer -Action ([InstallerAction]::Configure);
} ` } `
-Configurator { -Configurator {
& "$PSScriptRoot/../../../Common/Software/git/Manage.ps1" @Parameters; & $base ([InstallerAction]::Configure);
}; } `
-UserConfigurator {
param(
$Arguments
)
Export-ModuleMember -Function @(); & $base ([InstallerAction]::ConfigureUser) @PSBoundParameterrs;
} -ArgumentList $PSBoundParameters };
} $PSBoundParameters;

View file

@ -8,23 +8,7 @@ param(
Start-SoftwareInstaller @PSBoundParameters ` Start-SoftwareInstaller @PSBoundParameters `
-Installer { -Installer {
$file = "osu!lazer.exe"; Install-WingetPackage "ppy.osu";
$processName = "osu!";
$dir = New-TemporaryDirectory;
Push-Location $dir;
Invoke-WebRequest "https://github.com/ppy/osu/releases/latest/download/install.exe" -OutFile $file;
Start-Process -FilePath $file;
while (-not (Get-Process -ErrorAction SilentlyContinue $processName)) {
Start-Sleep 1;
}
Start-Sleep 10;
Get-Process $processName | Stop-Process -Force;
Pop-Location;
Remove-Item -Recurse $dir;
Remove-DesktopIcon "*osu*"; Remove-DesktopIcon "*osu*";
}; };

View file

@ -11,7 +11,7 @@ Start-SoftwareInstaller @PSBoundParameters `
-Installer { -Installer {
Write-Host "Downloading reWASD…"; Write-Host "Downloading reWASD…";
$dir = New-TemporaryDirectory; $dir = New-TemporaryDirectory;
$file = Start-BrowserDownload -URL "https://rewasd.com/" -ButtonSelector 'a.btn-default[href="#"]' -OutDir $dir; $file = Start-BrowserDownload -URL "https://rewasd.com/" -ButtonSelector 'a.btn-default[href="#"]' -OutDir $dir -Timeout 1;
Write-Host "Installing reWASD…"; Write-Host "Installing reWASD…";
Start-Process -Wait -FilePath $($file.FullName) -ArgumentList "/S"; Start-Process -Wait -FilePath $($file.FullName) -ArgumentList "/S";

View file

@ -0,0 +1,28 @@
param(
$Action,
[hashtable] $Arguments
)
& {
param (
[hashtable] $Parameters
)
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1";
$base = "$PSScriptRoot/../../../Common/Software/vscode/Main.ps1";
Start-SoftwareInstaller @Parameters `
-Installer {
Install-ChocoPackage vscode -ArgumentList "--params","/NoDesktopIcon";
Install-ChocoPackage vscodium -ArgumentList "--params","/NoDesktopIcon /AssociateWithFiles";
refreshenv;
} `
-UserConfigurator {
param(
$Arguments
)
& $base ([InstallerAction]::ConfigureUser) @PSBoundParameters;
};
} $PSBoundParameters;

View file

@ -14,7 +14,6 @@ Start-SoftwareInstaller @PSBoundParameters `
Install-ChocoPackage zoxide; Install-ChocoPackage zoxide;
Install-WingetPackage junegunn.fzf; Install-WingetPackage junegunn.fzf;
& $Installer -Action ([InstallerAction]::Configure);
} ` } `
-Configurator { -Configurator {
Add-PowerShellProfileStatement ` Add-PowerShellProfileStatement `

View file

@ -0,0 +1,4 @@
enum WindowsInstallerAction {
Backup
Install
}

View file

@ -16,6 +16,7 @@ begin
argparse --name (status filename) -x "iso,usb" "iso" "usb" "debug" -- $argv argparse --name (status filename) -x "iso,usb" "iso" "usb" "debug" -- $argv
or exit 1 or exit 1
set -l mountDir "/mnt"
set -l setupLabel "winiso-valhalla" set -l setupLabel "winiso-valhalla"
set -l projectPath "PortValhalla" set -l projectPath "PortValhalla"
set -l systemDrivePath "sources/\$OEM\$/\$1" set -l systemDrivePath "sources/\$OEM\$/\$1"
@ -23,9 +24,9 @@ begin
set -l localProjectPath "$systemDrivePath/$projectPath" set -l localProjectPath "$systemDrivePath/$projectPath"
set -l cacheDir ~/.cache/winiso-valhalla set -l cacheDir ~/.cache/winiso-valhalla
set -l winpe "$cacheDir/winpe.iso" set -l winpe "$cacheDir/winpe.iso"
set -l winPath "/media/win" set -l winPath "$mountDir/win"
set -l winpePath "/media/winpe" set -l winpePath "$mountDir/winpe"
set -l valhallaPath "/media/winiso-valhalla" set -l valhallaPath "$mountDir/winiso-valhalla"
set -l winpeOverlay (mktemp -d) set -l winpeOverlay (mktemp -d)
set -l winOverlay (mktemp -d) set -l winOverlay (mktemp -d)
set -l upperDir (mktemp -d) set -l upperDir (mktemp -d)
@ -202,7 +203,7 @@ begin
find "$projectPath/profiles" -type f -name "*.nix" | while read -l file find "$projectPath/profiles" -type f -name "*.nix" | while read -l file
set -l CONFIG_MODULE "$file" set -l CONFIG_MODULE "$file"
getConfig "valhalla.windows" --json > "$file.json" getConfig "valhalla.windows.config" --json > "$file.json"
end end
end end
@ -228,8 +229,8 @@ begin
-output "$isoFile" \ -output "$isoFile" \
"$valhallaPath" "$valhallaPath"
else else
set -l bootPath "/media/boot" set -l bootPath "$mountDir/boot"
set -l dataPath "/media/data" set -l dataPath "$mountDir/data"
set -a mountPaths \ set -a mountPaths \
"$bootPath" \ "$bootPath" \