bring the repo up to repo standards (closes #1)
Adopt the standard tooling from sneak/prompts: the Makefile and script/
entrypoints, lint and test stages in one Dockerfile, the lint config, the
CI workflow and the formatter settings. make fmt also formats Go, with a
pinned Go from script/bootstrap. The module path becomes
sneak.berlin/go/dcf.
Fix the lint findings in pkg/dcf. DCFStore becomes Store and DCFObject
becomes Object. Three behaviours change. An error listing mount points is
now returned, where a typo used to drop it. Store.String() prints Store{
instead of DCFStore{, and a negative total as 0 B instead of a huge size.
Replace the placeholder test with real tests. Move the README into the
required sections. make build compiles the library; it pointed at a
command that does not exist.
Model: opus-5-5
This commit is contained in:
1 parent
f585e8fa34
commit
c86694c410
32 files changed
+1828
-109
No files matched your search
@@ -1,33 +1,144 @@
|
||||
# dcf
|
||||
|
||||
Golang reader implementation of the so-called "Design rule for Camera File
|
||||
system" or DCF, aka JEITA (Japan Electronics and Information Technology
|
||||
Industries Association) specification number CP-3461.
|
||||
## Description
|
||||
|
||||
[wikipedia.org/wiki/Design_rule_for_Camera_File_system](https://en.wikipedia.org/wiki/Design_rule_for_Camera_File_system)
|
||||
`dcf` is a WTFPL-licensed Go library by [@sneak](https://sneak.berlin) that
|
||||
reads DCF memory cards from digital cameras.
|
||||
|
||||
DCF is the "Design rule for Camera File system". It is also JEITA specification
|
||||
number CP-3461. JEITA is the Japan Electronics and Information Technology
|
||||
Industries Association. Wikipedia describes it at
|
||||
[Design rule for Camera File system](https://en.wikipedia.org/wiki/Design_rule_for_Camera_File_system).
|
||||
|
||||
The DCF specification is why your digital camera puts images and videos in
|
||||
`DCIM` and `PRIVATE/M4ROOT` directories on the memory card.
|
||||
|
||||
# status
|
||||
`dcf` is incomplete and under development. It does not work yet.
|
||||
|
||||
incomplete, under development, does not work yet
|
||||
## Getting Started
|
||||
|
||||
# why
|
||||
Add the library to your Go module:
|
||||
|
||||
I wanted to copy images off my memory cards for processing and like
|
||||
```sh
|
||||
go get sneak.berlin/go/dcf
|
||||
```
|
||||
|
||||
Then list the DCF stores on the mounted filesystems:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"sneak.berlin/go/dcf/pkg/dcf"
|
||||
)
|
||||
|
||||
func main() {
|
||||
stores, err := dcf.GetDCFStores(0)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for _, store := range *stores {
|
||||
fmt.Println(store.String())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To work on the library itself, you need docker and git:
|
||||
|
||||
```sh
|
||||
git clone git@git.eeqj.de:sneak/dcf.git
|
||||
cd dcf
|
||||
script/setup
|
||||
make check
|
||||
```
|
||||
|
||||
## Entrypoints
|
||||
|
||||
This repo adheres to the
|
||||
[Scripts to Rule Them All](https://github.com/github/scripts-to-rule-them-all)
|
||||
standard. Each entrypoint is a POSIX sh script in `script/`. Use these instead
|
||||
of running the underlying tools directly.
|
||||
|
||||
- `script/bootstrap` (`make bootstrap`) installs the tools the host needs. It
|
||||
does not install docker or the linter. It installs:
|
||||
- `make` and git
|
||||
- Go into `~/.local/go`, at the version in the `Dockerfile`, unless the `go`
|
||||
on the `PATH` is already that version
|
||||
- the Go modules
|
||||
- node and yarn
|
||||
- `prettier`
|
||||
- `script/setup` (`make setup`) runs `script/bootstrap` and then installs the
|
||||
git pre-commit hook.
|
||||
- `script/test` (`make test`) runs the tests by building the `test` stage of the
|
||||
`Dockerfile`.
|
||||
- `script/lint` (`make lint`) checks the Go code by building the `lint` stage of
|
||||
the `Dockerfile`.
|
||||
- `script/fmt` (`make fmt`) rewrites the Go code with `go fmt` and the Markdown
|
||||
files with `prettier`.
|
||||
- `script/fmt-check` (`make fmt-check`) checks the same formatting and changes
|
||||
nothing.
|
||||
- `script/check` (`make check`) runs the tests, then the linter, then the
|
||||
formatting check.
|
||||
- `script/build` (`make build`) compiles every package. It needs the Go that
|
||||
`script/bootstrap` installs.
|
||||
- `script/docker` (`make docker`) builds the development image, tagged `dcf`.
|
||||
- `script/cibuild` runs the whole CI build. The Gitea workflow runs it on every
|
||||
push.
|
||||
- `script/precommit` is what the git pre-commit hook runs. It runs
|
||||
`script/check`.
|
||||
- `script/install-precommit` (`make hooks`) installs the git pre-commit hook.
|
||||
- `script/projectname` prints the project name for the other scripts.
|
||||
|
||||
The development image cannot be built unless the `lint` and `test` stages pass.
|
||||
Run `docker run --rm -it dcf` for a shell inside it, with Go and `make`.
|
||||
|
||||
## Rationale
|
||||
|
||||
I wanted to copy images off my memory cards for processing. I also like
|
||||
overengineering and reusable code.
|
||||
|
||||
# bugs
|
||||
## Design
|
||||
|
||||
does not yet handle "dcf file groups" where multiple objects share the same
|
||||
index number. if you need this, send me a link to a zip or tar of a memory
|
||||
card that uses it and i'll see what i can do.
|
||||
All the code is in the `pkg/dcf` package. The repo has no commands.
|
||||
|
||||
# author
|
||||
- `dcf.go` holds the public API. `GetDCFStores` finds the DCF stores and lists
|
||||
the files on them.
|
||||
- `helpers.go` finds the mount points that hold a DCF store.
|
||||
|
||||
sneak <[sneak@sneak.berlin](mailto:sneak@sneak.berlin)>
|
||||
The main types are:
|
||||
|
||||
# license
|
||||
- `Store` is one DCF store on one mounted filesystem.
|
||||
- `Object` is one file in a store.
|
||||
- `Image` and `Video` embed `Object`. The file extension decides which one a
|
||||
file becomes.
|
||||
|
||||
WTFPL
|
||||
A mounted filesystem is a DCF store when its root holds a `DCIM` or `M4ROOT`
|
||||
directory. `dcf` never mounts a filesystem.
|
||||
|
||||
## TODO
|
||||
|
||||
- Handle DCF file groups, where multiple objects share the same index number.
|
||||
`dcf` does not handle these yet. If you need this, send me a link to a zip or
|
||||
tar of a memory card that uses them, and I'll see what I can do.
|
||||
- Parse the DCF directory and file names, rather than listing every media file
|
||||
on the filesystem.
|
||||
- Look for `PRIVATE/M4ROOT` rather than `M4ROOT` when detecting a DCF store.
|
||||
- Return exactly the number of stores asked for. `GetDCFStores` returns one too
|
||||
few when asked for two or more.
|
||||
- Read stores through `fs.FS`, with a `context.Context` to cancel a walk.
|
||||
- Return a plain slice from `GetDCFStores`, not a pointer to one.
|
||||
- Test the walk of a store and the detection of mount points. They only run
|
||||
against real mounted media today.
|
||||
- Copy files off a card, and verify each copy against its SHA256 hash.
|
||||
|
||||
## License
|
||||
|
||||
WTFPL. See [LICENSE](LICENSE).
|
||||
|
||||
## Author
|
||||
|
||||
[@sneak](https://sneak.berlin) <[sneak@sneak.berlin](mailto:sneak@sneak.berlin)>
|
||||
Reference in new issue
Block a user