detached 95606ea

refactor(shell): strip to no-op, shell config handled by cli-tools.sh post-boot

commit
95606ea1beeade14918039c29eb839cf4ff6d5fb
author
bnema · · 2026-02-26 21:07 UTC
parent
bea76ec
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
2 files · +5 -316
M internal/shell/configurator.go +3 -121
@@ -1,10 +1,6 @@
11 package shell
22
33 import (
4- "fmt"
5- "path/filepath"
6- "strings"
7-
84 "github.com/bnema/archup/internal/config"
95 "github.com/bnema/archup/internal/interfaces"
106 "github.com/bnema/archup/internal/logger"
@@ -43,125 +39,11 @@ func NewConfigurator(
4339 }
4440 }
4541
46-// Configure sets up shell and CLI tool theming for a user
42+// Configure is a no-op. Shell configuration is handled by cli-tools.sh at first boot.
4743 func (c *Configurator) Configure(username, userHome string) (ConfigResult, error) {
48- result := ConfigResult{
44+ return ConfigResult{
4945 ThemesApplied: 0,
5046 ThemesFailed: []string{},
5147 Warnings: []string{},
52- }
53-
54- // Create archup shell directory structure
55- archupDefault := filepath.Join(userHome, ".local", "share", "archup", "default")
56- archupDefaultBash := filepath.Join(archupDefault, "bash")
57-
58- if err := c.fs.MkdirAll(archupDefaultBash, 0755); err != nil {
59- return result, fmt.Errorf("failed to create shell config directory: %w", err)
60- }
61-
62- // Copy shell configuration files from templates
63- if err := c.copyShellTemplates(archupDefault, archupDefaultBash); err != nil {
64- return result, fmt.Errorf("failed to copy shell templates: %w", err)
65- }
66-
67- // Create .bashrc
68- bashrcContent, err := c.readTemplate(config.BashrcTemplate)
69- if err != nil {
70- return result, fmt.Errorf("failed to read bashrc template: %w", err)
71- }
72-
73- bashrcPath := filepath.Join(userHome, ".bashrc")
74- if err := c.fs.WriteFile(bashrcPath, bashrcContent, 0644); err != nil {
75- return result, fmt.Errorf("failed to write .bashrc: %w", err)
76- }
77-
78- // Set ownership to user
79- if err := c.setShellOwnership(userHome, username); err != nil {
80- return result, fmt.Errorf("failed to set ownership: %w", err)
81- }
82-
83- // Clone bleu-theme repository
84- relativeHome := strings.TrimPrefix(userHome, config.PathMnt)
85- themesDir := filepath.Join(relativeHome, ".local", "share", "archup", "themes")
86- bleuThemeDir := filepath.Join(themesDir, "bleu")
87- currentDir := filepath.Join(relativeHome, ".local", "share", "archup", "current")
88-
89- cloneCmd := fmt.Sprintf("su - %s -c 'mkdir -p %s && git clone https://github.com/bnema/bleu-theme.git %s'",
90- username, themesDir, bleuThemeDir)
91- if err := c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, cloneCmd); err != nil {
92- result.Warnings = append(result.Warnings, "Failed to clone bleu-theme repository")
93- }
94-
95- // Create current theme symlink
96- symlinkCmd := fmt.Sprintf("su - %s -c 'mkdir -p %s && ln -snf %s %s/theme'",
97- username, currentDir, bleuThemeDir, currentDir)
98- if err := c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, symlinkCmd); err != nil {
99- result.Warnings = append(result.Warnings, "Failed to create theme symlink")
100- }
101-
102- // Apply themes to CLI tools
103- themeResult := c.applyThemes(username, userHome)
104- result.ThemesApplied = themeResult.Applied
105- result.ThemesFailed = themeResult.Failed
106- result.Warnings = append(result.Warnings, themeResult.Warnings...)
107-
108- // Configure git delta
109- gitCommands := []string{
110- fmt.Sprintf("su - %s -c 'git config --global core.pager delta'", username),
111- fmt.Sprintf("su - %s -c 'git config --global interactive.diffFilter \"delta --color-only\"'", username),
112- fmt.Sprintf("su - %s -c 'git config --global delta.navigate true'", username),
113- fmt.Sprintf("su - %s -c 'git config --global delta.light false'", username),
114- fmt.Sprintf("su - %s -c 'git config --global delta.side-by-side true'", username),
115- fmt.Sprintf("su - %s -c 'git config --global merge.conflictstyle diff3'", username),
116- fmt.Sprintf("su - %s -c 'git config --global diff.colorMoved default'", username),
117- }
118-
119- for _, gitCmd := range gitCommands {
120- if err := c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, gitCmd); err != nil {
121- result.Warnings = append(result.Warnings, "Failed to configure git delta")
122- break
123- }
124- }
125-
126- return result, nil
127-}
128-
129-// copyShellTemplates copies shell config templates to user directory
130-func (c *Configurator) copyShellTemplates(archupDefault, archupDefaultBash string) error {
131- templates := map[string]string{
132- config.ShellConfigTemplate: filepath.Join(archupDefaultBash, "shell"),
133- config.ShellInitTemplate: filepath.Join(archupDefaultBash, "init"),
134- config.ShellAliasesTemplate: filepath.Join(archupDefaultBash, "aliases"),
135- config.ShellEnvsTemplate: filepath.Join(archupDefaultBash, "envs"),
136- config.ShellRcTemplate: filepath.Join(archupDefaultBash, "rc"),
137- }
138-
139- for template, dest := range templates {
140- content, err := c.readTemplate(template)
141- if err != nil {
142- return fmt.Errorf("failed to read template %s: %w", template, err)
143- }
144-
145- if err := c.fs.WriteFile(dest, content, 0644); err != nil {
146- return fmt.Errorf("failed to write %s: %w", dest, err)
147- }
148- }
149-
150- return nil
151-}
152-
153-// readTemplate reads a template file from install path
154-func (c *Configurator) readTemplate(filename string) ([]byte, error) {
155- // Use DefaultInstallDir directly to match where bootstrap downloads files
156- templatePath := filepath.Join(config.DefaultInstallDir, filename)
157- return c.fs.ReadFile(templatePath)
158-}
159-
160-// setShellOwnership sets ownership of shell config files to user
161-func (c *Configurator) setShellOwnership(userHome, username string) error {
162- // Use chroot to run chown
163- relativeHome := strings.TrimPrefix(userHome, config.PathMnt)
164- chownCmd := fmt.Sprintf("chown -R %s:%s %s/.local %s/.bashrc",
165- username, username, relativeHome, relativeHome)
166- return c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, chownCmd)
48+ }, nil
16749 }
@@ -1,10 +1,6 @@
1 package shell1 package shell
2 2
3 import (3 import (
4- "fmt"
5- "path/filepath"
6- "strings"
7-
8 "github.com/bnema/archup/internal/config"4 "github.com/bnema/archup/internal/config"
9 "github.com/bnema/archup/internal/interfaces"5 "github.com/bnema/archup/internal/interfaces"
10 "github.com/bnema/archup/internal/logger"6 "github.com/bnema/archup/internal/logger"
@@ -43,125 +39,11 @@ func NewConfigurator(
43 }39 }
44 }40 }
45 41
46-// Configure sets up shell and CLI tool theming for a user42+// Configure is a no-op. Shell configuration is handled by cli-tools.sh at first boot.
47 func (c *Configurator) Configure(username, userHome string) (ConfigResult, error) {43 func (c *Configurator) Configure(username, userHome string) (ConfigResult, error) {
48- result := ConfigResult{44+ return ConfigResult{
49 ThemesApplied: 0,45 ThemesApplied: 0,
50 ThemesFailed: []string{},46 ThemesFailed: []string{},
51 Warnings: []string{},47 Warnings: []string{},
52- }48+ }, nil
53-
54- // Create archup shell directory structure
55- archupDefault := filepath.Join(userHome, ".local", "share", "archup", "default")
56- archupDefaultBash := filepath.Join(archupDefault, "bash")
57-
58- if err := c.fs.MkdirAll(archupDefaultBash, 0755); err != nil {
59- return result, fmt.Errorf("failed to create shell config directory: %w", err)
60- }
61-
62- // Copy shell configuration files from templates
63- if err := c.copyShellTemplates(archupDefault, archupDefaultBash); err != nil {
64- return result, fmt.Errorf("failed to copy shell templates: %w", err)
65- }
66-
67- // Create .bashrc
68- bashrcContent, err := c.readTemplate(config.BashrcTemplate)
69- if err != nil {
70- return result, fmt.Errorf("failed to read bashrc template: %w", err)
71- }
72-
73- bashrcPath := filepath.Join(userHome, ".bashrc")
74- if err := c.fs.WriteFile(bashrcPath, bashrcContent, 0644); err != nil {
75- return result, fmt.Errorf("failed to write .bashrc: %w", err)
76- }
77-
78- // Set ownership to user
79- if err := c.setShellOwnership(userHome, username); err != nil {
80- return result, fmt.Errorf("failed to set ownership: %w", err)
81- }
82-
83- // Clone bleu-theme repository
84- relativeHome := strings.TrimPrefix(userHome, config.PathMnt)
85- themesDir := filepath.Join(relativeHome, ".local", "share", "archup", "themes")
86- bleuThemeDir := filepath.Join(themesDir, "bleu")
87- currentDir := filepath.Join(relativeHome, ".local", "share", "archup", "current")
88-
89- cloneCmd := fmt.Sprintf("su - %s -c 'mkdir -p %s && git clone https://github.com/bnema/bleu-theme.git %s'",
90- username, themesDir, bleuThemeDir)
91- if err := c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, cloneCmd); err != nil {
92- result.Warnings = append(result.Warnings, "Failed to clone bleu-theme repository")
93- }
94-
95- // Create current theme symlink
96- symlinkCmd := fmt.Sprintf("su - %s -c 'mkdir -p %s && ln -snf %s %s/theme'",
97- username, currentDir, bleuThemeDir, currentDir)
98- if err := c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, symlinkCmd); err != nil {
99- result.Warnings = append(result.Warnings, "Failed to create theme symlink")
100- }
101-
102- // Apply themes to CLI tools
103- themeResult := c.applyThemes(username, userHome)
104- result.ThemesApplied = themeResult.Applied
105- result.ThemesFailed = themeResult.Failed
106- result.Warnings = append(result.Warnings, themeResult.Warnings...)
107-
108- // Configure git delta
109- gitCommands := []string{
110- fmt.Sprintf("su - %s -c 'git config --global core.pager delta'", username),
111- fmt.Sprintf("su - %s -c 'git config --global interactive.diffFilter \"delta --color-only\"'", username),
112- fmt.Sprintf("su - %s -c 'git config --global delta.navigate true'", username),
113- fmt.Sprintf("su - %s -c 'git config --global delta.light false'", username),
114- fmt.Sprintf("su - %s -c 'git config --global delta.side-by-side true'", username),
115- fmt.Sprintf("su - %s -c 'git config --global merge.conflictstyle diff3'", username),
116- fmt.Sprintf("su - %s -c 'git config --global diff.colorMoved default'", username),
117- }
118-
119- for _, gitCmd := range gitCommands {
120- if err := c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, gitCmd); err != nil {
121- result.Warnings = append(result.Warnings, "Failed to configure git delta")
122- break
123- }
124- }
125-
126- return result, nil
127-}
128-
129-// copyShellTemplates copies shell config templates to user directory
130-func (c *Configurator) copyShellTemplates(archupDefault, archupDefaultBash string) error {
131- templates := map[string]string{
132- config.ShellConfigTemplate: filepath.Join(archupDefaultBash, "shell"),
133- config.ShellInitTemplate: filepath.Join(archupDefaultBash, "init"),
134- config.ShellAliasesTemplate: filepath.Join(archupDefaultBash, "aliases"),
135- config.ShellEnvsTemplate: filepath.Join(archupDefaultBash, "envs"),
136- config.ShellRcTemplate: filepath.Join(archupDefaultBash, "rc"),
137- }
138-
139- for template, dest := range templates {
140- content, err := c.readTemplate(template)
141- if err != nil {
142- return fmt.Errorf("failed to read template %s: %w", template, err)
143- }
144-
145- if err := c.fs.WriteFile(dest, content, 0644); err != nil {
146- return fmt.Errorf("failed to write %s: %w", dest, err)
147- }
148- }
149-
150- return nil
151-}
152-
153-// readTemplate reads a template file from install path
154-func (c *Configurator) readTemplate(filename string) ([]byte, error) {
155- // Use DefaultInstallDir directly to match where bootstrap downloads files
156- templatePath := filepath.Join(config.DefaultInstallDir, filename)
157- return c.fs.ReadFile(templatePath)
158-}
159-
160-// setShellOwnership sets ownership of shell config files to user
161-func (c *Configurator) setShellOwnership(userHome, username string) error {
162- // Use chroot to run chown
163- relativeHome := strings.TrimPrefix(userHome, config.PathMnt)
164- chownCmd := fmt.Sprintf("chown -R %s:%s %s/.local %s/.bashrc",
165- username, username, relativeHome, relativeHome)
166- return c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, chownCmd)
167 }49 }
M internal/shell/themes.go +2 -195
@@ -1,13 +1,5 @@
11 package shell
22
3-import (
4- "fmt"
5- "path/filepath"
6- "strings"
7-
8- "github.com/bnema/archup/internal/config"
9-)
10-
113 // ThemeResult holds the result of theme application
124 type ThemeResult struct {
135 Applied int
@@ -15,196 +7,11 @@ type ThemeResult struct {
157 Warnings []string
168 }
179
18-// applyThemes orchestrates centralized theme symlink setup for all CLI tools
10+// applyThemes is a no-op. Theme setup is handled by cli-tools.sh at first boot.
1911 func (c *Configurator) applyThemes(username, userHome string) ThemeResult {
20- result := ThemeResult{
12+ return ThemeResult{
2113 Applied: 0,
2214 Failed: []string{},
2315 Warnings: []string{},
2416 }
25-
26- // Strip /mnt prefix for use in chroot commands
27- relativeHome := strings.TrimPrefix(userHome, config.PathMnt)
28-
29- // Step 1: Setup central theme directory structure
30- if err := c.setupCentralThemeDirectory(username, relativeHome); err != nil {
31- result.Warnings = append(result.Warnings, fmt.Sprintf("Failed to setup central theme directory: %v", err))
32- return result
33- }
34-
35- // Step 2: Create central symlinks pointing to active theme (bleu)
36- if err := c.createCentralSymlinks(username, relativeHome, "bleu"); err != nil {
37- result.Warnings = append(result.Warnings, fmt.Sprintf("Failed to create central symlinks: %v", err))
38- return result
39- }
40-
41- // Step 3: Apply each tool's theme configuration
42- tools := []struct {
43- name string
44- apply func(string, string) error
45- }{
46- {"starship", c.applyStarshipTheme},
47- {"eza", c.applyEzaTheme},
48- {"bat", c.applyBatTheme},
49- {"btop", c.applyBtopTheme},
50- {"yazi", c.applyYaziTheme},
51- }
52-
53- for _, tool := range tools {
54- if err := tool.apply(username, relativeHome); err != nil {
55- result.Failed = append(result.Failed, tool.name)
56- result.Warnings = append(result.Warnings, fmt.Sprintf("Failed to configure %s: %v", tool.name, err))
57- } else {
58- result.Applied++
59- }
60- }
61-
62- return result
63-}
64-
65-// setupCentralThemeDirectory creates ~/.local/share/archup/themes/current/
66-func (c *Configurator) setupCentralThemeDirectory(username, relativeHome string) error {
67- centralThemeDir := filepath.Join(relativeHome, ".local", "share", "archup", "themes", "current")
68-
69- mkdirCmd := fmt.Sprintf("su - %s -c 'mkdir -p %s'", username, centralThemeDir)
70- if err := c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, mkdirCmd); err != nil {
71- return fmt.Errorf("failed to create central theme directory: %w", err)
72- }
73-
74- return nil
75-}
76-
77-// createCentralSymlinks creates symlinks in themes/current/ pointing to active theme files
78-func (c *Configurator) createCentralSymlinks(username, relativeHome, activeTheme string) error {
79- themesDir := filepath.Join(relativeHome, ".local", "share", "archup", "themes")
80- centralDir := filepath.Join(themesDir, "current")
81- themeSource := filepath.Join(themesDir, activeTheme)
82-
83- // Map of symlink name -> target path
84- symlinks := map[string]string{
85- "starship.toml": filepath.Join(themeSource, "starship", "bleu.toml"),
86- "eza.yml": filepath.Join(themeSource, "eza", "theme.yml"),
87- "bat.tmTheme": filepath.Join(themeSource, "bat", "bleu.tmTheme"),
88- "btop.theme": filepath.Join(themeSource, "btop", "bleu.theme"),
89- "yazi.toml": filepath.Join(themeSource, "yazi", "bleu.toml"),
90- "fzf.sh": filepath.Join(themeSource, "fzf", "bleu.sh"),
91- }
92-
93- for linkName, target := range symlinks {
94- linkPath := filepath.Join(centralDir, linkName)
95-
96- // Use ln -snf: -s for symbolic, -n to handle existing symlink as file, -f to force overwrite
97- symlinkCmd := fmt.Sprintf("su - %s -c 'ln -snf %s %s'",
98- username, target, linkPath)
99-
100- if err := c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, symlinkCmd); err != nil {
101- return fmt.Errorf("failed to create symlink %s -> %s: %w", linkName, target, err)
102- }
103- }
104-
105- return nil
106-}
107-
108-// applyStarshipTheme configures starship to use central symlink
109-// Note: Actual configuration happens via STARSHIP_CONFIG env var in configs/shell/init
110-func (c *Configurator) applyStarshipTheme(username, relativeHome string) error {
111- // Starship uses STARSHIP_CONFIG environment variable pointing to themes/current/starship.toml
112- // No additional setup needed - the symlink is already created by createCentralSymlinks()
113- // Shell config will be updated separately to export STARSHIP_CONFIG
114- return nil
115-}
116-
117-// applyEzaTheme creates symlink in eza config directory pointing to central theme
118-func (c *Configurator) applyEzaTheme(username, relativeHome string) error {
119- ezaConfigDir := filepath.Join(relativeHome, ".config", "eza")
120- centralTheme := filepath.Join(relativeHome, ".local", "share", "archup", "themes", "current", "eza.yml")
121- ezaThemeLink := filepath.Join(ezaConfigDir, "theme.yml")
122-
123- commands := []string{
124- fmt.Sprintf("su - %s -c 'mkdir -p %s'", username, ezaConfigDir),
125- fmt.Sprintf("su - %s -c 'ln -snf %s %s'", username, centralTheme, ezaThemeLink),
126- }
127-
128- for _, cmd := range commands {
129- if err := c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, cmd); err != nil {
130- return fmt.Errorf("eza theme setup failed: %w", err)
131- }
132- }
133-
134- return nil
135-}
136-
137-// applyBatTheme creates symlink in bat themes directory and configures bat.conf
138-func (c *Configurator) applyBatTheme(username, relativeHome string) error {
139- batThemesDir := filepath.Join(relativeHome, ".config", "bat", "themes")
140- centralTheme := filepath.Join(relativeHome, ".local", "share", "archup", "themes", "current", "bat.tmTheme")
141- batThemeLink := filepath.Join(batThemesDir, "current.tmTheme")
142-
143- commands := []string{
144- // Create bat themes directory
145- fmt.Sprintf("su - %s -c 'mkdir -p %s'", username, batThemesDir),
146-
147- // Create symlink: ~/.config/bat/themes/current.tmTheme -> themes/current/bat.tmTheme
148- fmt.Sprintf("su - %s -c 'ln -snf %s %s'", username, centralTheme, batThemeLink),
149-
150- // Create bat config referencing "current" theme
151- fmt.Sprintf("su - %s -c 'echo \"--theme=\\\"current\\\"\" > ~/.config/bat/bat.conf'", username),
152-
153- // Build bat cache to register the theme
154- fmt.Sprintf("su - %s -c 'bat cache --build'", username),
155- }
156-
157- for _, cmd := range commands {
158- if err := c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, cmd); err != nil {
159- return fmt.Errorf("bat theme setup failed: %w", err)
160- }
161- }
162-
163- return nil
164-}
165-
166-// applyBtopTheme creates symlink in btop themes directory
167-func (c *Configurator) applyBtopTheme(username, relativeHome string) error {
168- btopThemesDir := filepath.Join(relativeHome, ".config", "btop", "themes")
169- centralTheme := filepath.Join(relativeHome, ".local", "share", "archup", "themes", "current", "btop.theme")
170- btopThemeLink := filepath.Join(btopThemesDir, "current.theme")
171-
172- commands := []string{
173- // Create btop themes directory
174- fmt.Sprintf("su - %s -c 'mkdir -p %s'", username, btopThemesDir),
175-
176- // Create symlink: ~/.config/btop/themes/current.theme -> themes/current/btop.theme
177- fmt.Sprintf("su - %s -c 'ln -snf %s %s'", username, centralTheme, btopThemeLink),
178- }
179-
180- for _, cmd := range commands {
181- if err := c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, cmd); err != nil {
182- return fmt.Errorf("btop theme setup failed: %w", err)
183- }
184- }
185-
186- return nil
187-}
188-
189-// applyYaziTheme creates yazi flavor directory with symlink to central theme
190-func (c *Configurator) applyYaziTheme(username, relativeHome string) error {
191- yaziFlavorDir := filepath.Join(relativeHome, ".config", "yazi", "flavors", "current")
192- centralTheme := filepath.Join(relativeHome, ".local", "share", "archup", "themes", "current", "yazi.toml")
193- yaziFlavorLink := filepath.Join(yaziFlavorDir, "flavor.toml")
194-
195- commands := []string{
196- // Create yazi flavor directory for "current" theme
197- fmt.Sprintf("su - %s -c 'mkdir -p %s'", username, yaziFlavorDir),
198-
199- // Create symlink: ~/.config/yazi/flavors/current/flavor.toml -> themes/current/yazi.toml
200- fmt.Sprintf("su - %s -c 'ln -snf %s %s'", username, centralTheme, yaziFlavorLink),
201- }
202-
203- for _, cmd := range commands {
204- if err := c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, cmd); err != nil {
205- return fmt.Errorf("yazi theme setup failed: %w", err)
206- }
207- }
208-
209- return nil
21017 }
@@ -1,13 +1,5 @@
1 package shell1 package shell
2 2
3-import (
4- "fmt"
5- "path/filepath"
6- "strings"
7-
8- "github.com/bnema/archup/internal/config"
9-)
10-
11 // ThemeResult holds the result of theme application3 // ThemeResult holds the result of theme application
12 type ThemeResult struct {4 type ThemeResult struct {
13 Applied int5 Applied int
@@ -15,196 +7,11 @@ type ThemeResult struct {
15 Warnings []string7 Warnings []string
16 }8 }
17 9
18-// applyThemes orchestrates centralized theme symlink setup for all CLI tools10+// applyThemes is a no-op. Theme setup is handled by cli-tools.sh at first boot.
19 func (c *Configurator) applyThemes(username, userHome string) ThemeResult {11 func (c *Configurator) applyThemes(username, userHome string) ThemeResult {
20- result := ThemeResult{12+ return ThemeResult{
21 Applied: 0,13 Applied: 0,
22 Failed: []string{},14 Failed: []string{},
23 Warnings: []string{},15 Warnings: []string{},
24 }16 }
25-
26- // Strip /mnt prefix for use in chroot commands
27- relativeHome := strings.TrimPrefix(userHome, config.PathMnt)
28-
29- // Step 1: Setup central theme directory structure
30- if err := c.setupCentralThemeDirectory(username, relativeHome); err != nil {
31- result.Warnings = append(result.Warnings, fmt.Sprintf("Failed to setup central theme directory: %v", err))
32- return result
33- }
34-
35- // Step 2: Create central symlinks pointing to active theme (bleu)
36- if err := c.createCentralSymlinks(username, relativeHome, "bleu"); err != nil {
37- result.Warnings = append(result.Warnings, fmt.Sprintf("Failed to create central symlinks: %v", err))
38- return result
39- }
40-
41- // Step 3: Apply each tool's theme configuration
42- tools := []struct {
43- name string
44- apply func(string, string) error
45- }{
46- {"starship", c.applyStarshipTheme},
47- {"eza", c.applyEzaTheme},
48- {"bat", c.applyBatTheme},
49- {"btop", c.applyBtopTheme},
50- {"yazi", c.applyYaziTheme},
51- }
52-
53- for _, tool := range tools {
54- if err := tool.apply(username, relativeHome); err != nil {
55- result.Failed = append(result.Failed, tool.name)
56- result.Warnings = append(result.Warnings, fmt.Sprintf("Failed to configure %s: %v", tool.name, err))
57- } else {
58- result.Applied++
59- }
60- }
61-
62- return result
63-}
64-
65-// setupCentralThemeDirectory creates ~/.local/share/archup/themes/current/
66-func (c *Configurator) setupCentralThemeDirectory(username, relativeHome string) error {
67- centralThemeDir := filepath.Join(relativeHome, ".local", "share", "archup", "themes", "current")
68-
69- mkdirCmd := fmt.Sprintf("su - %s -c 'mkdir -p %s'", username, centralThemeDir)
70- if err := c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, mkdirCmd); err != nil {
71- return fmt.Errorf("failed to create central theme directory: %w", err)
72- }
73-
74- return nil
75-}
76-
77-// createCentralSymlinks creates symlinks in themes/current/ pointing to active theme files
78-func (c *Configurator) createCentralSymlinks(username, relativeHome, activeTheme string) error {
79- themesDir := filepath.Join(relativeHome, ".local", "share", "archup", "themes")
80- centralDir := filepath.Join(themesDir, "current")
81- themeSource := filepath.Join(themesDir, activeTheme)
82-
83- // Map of symlink name -> target path
84- symlinks := map[string]string{
85- "starship.toml": filepath.Join(themeSource, "starship", "bleu.toml"),
86- "eza.yml": filepath.Join(themeSource, "eza", "theme.yml"),
87- "bat.tmTheme": filepath.Join(themeSource, "bat", "bleu.tmTheme"),
88- "btop.theme": filepath.Join(themeSource, "btop", "bleu.theme"),
89- "yazi.toml": filepath.Join(themeSource, "yazi", "bleu.toml"),
90- "fzf.sh": filepath.Join(themeSource, "fzf", "bleu.sh"),
91- }
92-
93- for linkName, target := range symlinks {
94- linkPath := filepath.Join(centralDir, linkName)
95-
96- // Use ln -snf: -s for symbolic, -n to handle existing symlink as file, -f to force overwrite
97- symlinkCmd := fmt.Sprintf("su - %s -c 'ln -snf %s %s'",
98- username, target, linkPath)
99-
100- if err := c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, symlinkCmd); err != nil {
101- return fmt.Errorf("failed to create symlink %s -> %s: %w", linkName, target, err)
102- }
103- }
104-
105- return nil
106-}
107-
108-// applyStarshipTheme configures starship to use central symlink
109-// Note: Actual configuration happens via STARSHIP_CONFIG env var in configs/shell/init
110-func (c *Configurator) applyStarshipTheme(username, relativeHome string) error {
111- // Starship uses STARSHIP_CONFIG environment variable pointing to themes/current/starship.toml
112- // No additional setup needed - the symlink is already created by createCentralSymlinks()
113- // Shell config will be updated separately to export STARSHIP_CONFIG
114- return nil
115-}
116-
117-// applyEzaTheme creates symlink in eza config directory pointing to central theme
118-func (c *Configurator) applyEzaTheme(username, relativeHome string) error {
119- ezaConfigDir := filepath.Join(relativeHome, ".config", "eza")
120- centralTheme := filepath.Join(relativeHome, ".local", "share", "archup", "themes", "current", "eza.yml")
121- ezaThemeLink := filepath.Join(ezaConfigDir, "theme.yml")
122-
123- commands := []string{
124- fmt.Sprintf("su - %s -c 'mkdir -p %s'", username, ezaConfigDir),
125- fmt.Sprintf("su - %s -c 'ln -snf %s %s'", username, centralTheme, ezaThemeLink),
126- }
127-
128- for _, cmd := range commands {
129- if err := c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, cmd); err != nil {
130- return fmt.Errorf("eza theme setup failed: %w", err)
131- }
132- }
133-
134- return nil
135-}
136-
137-// applyBatTheme creates symlink in bat themes directory and configures bat.conf
138-func (c *Configurator) applyBatTheme(username, relativeHome string) error {
139- batThemesDir := filepath.Join(relativeHome, ".config", "bat", "themes")
140- centralTheme := filepath.Join(relativeHome, ".local", "share", "archup", "themes", "current", "bat.tmTheme")
141- batThemeLink := filepath.Join(batThemesDir, "current.tmTheme")
142-
143- commands := []string{
144- // Create bat themes directory
145- fmt.Sprintf("su - %s -c 'mkdir -p %s'", username, batThemesDir),
146-
147- // Create symlink: ~/.config/bat/themes/current.tmTheme -> themes/current/bat.tmTheme
148- fmt.Sprintf("su - %s -c 'ln -snf %s %s'", username, centralTheme, batThemeLink),
149-
150- // Create bat config referencing "current" theme
151- fmt.Sprintf("su - %s -c 'echo \"--theme=\\\"current\\\"\" > ~/.config/bat/bat.conf'", username),
152-
153- // Build bat cache to register the theme
154- fmt.Sprintf("su - %s -c 'bat cache --build'", username),
155- }
156-
157- for _, cmd := range commands {
158- if err := c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, cmd); err != nil {
159- return fmt.Errorf("bat theme setup failed: %w", err)
160- }
161- }
162-
163- return nil
164-}
165-
166-// applyBtopTheme creates symlink in btop themes directory
167-func (c *Configurator) applyBtopTheme(username, relativeHome string) error {
168- btopThemesDir := filepath.Join(relativeHome, ".config", "btop", "themes")
169- centralTheme := filepath.Join(relativeHome, ".local", "share", "archup", "themes", "current", "btop.theme")
170- btopThemeLink := filepath.Join(btopThemesDir, "current.theme")
171-
172- commands := []string{
173- // Create btop themes directory
174- fmt.Sprintf("su - %s -c 'mkdir -p %s'", username, btopThemesDir),
175-
176- // Create symlink: ~/.config/btop/themes/current.theme -> themes/current/btop.theme
177- fmt.Sprintf("su - %s -c 'ln -snf %s %s'", username, centralTheme, btopThemeLink),
178- }
179-
180- for _, cmd := range commands {
181- if err := c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, cmd); err != nil {
182- return fmt.Errorf("btop theme setup failed: %w", err)
183- }
184- }
185-
186- return nil
187-}
188-
189-// applyYaziTheme creates yazi flavor directory with symlink to central theme
190-func (c *Configurator) applyYaziTheme(username, relativeHome string) error {
191- yaziFlavorDir := filepath.Join(relativeHome, ".config", "yazi", "flavors", "current")
192- centralTheme := filepath.Join(relativeHome, ".local", "share", "archup", "themes", "current", "yazi.toml")
193- yaziFlavorLink := filepath.Join(yaziFlavorDir, "flavor.toml")
194-
195- commands := []string{
196- // Create yazi flavor directory for "current" theme
197- fmt.Sprintf("su - %s -c 'mkdir -p %s'", username, yaziFlavorDir),
198-
199- // Create symlink: ~/.config/yazi/flavors/current/flavor.toml -> themes/current/yazi.toml
200- fmt.Sprintf("su - %s -c 'ln -snf %s %s'", username, centralTheme, yaziFlavorLink),
201- }
202-
203- for _, cmd := range commands {
204- if err := c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, cmd); err != nil {
205- return fmt.Errorf("yazi theme setup failed: %w", err)
206- }
207- }
208-
209- return nil
210 }17 }

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 0

    ↑↓ moveenter openesc close