Add standalone desktop workflow
This commit is contained in:
@@ -12,6 +12,47 @@ import (
|
||||
"jukebox_maker/internal/disk"
|
||||
)
|
||||
|
||||
func (s *Server) copyOptions(cfg *config.Config, diskInfo disk.DiskInfo, overwriteMode config.OverwriteMode) copier.Options {
|
||||
return copier.Options{
|
||||
DiskID: diskInfo.DiskID,
|
||||
MountPath: diskInfo.MountPath,
|
||||
MediaPath: cfg.MediaPath,
|
||||
DestFolder: cfg.DestFolder,
|
||||
SourceRules: cfg.Sources,
|
||||
ReserveFreeGB: cfg.ReserveFreeGB,
|
||||
OverwriteMode: overwriteMode,
|
||||
FileSelectMode: cfg.FileSelectMode,
|
||||
}
|
||||
}
|
||||
|
||||
func hasEnabledSources(cfg *config.Config) bool {
|
||||
for _, src := range cfg.Sources {
|
||||
if src.Enabled {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func decodeCopyMode(r *http.Request, fallback config.OverwriteMode) (config.OverwriteMode, error) {
|
||||
var req struct {
|
||||
Mode string `json:"mode"`
|
||||
}
|
||||
if r.Body != nil {
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil && !errors.Is(err, io.EOF) {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
switch req.Mode {
|
||||
case "", "add":
|
||||
return config.OverwriteSkip, nil
|
||||
case "replace":
|
||||
return config.OverwriteDelete, nil
|
||||
default:
|
||||
return fallback, errors.New("invalid copy mode")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) handleCopyStart(w http.ResponseWriter, r *http.Request) {
|
||||
diskID := r.PathValue("diskID")
|
||||
diskInfo, ok := s.deps.Watcher.DiskByID(diskID)
|
||||
@@ -21,26 +62,67 @@ func (s *Server) handleCopyStart(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
cfg := s.deps.Config
|
||||
hasEnabledSources := false
|
||||
for _, src := range cfg.Sources {
|
||||
if src.Enabled {
|
||||
hasEnabledSources = true
|
||||
break
|
||||
}
|
||||
if !hasEnabledSources(cfg) {
|
||||
jsonErr(w, http.StatusUnprocessableEntity, "no source folders selected")
|
||||
return
|
||||
}
|
||||
if !hasEnabledSources {
|
||||
|
||||
overwriteMode, err := decodeCopyMode(r, cfg.OverwriteMode)
|
||||
if err != nil {
|
||||
if err.Error() == "invalid copy mode" {
|
||||
jsonErr(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
jsonErr(w, http.StatusBadRequest, "invalid JSON: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
reserveBytes := int64(cfg.ReserveFreeGB * 1e9)
|
||||
if diskInfo.FreeBytes <= reserveBytes {
|
||||
jsonErr(w, http.StatusUnprocessableEntity, "free space is below reserve threshold")
|
||||
return
|
||||
}
|
||||
|
||||
opts := s.copyOptions(cfg, diskInfo, overwriteMode)
|
||||
|
||||
taskID, err := s.deps.Copier.Start(context.Background(), opts)
|
||||
if err != nil {
|
||||
switch err.Error() {
|
||||
case "copy already running":
|
||||
jsonErr(w, http.StatusConflict, err.Error())
|
||||
default:
|
||||
jsonErr(w, http.StatusUnprocessableEntity, err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
jsonOK(w, map[string]string{"task_id": taskID})
|
||||
}
|
||||
|
||||
func (s *Server) handleCopyStartSelected(w http.ResponseWriter, r *http.Request) {
|
||||
cfg := s.deps.Config
|
||||
if !hasEnabledSources(cfg) {
|
||||
jsonErr(w, http.StatusUnprocessableEntity, "no source folders selected")
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
Mode string `json:"mode"`
|
||||
MountPath string `json:"mount_path"`
|
||||
Mode string `json:"mode"`
|
||||
}
|
||||
if r.Body != nil {
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil && !errors.Is(err, io.EOF) {
|
||||
jsonErr(w, http.StatusBadRequest, "invalid JSON: "+err.Error())
|
||||
return
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
jsonErr(w, http.StatusBadRequest, "invalid JSON: "+err.Error())
|
||||
return
|
||||
}
|
||||
diskInfo, err := s.deps.ProbeDisk(req.MountPath)
|
||||
if err != nil {
|
||||
jsonErr(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
if diskInfo.State != disk.DiskKnown {
|
||||
jsonErr(w, http.StatusUnprocessableEntity, "selected directory is not an initialized jukebox disk")
|
||||
return
|
||||
}
|
||||
|
||||
overwriteMode := cfg.OverwriteMode
|
||||
@@ -60,18 +142,10 @@ func (s *Server) handleCopyStart(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
opts := copier.Options{
|
||||
DiskID: diskInfo.DiskID,
|
||||
MountPath: diskInfo.MountPath,
|
||||
MediaPath: s.deps.MediaPath,
|
||||
DestFolder: cfg.DestFolder,
|
||||
SourceRules: cfg.Sources,
|
||||
ReserveFreeGB: cfg.ReserveFreeGB,
|
||||
OverwriteMode: overwriteMode,
|
||||
FileSelectMode: cfg.FileSelectMode,
|
||||
if s.deps.OnDiskInit != nil {
|
||||
s.deps.OnDiskInit(diskInfo.MountPath, diskInfo.DiskID)
|
||||
}
|
||||
|
||||
taskID, err := s.deps.Copier.Start(context.Background(), opts)
|
||||
taskID, err := s.deps.Copier.Start(context.Background(), s.copyOptions(cfg, diskInfo, overwriteMode))
|
||||
if err != nil {
|
||||
switch err.Error() {
|
||||
case "copy already running":
|
||||
|
||||
Reference in New Issue
Block a user