Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jankelemen committed Sep 6, 2021
0 parents commit 9d88ac9
Show file tree
Hide file tree
Showing 7 changed files with 873 additions and 0 deletions.
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Ignore all
*

# Unignore all with extensions
!*.*

# Unignore all dirs
!*/

### Above combination will ignore all files without extension ###

# Ignore all dirs that start with dot
.*/

# Ignore my personal Makefile
Makefile
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
This program takes two flags - `src` and `dst` and copies files that are present in `src` but not in `dst` and files
that are a different size (I tried using hashes to determine whether a file is different, but it was painfully slow).
Also, folders that are named `dont_mirror` will be ignored.

There's also an optional `c` flag that turns on "cleaning mode". In this mode, every file and directory that is present
in `dst` but not in `src` will be deleted. (Files with different sizes will be left alone)

I use this program for my personal use, so it isn't the fastest thing ever written, but it can handle a few million
files just fine.
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module mirror

go 1.17
20 changes: 20 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
110 changes: 110 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// This package's main function copies files from one folder to another but doesn't override files that are the same (files are the same if they have the same size)
package main

import (
"fmt"
"log"
"mirror/mirror"
"os"
)

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"
)

func main() {
dst, src, cleaningMode, err := mirror.VetFlags()
checkErr(err)

if cleaningMode {
doCleaning(dst, src)
} else {
doCopying(dst, src)
}
}

func doCopying(dst, src string) {
if !mirror.AskQuestion(fmt.Sprintf("files from %q will be copied to %q. %s", src, dst, MgsAreYouSure)) {
log.Fatalln(MsgCanceling)
}

missingFolders, missingFiles, totalSize := srcDstDiff(dst, src, false)

if !mirror.AskQuestion(fmt.Sprintf("%d files will be coppied (%s MB) and %d folders will be created. %s %s", len(missingFiles), mirror.BytesToMB(totalSize), len(missingFolders), MsgLogging, MgsAreYouSure)) {
log.Fatalln(MsgCanceling)
}

err := mirror.TruncateLogFile()
checkErr(err)

if len(missingFolders) > 0 {
err = mirror.MakeFolders(missingFolders, dst)
checkErr(err)
}

if len(missingFiles) > 0 {
err = mirror.CopyFiles(missingFiles, totalSize, src, dst)
checkErr(err)
}
}

func doCleaning(dst, src string) {
if !mirror.AskQuestion(fmt.Sprintf("files may be deleted in the %q folder. %s", dst, MgsAreYouSure)) {
log.Fatalln(MsgCanceling)
}

foldersToClean, filesToClean, totalSize := srcDstDiff(dst, src, true)

if !mirror.AskQuestion(fmt.Sprintf("%d files and %d folders will be deleted (%s MB). %s %s", len(filesToClean), len(foldersToClean), mirror.BytesToMB(totalSize), MsgLogging, MgsAreYouSure)) {
log.Fatalln(MsgCanceling)
}

err := mirror.TruncateLogFile()
checkErr(err)

if len(filesToClean) > 0 {
err = mirror.CleanFiles(filesToClean, dst)
checkErr(err)
}

if len(foldersToClean) > 0 {
err = mirror.CleanFolders(foldersToClean, dst)
checkErr(err)
}
}

func srcDstDiff(dst, src string, cleaningMod bool) (folders mirror.Folder, files mirror.File, totalSize int64) {
log.Println(MsgCalculating)

srcFolders, srcFiles, err := mirror.ReadFolder(src)
checkErr(err)

dstFolders, dstFiles, err := mirror.ReadFolder(dst)
checkErr(err)

if cleaningMod {
folders = mirror.FoldersToClean(dstFolders, srcFolders)
files, totalSize = mirror.FilesToClean(dstFiles, srcFiles)
} else {
folders = mirror.MissingFolders(dstFolders, srcFolders)
files, totalSize = mirror.MissingFiles(dstFiles, srcFiles)
}

if len(files) == 0 && len(folders) == 0 {
log.Println(MsgNothingToDo)
os.Exit(0)
}

return
}

func checkErr(err error) {
if err != nil {
log.Fatalln(MsgErrOccurred, err)
}
}
Loading

0 comments on commit 9d88ac9

Please sign in to comment.