Adopt the standard tooling: a Makefile of thin shims over a full scripts-to-rule-them-all `script/` set, the canonical `.golangci.yml` vendored byte-identical from `sneak/prompts`, docker-only linting via `Dockerfile.lint`, a `Dockerfile` and Gitea workflow that gate every push, and prettier/editorconfig/dockerignore config. `make build` pointed at a `cmd/dcfinfo` that is not in the tree and could never have succeeded; this repo is a library, so `build` is now the compile check over every package. Clear the 57 findings the canonical linter config reports on `pkg/dcf`. Two were real: `findDCFMountPoints` checked a never-assigned `erro` instead of the error from `findAllMountPoints`, discarding it, and `privatePath` was computed twice so the first computation was dead. Mountpoint selection otherwise behaves exactly as before; the defects that survive are filed as issue #6, not fixed here. Rename `DCFStore` to `Store` and `DCFObject` to `Object` (with its `DCFStoreRoot` field to `StoreRoot`), which revive's stutter rule requires and which the `fs.FS` rework in issue #4 will build on. Replace the placeholder test with tests over the exported surface. The filesystem walk stays uncovered: it is reachable only through `GetDCFStores`, which needs real mounted media. README keeps its content, reorganised into the required sections and gaining Entrypoints. (closes #1)
85 lines
1.9 KiB
Go
85 lines
1.9 KiB
Go
package dcf
|
|
|
|
import (
|
|
"log/slog"
|
|
"os"
|
|
"path/filepath"
|
|
"slices"
|
|
|
|
"github.com/shirou/gopsutil/disk"
|
|
)
|
|
|
|
// dcfMarkerDirectories are the directory names whose presence in a
|
|
// filesystem root identifies that filesystem as a DCF store.
|
|
func dcfMarkerDirectories() []string {
|
|
return []string{"DCIM", "M4ROOT"}
|
|
}
|
|
|
|
// findAllMountPoints returns the distinct mountpoints of the system's
|
|
// physical filesystems.
|
|
func findAllMountPoints() ([]string, error) {
|
|
partitions, err := disk.Partitions(false) // physical devices only
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
mountpoints := []string{}
|
|
|
|
for _, partition := range partitions {
|
|
if !slices.Contains(mountpoints, partition.Mountpoint) {
|
|
mountpoints = append(mountpoints, partition.Mountpoint)
|
|
}
|
|
}
|
|
|
|
return mountpoints, nil
|
|
}
|
|
|
|
// findDCFMountPoints returns the paths of the mountpoints that contain
|
|
// one of the marker directories a DCF store is identified by. Its only
|
|
// argument is how many mountpoints to return; 0 returns all of them.
|
|
func findDCFMountPoints(requestedCount int) ([]string, error) {
|
|
mountpoints, err := findAllMountPoints()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
filteredMountpoints := []string{}
|
|
|
|
for _, mountpoint := range mountpoints {
|
|
if !isDCFMountPoint(mountpoint) {
|
|
continue
|
|
}
|
|
|
|
slog.Debug("keeping mountpoint", "mountpoint", mountpoint)
|
|
|
|
filteredMountpoints = append(filteredMountpoints, mountpoint)
|
|
|
|
if requestedCount > 0 && len(filteredMountpoints)+1 >= requestedCount {
|
|
break
|
|
}
|
|
}
|
|
|
|
return filteredMountpoints, nil
|
|
}
|
|
|
|
// isDCFMountPoint reports whether mountpoint holds any of the marker
|
|
// directories a DCF store is identified by.
|
|
func isDCFMountPoint(mountpoint string) bool {
|
|
found := false
|
|
|
|
for _, marker := range dcfMarkerDirectories() {
|
|
markerPath := filepath.Join(mountpoint, marker)
|
|
|
|
_, err := os.Stat(markerPath)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
slog.Debug("found marker directory", "path", markerPath)
|
|
|
|
found = true
|
|
}
|
|
|
|
return found
|
|
}
|