feat: add Linux system-wide setup

Install shared shims, managed configuration, and login-shell PATH integration so golden images and multi-user hosts can protect package installs for every user.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Sahilb315
2026-07-11 02:19:59 +05:30
co-authored by Cursor
parent d3e656edcd
commit 8f6d0fcce0
19 changed files with 915 additions and 66 deletions
+35
View File
@@ -18,6 +18,11 @@ type ShimConfig struct {
PMGBin string
PackageManagers []string
Shells []alias.Shell
// SkipShellRc skips per-user shell rc PATH edits. Used by system install,
// which relies on /etc/profile.d or ENV PATH instead.
SkipShellRc bool
// ManageProfile writes and removes /etc/profile.d/pmg.sh with Install/Remove.
ManageProfile bool
}
type ShimManager struct {
@@ -68,6 +73,16 @@ func (m *ShimManager) Install() error {
}
}
if m.config.ManageProfile {
if err := writeSystemProfile(); err != nil {
return fmt.Errorf("failed to write system profile: %w", err)
}
}
if m.config.SkipShellRc {
return nil
}
if err := m.addPathToShells(); err != nil {
return fmt.Errorf("failed to update shell configs: %w", err)
}
@@ -80,6 +95,16 @@ func (m *ShimManager) Remove() error {
log.Warnf("Warning: failed to remove shim directory: %v", err)
}
if m.config.ManageProfile {
if err := removeSystemProfile(); err != nil {
return fmt.Errorf("failed to remove system profile: %w", err)
}
}
if m.config.SkipShellRc {
return nil
}
if err := m.removePathFromShells(); err != nil {
return fmt.Errorf("failed to clean shell configs: %w", err)
}
@@ -207,3 +232,13 @@ func (m *ShimManager) removePathFromShells() error {
return nil
}
// UserShimsInstalled reports whether the per-user shim directory (~/.pmg/bin)
// contains at least one shim script.
func UserShimsInstalled() bool {
homeDir, err := os.UserHomeDir()
if err != nil {
return false
}
return shimsPresent(filepath.Join(homeDir, ".pmg", "bin"))
}