@@ -8,6 +8,7 @@ file, You can obtain one at https://mozilla.org/MPL/2.0/.
88package output
99
1010import (
11+ "io"
1112 "os"
1213 "path/filepath"
1314
@@ -36,14 +37,52 @@ func (mv *FilepathMover) mkdir(dir string) error {
3637 return os .MkdirAll (dir , os .ModePerm )
3738}
3839
39- func (mv * FilepathMover ) move (src , dest string ) error {
40+ // rename attempts to rename the file
41+ // if the source and dest are on the same volume, this is preferred - it's fast
42+ // and atomic and handled by the filesystem
43+ // if src and dest are on different volumes, it will error with a cross-device
44+ // link message
45+ func (mv * FilepathMover ) rename (src , dest string ) error {
4046 if mv .DryRun {
41- log .Infof ("move_output: (DRY_RUN) mv %s -> %s" , src , dest )
47+ log .Infof ("move_output: (DRY_RUN) rename %s -> %s" , src , dest )
4248 return nil
4349 }
4450 return os .Rename (src , dest )
4551}
4652
53+ // move copies the file from src to dest
54+ // this is slow as it actually copies the bits over from src to dest
55+ // should only be used to move data between volumes since rename is always
56+ // faster within the filesystem boundary
57+ func (mv * FilepathMover ) move (src , dest string ) error {
58+ if mv .DryRun {
59+ log .Infof ("move_output: (DRY_RUN) copy %s -> %s" , src , dest )
60+ return nil
61+ }
62+
63+ in , err := os .Open (src )
64+ if err != nil {
65+ return errors .Errorf ("error opening src: %s" , err )
66+ }
67+ defer in .Close ()
68+
69+ out , err := os .Create (dest )
70+ if err != nil {
71+ return errors .Errorf ("error opening dest: %s" , err )
72+ }
73+ defer out .Close ()
74+
75+ if _ , err = io .Copy (out , in ); err != nil {
76+ return errors .Errorf ("error writing dest: %s" , err )
77+ }
78+
79+ err = os .Remove (src )
80+ if err != nil {
81+ return errors .Errorf ("error removing src: %s" , err )
82+ }
83+ return nil
84+ }
85+
4786func (mv * FilepathMover ) moveMedia (m types.Media ) error {
4887 if m .DestinationPath == "" {
4988 return errors .New ("move_output: no dest path" )
@@ -65,7 +104,11 @@ func (mv *FilepathMover) moveMedia(m types.Media) error {
65104 }
66105 }
67106 // move src to dest
68- return mv .move (m .SourcePath , m .DestinationPath )
107+ if err := mv .rename (m .SourcePath , m .DestinationPath ); err != nil {
108+ // failed to rename - probably cross-device link so try to move
109+ return mv .move (m .SourcePath , m .DestinationPath )
110+ }
111+ return nil
69112}
70113
71114// Receive implements the Plugin interface on the FilepathMover
0 commit comments