-
Notifications
You must be signed in to change notification settings - Fork 0
/
core.go
149 lines (129 loc) · 3.67 KB
/
core.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
147
148
149
package main
import (
"fmt"
"io/fs"
"io/ioutil"
"log"
"os"
"strings"
"sync"
"github.com/fatih/color"
"github.com/otiai10/copy"
)
/*
This is the main functionality of the program. It creates a symlink from the source
directory to the destination directory by copying all the files and creating the link.
Note that a new subdirectory will be created under the destination path.
For example, if the source folder is Desktop/GameX and the destination is
OneDrive/Backups, the created directory will be OneDrive/Backups/GameX
src - Source directory
dst - Destination directory
*/
func LinkDir(src, dst string) {
// Check that the source directory exists
if _, err := os.Stat(src); os.IsNotExist(err) {
color.Red("Source directory does not exist!")
os.Exit(1)
}
// Check that the source path is a directory
finfo, err := os.Lstat(src)
if err != nil {
log.Fatalf("Could not get info about source directory: %s\n", err.Error())
}
if !finfo.IsDir() {
color.Red("Source path is not a directory!")
os.Exit(1)
}
// Check that the destination directory exists
if _, err := os.Stat(dst); os.IsNotExist(err) {
color.Red("Destination parent directory does not exists!")
os.Exit(1)
}
// Generate the final directory path
srcFolderName := strings.Split(src, "\\")
srcFolderNameStr := srcFolderName[len(srcFolderName)-1]
dstWithSrcDir := fmt.Sprintf("%s/%s", dst, srcFolderNameStr)
// Copy files from source directory to destination directory directory
err = copy.Copy(src, dstWithSrcDir)
if err != nil {
log.Fatalf("Could not copy files from source directory: %s\n", err.Error())
}
// Remove source directory
err = os.RemoveAll(src)
if err != nil {
log.Fatalf("Could not remove source directory: %s\n", err.Error())
}
// Create symlink
err = os.Symlink(dstWithSrcDir, src)
if err != nil {
log.Fatal(err.Error())
}
// Create metadata file
err = CreateMetadataFile(dstWithSrcDir, Metadata{
SourcePath: src,
})
if err != nil {
log.Fatalf("Could not create metadata file: %s\n", err.Error())
}
}
/*
This is used when you need to re-link a directory - the destination directory exists but
the source directory doesn't exist. For example, after formatting a computer, the source
directories don't exist.
dst - The destination directory
*/
func RelinkDir(dst string, ignoreErrors bool) {
metadata, err := ReadMetadataFile(dst)
if err != nil {
if ignoreErrors {
return
}
log.Fatalf("Could not read metadata file: %s\n", err.Error())
}
if _, err := os.Stat(metadata.SourcePath); !os.IsNotExist(err) {
if ignoreErrors {
return
}
color.Red("Source directory already exists!")
os.Exit(1)
}
// Check that the source directory doesn't exist
if _, err := os.Stat(metadata.SourcePath); !os.IsNotExist(err) {
if ignoreErrors {
return
}
color.Red("Source directory already exists!")
os.Exit(1)
}
// Copy destination directory to source directory
err = copy.Copy(dst, metadata.SourcePath)
if err != nil {
if ignoreErrors {
return
}
log.Fatalf("Could not copy files from source directory: %s\n", err.Error())
}
// Remove metadata file from source directory
os.Remove(fmt.Sprintf("%s/%s", metadata.SourcePath, METADATA_FILENAME))
}
/*
This is used when you need to re-link a parent directory. It relinks all the
directories inside it.
dst - The parent directory
*/
func RelinkParentDir(dir string) {
files, err := ioutil.ReadDir(dir)
if err != nil {
log.Fatalf("Could not read parent directory: %s\n", err.Error())
}
// Relink all directories of the parent directory
var wg sync.WaitGroup
for _, f := range files {
wg.Add(1)
go func(f fs.FileInfo) {
defer wg.Done()
RelinkDir(fmt.Sprintf("%s/%s", dir, f.Name()), true)
}(f)
}
wg.Wait()
}