A tool for archiving & converting scans of postcards, and information about them.
at main 104 lines 2.1 kB view raw
1package postcards 2 3import ( 4 "fmt" 5 "io/fs" 6 "os" 7 "path" 8 9 "github.com/jphastings/dotpostcard/formats" 10) 11 12// MakeBundles takes paths of files and directories and will figure out the bundles of files that need to be processed together. 13// Subdirectories are not descended into. 14func MakeBundles(filesAndDirPaths []string) ([]formats.Bundle, error) { 15 groups, err := groupFiles(filesAndDirPaths) 16 if err != nil { 17 return nil, err 18 } 19 20 var bundles []formats.Bundle 21 for _, group := range groups { 22 for _, codecID := range Codecs { 23 codec := codecs[codecID] 24 newBundles, remaining, err := codec.Bundle(group) 25 if err != nil { 26 return bundles, err 27 } 28 29 bundles = append(bundles, newBundles...) 30 group.Files = remaining 31 if len(group.Files) == 0 { 32 break 33 } 34 } 35 } 36 37 return bundles, nil 38} 39 40func groupFiles(inputPaths []string) ([]formats.FileGroup, error) { 41 dirset := make(map[string]map[string]struct{}) 42 43 addToFiles := func(filepath string) { 44 dir := path.Dir(filepath) 45 base := path.Base(filepath) 46 47 fileset, ok := dirset[dir] 48 if !ok { 49 fileset = make(map[string]struct{}) 50 } 51 52 fileset[base] = struct{}{} 53 dirset[dir] = fileset 54 } 55 56 for _, inputPath := range inputPaths { 57 info, err := os.Stat(inputPath) 58 if err != nil { 59 return nil, fmt.Errorf("input path '%s' not usable: %w", inputPath, err) 60 } 61 if !info.IsDir() { 62 addToFiles(inputPath) 63 } 64 } 65 66 var groups []formats.FileGroup 67 68 for dir, fileset := range dirset { 69 dirFS := os.DirFS(dir) 70 var fileFSs []fs.File 71 for base, _ := range fileset { 72 f, err := dirFS.Open(base) 73 if err != nil { 74 return nil, fmt.Errorf("file path '%s' not usable: %w", path.Join(dir, base), err) 75 } 76 fileFSs = append(fileFSs, f) 77 } 78 79 groups = append(groups, formats.FileGroup{ 80 Dir: dirFS, 81 Files: fileFSs, 82 DirPath: dir, 83 }) 84 } 85 86 return groups, nil 87} 88 89func allFilesInDir(dir string) ([]string, error) { 90 var files []string 91 92 des, err := os.ReadDir(dir) 93 if err != nil { 94 return nil, err 95 } 96 97 for _, de := range des { 98 if !de.IsDir() { 99 files = append(files, path.Join(dir, de.Name())) 100 } 101 } 102 103 return files, err 104}