/
copy.go
86 lines (77 loc) · 1.64 KB
/
copy.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package common
import (
"fmt"
"io"
"io/fs"
"log"
"os"
"sync"
)
// From https://opensource.com/article/18/6/copying-files-go
func CopyFile(src string, dst string) error {
source, err := os.Open(src)
if err != nil {
return err
}
defer source.Close()
destination, err := os.Create(dst)
if err != nil {
return err
}
defer destination.Close()
_, err = io.Copy(destination, source)
return err
}
func Copy(opts CopyOpts) {
if !opts.info.Mode().IsRegular() {
log.Fatalf("%s is not a regular file", opts.src)
}
if opts.hardlink {
// hardlink this file
if opts.verbose {
fmt.Printf("hardlink %v => %v\n", opts.src, opts.dst)
}
err := os.Link(opts.src, opts.dst)
if err != nil {
// fallback to copy
if opts.verbose {
fmt.Printf("hardlink failed: %v\n", err)
fmt.Printf("copy (fallback) %v => %v\n", opts.src, opts.dst)
}
err = CopyFile(opts.src, opts.dst)
if err != nil {
log.Fatal(err)
}
}
} else {
// copy this file
if opts.verbose {
fmt.Printf("copy %v => %v\n", opts.src, opts.dst)
}
err := CopyFile(opts.src, opts.dst)
if err != nil {
log.Fatal(err)
}
}
}
type CopyWorker struct {
queue <-chan CopyOpts
}
func NewCopyWorker(queue <-chan CopyOpts) *CopyWorker {
return &CopyWorker{queue: queue}
}
func (w *CopyWorker) Run(wg *sync.WaitGroup) {
defer wg.Done()
for opts := range w.queue {
Copy(opts)
}
}
type CopyOpts struct {
src, dst string
info fs.FileInfo
hardlink bool
verbose bool
}
func NewCopyOpts(src string, dst string, info fs.FileInfo, hardlink bool, verbose bool) CopyOpts {
return CopyOpts{src: src, dst: dst, info: info, hardlink: hardlink, verbose: verbose}
}