272 lines
5.8 KiB
Go
272 lines
5.8 KiB
Go
package copy
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
|
|
"github.com/akamensky/argparse"
|
|
"github.com/rs/zerolog/log"
|
|
"gitlab.com/ChaotiCryptidz/musicutil/types"
|
|
"gitlab.com/ChaotiCryptidz/musicutil/utils"
|
|
"gitlab.com/ChaotiCryptidz/musicutil/utils/transcoder"
|
|
)
|
|
|
|
type CopyCommandArgs struct {
|
|
Source *string
|
|
Dest *string
|
|
TranscodePreset *string
|
|
SkipExisting *bool
|
|
SingleDirectory *bool
|
|
}
|
|
|
|
func dirNotExistValidator(directory string) error {
|
|
fileInfo, err := os.Stat(directory)
|
|
if err != nil {
|
|
return fmt.Errorf("%s does not exist", directory)
|
|
}
|
|
|
|
if !fileInfo.IsDir() {
|
|
return fmt.Errorf("%s is not a directory", directory)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func fileExists(filepath string) bool {
|
|
if _, err := os.Stat(filepath); err == nil {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
|
|
func copyFile(src, dest string) error {
|
|
_, err := os.Stat(src)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
source, err := os.Open(src)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer source.Close()
|
|
|
|
destination, err := os.Create(dest)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer destination.Close()
|
|
|
|
_, err = io.Copy(destination, source)
|
|
return err
|
|
}
|
|
|
|
func RegisterCopyCommand(parser *argparse.Parser) (*argparse.Command, *CopyCommandArgs) {
|
|
cmd := parser.NewCommand("copy", "copies files with or without transcoding")
|
|
|
|
arguments := &CopyCommandArgs{}
|
|
arguments.Source = cmd.String("s", "src", &argparse.Options{
|
|
Required: true,
|
|
Validate: func(args []string) error {
|
|
return dirNotExistValidator(args[0])
|
|
},
|
|
})
|
|
|
|
arguments.Dest = cmd.String("d", "dest", &argparse.Options{
|
|
Required: true,
|
|
Validate: func(args []string) error {
|
|
return dirNotExistValidator(args[0])
|
|
},
|
|
})
|
|
|
|
arguments.TranscodePreset = cmd.String("p", "transcode-preset", &argparse.Options{
|
|
Required: true,
|
|
Validate: func(args []string) error {
|
|
if args[0] == "list" {
|
|
transcoder.PrintTranscodePresets()
|
|
os.Exit(0)
|
|
} else if args[0] == "copy" {
|
|
return nil
|
|
}
|
|
|
|
if _, err := transcoder.GetPresetByName(args[0]); err != nil {
|
|
return fmt.Errorf("Preset does not exist")
|
|
}
|
|
|
|
return nil
|
|
},
|
|
})
|
|
|
|
arguments.SkipExisting = cmd.Flag("", "skip-existing", &argparse.Options{
|
|
Default: false,
|
|
})
|
|
|
|
arguments.SingleDirectory = cmd.Flag("", "single-directory", &argparse.Options{
|
|
Default: false,
|
|
})
|
|
|
|
return cmd, arguments
|
|
}
|
|
|
|
type CopyCommand struct {
|
|
Args *CopyCommandArgs
|
|
Files []*types.File
|
|
}
|
|
|
|
func NewCopyCommand(args *CopyCommandArgs) *CopyCommand {
|
|
return &CopyCommand{
|
|
Args: args,
|
|
Files: make([]*types.File, 0),
|
|
}
|
|
}
|
|
|
|
func (c *CopyCommand) scan_for_music() {
|
|
log.Info().Msg("Scanning For Music")
|
|
|
|
files, err := utils.ScanForMusic(*c.Args.Source)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
c.Files = files
|
|
}
|
|
|
|
func (c *CopyCommand) check_for_duplicates() {
|
|
log.Info().Msg("Creating For Duplicates")
|
|
seen := make(map[string]bool)
|
|
dupes := make([]string, 0)
|
|
|
|
for _, file := range c.Files {
|
|
filename := file.JoinFilename()
|
|
if _, ok := seen[filename]; ok {
|
|
dupes = append(dupes, filename)
|
|
} else {
|
|
seen[filename] = true
|
|
}
|
|
}
|
|
|
|
if len(dupes) > 0 {
|
|
log.Fatal().Strs("dupes", dupes).Msg("Duplicates Found, please rename/remove.")
|
|
}
|
|
}
|
|
|
|
func (c *CopyCommand) create_directories() {
|
|
log.Info().Msg("Creating Directories")
|
|
|
|
directories := make(map[string]bool)
|
|
for _, file := range c.Files {
|
|
directories[file.PathFromSource] = true
|
|
}
|
|
|
|
for dir := range directories {
|
|
if file_info, err := os.Stat(*c.Args.Dest + "/" + dir); err == nil {
|
|
if file_info.IsDir() {
|
|
continue
|
|
}
|
|
}
|
|
|
|
log.Info().Str("dir", dir).Msg("Creating Directory")
|
|
|
|
err := os.MkdirAll(*c.Args.Dest+"/"+dir, os.ModePerm)
|
|
if err != nil {
|
|
log.Fatal().Err(err).Msg("Could not create directory")
|
|
}
|
|
}
|
|
}
|
|
|
|
func (c *CopyCommand) _transcode_file(file *types.File, trans_config *transcoder.TranscodeConfig) {
|
|
new_filename := file.Filename + "." + trans_config.FileExtension
|
|
dest_filepath := *c.Args.Dest + "/"
|
|
|
|
if *c.Args.SingleDirectory {
|
|
dest_filepath = dest_filepath + new_filename
|
|
} else {
|
|
dest_filepath = dest_filepath + file.PathFromSource + "/" + new_filename
|
|
}
|
|
|
|
if *c.Args.SkipExisting && fileExists(dest_filepath) {
|
|
log.Info().Str("file", new_filename).
|
|
Msg("Skipping transcode as file already exists")
|
|
return
|
|
} else {
|
|
log.Info().Str("file", new_filename).Msg("Transcoding File")
|
|
}
|
|
|
|
output, err := transcoder.Transcode(file, trans_config, dest_filepath)
|
|
if err != nil {
|
|
log.Fatal().Err(err).Str("output", output).Msg("Transcode Failed")
|
|
}
|
|
}
|
|
|
|
func (c *CopyCommand) transcode_files() {
|
|
log.Info().Msg("Transcoding Files")
|
|
|
|
// TODO: Implement custom transcode config file
|
|
trans_preset, err :=
|
|
transcoder.GetPresetByName(*c.Args.TranscodePreset)
|
|
if err != nil {
|
|
log.Fatal().Err(err).Msg("Could not get transcode preset")
|
|
}
|
|
|
|
for _, file := range c.Files {
|
|
c._transcode_file(file, trans_preset.Config)
|
|
}
|
|
}
|
|
|
|
func (c *CopyCommand) _copy_file(file *types.File) {
|
|
src_filepath := file.JoinPathTo()
|
|
dest_filepath := ""
|
|
if *c.Args.SingleDirectory {
|
|
dest_filepath = *c.Args.Dest + "/" + file.JoinFilename()
|
|
} else {
|
|
dest_filepath = *c.Args.Dest + "/" + file.JoinPathFromSource()
|
|
}
|
|
|
|
exists := fileExists(dest_filepath)
|
|
|
|
if exists {
|
|
log.Info().Str("file", dest_filepath).
|
|
Msg("Skipping as already exists in destination")
|
|
} else {
|
|
log.Info().
|
|
Str("file", file.JoinFilename()).
|
|
Msg("Copying File")
|
|
err := copyFile(src_filepath, dest_filepath)
|
|
if err != nil {
|
|
log.Panic().
|
|
Err(err).
|
|
Str("file", file.JoinFilename()).
|
|
Msg("Error Copying File")
|
|
}
|
|
}
|
|
}
|
|
|
|
func (c *CopyCommand) copy_files() {
|
|
log.Info().Msg("Copying Files Into Dest")
|
|
|
|
for _, file := range c.Files {
|
|
c._copy_file(file)
|
|
}
|
|
}
|
|
|
|
func (c *CopyCommand) Run() {
|
|
log.Info().Msg("Copying Files")
|
|
|
|
c.scan_for_music()
|
|
|
|
if !*c.Args.SingleDirectory {
|
|
c.create_directories()
|
|
} else {
|
|
c.check_for_duplicates()
|
|
}
|
|
|
|
if *c.Args.TranscodePreset == "copy" {
|
|
c.copy_files()
|
|
} else {
|
|
c.transcode_files()
|
|
}
|
|
|
|
}
|