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:
+105
-2
@@ -1,9 +1,20 @@
|
||||
package alias
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type bashShell struct{}
|
||||
|
||||
var _ Shell = &bashShell{}
|
||||
|
||||
// bashLoginFiles are the login startup files in the order bash reads them.
|
||||
var bashLoginFiles = []string{".bash_profile", ".bash_login", ".profile"}
|
||||
|
||||
func NewBashShell() (*bashShell, error) {
|
||||
return &bashShell{}, nil
|
||||
}
|
||||
@@ -20,6 +31,98 @@ func (b bashShell) Name() string {
|
||||
return "bash"
|
||||
}
|
||||
|
||||
func (b bashShell) Path() string {
|
||||
return ".bashrc"
|
||||
func (b bashShell) CandidateRcFiles(homeDir string) []string {
|
||||
files := []string{filepath.Join(homeDir, ".bashrc")}
|
||||
for _, name := range bashLoginFiles {
|
||||
files = append(files, filepath.Join(homeDir, name))
|
||||
}
|
||||
|
||||
return files
|
||||
}
|
||||
|
||||
func (b bashShell) InstallRcFiles(homeDir string, create bool) ([]string, error) {
|
||||
return bashInstallRcFiles(homeDir, create, runtime.GOOS)
|
||||
}
|
||||
|
||||
// bashInstallRcFiles resolves where bash should load PMG. bash reads .bashrc for
|
||||
// interactive non-login shells and a login file (.bash_profile, .bash_login, or
|
||||
// .profile) for login shells such as macOS Terminal, so the lines may need to
|
||||
// land in both. goos is a parameter for testability.
|
||||
func bashInstallRcFiles(homeDir string, create bool, goos string) ([]string, error) {
|
||||
bashrc := filepath.Join(homeDir, ".bashrc")
|
||||
bashrcExists := fileExists(bashrc)
|
||||
login := firstExistingFile(homeDir, bashLoginFiles)
|
||||
|
||||
var files []string
|
||||
if bashrcExists {
|
||||
files = append(files, bashrc)
|
||||
}
|
||||
|
||||
// macOS Terminal starts bash as a login shell, which does not read .bashrc.
|
||||
// Create .bash_profile so the lines reach login shells too.
|
||||
if login == "" && create && goos == "darwin" {
|
||||
login = filepath.Join(homeDir, ".bash_profile")
|
||||
if err := ensureFile(login); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Skip the login file when it already sources .bashrc, to avoid loading the
|
||||
// lines twice.
|
||||
if login != "" && (!bashrcExists || !referencesBashrc(login)) {
|
||||
files = append(files, login)
|
||||
}
|
||||
|
||||
if len(files) > 0 {
|
||||
return files, nil
|
||||
}
|
||||
|
||||
if !create {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Nothing exists yet: create the canonical file for this OS.
|
||||
target := bashrc
|
||||
if goos == "darwin" {
|
||||
target = filepath.Join(homeDir, ".bash_profile")
|
||||
}
|
||||
|
||||
if err := ensureFile(target); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return []string{target}, nil
|
||||
}
|
||||
|
||||
// bashrcSourceRe matches a real sourcing of a bashrc file: a `source` or `.`
|
||||
// command whose argument ends in `.bashrc` (for example `source ~/.bashrc` or
|
||||
// `. "$HOME/.bashrc"`). Requiring the command keyword avoids matching mere
|
||||
// mentions in comments or unrelated commands.
|
||||
var bashrcSourceRe = regexp.MustCompile(`(^|[\s;&|()])(source|\.)\s+\S*\.bashrc($|[\s;'"&|)])`)
|
||||
|
||||
// referencesBashrc reports whether the file at path actually sources a bashrc
|
||||
// file. It skips comment lines and inline comments so a commented mention does
|
||||
// not wrongly suppress wiring the login file.
|
||||
func referencesBashrc(path string) bool {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, raw := range strings.Split(string(data), "\n") {
|
||||
line := strings.TrimSpace(raw)
|
||||
if line == "" || strings.HasPrefix(line, "#") {
|
||||
continue
|
||||
}
|
||||
|
||||
if i := strings.Index(line, "#"); i >= 0 {
|
||||
line = line[:i]
|
||||
}
|
||||
|
||||
if bashrcSourceRe.MatchString(line) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user