mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
fix: MacOS MDM based Deployment (#277)
* fix: MacOS MDM deployment script * fix: Handle shell alias for bash on macos * fix: Code review fixes * fix: Code review fixes * feat: Add support for global config file * feat: Add support for global config file * fix: Code review fixes * fix: Avoid blocking CLI for analytics flush
This commit is contained in:
+51
-84
@@ -1,8 +1,6 @@
|
||||
package shim
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -91,19 +89,19 @@ func (m *ShimManager) Remove() error {
|
||||
|
||||
func (m *ShimManager) IsInstalled() (bool, error) {
|
||||
for _, shell := range m.config.Shells {
|
||||
configPath := filepath.Join(m.config.HomeDir, shell.Path())
|
||||
|
||||
data, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
for _, configPath := range shell.CandidateRcFiles(m.config.HomeDir) {
|
||||
data, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
log.Warnf("Warning: could not read %s (%s)", configPath, err)
|
||||
continue
|
||||
}
|
||||
log.Warnf("Warning: could not read %s (%s)", shell.Name(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.Contains(string(data), shimMarker) {
|
||||
return true, nil
|
||||
if strings.Contains(string(data), shimMarker) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,93 +149,62 @@ func shellQuote(value string) string {
|
||||
}
|
||||
|
||||
func (m *ShimManager) addPathToShells() error {
|
||||
primary := alias.PrimaryShellName()
|
||||
for _, shell := range m.config.Shells {
|
||||
configPath := filepath.Join(m.config.HomeDir, shell.Path())
|
||||
|
||||
data, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
log.Warnf("Warning: skipping %s (%s)", shell.Name(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.Contains(string(data), shimMarker) {
|
||||
continue
|
||||
}
|
||||
|
||||
f, err := os.OpenFile(configPath, os.O_APPEND|os.O_WRONLY, 0o644)
|
||||
files, err := shell.InstallRcFiles(m.config.HomeDir, shell.Name() == primary)
|
||||
if err != nil {
|
||||
log.Warnf("Warning: skipping %s (%s)", shell.Name(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintf(f, "\n%s", shell.PathExport(m.config.BinDir))
|
||||
if closeErr := f.Close(); closeErr != nil {
|
||||
log.Warnf("Warning: failed to close %s: %s", shell.Name(), closeErr)
|
||||
}
|
||||
if err != nil {
|
||||
log.Warnf("Warning: failed to write PATH export to %s: %s", shell.Name(), err)
|
||||
for _, configPath := range files {
|
||||
m.addPathToFile(configPath, shell)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// addPathToFile appends the shell's PATH export to a single config file unless
|
||||
// it is already present. A missing file is a no-op.
|
||||
func (m *ShimManager) addPathToFile(configPath string, shell alias.Shell) {
|
||||
data, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
log.Warnf("Warning: skipping %s (%s)", configPath, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if strings.Contains(string(data), shimMarker) {
|
||||
return
|
||||
}
|
||||
|
||||
f, err := os.OpenFile(configPath, os.O_APPEND|os.O_WRONLY, 0o644)
|
||||
if err != nil {
|
||||
log.Warnf("Warning: skipping %s (%s)", configPath, err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintf(f, "\n%s", shell.PathExport(m.config.BinDir))
|
||||
if closeErr := f.Close(); closeErr != nil {
|
||||
log.Warnf("Warning: failed to close %s: %s", configPath, closeErr)
|
||||
}
|
||||
if err != nil {
|
||||
log.Warnf("Warning: failed to write PATH export to %s: %s", configPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *ShimManager) removePathFromShells() error {
|
||||
drop := func(line string) bool {
|
||||
return strings.Contains(line, shimMarker)
|
||||
}
|
||||
|
||||
for _, shell := range m.config.Shells {
|
||||
configPath := filepath.Join(m.config.HomeDir, shell.Path())
|
||||
|
||||
data, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
continue
|
||||
for _, configPath := range shell.CandidateRcFiles(m.config.HomeDir) {
|
||||
if err := alias.RewriteFileDroppingLines(configPath, drop); err != nil {
|
||||
log.Warnf("Warning: failed to update %s: %s", configPath, err)
|
||||
}
|
||||
log.Warnf("Warning: skipping %s (%s)", shell.Name(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
info, err := os.Stat(configPath)
|
||||
if err != nil {
|
||||
log.Warnf("Warning: skipping %s (%s)", shell.Name(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
tempFile, err := os.CreateTemp(filepath.Dir(configPath), ".tmp-"+filepath.Base(configPath))
|
||||
if err != nil {
|
||||
log.Warnf("Warning: failed to create temporary file for %s: %s", configPath, err)
|
||||
continue
|
||||
}
|
||||
tempPath := tempFile.Name()
|
||||
|
||||
scanner := bufio.NewScanner(bytes.NewReader(data))
|
||||
writer := bufio.NewWriter(tempFile)
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if strings.Contains(line, shimMarker) {
|
||||
continue
|
||||
}
|
||||
if _, err := writer.WriteString(line + "\n"); err != nil {
|
||||
log.Warnf("Warning: failed to write to temporary file: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := writer.Flush(); err != nil {
|
||||
log.Warnf("Warning: failed to flush temporary file: %s", err)
|
||||
}
|
||||
if err := tempFile.Close(); err != nil {
|
||||
log.Warnf("Warning: failed to close temporary file: %s", err)
|
||||
}
|
||||
|
||||
if err := os.Chmod(tempPath, info.Mode()); err != nil {
|
||||
log.Warnf("Warning: failed to set permissions on temporary file: %s", err)
|
||||
}
|
||||
|
||||
if err := os.Rename(tempPath, configPath); err != nil {
|
||||
_ = os.Remove(tempPath)
|
||||
log.Warnf("Warning: failed to update %s: %s", configPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -197,4 +197,31 @@ func (s *stubShell) PathExport(binDir string) string {
|
||||
}
|
||||
|
||||
func (s *stubShell) Name() string { return s.name }
|
||||
func (s *stubShell) Path() string { return s.path }
|
||||
|
||||
func (s *stubShell) CandidateRcFiles(homeDir string) []string {
|
||||
return []string{filepath.Join(homeDir, s.path)}
|
||||
}
|
||||
|
||||
func (s *stubShell) InstallRcFiles(homeDir string, create bool) ([]string, error) {
|
||||
path := filepath.Join(homeDir, s.path)
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
return []string{path}, nil
|
||||
}
|
||||
|
||||
if !create {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0o644)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := f.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return []string{path}, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user