Skip to content

Commit a0683df

Browse files
committed
Following changes:
* Upgrade to Go 18 (along with use of generics) * OS version upgrades in Docker image and test cases * verbose option * increased test case coverage * POSIX-compliance in command-line option * show version * Check if file exists before moving * dynamic parallelism
1 parent 40ba2d7 commit a0683df

27 files changed

+613
-283
lines changed

.github/workflows/build-and-test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ on:
55
- main
66
jobs:
77
build:
8-
runs-on: ubuntu-20.04
8+
runs-on: ubuntu-22.04
99
steps:
1010
- name: Checkout code
1111
uses: actions/checkout@v2
1212
- name: Setup Golang
1313
uses: actions/setup-go@v2
1414
with:
15-
go-version: 1.17
15+
go-version: 1.18
1616
- name: Build code
1717
run: go build
1818
- name: Test code

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
/rsync-sidekick
22
/.idea/
33
*.sh
4-
*.txt
4+
*.txt
5+
*.out
6+
/test_cases_*

Dockerfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM golang:1.17-alpine3.14 as builder
1+
FROM golang:1.18-alpine3.15 as builder
22

33
RUN apk --no-cache add build-base
44

@@ -12,9 +12,9 @@ COPY . .
1212

1313
RUN go build
1414

15-
RUN go test ./...
15+
RUN go test -v ./...
1616

17-
FROM alpine:3.14
17+
FROM alpine:3.15
1818

1919
RUN apk --no-cache add bash rsync
2020

README.md

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ photos, etc.) _that are reorganized frequently_.
1212

1313
`rsync-sidekick` is a safe and simple tool that is designed to run **before** `rsync` is run.
1414

15-
This propagates following changes from _source directory_ to _destination directory_ (or any combination of below):
15+
This propagates following changes (or any combination) from _source directory_ to _destination directory_:
1616

1717
1. Change in file modification timestamp
1818
2. Rename of file/directory
@@ -22,7 +22,7 @@ Note:
2222

2323
* This tool **does not delete** any files or folders (under any circumstances) -- that's why safe-to-use 😌
2424
* Your files are just _moved around_
25-
* Now, if you're uncomfortable with this tool even moving your files around, there is a `-shellscript` option, that
25+
* Now, if you're uncomfortable with this tool even moving your files around, there is a `--shellscript` option, that
2626
just generates a script for you to read and run (think of it like a `--dry-run` option)
2727
* This tool **does not** actually **transfer** files -- that's for `rsync` to do 🙂
2828
* Since you'd run `rsync` after this tool is run, any changes that this tool couldn't propagate would just be propagated
@@ -32,8 +32,10 @@ Note:
3232

3333
## How to install?
3434

