github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/internal/osutils/autostart/autostart_linux.go (about) 1 package autostart 2 3 import ( 4 "os" 5 "path/filepath" 6 "strings" 7 8 "github.com/ActiveState/cli/internal/constants" 9 "github.com/ActiveState/cli/internal/errs" 10 "github.com/ActiveState/cli/internal/fileutils" 11 "github.com/ActiveState/cli/internal/osutils" 12 "github.com/ActiveState/cli/internal/osutils/user" 13 "github.com/ActiveState/cli/internal/subshell/sscommon" 14 ) 15 16 func enable(exec string, opts Options) error { 17 profile, err := profilePath() 18 if err != nil { 19 return errs.Wrap(err, "Could not get profile path") 20 } 21 22 enabled, err := isEnabled(exec, opts) 23 if err != nil { 24 return errs.Wrap(err, "Could not check if autostart is already enabled") 25 } 26 if enabled { 27 return nil 28 } 29 30 esc := osutils.NewBashEscaper() 31 exec = esc.Quote(exec) 32 for _, arg := range opts.Args { 33 exec += " " + esc.Quote(arg) 34 } 35 36 if err := sscommon.WriteRcData(exec, profile, sscommon.AutostartID); err != nil { 37 return errs.Wrap(err, "Could not update %s with autostart entry", profile) 38 } 39 40 return nil 41 } 42 43 func disable(exec string, opts Options) error { 44 profile, err := profilePath() 45 if err != nil { 46 return errs.Wrap(err, "Could not get profile path") 47 } 48 49 if fileutils.FileExists(profile) { 50 if err := sscommon.CleanRcFile(profile, sscommon.AutostartID); err != nil { 51 return errs.Wrap(err, "Could not clean autostart entry from %s", profile) 52 } 53 } 54 55 return nil 56 } 57 58 // isEnabled, for Linux, does not verify legacy "Desktop" autostart setups, so 59 // should be used carefully with that in mind. External code should only use it 60 // within tests. 61 func isEnabled(exec string, opts Options) (bool, error) { 62 profile, err := profilePath() 63 if err != nil { 64 return false, errs.Wrap(err, "Could not get profile path") 65 } 66 67 if fileutils.FileExists(profile) { 68 data, err := fileutils.ReadFile(profile) 69 if err != nil { 70 return false, errs.Wrap(err, "Could not read %s", profile) 71 } 72 return strings.Contains(string(data), exec), nil 73 } 74 75 return false, nil 76 } 77 78 func autostartPath(name string, opts Options) (string, error) { 79 // Linux uses ~/.profile modification for autostart, there is no actual 80 // autostartPath. 81 return "", nil 82 } 83 84 func upgrade(_ string, opts Options) error { 85 if err := legacyDisableOnDesktop(opts.LaunchFileName); err != nil { 86 return errs.Wrap(err, "Could not disable legacy autostart (desktop)") 87 } 88 89 profile, err := profilePath() 90 if err != nil { 91 return errs.Wrap(err, "Could not get profile path") 92 } 93 94 if err := legacyRemoveAutostartEntry(profile); err != nil { 95 return errs.Wrap(err, "Could not clean up legacy autostart entry (server)") 96 } 97 98 return nil 99 } 100 101 func prependHomeDir(path string) (string, error) { 102 homeDir, err := user.HomeDir() 103 if err != nil { 104 return "", errs.Wrap(err, "Could not get home directory") 105 } 106 if testDir, ok := os.LookupEnv(constants.AutostartPathOverrideEnvVarName); ok { 107 homeDir = testDir 108 } 109 return filepath.Join(homeDir, path), nil 110 } 111 112 func profilePath() (string, error) { 113 autostartFile := ".profile" 114 115 profile, err := prependHomeDir(autostartFile) 116 if err != nil { 117 return "", errs.Wrap(err, "Could not find ~/%s", autostartFile) 118 } 119 120 return profile, nil 121 } 122 123 // https://activestatef.atlassian.net/browse/DX-1677 124 func legacyDisableOnDesktop(launchFileName string) error { 125 autostartDir := ".config/autostart" 126 127 dir, err := prependHomeDir(autostartDir) 128 if err != nil { 129 return errs.Wrap(err, "Could not find ~/%s", autostartDir) 130 } 131 132 path := filepath.Join(dir, launchFileName) 133 134 if fileutils.FileExists(path) { 135 err := os.Remove(path) 136 if err != nil { 137 return errs.Wrap(err, "Could not remove shortcut") 138 } 139 } 140 141 return nil 142 } 143 144 // https://activestatef.atlassian.net/browse/DX-1677 145 func legacyRemoveAutostartEntry(profileFile string) error { 146 if !fileutils.FileExists(profileFile) { 147 return nil 148 } 149 150 if err := sscommon.CleanRcFile(profileFile, sscommon.InstallID); err != nil { 151 return errs.Wrap(err, "Could not clean %s", profileFile) 152 } 153 154 return nil 155 }