mirror of
https://github.com/derfenix/photocatalog.git
synced 2026-03-11 11:52:57 +03:00
Permanent fallback to copy on hardlink error
This commit is contained in:
@@ -30,7 +30,8 @@ sudo cp ${GOPATH}/bin/photocatalog /usr/local/bin/photocatalog
|
||||
The tool supports the following organization modes:
|
||||
|
||||
- **copy** — Copies files to the target directory. If the filesystem supports it, uses Copy-on-Write (COW) for efficiency (via FICLONE ioctl call).
|
||||
- **hardlink** — Creates hardlinks to the source files, saving disk space. Ideal if the source and target are on the same partition, though file permissions remain linked to the original.
|
||||
- **hardlink** — Creates hardlinks to the source files, saving disk space. Ideal (and usable only) if the source and target are on the same partition,
|
||||
though file permissions remain linked to the original. Fallback to copy on fail.
|
||||
- **move** — Moves files from the source to the target directory.
|
||||
- **symlink** — Creates symbolic links at the target pointing to the source files.
|
||||
|
||||
|
||||
@@ -1,20 +1,36 @@
|
||||
package modes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
var hardLinkNotSupported = atomic.Bool{}
|
||||
|
||||
type HardLink struct {
|
||||
}
|
||||
|
||||
func (h HardLink) PlaceIt(sourcePath, targetPath string, mode os.FileMode) error {
|
||||
if hardLinkNotSupported.Load() {
|
||||
if copyErr := (Copy{}).PlaceIt(sourcePath, targetPath, mode); copyErr != nil {
|
||||
return copyErr
|
||||
}
|
||||
}
|
||||
|
||||
if err := os.Link(sourcePath, targetPath); err != nil {
|
||||
if os.IsExist(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("create hard link: %w", err)
|
||||
log.Println("Create hardlink failed:", err.Error())
|
||||
hardLinkNotSupported.Store(true)
|
||||
|
||||
if copyErr := (Copy{}).PlaceIt(sourcePath, targetPath, mode); copyErr != nil {
|
||||
return copyErr
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
|
||||
@@ -130,6 +131,8 @@ func (o *Organizer) Watch(ctx context.Context, wg *sync.WaitGroup) error {
|
||||
if err := watcher.Close(); err != nil {
|
||||
o.logErr(fmt.Errorf("close watcher: %w", err))
|
||||
}
|
||||
|
||||
syscall.Sync()
|
||||
}()
|
||||
|
||||
go func() {
|
||||
@@ -155,9 +158,11 @@ func (o *Organizer) Watch(ctx context.Context, wg *sync.WaitGroup) error {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := o.processFile(event.Name); err != nil {
|
||||
o.logErr(fmt.Errorf("process file %s: %w", event.Name, err))
|
||||
}
|
||||
go func() {
|
||||
if err := o.processFile(event.Name); err != nil {
|
||||
o.logErr(fmt.Errorf("process file %s: %w", event.Name, err))
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
case <-ctx.Done():
|
||||
|
||||
Reference in New Issue
Block a user