// Remove the app. func (a *App) Remove(removeBackups bool) error { // Lock the task mutex. // The app should not be started during a remove process. a.taskMutex.Lock() defer a.taskMutex.Unlock() // Abort if any app task is running. if a.IsTaskRunning() { return fmt.Errorf("the app is running!") } if !removeBackups { // Create a backup first. // Call the private method, because we locked the taskMutex already. err := a.backup() if err != nil { return err } } // Remove the app subvolume if it exists. e, err := utils.Exists(a.path) if err != nil { return err } else if e { if err = btrfs.DeleteSubvolume(a.path); err != nil { return err } } func() { // Lock the apps mutex. appsMutex.Lock() defer appsMutex.Unlock() // Remove the app from the apps map. delete(apps, a.name) }() // Remove all backups if requested. if removeBackups { if err = a.RemoveAllBackups(); err != nil { return err } } return nil }
// RemoveBackup removes the given backup. func (a *App) RemoveBackup(timestamp string) error { // Create the backup directory path. path := a.BackupDirectoryPath() + "/" + timestamp // Check if the backup exists. if !btrfs.IsSubvolume(path) { return fmt.Errorf("no backup '%s' found!", timestamp) } log.Infof("Removing backup '%s' of app '%s'.", timestamp, a.name) // Remove the backup subvolume. err := btrfs.DeleteSubvolume(path) if err != nil { return fmt.Errorf("failed to delete backup subvolume '%s': %v", timestamp, err) } return nil }
// Add and register a new turtle App. // A turtle App name should not not contain any whitespaces. func Add(name, sourceURL, branch string) (err error) { var a *App // Cleanup on any error. defer func() { if err == nil || a == nil { return } // Remove the app subvolume if it exists. e, errC := utils.Exists(a.path) if errC != nil { log.Errorf("failed to cleanup failed add app action: %v", errC) } else if e { if errC = btrfs.DeleteSubvolume(a.path); errC != nil { log.Errorf("failed to cleanup failed add app action: %v", errC) } } }() // Lock the mutex. appsMutex.Lock() defer appsMutex.Unlock() // Check if an app with the same name already exists. _, ok := apps[name] if ok { return fmt.Errorf("an App with the name '%s' already exists!", name) } // Create a new app value. a, err = newApp(name) if err != nil { return fmt.Errorf("failed to create add: %v", err) } // Set the app's settings. a.settings.SourceURL = sourceURL a.settings.Branch = branch // Create the app's subvolume. if err = btrfs.CreateSubvolume(a.path); err != nil { return fmt.Errorf("failed to prepare app's environment: %v", err) } // Save the app's settings to the app settings file. if err = a.saveSettings(); err != nil { return fmt.Errorf("failed to prepare app's environment: %v", err) } // Create the source directory. err = utils.MkDirIfNotExists(a.SourceDirectoryPath()) if err != nil { return fmt.Errorf("failed to prepare app's environment: %v", err) } // Clone the source in a new task. if err = a.cloneSource(); err != nil { return err } // Finally add the app to the map. apps[name] = a return nil }