feat: initial commit
This commit is contained in:
119
pkg/wails3kit/updates/platform/apply.go
Normal file
119
pkg/wails3kit/updates/platform/apply.go
Normal file
@@ -0,0 +1,119 @@
|
||||
package platform
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
||||
"github.com/Eriyc/rules_wails/pkg/wails3kit/updates"
|
||||
)
|
||||
|
||||
type restorePoint struct {
|
||||
path string
|
||||
backup string
|
||||
hadPrior bool
|
||||
}
|
||||
|
||||
func applyBundle(request helperRequest) error {
|
||||
backupDir, err := os.MkdirTemp("", "wails3kit-backup-*")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
restores := make([]restorePoint, 0, len(request.Bundle.Files))
|
||||
for _, file := range request.Bundle.Files {
|
||||
source := filepath.Join(request.StagedPath, filepath.FromSlash(file.Path))
|
||||
target := filepath.Join(request.InstallRoot, filepath.FromSlash(file.Path))
|
||||
modeValue, err := strconv.ParseUint(file.Mode, 8, 32)
|
||||
if err != nil {
|
||||
rollback(restores)
|
||||
return err
|
||||
}
|
||||
mode := os.FileMode(modeValue)
|
||||
|
||||
restore, err := backupTarget(backupDir, target)
|
||||
if err != nil {
|
||||
rollback(restores)
|
||||
return err
|
||||
}
|
||||
restores = append(restores, restore)
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(target), 0o755); err != nil {
|
||||
rollback(restores)
|
||||
return err
|
||||
}
|
||||
if err := os.RemoveAll(target); err != nil {
|
||||
rollback(restores)
|
||||
return err
|
||||
}
|
||||
if err := copyFile(source, target, mode); err != nil {
|
||||
rollback(restores)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func backupTarget(backupDir string, target string) (restorePoint, error) {
|
||||
point := restorePoint{path: target}
|
||||
info, err := os.Stat(target)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return point, nil
|
||||
}
|
||||
return point, err
|
||||
}
|
||||
if info.IsDir() {
|
||||
return point, fmt.Errorf("%w: target %s is a directory", updates.ErrInvalidArtifact, target)
|
||||
}
|
||||
|
||||
backupPath := filepath.Join(backupDir, filepath.Base(target))
|
||||
if err := copyFile(target, backupPath, info.Mode()); err != nil {
|
||||
return point, err
|
||||
}
|
||||
point.hadPrior = true
|
||||
point.backup = backupPath
|
||||
return point, nil
|
||||
}
|
||||
|
||||
func rollback(restores []restorePoint) {
|
||||
for index := len(restores) - 1; index >= 0; index-- {
|
||||
restore := restores[index]
|
||||
if restore.hadPrior {
|
||||
info, err := os.Stat(restore.backup)
|
||||
if err == nil {
|
||||
_ = os.RemoveAll(restore.path)
|
||||
_ = os.MkdirAll(filepath.Dir(restore.path), 0o755)
|
||||
_ = copyFile(restore.backup, restore.path, info.Mode())
|
||||
}
|
||||
continue
|
||||
}
|
||||
_ = os.RemoveAll(restore.path)
|
||||
}
|
||||
}
|
||||
|
||||
func copyFile(sourcePath string, destinationPath string, mode os.FileMode) error {
|
||||
source, err := os.Open(sourcePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer source.Close()
|
||||
|
||||
return writeFile(destinationPath, source, mode)
|
||||
}
|
||||
|
||||
func writeFile(path string, source io.Reader, mode os.FileMode) error {
|
||||
file, err := os.Create(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
if _, err := io.Copy(file, source); err != nil {
|
||||
return err
|
||||
}
|
||||
return file.Chmod(mode)
|
||||
}
|
||||
Reference in New Issue
Block a user