From e300b14dde3a5b969e145499444306af3e6e6cc6 Mon Sep 17 00:00:00 2001 From: bbedward Date: Sun, 19 Jul 2026 19:03:10 -0400 Subject: [PATCH] core: some fixes for embedded distribution, VERSION file, matugen scripts, and embed scripts --- core/Makefile | 16 ++++++---- core/cmd/dms/commands_common.go | 41 +++++++++++++++++--------- core/internal/shellembed/shellembed.go | 15 ++++++++-- quickshell/Common/Theme.qml | 8 +++-- 4 files changed, 56 insertions(+), 24 deletions(-) diff --git a/core/Makefile b/core/Makefile index 2d9999d02..5b7d64154 100644 --- a/core/Makefile +++ b/core/Makefile @@ -38,17 +38,23 @@ endif all: build # Copy the quickshell UI into the embed dir (gitignored) so tagged builds -# can bake it into the binary. Dev-only files are stripped. tar -h dereferences -# the DankCommon submodule symlink; go:embed rejects symlinks. .qmlls.ini is -# excluded at copy time: it's a symlink into the quickshell runtime VFS and -# dereferencing it fails whenever the shell isn't running. +# can bake it into the binary. Dev-only files are stripped; scripts/ is kept +# minus its dev entries, since Theme.qml and BluetoothService.qml run +# gtk.sh/qt.sh/bluez-card-profile.lua out of the resolved shell dir. +# tar -h dereferences the DankCommon submodule symlink; go:embed rejects +# symlinks. .qmlls.ini is excluded at copy time: it's a symlink into the +# quickshell runtime VFS and dereferencing it fails whenever the shell isn't +# running. sync-shell: @test -e $(SHELL_SRC)/DankCommon/Widgets/DankIcon.qml || { echo "DankCommon missing: run git submodule update --init"; exit 1; } @rm -rf $(EMBED_DIR) @mkdir -p $(EMBED_DIR) @tar -C $(SHELL_SRC) --exclude=.qmlls.ini -chf - . | tar -C $(EMBED_DIR) -xf - - @rm -rf $(EMBED_DIR)/scripts $(EMBED_DIR)/.claude $(EMBED_DIR)/.git* $(EMBED_DIR)/.github + @rm -rf $(EMBED_DIR)/.git* $(EMBED_DIR)/.github + @find $(EMBED_DIR) -type d \( -name .claude -o -name .vscode \) -prune -exec rm -rf {} + @rm -f $(EMBED_DIR)/AGENTS.md $(EMBED_DIR)/qmlformat-all.sh + @rm -f $(EMBED_DIR)/scripts/i18nsync.py $(EMBED_DIR)/scripts/build-vscode-vsix.sh $(EMBED_DIR)/scripts/qmllint-entrypoints.sh + @rm -f $(EMBED_DIR)/scripts/spam-notifications.sh $(EMBED_DIR)/scripts/verify-notifications.sh @rm -f $(EMBED_DIR)/translations/*.py $(EMBED_DIR)/translations/WORKFLOW.md @cd $(EMBED_DIR) && find . -type f -print0 | LC_ALL=C sort -z | xargs -0 sha256sum | sha256sum | cut -c1-16 > .dankrev diff --git a/core/cmd/dms/commands_common.go b/core/cmd/dms/commands_common.go index f64f5bef9..c7f9fb574 100644 --- a/core/cmd/dms/commands_common.go +++ b/core/cmd/dms/commands_common.go @@ -9,6 +9,7 @@ import ( "github.com/AvengeMedia/DankMaterialShell/core/internal/log" "github.com/AvengeMedia/DankMaterialShell/core/internal/plugins" "github.com/AvengeMedia/DankMaterialShell/core/internal/server" + "github.com/AvengeMedia/DankMaterialShell/core/internal/shellembed" "github.com/spf13/cobra" ) @@ -206,29 +207,41 @@ func formatVersion(version string) string { return fmt.Sprintf("dms %s", version) } +var baseVersionRe = regexp.MustCompile(`^([\d.]+)`) + +// Installed UI trees, for builds without an embedded UI. +var shellVersionPaths = []string{ + "/usr/share/quickshell/dms/VERSION", + "/usr/local/share/quickshell/dms/VERSION", + "/etc/xdg/quickshell/dms/VERSION", +} + func getBaseVersion() string { - paths := []string{ - "/usr/share/quickshell/dms/VERSION", - "/usr/local/share/quickshell/dms/VERSION", - "/etc/xdg/quickshell/dms/VERSION", + if ver := parseBaseVersion(shellembed.Version()); ver != "" { + return ver } - for _, path := range paths { - if content, err := os.ReadFile(path); err == nil { - ver := strings.TrimSpace(string(content)) - ver = strings.TrimPrefix(ver, "v") - if re := regexp.MustCompile(`^([\d.]+)`); re.MatchString(ver) { - if matches := re.FindStringSubmatch(ver); matches != nil { - return matches[1] - } - } + for _, path := range shellVersionPaths { + content, err := os.ReadFile(path) + if err != nil { + continue + } + if ver := parseBaseVersion(string(content)); ver != "" { + return ver } } - // Fallback return "1.0.2" } +func parseBaseVersion(raw string) string { + matches := baseVersionRe.FindStringSubmatch(strings.TrimPrefix(strings.TrimSpace(raw), "v")) + if matches == nil { + return "" + } + return matches[1] +} + func startDebugServer() error { server.CLIVersion = Version return server.Start(true) diff --git a/core/internal/shellembed/shellembed.go b/core/internal/shellembed/shellembed.go index f4a10796b..c09843e6e 100644 --- a/core/internal/shellembed/shellembed.go +++ b/core/internal/shellembed/shellembed.go @@ -7,13 +7,15 @@ package shellembed import ( "io/fs" "path" + "strings" "github.com/AvengeMedia/dankgo/shellapp/shellfs" ) const ( - distRoot = "dist" - shellEntry = "shell.qml" + distRoot = "dist" + shellEntry = "shell.qml" + versionFile = "VERSION" ) // Available reports whether this binary was built with the embedded UI @@ -23,6 +25,15 @@ func Available() bool { return err == nil && !info.IsDir() } +// Version reports the embedded UI's VERSION, empty when unavailable. +func Version() string { + data, err := fs.ReadFile(distFS, path.Join(distRoot, versionFile)) + if err != nil { + return "" + } + return strings.TrimSpace(string(data)) +} + func Extract(baseDir string) (string, error) { sub, err := fs.Sub(distFS, distRoot) if err != nil { diff --git a/quickshell/Common/Theme.qml b/quickshell/Common/Theme.qml index c8e91b22e..55fbfce93 100644 --- a/quickshell/Common/Theme.qml +++ b/quickshell/Common/Theme.qml @@ -142,7 +142,9 @@ Singleton { Component.onCompleted: { Quickshell.execDetached(["mkdir", "-p", stateDir]); - Quickshell.execDetached([shellDir + "/scripts/gtk.sh", configDir, "", shellDir, "assets-only"]); + // shellDir may be an embedded-UI extraction, which is read-only and + // unexecutable (dankgo shellapp/shellfs makeReadOnly chmods 0444) + Quickshell.execDetached(["bash", shellDir + "/scripts/gtk.sh", configDir, "", shellDir, "assets-only"]); Proc.runCommand("matugenCheck", ["sh", "-c", "command -v matugen"], (output, code) => { matugenAvailable = (code === 0) && !envDisableMatugen; @@ -1933,7 +1935,7 @@ Singleton { } const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode) ? "true" : "false"; - Proc.runCommand("gtkApplier", [shellDir + "/scripts/gtk.sh", configDir, isLight, shellDir], (output, exitCode) => { + Proc.runCommand("gtkApplier", ["bash", shellDir + "/scripts/gtk.sh", configDir, isLight, shellDir], (output, exitCode) => { if (exitCode === 0) { if (typeof ToastService !== "undefined" && typeof NiriService !== "undefined" && !NiriService.matugenSuppression) { ToastService.showInfo(I18n.tr("GTK colors applied successfully")); @@ -1954,7 +1956,7 @@ Singleton { return; } - Proc.runCommand("qtApplier", [shellDir + "/scripts/qt.sh", configDir], (output, exitCode) => { + Proc.runCommand("qtApplier", ["bash", shellDir + "/scripts/qt.sh", configDir], (output, exitCode) => { if (exitCode === 0) { if (typeof ToastService !== "undefined") { ToastService.showInfo(I18n.tr("Qt colors applied successfully"));