github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/install/libnativeinstaller/app.go (about)

     1  // Copyright 2017 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  package libnativeinstaller
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  	"os/exec"
    10  	"path/filepath"
    11  	"strings"
    12  
    13  	"github.com/keybase/client/go/libkb"
    14  	"github.com/keybase/client/go/utils"
    15  )
    16  
    17  // Log is the logging interface for this package
    18  type Log interface {
    19  	Debug(s string, args ...interface{})
    20  	Info(s string, args ...interface{})
    21  	Warning(s string, args ...interface{})
    22  	Errorf(s string, args ...interface{})
    23  }
    24  
    25  // Context is the environment for install package.
    26  type Context interface {
    27  	GetConfigDir() string
    28  	GetCacheDir() string
    29  	GetRuntimeDir() string
    30  	GetMountDir() (string, error)
    31  	GetLogDir() string
    32  	GetRunMode() libkb.RunMode
    33  	GetServiceInfoPath() string
    34  	GetKBFSInfoPath() string
    35  }
    36  
    37  // AppBundleForPath returns path to app bundle
    38  func AppBundleForPath() (string, error) {
    39  	path, err := utils.BinPath()
    40  	if err != nil {
    41  		return "", err
    42  	}
    43  	if path == "" {
    44  		return "", errors.New("Could not get executable name")
    45  	}
    46  	paths := strings.SplitN(path, ".app", 2)
    47  	// If no match, return ""
    48  	if len(paths) <= 1 {
    49  		return "", fmt.Errorf("Unable to resolve bundle for valid path: %s", path)
    50  	}
    51  
    52  	appPath := paths[0] + ".app"
    53  	if exists, _ := libkb.FileExists(appPath); !exists {
    54  		return "", fmt.Errorf("App not found: %s", appPath)
    55  	}
    56  
    57  	return appPath, nil
    58  }
    59  
    60  func nativeInstallerAppBundlePath(appPath string) string {
    61  	return filepath.Join(appPath, "Contents/Resources/KeybaseInstaller.app")
    62  }
    63  
    64  func nativeInstallerAppBundleExecPath(appPath string) string {
    65  	return filepath.Join(nativeInstallerAppBundlePath(appPath), "Contents/MacOS/Keybase")
    66  }
    67  
    68  func execNativeInstallerWithArg(args []string, runMode libkb.RunMode, log Log) error {
    69  	appPath, err := AppBundleForPath()
    70  	if err != nil {
    71  		return err
    72  	}
    73  	includeArgs := []string{"--debug", fmt.Sprintf("--run-mode=%s", runMode), fmt.Sprintf("--app-path=%s", appPath), "--timeout=10"}
    74  	args = append(includeArgs, args...)
    75  	cmd := exec.Command(nativeInstallerAppBundleExecPath(appPath), args...)
    76  	output, err := cmd.CombinedOutput()
    77  	log.Debug("Output (%s): %s", args, string(output))
    78  	return err
    79  }
    80  
    81  // InstallMountDir calls the installer with --install-mountdir.
    82  func InstallMountDir(runMode libkb.RunMode, log Log) error {
    83  	log.Info("Creating mount directory")
    84  	return execNativeInstallerWithArg([]string{"--install-mountdir"}, runMode, log)
    85  }
    86  
    87  // UninstallMountDir calls the installer with --uninstall-mountdir.
    88  func UninstallMountDir(runMode libkb.RunMode, log Log) error {
    89  	// We need the installer to remove the mount directory (since it's in the root, only the helper tool can do it)
    90  	return execNativeInstallerWithArg([]string{"--uninstall-mountdir"}, runMode, log)
    91  }
    92  
    93  // InstallRedirector calls the installer with --install-redirector.
    94  func InstallRedirector(runMode libkb.RunMode, log Log) error {
    95  	log.Info("Starting redirector")
    96  	return execNativeInstallerWithArg([]string{"--install-redirector"}, runMode, log)
    97  }
    98  
    99  // UninstallRedirector calls the installer with --uninstall-redirector.
   100  func UninstallRedirector(runMode libkb.RunMode, log Log) error {
   101  	return execNativeInstallerWithArg([]string{"--uninstall-redirector"}, runMode, log)
   102  }
   103  
   104  // InstallFuse calls the installer with --install-fuse.
   105  func InstallFuse(runMode libkb.RunMode, log Log) error {
   106  	log.Info("Installing KBFuse")
   107  	return execNativeInstallerWithArg([]string{"--install-fuse"}, runMode, log)
   108  }
   109  
   110  // UninstallFuse calls the installer with --uninstall-fuse.
   111  func UninstallFuse(runMode libkb.RunMode, log Log) error {
   112  	log.Info("Removing KBFuse")
   113  	return execNativeInstallerWithArg([]string{"--uninstall-fuse"}, runMode, log)
   114  }
   115  
   116  // InstallHelper calls the installer with --install-helper.
   117  func InstallHelper(runMode libkb.RunMode, log Log) error {
   118  	log.Info("Installing Helper")
   119  	return execNativeInstallerWithArg([]string{"--install-helper"}, runMode, log)
   120  }
   121  
   122  // UninstallHelper calls the installer with --uninstall-helper.
   123  func UninstallHelper(runMode libkb.RunMode, log Log) error {
   124  	log.Info("Removing privileged helper tool")
   125  	return execNativeInstallerWithArg([]string{"--uninstall-helper"}, runMode, log)
   126  }
   127  
   128  // InstallCommandLinePrivileged calls the installer with --install-cli.
   129  func InstallCommandLinePrivileged(runMode libkb.RunMode, log Log) error {
   130  	log.Info("Installing command line (privileged)")
   131  	return execNativeInstallerWithArg([]string{"--install-cli"}, runMode, log)
   132  }
   133  
   134  // UninstallCommandLinePrivileged calls the installer with --uninstall-cli.
   135  func UninstallCommandLinePrivileged(runMode libkb.RunMode, log Log) error {
   136  	log.Info("Removing command line (privileged)")
   137  	return execNativeInstallerWithArg([]string{"--uninstall-cli"}, runMode, log)
   138  }
   139  
   140  // InstallAppBundle calls the installer with --install-app-bundle.
   141  func InstallAppBundle(context Context, sourcePath string, log Log) error {
   142  	log.Info("Install app bundle")
   143  	return execNativeInstallerWithArg([]string{"--install-app-bundle", fmt.Sprintf("--source-path=%s", sourcePath)}, context.GetRunMode(), log)
   144  }
   145  
   146  // UninstallApp calls the installer with --install-app.
   147  func UninstallApp(runMode libkb.RunMode, log Log) error {
   148  	log.Info("Removing app")
   149  	return execNativeInstallerWithArg([]string{"--uninstall-app"}, runMode, log)
   150  }