Skip to content
This repository has been archived by the owner on Jan 4, 2025. It is now read-only.

Commit

Permalink
Merge pull request #40 from tulilirockz/feat-parallel-ops
Browse files Browse the repository at this point in the history
feat: Parallel operations
  • Loading branch information
bketelsen authored Feb 27, 2024
2 parents 2f8d223 + ceb6c97 commit c74eb06
Show file tree
Hide file tree
Showing 7 changed files with 385 additions and 342 deletions.
114 changes: 69 additions & 45 deletions cmd/layer/activate/activate.go
Original file line number Diff line number Diff line change
@@ -1,89 +1,113 @@
package activate

import (
"errors"
"fmt"
"log/slog"
"os"
"path"
"path/filepath"
"strings"
"sync"

"github.com/spf13/cobra"
"github.com/ublue-os/bext/internal"
)

var ActivateCmd = &cobra.Command{
Use: "activate [TARGET]",
Short: "Activate a layer and refresh sysext",
Long: `Activate a selected layer (symlink it to /var/lib/extensions) and refresh the system extensions store.`,
Use: "activate [TARGET...]",
Short: "Activate layers and refresh sysext",
Long: `Activate selected layers and refresh the system extensions store.`,
RunE: activateCmd,
Args: cobra.MinimumNArgs(1),
}

var (
fFromFile *string
fFromFile bool
fOverride bool
)

func init() {
fFromFile = ActivateCmd.Flags().StringP("file", "f", "", "Activate directly from file instead of cache")
ActivateCmd.Flags().BoolVarP(&fFromFile, "file", "f", false, "Parse positional arguments as files instead of layers")
ActivateCmd.Flags().BoolVar(&fOverride, "override", true, "Write over old symlinks")
}

func activateCmd(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return internal.NewPositionalError("TARGET")
}

target_layer := args[0]

extensions_dir, err := filepath.Abs(path.Clean(internal.Config.ExtensionsDir))
if err != nil {
return err
}

if *fFromFile != "" {
if !strings.HasSuffix(target_layer, internal.ValidSysextExtension) {
target_layer, err = filepath.Abs(path.Clean(target_layer + internal.ValidSysextExtension))
if err != nil {
return err
}
}

target_path := path.Join(extensions_dir, target_layer)
slog.Debug("acitavate",
slog.String("fromfile", *fFromFile),
slog.String("layer", target_layer),
slog.String("path", target_path),
)
if err := os.Symlink(target_layer, path.Join(extensions_dir, target_layer)); err != nil {
return err
}
slog.Info(fmt.Sprintf("Successfully activated layer %s\n", path.Base(target_layer)))
return nil
}

var (
errChan = make(chan error, len(args))
wg sync.WaitGroup
)
cache_dir, err := filepath.Abs(path.Clean(internal.Config.CacheDir))
if err != nil {
return err
}

current_blob_path := path.Join(cache_dir, target_layer, internal.CurrentBlobName)
if _, err := os.Stat(current_blob_path); err != nil {
if err := os.MkdirAll(internal.Config.ExtensionsDir, 0755); err != nil {
return err
}

if err := os.MkdirAll(internal.Config.ExtensionsDir, 0755); err != nil {
return err
for _, target_file := range args {
slog.Debug("Activating layer "+target_file,
slog.Bool("fromfile", fFromFile),
slog.String("layer", target_file),
)

wg.Add(1)
go func(errChan chan<- error, target string) {
defer wg.Done()
var (
deployment_path string
target_path string
)

if !strings.HasSuffix(target, internal.ValidSysextExtension) && fFromFile {
errChan <- errors.New("failed to parse file name, invalid sysext extension. should be " + internal.ValidSysextExtension)
return
}

if fFromFile {
layer_name := strings.Split(path.Base(target), ".")[0]
target_path = path.Join(extensions_dir, layer_name)
deployment_path, err = filepath.Abs(layer_name)
if err != nil {
errChan <- err
return
}
} else {
deployment_path = path.Join(cache_dir, target, internal.CurrentBlobName)
if _, err := os.Stat(deployment_path); err != nil {
errChan <- errors.New("target layer " + target + " could not be found")
return
}
target_path = path.Join(extensions_dir, target+internal.ValidSysextExtension)
}
if fOverride {
_ = os.Remove(target_path)
} else {
errChan <- errors.New(target + " is already activated")
}
if err := os.Symlink(deployment_path, target_path); err != nil {
errChan <- err
}
}(errChan, target_file)
}

target_path := path.Join(extensions_dir, path.Base(path.Dir(current_blob_path))+internal.ValidSysextExtension)
slog.Debug("acitavate",
slog.String("fromfile", *fFromFile),
slog.String("layer", target_layer),
slog.String("blob", current_blob_path),
)
if err := os.Symlink(current_blob_path, target_path); err != nil {
return err
go func() {
wg.Wait()
close(errChan)
}()

for err := range errChan {
slog.Warn(fmt.Sprintf("Error encountered when activating layers: %s", err.Error()), slog.String("error", err.Error()))
}

slog.Info(fmt.Sprintf("Successfully activated layer %s\n", path.Base(target_layer)))
if len(errChan) == 0 {
slog.Info("Successfully activated layers", slog.String("layers", strings.Join(args, " ")))
}
return nil
}
Loading

0 comments on commit c74eb06

Please sign in to comment.