Add extension normalization command
This commit is contained in:
100
internal/extension/request.go
Normal file
100
internal/extension/request.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package extension
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/rogeecn/renamer/internal/listing"
|
||||
)
|
||||
|
||||
// ExtensionRequest captures all inputs required to evaluate an extension normalization run.
|
||||
type ExtensionRequest struct {
|
||||
WorkingDir string
|
||||
SourceExtensions []string
|
||||
DisplaySourceExtensions []string
|
||||
TargetExtension string
|
||||
DuplicateSources []string
|
||||
NoOpSources []string
|
||||
|
||||
IncludeDirs bool
|
||||
Recursive bool
|
||||
IncludeHidden bool
|
||||
|
||||
ExtensionFilter []string
|
||||
|
||||
DryRun bool
|
||||
AutoConfirm bool
|
||||
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
// NewRequest seeds an ExtensionRequest using the shared listing scope settings.
|
||||
func NewRequest(scope *listing.ListingRequest) *ExtensionRequest {
|
||||
if scope == nil {
|
||||
return &ExtensionRequest{}
|
||||
}
|
||||
|
||||
filterCopy := append([]string(nil), scope.Extensions...)
|
||||
|
||||
return &ExtensionRequest{
|
||||
WorkingDir: scope.WorkingDir,
|
||||
IncludeDirs: scope.IncludeDirectories,
|
||||
Recursive: scope.Recursive,
|
||||
IncludeHidden: scope.IncludeHidden,
|
||||
ExtensionFilter: filterCopy,
|
||||
}
|
||||
}
|
||||
|
||||
// SetExecutionMode records dry-run/auto-apply preferences inherited from CLI flags.
|
||||
func (r *ExtensionRequest) SetExecutionMode(dryRun, autoConfirm bool) {
|
||||
r.DryRun = dryRun
|
||||
r.AutoConfirm = autoConfirm
|
||||
}
|
||||
|
||||
// SetExtensions stores source and target extensions before normalization.
|
||||
func (r *ExtensionRequest) SetExtensions(canonical []string, display []string, target string) {
|
||||
r.SourceExtensions = append(r.SourceExtensions[:0], canonical...)
|
||||
r.DisplaySourceExtensions = append(r.DisplaySourceExtensions[:0], display...)
|
||||
r.TargetExtension = target
|
||||
}
|
||||
|
||||
// SetWarnings captures duplicate or no-op tokens for later surfacing in preview output.
|
||||
func (r *ExtensionRequest) SetWarnings(dupes, noOps []string) {
|
||||
r.DuplicateSources = append(r.DuplicateSources[:0], dupes...)
|
||||
r.NoOpSources = append(r.NoOpSources[:0], noOps...)
|
||||
}
|
||||
|
||||
// Normalize ensures working directory and timestamp fields are ready for execution.
|
||||
func (r *ExtensionRequest) Normalize() error {
|
||||
if r.WorkingDir == "" {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return fmt.Errorf("determine working directory: %w", err)
|
||||
}
|
||||
r.WorkingDir = cwd
|
||||
}
|
||||
|
||||
if !filepath.IsAbs(r.WorkingDir) {
|
||||
abs, err := filepath.Abs(r.WorkingDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolve working directory: %w", err)
|
||||
}
|
||||
r.WorkingDir = abs
|
||||
}
|
||||
|
||||
info, err := os.Stat(r.WorkingDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("stat working directory: %w", err)
|
||||
}
|
||||
if !info.IsDir() {
|
||||
return fmt.Errorf("working directory %q is not a directory", r.WorkingDir)
|
||||
}
|
||||
|
||||
if r.Timestamp.IsZero() {
|
||||
r.Timestamp = time.Now().UTC()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user