func (appGallery *AppGallery) resolveAppDir(bootDescriptor descriptors.AppDescriptor) (appDir string) { baseURL := bootDescriptor.GetDeclaredBaseURL() hostComponent := strings.Replace(baseURL.Host, ":", "_", -1) appDirComponents := []string{ appGallery.Directory, hostComponent} trimmedBasePath := strings.Trim(baseURL.Path, "/") baseComponents := strings.Split(trimmedBasePath, "/") appDirComponents = append(appDirComponents, baseComponents...) if hostComponent == "github.com" && len(appDirComponents) > 2 && appDirComponents[len(appDirComponents)-2] == "releases" && appDirComponents[len(appDirComponents)-1] == "latest" { appDirComponents = appDirComponents[0 : len(appDirComponents)-2] } appDir = filepath.Join(appDirComponents...) return appDir }
func (appGallery *AppGallery) GetApp(bootDescriptor descriptors.AppDescriptor) (app *App, err error) { appDir := appGallery.resolveAppDir(bootDescriptor) return &App{ Directory: appDir, bootDescriptor: bootDescriptor, filesDirectory: filepath.Join(appDir, filesDirName), localDescriptorPath: filepath.Join(appDir, bootDescriptor.GetDescriptorFileName()), }, nil }
func (app *App) CreateDesktopShortcut(launcher launchers.Launcher, referenceDescriptor descriptors.AppDescriptor) (err error) { desktopDir, err := caravel.GetUserDesktop() if err != nil { return err } if !caravel.DirectoryExists(desktopDir) { return fmt.Errorf("Expected desktop dir '%v' not found", desktopDir) } scriptFileName := caravel.FormatFileName(referenceDescriptor.GetName()) log.Debug("Bash shortcut name: '%v'", scriptFileName) scriptFilePath := filepath.Join(desktopDir, scriptFileName) log.Info("Creating Bash shortcut: '%v'...", scriptFilePath) scriptFile, err := os.OpenFile(scriptFilePath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0700) if err != nil { return err } defer func() { scriptFile.Close() if err != nil { os.Remove(scriptFilePath) } }() scriptContent := fmt.Sprintf(macScriptContentFormat, launcher.GetExecutable(), app.localDescriptorPath) _, err = scriptFile.Write([]byte(scriptContent)) if err != nil { return err } log.Notice("Bash shortcut script created") return nil }
func FormatSecureFirstRunPrompt(bootDescriptor descriptors.AppDescriptor) string { const basicFirstRunTemplate = "You are running an application for the first time." + "\n\n\nTitle: %v" + "\n\nPublisher: %v" + "\n\nAddress: %v\n\n\nDo you wish to proceed?" return fmt.Sprintf(basicFirstRunTemplate, bootDescriptor.GetTitle(), bootDescriptor.GetPublisher(), bootDescriptor.GetDeclaredBaseURL()) }
func (app *App) CreateDesktopShortcut(launcher launchers.Launcher, referenceDescriptor descriptors.AppDescriptor) (err error) { desktopDir, err := caravel.GetUserDesktop() if err != nil { return err } if !caravel.DirectoryExists(desktopDir) { return fmt.Errorf("Expected desktop dir '%v' not found", desktopDir) } shortcutFileName := caravel.FormatFileName(referenceDescriptor.GetName()) + ".desktop" log.Debug("Shortcut file name: '%v'", shortcutFileName) shortcutFilePath := filepath.Join(desktopDir, shortcutFileName) log.Info("Creating desktop shortcut: '%v'...", shortcutFilePath) shortcutFile, err := os.OpenFile(shortcutFilePath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0700) if err != nil { return err } defer func() { shortcutFile.Close() if err != nil { os.Remove(shortcutFilePath) } }() actualIconPath := app.GetActualIconPath(launcher) shortcutContent := fmt.Sprintf(linuxShortcutContent, referenceDescriptor.GetName(), referenceDescriptor.GetDescription(), launcher.GetExecutable(), app.GetLocalDescriptorPath(), actualIconPath) _, err = shortcutFile.Write([]byte(shortcutContent)) if err != nil { return err } log.Notice("Desktop shortcut created") return nil }
func (app *App) CreateDesktopShortcut(launcher launchers.Launcher, referenceDescriptor descriptors.AppDescriptor) (err error) { desktopDir, err := caravel.GetUserDesktop() if err != nil { return err } shortcutName := caravel.FormatFileName(referenceDescriptor.GetName()) + ".lnk" log.Debug("Shortcut file name: '%v'", shortcutName) shortcutFilePath := filepath.Join(desktopDir, shortcutName) log.Debug("Shortcut path: '%v'", shortcutFilePath) log.Info("Creating desktop shortcut: '%v'...", shortcutFilePath) log.Debug("Creating temp file for script...") salt := rand.Int63() tempFileName := fmt.Sprintf("shortcutScript_%v_%v.vbs", time.Now().Unix(), salt) tempFilePath := filepath.Join(os.TempDir(), tempFileName) tempFile, err := os.Create(tempFilePath) if err != nil { return err } defer func() { tempFile.Close() tempRemovalErr := os.Remove(tempFilePath) if tempRemovalErr != nil { log.Warning("Cannot remove the temp script: %v", tempFilePath) } else { log.Debug("Temp script successfully removed") } if err != nil { os.Remove(shortcutFilePath) } }() log.Debug("Temp script file created: %v", tempFilePath) actualIconPath := app.GetActualIconPath(launcher) log.Debug("Actual icon path: '%v'", actualIconPath) workingDirectory := filepath.Dir(app.GetLocalDescriptorPath()) log.Debug("Working directory: '%v'", workingDirectory) shortcutScript := fmt.Sprintf(windowsShortcutContent, shortcutFilePath, app.GetLocalDescriptorPath(), referenceDescriptor.GetDescription(), actualIconPath, workingDirectory) log.Debug("Writing script temp file...") tempFile.Write([]byte(shortcutScript)) tempFile.Close() log.Debug("Temp script ready") log.Debug("Now executing the temp script...") shortcutCreationCommand := exec.Command("wscript", "/b", "/nologo", tempFilePath) err = shortcutCreationCommand.Run() if err != nil { return err } if !shortcutCreationCommand.ProcessState.Success() { return fmt.Errorf("The script did not run successfully") } log.Debug("The script was successful") return nil }
/* Run is the entry point you must employ to create a custom installer, for example to employ custom settings or a brand-new user interface, based on any technology */ func Run( launcher launchers.Launcher, userInterface ui.UserInterface, bootDescriptor descriptors.AppDescriptor) (err error) { settings := launcher.GetSettings() //---------------------------------------------------------------------------- setupUserInterface(launcher, userInterface) defer dismissUserInterface(userInterface) //---------------------------------------------------------------------------- userInterface.SetHeader("Performing startup operations") log.Debug("The boot descriptor is: %#v", bootDescriptor) //---------------------------------------------------------------------------- userInterface.SetApp(bootDescriptor.GetName()) //---------------------------------------------------------------------------- appGallery := apps.NewAppGallery(settings.GetGalleryDirectory()) log.Debug("The app gallery is: %#v", appGallery) //---------------------------------------------------------------------------- log.Info("Resolving the app...") app, err := appGallery.GetApp(bootDescriptor) if err != nil { return err } log.Notice("The app directory is: '%v'", app.Directory) log.Debug("App is: %#v", app) firstRun := !app.DirectoryExists() log.Debug("Is this a first run for the app? %v", firstRun) //---------------------------------------------------------------------------- if firstRun { log.Info("Now asking the user if the app can run...") canRun := app.CanPerformFirstRun(userInterface) if !canRun { return &ExecutionCanceled{} } log.Debug("The user agreed to proceed") log.Info("Ensuring the app dir is available...") err = app.EnsureDirectory() if err != nil { return err } log.Notice("App dir available") } //---------------------------------------------------------------------------- log.Info("Locking the app dir...") err = app.LockDirectory() if err != nil { return err } defer func() { unlockErr := app.UnlockDirectory() if unlockErr != nil { log.Warning(unlockErr.Error()) } }() log.Notice("App dir locked") //---------------------------------------------------------------------------- log.Info("Checking for conflicting local descriptors...") err = app.CheckForConflictingLocalDescriptors() if err != nil { return err } log.Notice("No conflicting local descriptors found") //---------------------------------------------------------------------------- log.Info("Resolving the local descriptor...") localDescriptor := app.GetLocalDescriptor() startedWithLocalDescriptor := localDescriptor != nil log.Debug("Started with local descriptor? %v", startedWithLocalDescriptor) if startedWithLocalDescriptor { log.Info("Checking that local descriptor and boot descriptor actually match...") err = descriptors.CheckDescriptorMatch(localDescriptor, bootDescriptor) if err != nil { return err } log.Notice("The descriptors match correctly") } //---------------------------------------------------------------------------- log.Info("Resolving the remote descriptor...") remoteDescriptor := app.GetRemoteDescriptor() if remoteDescriptor != nil { log.Info("Checking that remote descriptor and boot descriptor actually match...") err = descriptors.CheckDescriptorMatch(remoteDescriptor, bootDescriptor) if err != nil { return err } log.Notice("The descriptors match correctly") } //---------------------------------------------------------------------------- log.Info("Now choosing the reference descriptor...") referenceDescriptor, err := app.GetReferenceDescriptor() if err != nil { return err } log.Notice("Reference descriptor chosen") log.Debug("The reference descriptor is: %#v", referenceDescriptor) //---------------------------------------------------------------------------- err = referenceDescriptor.CheckRequirements() if err != nil { return err } //---------------------------------------------------------------------------- userInterface.SetApp(referenceDescriptor.GetTitle()) //---------------------------------------------------------------------------- log.Info("Resolving the OS-specific app command line...") commandLine := referenceDescriptor.GetCommandLine() log.Notice("Command line resolved") log.Debug("Command line is: %v", commandLine) //---------------------------------------------------------------------------- err = app.CheckFiles(settings, userInterface) if err != nil { return err } //---------------------------------------------------------------------------- userInterface.SetHeader("Preparing the command...") log.Info("Creating the command...") command := app.PrepareCommand(commandLine) log.Notice("Command created") log.Debug("Command path: %v", command.Path) log.Debug("Command arguments: %v", command.Args) //---------------------------------------------------------------------------- referenceDescriptorSaved := app.SaveReferenceDescriptor() if !startedWithLocalDescriptor && referenceDescriptorSaved { if userInterface.AskForDesktopShortcut(referenceDescriptor) { log.Info("Creating desktop shortcut...") err = app.CreateDesktopShortcut(launcher, referenceDescriptor) if err != nil { log.Warning("Could not create desktop shortcut: %v", err) } else { log.Notice("Desktop shortcut created") } } else { log.Info("The user refused to create a desktop shortcut") } } //---------------------------------------------------------------------------- app.UnlockDirectory() //---------------------------------------------------------------------------- userInterface.SetHeader("Launching the application") userInterface.SetStatus("") return app.Launch(command, settings, userInterface) }