-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSyncFiles.go
143 lines (114 loc) · 2.7 KB
/
SyncFiles.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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package main
import (
"bufio"
"database/sql"
"fmt"
"io/ioutil"
"os"
"sync"
"github.com/JojiiOfficial/gaw"
)
func syncFiles(dryRun, noconfirm bool) error {
// List locally available files
files, err := ioutil.ReadDir(config.Server.PathConfig.FileStore)
if err != nil {
return err
}
// Get Local files+ID
rows, err := db.Table("files").Where("deleted_at is NULL").Select("id, local_name").Rows()
if err != nil {
return err
}
var untrackedInFS []int64 // Database file rows without local file
var untrackedInDB []string // Local files which don't have any reference in database
var wg sync.WaitGroup
wg.Add(2)
cerr := make(chan error, 2)
go func() {
untrackedInFS, err = searchLocalFS(rows, files)
cerr <- err
wg.Done()
}()
go func() {
untrackedInDB, err = searchDB(files)
cerr <- err
wg.Done()
}()
wg.Wait()
close(cerr)
for i := range cerr {
if i != nil {
return i
}
}
if len(untrackedInDB) == 0 && len(untrackedInFS) == 0 {
fmt.Println("Nothing to do")
return nil
}
fmt.Println()
fmt.Printf("Found %d files missing in local filesystem\n", len(untrackedInFS))
fmt.Printf("Found %d files untracked in database\n", len(untrackedInDB))
if dryRun {
return nil
}
if !noconfirm {
if y, _ := gaw.ConfirmInput("\nDelete all untracked files? [y/n/a]> ", bufio.NewReader(os.Stdin)); !y {
return nil
}
}
fmt.Println("Deleting...")
return nil
}
// Returns a slice of FileIDs which have no local file
func searchLocalFS(rows *sql.Rows, files []os.FileInfo) ([]int64, error) {
var untrackedInFS []int64
var fileName string
var id int64
for rows.Next() {
if err := rows.Scan(&id, &fileName); err != nil {
return nil, err
}
if !hasLocalFile(files, fileName) {
untrackedInFS = append(untrackedInFS, id)
}
}
return untrackedInFS, nil
}
// Returns a slice of local files which don't have a reference in DB
func searchDB(localFiles []os.FileInfo) ([]string, error) {
var untrackedInDB []string
var i, j, end int
for {
if i >= len(localFiles) {
break
}
end = i + 1000000
if end > len(localFiles) {
end = len(localFiles)
}
var res []string
fmt.Println(i, end)
if err := db.Table("files").Where("local_name NOT IN (?) AND deleted_at IS NULL", fifoToStr(localFiles[i:end])).Select("local_name").Find(&res).Error; err != nil {
return nil, err
}
untrackedInDB = append(untrackedInDB, res...)
i = end + 1
j++
}
return untrackedInDB, nil
}
func fifoToStr(f []os.FileInfo) []string {
s := make([]string, len(f))
for i := range f {
s[i] = f[i].Name()
}
return s
}
func hasLocalFile(localFiles []os.FileInfo, name string) bool {
for i := range localFiles {
if localFiles[i].Name() == name {
return true
}
}
return false
}