This commit is contained in:
2026-04-09 19:21:08 +02:00
parent 07bc594fb5
commit 9dd36b340c
7 changed files with 191 additions and 0 deletions

70
hardlink.go Normal file
View File

@@ -0,0 +1,70 @@
package main
import (
"fmt"
"io/fs"
"log"
"os"
"path/filepath"
)
// processHardlinks creates hardlinks in destBase/destSubdir mirroring the
// structure found at contentPath (either a single file or a directory tree).
func processHardlinks(cfg *Config, contentPath, destSubdir string) error {
info, err := os.Stat(contentPath)
if err != nil {
return fmt.Errorf("stat %q: %w", contentPath, err)
}
destDir := filepath.Join(cfg.DestBase, destSubdir)
if info.IsDir() {
return hardlinkDir(contentPath, destDir)
}
return hardlinkFile(contentPath, filepath.Join(destDir, filepath.Base(contentPath)))
}
// hardlinkDir walks srcDir and recreates the directory tree under destDir,
// creating hardlinks for every file found.
func hardlinkDir(srcDir, destDir string) error {
return filepath.WalkDir(srcDir, func(srcPath string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
rel, err := filepath.Rel(srcDir, srcPath)
if err != nil {
return err
}
destPath := filepath.Join(destDir, rel)
if d.IsDir() {
if err := os.MkdirAll(destPath, 0755); err != nil {
return fmt.Errorf("mkdir %q: %w", destPath, err)
}
return nil
}
return hardlinkFile(srcPath, destPath)
})
}
// hardlinkFile creates a hardlink at destPath pointing to srcPath.
// It creates parent directories as needed and skips if the link already exists.
func hardlinkFile(srcPath, destPath string) error {
if err := os.MkdirAll(filepath.Dir(destPath), 0755); err != nil {
return fmt.Errorf("mkdir %q: %w", filepath.Dir(destPath), err)
}
if _, err := os.Lstat(destPath); err == nil {
log.Printf("skip (already exists): %s", destPath)
return nil
}
if err := os.Link(srcPath, destPath); err != nil {
return fmt.Errorf("hardlink %q -> %q: %w", srcPath, destPath, err)
}
log.Printf("hardlinked: %s -> %s", srcPath, destPath)
return nil
}