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  }