From de9416a35b8b598fc2e5637608f50fe79d29cc7a Mon Sep 17 00:00:00 2001 From: Jan Kelemen Date: Mon, 13 Sep 2021 00:26:08 +0200 Subject: [PATCH] refactoring --- main.go | 18 ++++++------ mirror/mirror.go | 65 ++++++++++++++++++++++++------------------- mirror/mirror_test.go | 47 +++++++++++++------------------ 3 files changed, 66 insertions(+), 64 deletions(-) diff --git a/main.go b/main.go index dd65871..f991b10 100644 --- a/main.go +++ b/main.go @@ -9,14 +9,14 @@ import ( ) const ( - MsgCanceling = "canceling" - MsgCalculating = "gathering info about files" - MgsAreYouSure = "Do you want to continue?" - MsgLogging = "Also a log file named 'log' will be generated." - MsgNothingToDo = "there is nothing to do" - MsgErrOccurred = "an error occurred" - MsgFinished = "the program finished successfully" - MsgDone = "done" + MsgCanceling = "canceling" + MsgGatheringInfo = "gathering info about files" + MgsAreYouSure = "Do you want to continue?" + MsgLogging = "Also a log file named 'log' will be generated." + MsgNothingToDo = "there is nothing to do" + MsgErrOccurred = "an error occurred:" + MsgFinished = "the program finished successfully" + MsgDone = "done" ) func main() { @@ -87,7 +87,7 @@ func doCleaning(dst, src string) { } func srcDstDiff(dst, src string, cleaningMod bool) (folders mirror.Folder, files mirror.File, totalSize int64) { - log.Println(MsgCalculating) + log.Println(MsgGatheringInfo) srcFolders, srcFiles, err := mirror.ReadFolder(src) checkErr(err) diff --git a/mirror/mirror.go b/mirror/mirror.go index a6af0c5..d85cf89 100644 --- a/mirror/mirror.go +++ b/mirror/mirror.go @@ -4,7 +4,6 @@ package mirror import ( "bufio" "flag" - "fmt" "io" "log" "os" @@ -19,6 +18,7 @@ const ( ErrWrongArgs = CustomErr("wrong arguments, use the -h flag for help") ErrSrcNotFound = CustomErr("source folder doesn't exist") ErrDstNotFound = CustomErr("destination folder doesn't exist") + ErrOnlyFoldersOrFiles = CustomErr("the function accepts only folders and files") FolderToIgnore = "dont_mirror" LogFile = "log" BytesInMB = 1e6 @@ -120,7 +120,6 @@ func readFolder(path string, startingPath string, folders Folder, files File) er } for _, item := range items { - currentName := item.Name() currentPath := filepath.Join(path, currentName) currentTrimmedPath, err := filepath.Rel(startingPath, currentPath) @@ -140,7 +139,9 @@ func readFolder(path string, startingPath string, folders Folder, files File) er if err != nil { return err } - files[currentTrimmedPath] = info.Size() + if info.Mode()&os.ModeSymlink != os.ModeSymlink { + files[currentTrimmedPath] = info.Size() + } } } return nil @@ -198,7 +199,7 @@ func FilesToClean(dst, src File) (res File, totalSize int64) { // MakeFolders makes directories with os.MkdirAll in path directory and logs progress func MakeFolders(folders Folder, path string) error { - var progressInPercentage, counter int + var recentlyLoggedProgress, counter int f, err := initLogFile() if err != nil { @@ -207,12 +208,13 @@ func MakeFolders(folders Folder, path string) error { LogToFile(f, LogMadeFolders+"\n") - for _, folder := range keepFoldersWithLongestPrefix(folders) { + sortedFolders := keepFoldersWithLongestPrefix(folders) + for _, folder := range sortedFolders { if err = os.MkdirAll(filepath.Join(path, folder), FolderPerm); err != nil { return err } - logProgressFolders(&progressInPercentage, &counter, len(folders), fmt.Sprintf("%s %d%%", MsgProgressMakingFolders, progressInPercentage)) + logProgressFolders(&recentlyLoggedProgress, &counter, len(sortedFolders), MsgProgressMakingFolders) LogToFile(f, folder) } @@ -223,7 +225,7 @@ func MakeFolders(folders Folder, path string) error { // CleanFolders removes directories with os.RemoveAll in path directory and logs progress func CleanFolders(folders Folder, path string) error { - var progressInPercentage, counter int + var recentlyLoggedProgress, counter int f, err := initLogFile() if err != nil { @@ -232,12 +234,13 @@ func CleanFolders(folders Folder, path string) error { LogToFile(f, LogCleanedFolders+"\n") - for _, folder := range keepFoldersWithShortestPrefix(folders) { + sortedFolders := keepFoldersWithShortestPrefix(folders) + for _, folder := range sortedFolders { if err = os.RemoveAll(filepath.Join(path, folder)); err != nil { return err } - logProgressFolders(&progressInPercentage, &counter, len(folders), fmt.Sprintf("%s %d%%", MsgProgressCleaningFolders, progressInPercentage)) + logProgressFolders(&recentlyLoggedProgress, &counter, len(sortedFolders), MsgProgressCleaningFolders) LogToFile(f, folder) } @@ -248,7 +251,7 @@ func CleanFolders(folders Folder, path string) error { // CopyFiles copies files and logs progress. The 'files' parameter should contain relative paths func CopyFiles(files File, totalSize int64, src, dst string) error { - var bytesWritten, progressInPercentage int64 + var bytesWritten, recentlyLoggedProgress int64 l, err := initLogFile() if err != nil { @@ -281,7 +284,7 @@ func CopyFiles(files File, totalSize int64, src, dst string) error { return err } - logProgressFiles(&progressInPercentage, totalSize, bytesWritten, fmt.Sprintf("%s %d%%", MsgProgressCopyingFiles, progressInPercentage)) + logProgressFiles(&recentlyLoggedProgress, totalSize, bytesWritten, MsgProgressCopyingFiles) LogToFile(l, file) } @@ -295,7 +298,7 @@ func CopyFiles(files File, totalSize int64, src, dst string) error { // CleanFiles removes files and logs progress. The 'files' parameter should contain relative paths func CleanFiles(files File, totalSize int64, path string) error { - var bytesDeleted, progressInPercentage int64 + var bytesDeleted, recentlyLoggedProgress int64 l, err := initLogFile() if err != nil { @@ -315,7 +318,7 @@ func CleanFiles(files File, totalSize int64, path string) error { return err } - logProgressFiles(&progressInPercentage, totalSize, bytesDeleted, fmt.Sprintf("%s %d%%", MsgProgressCleaningFiles, progressInPercentage)) + logProgressFiles(&recentlyLoggedProgress, totalSize, bytesDeleted, MsgProgressCleaningFiles) LogToFile(l, file) } @@ -364,24 +367,30 @@ func BytesToMB(size int64) string { return ThousandSeparator(strconv.FormatInt(size/BytesInMB, 10)) } -func logProgressFiles(progressInPercentage *int64, totalSize, bytesWritten int64, msg string) { - // howOftenToLog is in percentage - var howOftenToLog int64 = 10 +func logProgressFiles(recentlyLoggedProgress *int64, totalSize, bytesWritten int64, msg string) { + // howOftenToLog and progress are in percentage + var howOftenToLog, progress int64 = 10, 100 + + if totalSize > 0 { + progress = bytesWritten * 100 / totalSize + } else if totalSize == 0 && *recentlyLoggedProgress > 0 { + return + } - if totalSize > 0 && bytesWritten*100/totalSize > *progressInPercentage { - log.Println(msg) - *progressInPercentage += howOftenToLog + if progress > *recentlyLoggedProgress+howOftenToLog { + log.Printf("%s %d%%\n", msg, progress) + *recentlyLoggedProgress += progress } } -func logProgressFolders(progressInPercentage, counter *int, foldersLen int, msg string) { - // howOftenToLog is in percentage - howOftenToLog := 10 +func logProgressFolders(recentlyLoggedProgress, counter *int, foldersLen int, msg string) { *counter++ + // howOftenToLog and progress are in percentage + var howOftenToLog, progress = 10, *counter * 100 / foldersLen - if *counter*100/foldersLen > *progressInPercentage { - log.Println(msg) - *progressInPercentage += howOftenToLog + if progress > *recentlyLoggedProgress+howOftenToLog { + log.Printf("%s %d%%\n", msg, progress) + *recentlyLoggedProgress += progress } return } @@ -391,7 +400,7 @@ func sortFoldersOrFiles(m interface{}) []string { _, isFile := m.(File) if !isFolder && !isFile { - panic("the function accepts only files and folders") + panic(ErrOnlyFoldersOrFiles) } res := make([]string, 0, reflect.ValueOf(m).Len()) @@ -418,7 +427,7 @@ func keepFoldersWithLongestPrefix(folders Folder) (res []string) { sorted := sortFoldersOrFiles(folders) for i := 0; i < len(folders)-1; i++ { - if !strings.HasPrefix(sorted[i+1], sorted[i]) { + if filepath.Dir(sorted[i+1]) == filepath.Dir(sorted[i]) || !strings.HasPrefix(sorted[i+1], sorted[i]) { res = append(res, sorted[i]) } } @@ -431,7 +440,7 @@ func keepFoldersWithShortestPrefix(folders Folder) (res []string) { sorted := sortFoldersOrFiles(folders) for i := len(folders) - 1; i > 0; i-- { - if !strings.HasPrefix(sorted[i], sorted[i-1]) { + if filepath.Dir(sorted[i]) == filepath.Dir(sorted[i-1]) || !strings.HasPrefix(sorted[i], sorted[i-1]) { res = append(res, sorted[i]) } } diff --git a/mirror/mirror_test.go b/mirror/mirror_test.go index f8157c3..4172a43 100644 --- a/mirror/mirror_test.go +++ b/mirror/mirror_test.go @@ -10,7 +10,6 @@ import ( "path/filepath" "reflect" "strconv" - "strings" "testing" ) @@ -263,8 +262,8 @@ func TestSortFoldersOrFiles2(t *testing.T) { } func TestKeepFoldersWithLongestPrefix(t *testing.T) { - input := Folder{"a/b/c": {}, "a": {}, "a/b": {}, "q": {}, "g": {}} - expected := []string{"a/b/c", "g", "q"} + input := Folder{"a/b/c": {}, "a": {}, "a/b": {}, "q": {}, "g": {}, "a/b/cc": {}, "aa": {}} + expected := []string{"a/b/c", "a/b/cc", "aa", "g", "q"} got := keepFoldersWithLongestPrefix(input) if !reflect.DeepEqual(got, expected) { t.Errorf("input %v, got %v, expected %v", input, got, expected) @@ -272,8 +271,8 @@ func TestKeepFoldersWithLongestPrefix(t *testing.T) { } func TestKeepFoldersWithShortestPrefix(t *testing.T) { - input := Folder{"a/b/c": {}, "a": {}, "a/b": {}, "q": {}, "g": {}} - expected := []string{"q", "g", "a"} + input := Folder{"a/b/c": {}, "a": {}, "a/b": {}, "q": {}, "g": {}, "a/b/cc": {}, "aa": {}} + expected := []string{"q", "g", "aa", "a/b/cc", "a"} got := keepFoldersWithShortestPrefix(input) if !reflect.DeepEqual(got, expected) { t.Errorf("input %v, got %v, expected %v", input, got, expected) @@ -300,24 +299,24 @@ func makeTestSrcFolder(t testing.TB) { t.Helper() // make folders - err := os.MkdirAll(mcpp(srcPathTest+"/same_1/same_2/not_in_dst"), FolderPerm) + err := os.MkdirAll(filepath.Join(srcPathTest+"/same_1/same_2/not_in_dst"), FolderPerm) assertError(t, nil, err) - srcFolders = Folder{"same_1": {}, mcpp("same_1/same_2"): {}, mcpp("same_1/same_2/not_in_dst"): {}} - missingFolders = Folder{mcpp("same_1/same_2/not_in_dst"): {}} + srcFolders = Folder{"same_1": {}, filepath.Join("same_1/same_2"): {}, filepath.Join("same_1/same_2/not_in_dst"): {}} + missingFolders = Folder{filepath.Join("same_1/same_2/not_in_dst"): {}} // make files - err = ioutil.WriteFile(mcpp(srcPathTest+"/_same_1"), []byte("s"), FilePerm) + err = ioutil.WriteFile(filepath.Join(srcPathTest+"/_same_1"), []byte("s"), FilePerm) assertError(t, nil, err) - err = ioutil.WriteFile(mcpp(srcPathTest+"/same_1/same_2/_not_in_dst"), []byte("n"), FilePerm) + err = ioutil.WriteFile(filepath.Join(srcPathTest+"/same_1/same_2/_not_in_dst"), []byte("n"), FilePerm) assertError(t, nil, err) - err = ioutil.WriteFile(mcpp(srcPathTest+"/same_1/_different"), []byte("dd"), FilePerm) + err = ioutil.WriteFile(filepath.Join(srcPathTest+"/same_1/_different"), []byte("dd"), FilePerm) assertError(t, nil, err) - srcFiles = File{"_same_1": 1, mcpp("same_1/same_2/_not_in_dst"): 1, mcpp("same_1/_different"): 2} - missingFiles = File{mcpp("same_1/same_2/_not_in_dst"): 1, mcpp("same_1/_different"): 2} + srcFiles = File{"_same_1": 1, filepath.Join("same_1/same_2/_not_in_dst"): 1, filepath.Join("same_1/_different"): 2} + missingFiles = File{filepath.Join("same_1/same_2/_not_in_dst"): 1, filepath.Join("same_1/_different"): 2} sizeOfMissingFiles = 3 @@ -328,24 +327,24 @@ func makeTestDstFolder(t testing.TB) { t.Helper() // make folders - err := os.MkdirAll(mcpp(dstPathTest+"/same_1/same_2/not_in_src"), FolderPerm) + err := os.MkdirAll(filepath.Join(dstPathTest+"/same_1/same_2/not_in_src"), FolderPerm) assertError(t, nil, err) - dstFolders = Folder{"same_1": {}, mcpp("same_1/same_2"): {}, mcpp("same_1/same_2/not_in_src"): {}} - foldersToClean = Folder{mcpp("same_1/same_2/not_in_src"): {}} + dstFolders = Folder{"same_1": {}, filepath.Join("same_1/same_2"): {}, filepath.Join("same_1/same_2/not_in_src"): {}} + foldersToClean = Folder{filepath.Join("same_1/same_2/not_in_src"): {}} // make files - err = ioutil.WriteFile(mcpp(dstPathTest+"/_same_1"), []byte("s"), FilePerm) + err = ioutil.WriteFile(filepath.Join(dstPathTest+"/_same_1"), []byte("s"), FilePerm) assertError(t, nil, err) - err = ioutil.WriteFile(mcpp(dstPathTest+"/same_1/same_2/_not_in_src"), []byte("n"), FilePerm) + err = ioutil.WriteFile(filepath.Join(dstPathTest+"/same_1/same_2/_not_in_src"), []byte("n"), FilePerm) assertError(t, nil, err) - err = ioutil.WriteFile(mcpp(dstPathTest+"/same_1/_different"), []byte("d"), FilePerm) + err = ioutil.WriteFile(filepath.Join(dstPathTest+"/same_1/_different"), []byte("d"), FilePerm) assertError(t, nil, err) - dstFiles = File{"_same_1": 1, mcpp("same_1/same_2/_not_in_src"): 1, mcpp("same_1/_different"): 1} - filesToClean = File{mcpp("same_1/same_2/_not_in_src"): 1} + dstFiles = File{"_same_1": 1, filepath.Join("same_1/same_2/_not_in_src"): 1, filepath.Join("same_1/_different"): 1} + filesToClean = File{filepath.Join("same_1/same_2/_not_in_src"): 1} sizeOfFilesToClean = 1 @@ -362,12 +361,6 @@ func setFlags(t testing.TB, dst, src string, c bool) { os.Args = append(os.Args, "-"+FlagNameDst, dst, "-"+FlagNameSrc, src, "-"+FlagNameC, strconv.FormatBool(c)) } -// mcpp makes a cross-platform path from unix path -func mcpp(unixPath string) string { - pathSplit := strings.Split(unixPath, "/") - return filepath.Join(pathSplit...) -} - func assert(t testing.TB, want, got interface{}) { t.Helper()