A tool for archiving & converting scans of postcards, and information about them.
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}