-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
146 lines (120 loc) · 2.85 KB
/
main.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
144
145
146
package main
import (
"context"
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"sync"
"github.com/spf13/cobra"
"golang.org/x/sync/semaphore"
)
// set by goreleaser
var (
version = "v0.0.0"
date = "-"
)
// logic
var wg sync.WaitGroup
var sem = semaphore.NewWeighted(100) // don't run too many goroutines at once so we don't hit the 1000 threads limit
func handleDir(dir string, patternlist []string) {
defer wg.Done()
sem.Acquire(context.TODO(), 1)
defer sem.Release(1)
files, err := ioutil.ReadDir(dir)
if err != nil {
log.Fatal(err)
}
for _, f := range files {
if f.IsDir() {
wg.Add(1)
fullPath := filepath.Join(dir, f.Name())
if checkName(f.Name(), patternlist) {
go exclude(fullPath)
} else {
go handleDir(fullPath, patternlist)
}
}
}
}
func checkName(name string, patternList []string) bool {
for _, pattern := range patternList {
if match, _ := filepath.Match(pattern, name); match {
return true
}
}
return false
}
func exclude(dir string) {
defer wg.Done()
var err error
switch runtime.GOOS {
case "windows":
err = excludeWindows(dir)
case "linux":
err = excludeLinux(dir)
case "darwin":
err = excludeDarwin(dir)
default:
log.Fatalf("Unknown GOOS %v", runtime.GOOS)
}
if err != nil {
log.Printf("Error excluding %v: %v\n", dir, err)
} else {
log.Printf("Excluded %v\n", dir)
}
}
func excludeWindows(dir string) error {
ads, err := os.OpenFile(dir+":com.dropbox.ignored", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
return err
}
_, err = ads.WriteString("1")
if err != nil {
_ = ads.Close()
return err
}
err = ads.Close()
if err != nil {
return err
}
return nil
}
func excludeLinux(dir string) error {
return exec.Command("attr", "-s", "com.dropbox.ignored", "-V", "1", dir).Run()
}
func excludeDarwin(dir string) error {
return exec.Command("xattr", "-w", "com.dropbox.ignored", "1", dir).Run()
}
// command line handling
func defaultDropboxFolder() string {
homePath, err := os.UserHomeDir()
if err != nil {
return ""
}
return filepath.Join(homePath, "Dropbox")
}
func main() {
var dropboxFolder string
var rootCmd = &cobra.Command{
Use: "dropbox-ignorer <folder-name> [another-folder-name] [...]",
Short: "Quick and dirty way to make Dropbox ignore multiple folders by pattern (like node_modules)",
Version: fmt.Sprintf("%v (built on %v)", version, date),
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
log.Printf("Scanning %v for %v...\n", dropboxFolder, strings.Join(args, ", "))
wg.Add(1)
handleDir(dropboxFolder, args)
wg.Wait()
},
}
rootCmd.Flags().StringVarP(&dropboxFolder, "dropbox-folder", "d", defaultDropboxFolder(), "Override default Dropbox folder")
if err := rootCmd.Execute(); err != nil {
_, _ = fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}