mirror of
https://github.com/derfenix/photocatalog.git
synced 2026-03-11 20:46:24 +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:
|
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).
|
- **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.
|
- **move** — Moves files from the source to the target directory.
|
||||||
- **symlink** — Creates symbolic links at the target pointing to the source files.
|
- **symlink** — Creates symbolic links at the target pointing to the source files.
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,36 @@
|
|||||||
package modes
|
package modes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"sync/atomic"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var hardLinkNotSupported = atomic.Bool{}
|
||||||
|
|
||||||
type HardLink struct {
|
type HardLink struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h HardLink) PlaceIt(sourcePath, targetPath string, mode os.FileMode) error {
|
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 err := os.Link(sourcePath, targetPath); err != nil {
|
||||||
if os.IsExist(err) {
|
if os.IsExist(err) {
|
||||||
return nil
|
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
|
return nil
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"github.com/fsnotify/fsnotify"
|
"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 {
|
if err := watcher.Close(); err != nil {
|
||||||
o.logErr(fmt.Errorf("close watcher: %w", err))
|
o.logErr(fmt.Errorf("close watcher: %w", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
syscall.Sync()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
@@ -155,9 +158,11 @@ func (o *Organizer) Watch(ctx context.Context, wg *sync.WaitGroup) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := o.processFile(event.Name); err != nil {
|
go func() {
|
||||||
o.logErr(fmt.Errorf("process file %s: %w", event.Name, err))
|
if err := o.processFile(event.Name); err != nil {
|
||||||
}
|
o.logErr(fmt.Errorf("process file %s: %w", event.Name, err))
|
||||||
|
}
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
|
|||||||
Reference in New Issue
Block a user