35-
1. Install Go version at least **1.17**
36-
* See: [Go installation instructions](https://go.dev/doc/install)
35+
1. Install Go version at least **1.18**
36+
* On Ubuntu: `snap install go`
37+
* On Mac: `brew install go`
38+
* For anything else: [Go downloads page](https://go.dev/dl/)
3739
2. Run command:
3840
```bash
3941
go install github.com/m-manu/rsync-sidekick@latest
@@ -45,40 +47,44 @@ Note:
4547

4648
## How to use?
4749

48-
### Step 1
49-
50-
Run this tool:
50+
**Step 1**: Run this tool
5151

5252
```bash
5353
rsync-sidekick /Users/manu/Photos/ /Volumes/Portable/Photos/
5454
```
5555

56-
### Step 2
57-
58-
Run `rsync` as you would normally do:
56+
**Step 2**: Run `rsync` as you would normally do
5957

6058
```bash
61-
# (note the trailing slashes -- without them, rsync's behavior is different)
59+
# Note the trailing slashes below. Without them, rsync's behavior is different!
6260
rsync -av /Users/manu/Photos/ /Volumes/Portable/Photos/
6361
```
6462

6563
## Command line options
6664

67-
Running `rsync-sidekick -help` displays following information:
65+
Running `rsync-sidekick --help` displays following information:
6866

6967
```
70-
usage:
71-
rsync-sidekick <flags> [source-dir] [destination-dir]
72-
where:
73-
source-dir Source directory
74-
destination-dir Destination directory
68+
rsync-sidekick is a tool to propagate file renames, movements and timestamp changes from a source directory to a destination directory.
69+
70+
Usage:
71+
rsync-sidekick <flags> [source-dir] [destination-dir]
72+
73+
where,
74+
[source-dir] Source directory
75+
[destination-dir] Destination directory
76+
7577
flags: (all optional)
76-
-exclusions string
77-
path to a text file that contains ignorable file/directory names separated by new lines (even without this flag, this tool ignores commonly ignorable names such as 'System Volume Information', 'Thumbs.db' etc.)
78-
-extrainfo
79-
generate extra information (caution: makes it slow!)
80-
-shellscript
81-
instead of applying changes directly, generate a shell script (this flag is useful if you want run the shell script as a different user)
78+
-x, --exclusions string path to file containing newline separated list of file/directory names to be excluded
79+
(even if this is not set, files/directories such these will still be ignored: $RECYCLE.BIN, desktop.ini, Thumbs.db etc.)
80+
-h, --help display help
81+
--list list files along their metadata for given directory
82+
-s, --shellscript instead of applying changes directly, generate a shell script
83+
(this flag is useful if you want 'dry run' this tool or want to run the shell script as a different user)
84+
-v, --verbose generates extra information, even a file dump (caution: makes it slow!)
85+
--version show version
86+
87+
More details here: https://github.com/m-manu/rsync-sidekick
8288
```
8389

8490
## Running this from a Docker container

action/action.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ type SyncAction interface {
1616
Uniqueness() string
1717
}
1818

19+
const cmdSeparator = "\u0001"
20+
1921
func escape(path string) string {
2022
escaped := path
2123
escaped = strings.ReplaceAll(escaped, "\\", "\\\\") // This replace should be first

action/make_directory_action.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func (a MakeDirectoryAction) Perform() error {
3030

3131
// Uniqueness generates unique string for directory creation
3232
func (a MakeDirectoryAction) Uniqueness() string {
33-
return "Mkdir\u0001" + a.AbsoluteDirPath
33+
return "Mkdir" + cmdSeparator + a.AbsoluteDirPath
3434
}
3535

3636
func (a MakeDirectoryAction) String() string {

action/move_file_action.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package action
22

33
import (
4+
"errors"
45
"fmt"
56
"os"
67
"path/filepath"
@@ -23,17 +24,23 @@ func (a MoveFileAction) destinationPath() string {
2324

2425
// UnixCommand for moving or renaming a file
2526
func (a MoveFileAction) UnixCommand() string {
26-
return fmt.Sprintf(`mv -v "%s" "%s"`, escape(a.sourcePath()), escape(a.destinationPath()))
27+
return fmt.Sprintf(`mv -v -n "%s" "%s"`, escape(a.sourcePath()), escape(a.destinationPath()))
2728
}
2829

2930
// Perform 'file move/rename' action
3031
func (a MoveFileAction) Perform() error {
31-
return os.Rename(a.sourcePath(), a.destinationPath())
32+
if _, err := os.Stat(a.destinationPath()); err == nil {
33+
return fmt.Errorf(`error: file "%s" already exists`, a.destinationPath())
34+
} else if errors.Is(err, os.ErrNotExist) {
35+
return os.Rename(a.sourcePath(), a.destinationPath())
36+
} else {
37+
return err
38+
}
3239
}
3340

3441
// Uniqueness generates unique string for file renaming/movement
3542
func (a MoveFileAction) Uniqueness() string {
36-
return "mv\u0001" + a.RelativeFromPath
43+
return "mv" + cmdSeparator + a.RelativeFromPath
3744
}
3845

3946
func (a MoveFileAction) String() string {

action/propagate_timestamp_action.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func (a PropagateTimestampAction) Perform() error {
3939

4040
// Uniqueness generate unique string for 'file modification timestamp' propagation action
4141
func (a PropagateTimestampAction) Uniqueness() string {
42-
return "touch\u0001" + a.DestinationFileRelativePath
42+
return "touch" + cmdSeparator + a.DestinationFileRelativePath
4343
}
4444

4545
func (a PropagateTimestampAction) String() string {

entity/map_string_to_file_digest.go

Lines changed: 0 additions & 40 deletions
This file was deleted.

entity/multimap_file_digest_to_string.go

Lines changed: 0 additions & 36 deletions
This file was deleted.

0 commit comments

Comments
 (0)