Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32b468af8a |
@@ -1,12 +0,0 @@
|
|||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 4
|
|
||||||
end_of_line = lf
|
|
||||||
charset = utf-8
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
insert_final_newline = true
|
|
||||||
|
|
||||||
[Makefile]
|
|
||||||
indent_style = tab
|
|
||||||
+2
-21
@@ -10,24 +10,5 @@ modcache.tzst
|
|||||||
# Generated manifest files
|
# Generated manifest files
|
||||||
.index.mf
|
.index.mf
|
||||||
|
|
||||||
# Secrets
|
# Stale files
|
||||||
.env
|
.drone.yml
|
||||||
.env.*
|
|
||||||
*.key
|
|
||||||
*.pem
|
|
||||||
|
|
||||||
# OS files
|
|
||||||
.DS_Store
|
|
||||||
Thumbs.db
|
|
||||||
|
|
||||||
# Editor files
|
|
||||||
*.swp
|
|
||||||
*.swo
|
|
||||||
*~
|
|
||||||
.idea/
|
|
||||||
.vscode/
|
|
||||||
|
|
||||||
# Go build artifacts
|
|
||||||
*.log
|
|
||||||
*.out
|
|
||||||
*.test
|
|
||||||
|
|||||||
+12
@@ -11,6 +11,10 @@ COPY . .
|
|||||||
# Touch .pb.go so make does not try to regenerate via protoc (file is committed)
|
# Touch .pb.go so make does not try to regenerate via protoc (file is committed)
|
||||||
RUN touch mfer/mf.pb.go
|
RUN touch mfer/mf.pb.go
|
||||||
|
|
||||||
|
# Changing value from script/cibuild; forces the check steps below to
|
||||||
|
# re-run instead of being served from a stale layer cache.
|
||||||
|
ARG CHECK_EPOCH
|
||||||
|
|
||||||
# Go half of fmt-check only: this image has no node, so no prettier. The
|
# Go half of fmt-check only: this image has no node, so no prettier. The
|
||||||
# markdown half runs in the mdfmt stage below.
|
# markdown half runs in the mdfmt stage below.
|
||||||
RUN make fmt-check-go
|
RUN make fmt-check-go
|
||||||
@@ -27,6 +31,10 @@ RUN yarn install --frozen-lockfile
|
|||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
|
# Changing value from script/cibuild; forces the check step below to
|
||||||
|
# re-run instead of being served from a stale layer cache.
|
||||||
|
ARG CHECK_EPOCH
|
||||||
|
|
||||||
# No make in this image; call the script entrypoint directly.
|
# No make in this image; call the script entrypoint directly.
|
||||||
RUN script/prettier --check
|
RUN script/prettier --check
|
||||||
|
|
||||||
@@ -47,6 +55,10 @@ COPY . .
|
|||||||
# Touch .pb.go so make does not try to regenerate via protoc (file is committed)
|
# Touch .pb.go so make does not try to regenerate via protoc (file is committed)
|
||||||
RUN touch mfer/mf.pb.go
|
RUN touch mfer/mf.pb.go
|
||||||
|
|
||||||
|
# Changing value from script/cibuild; forces the check steps below to
|
||||||
|
# re-run instead of being served from a stale layer cache.
|
||||||
|
ARG CHECK_EPOCH
|
||||||
|
|
||||||
RUN make test
|
RUN make test
|
||||||
RUN cd cmd/mfer && go build -tags urfave_cli_no_docs -o /mfer .
|
RUN cd cmd/mfer && go build -tags urfave_cli_no_docs -o /mfer .
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
# mfer
|
# mfer
|
||||||
|
|
||||||
[mfer](https://git.eeqj.de/sneak/mfer) is a [WTFPL](https://wtfpl.net)-licensed
|
[mfer](https://git.eeqj.de/sneak/mfer) is a reference implementation library and
|
||||||
(public domain) [Go](https://golang.org) library and command-line tool by
|
thin wrapper command-line utility written in [Go](https://golang.org) and first
|
||||||
[@sneak](https://sneak.berlin) that specifies and generates `.mf` manifest files
|
published in 2022 under the [WTFPL](https://wtfpl.net) (public domain) license.
|
||||||
over a directory tree to encapsulate metadata about the files — such as
|
It specifies and generates `.mf` manifest files over a directory tree of files
|
||||||
cryptographic checksums and signatures over same — to aid in archiving,
|
to encapsulate metadata about them (such as cryptographic checksums or
|
||||||
downloading, streaming, and mirroring. It was first published in 2022. The
|
signatures over same) to aid in archiving, downloading, and streaming, or
|
||||||
manifest files' data is serialized with Google's
|
mirroring. The manifest files' data is serialized with Google's
|
||||||
[protobuf serialization format](https://developers.google.com/protocol-buffers).
|
[protobuf serialization format](https://developers.google.com/protocol-buffers).
|
||||||
The structure of these files can be found
|
The structure of these files can be found
|
||||||
[in the format specification](https://git.eeqj.de/sneak/mfer/src/branch/main/mfer/mf.proto)
|
[in the format specification](https://git.eeqj.de/sneak/mfer/src/branch/main/mfer/mf.proto)
|
||||||
@@ -21,36 +21,6 @@ This project was started by [@sneak](https://sneak.berlin) to scratch an itch in
|
|||||||
as a de-facto standard and be incorporated into other software. A compatible
|
as a de-facto standard and be incorporated into other software. A compatible
|
||||||
javascript library is planned.
|
javascript library is planned.
|
||||||
|
|
||||||
# Getting Started
|
|
||||||
|
|
||||||
`mfer` builds from source with a Go 1.23+ toolchain. The generated protobuf code
|
|
||||||
is committed, so no `protoc` toolchain is required:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git clone https://git.eeqj.de/sneak/mfer.git
|
|
||||||
cd mfer
|
|
||||||
go build -o bin/mfer ./cmd/mfer
|
|
||||||
```
|
|
||||||
|
|
||||||
Generate a manifest for a directory tree, verify it later, and fetch a published
|
|
||||||
tree by URL:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# Write .index.mf describing every file under the current directory.
|
|
||||||
bin/mfer gen .
|
|
||||||
|
|
||||||
# Verify the files on disk against the manifest. Exits nonzero if any file
|
|
||||||
# is missing or corrupted.
|
|
||||||
bin/mfer check .index.mf
|
|
||||||
|
|
||||||
# Download and cryptographically verify a tree published over HTTP: mfer
|
|
||||||
# fetches <url>/index.mf, then downloads every file it lists.
|
|
||||||
bin/mfer fetch https://example.com/tree/
|
|
||||||
```
|
|
||||||
|
|
||||||
Run `bin/mfer help` for the full command list, or `bin/mfer <command> --help`
|
|
||||||
for a single command's options.
|
|
||||||
|
|
||||||
# Build Status
|
# Build Status
|
||||||
|
|
||||||
CI runs via `script/cibuild` (`docker build .`), which executes `make check`
|
CI runs via `script/cibuild` (`docker build .`), which executes `make check`
|
||||||
@@ -111,9 +81,7 @@ Any changes submitted to this project must also be
|
|||||||
See [`REPO_POLICIES.md`](REPO_POLICIES.md) for detailed coding standards,
|
See [`REPO_POLICIES.md`](REPO_POLICIES.md) for detailed coding standards,
|
||||||
tooling requirements, and workflow conventions.
|
tooling requirements, and workflow conventions.
|
||||||
|
|
||||||
# Rationale
|
# Problem Statement
|
||||||
|
|
||||||
## The problem
|
|
||||||
|
|
||||||
Given a plain URL, there is no standard way to safely and programmatically
|
Given a plain URL, there is no standard way to safely and programmatically
|
||||||
download everything "under" that URL path. `wget -r` can traverse directory
|
download everything "under" that URL path. `wget -r` can traverse directory
|
||||||
@@ -137,7 +105,7 @@ Real issues I face:
|
|||||||
- when I download a large file via HTTP, I have no way of knowing if the file
|
- when I download a large file via HTTP, I have no way of knowing if the file
|
||||||
content is what it's supposed to be
|
content is what it's supposed to be
|
||||||
|
|
||||||
## The solution
|
# Proposed Solution
|
||||||
|
|
||||||
A standard, a manifest file format, and a tool for generating same.
|
A standard, a manifest file format, and a tool for generating same.
|
||||||
|
|
||||||
@@ -169,27 +137,6 @@ The manifest file would do several important things:
|
|||||||
- maybe a bittorrent chunklist for torrent client compatibility? perhaps a
|
- maybe a bittorrent chunklist for torrent client compatibility? perhaps a
|
||||||
top-level infohash for the whole manifest?
|
top-level infohash for the whole manifest?
|
||||||
|
|
||||||
# Design
|
|
||||||
|
|
||||||
The repository is split into a reusable library and a thin command-line wrapper
|
|
||||||
around it.
|
|
||||||
|
|
||||||
- `mfer/` is the reusable library and the heart of the project: it defines the
|
|
||||||
manifest format and implements building, scanning, checking, serialization,
|
|
||||||
and signing. The protobuf schema is `mfer/mf.proto`, and the generated code it
|
|
||||||
produces (`mfer/mf.pb.go`) is committed alongside it so the library builds
|
|
||||||
with `go get` and needs no `protoc` toolchain.
|
|
||||||
- `internal/cli/` holds the command implementations — `gen`, `check`, `freshen`,
|
|
||||||
`export`, `list`, and `fetch` — that wire the library to the command-line
|
|
||||||
interface.
|
|
||||||
- `internal/log/` provides the logging used across the commands.
|
|
||||||
- `internal/bork/` provides error-handling support.
|
|
||||||
- `cmd/mfer/` is the entrypoint: its `main` package assembles the pieces above
|
|
||||||
into the `mfer` binary.
|
|
||||||
|
|
||||||
Everything under `internal/` is private to this repository; only the `mfer/`
|
|
||||||
package is intended for import by other software.
|
|
||||||
|
|
||||||
# Design Goals
|
# Design Goals
|
||||||
|
|
||||||
- Replace SHASUMS/SHASUMS.asc files
|
- Replace SHASUMS/SHASUMS.asc files
|
||||||
@@ -515,9 +462,9 @@ proto `go_package` option. Which is canonical?
|
|||||||
- Issues:
|
- Issues:
|
||||||
[https://git.eeqj.de/sneak/mfer/issues](https://git.eeqj.de/sneak/mfer/issues)
|
[https://git.eeqj.de/sneak/mfer/issues](https://git.eeqj.de/sneak/mfer/issues)
|
||||||
|
|
||||||
# Author
|
# Authors
|
||||||
|
|
||||||
- [@sneak](https://sneak.berlin)
|
- [@sneak <sneak@sneak.berlin>](mailto:sneak@sneak.berlin)
|
||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
|
|||||||
@@ -24,14 +24,8 @@ only thing left of the `chore/align-repo-policies` branch is the list below.
|
|||||||
|
|
||||||
# Completed Steps
|
# Completed Steps
|
||||||
|
|
||||||
- 2026-09-21: added the required README sections — named author, license, and
|
- 2026-09-21: made `script/cibuild` re-run the checks on an unchanged tree via a
|
||||||
category in the Description first line; added Getting Started (verified
|
changing `CHECK_EPOCH` build arg in each Dockerfile check stage (#89)
|
||||||
install/usage block), Rationale (folding in Problem Statement and Proposed
|
|
||||||
Solution), and a Design section for the package layout; renamed Authors to
|
|
||||||
Author (#75)
|
|
||||||
- 2026-09-21: added the canonical `.editorconfig`, made `.gitignore` cover
|
|
||||||
secrets, OS, editor, and Go artifacts, and removed the dead Drone CI
|
|
||||||
references from `.gitignore` and `bin/gitrev.sh` (#72)
|
|
||||||
- 2026-08-09: added `.prettierrc`/`.prettierignore`, gave `script/fmt` and
|
- 2026-08-09: added `.prettierrc`/`.prettierignore`, gave `script/fmt` and
|
||||||
`script/fmt-check` one shared prettier file set via `script/prettier`, dropped
|
`script/fmt-check` one shared prettier file set via `script/prettier`, dropped
|
||||||
the `|| true` that hid prettier failures, and added a node-based Dockerfile
|
the `|| true` that hid prettier failures, and added a node-based Dockerfile
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
|
if [[ ! -z "$DRONE_COMMIT_SHA" ]]; then
|
||||||
|
echo "${DRONE_COMMIT_SHA:0:7}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ ! -z "$GITREV" ]]; then
|
if [[ ! -z "$GITREV" ]]; then
|
||||||
echo $GITREV
|
echo $GITREV
|
||||||
else
|
else
|
||||||
|
|||||||
+9
-4
@@ -1,14 +1,19 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# script/cibuild: run the CI build. The Dockerfile runs script/check
|
# script/cibuild: run the CI build. The Dockerfile runs make fmt-check-go,
|
||||||
# (via make check), so a successful build implies all checks pass.
|
# make lint, the prettier check, and make test as build steps. A bare
|
||||||
# Generic: needs no adaptation. The Gitea workflow runs this on push.
|
# `docker build .` would serve those steps from Docker's layer cache on an
|
||||||
|
# unchanged tree, exiting 0 without running them. CHECK_EPOCH is a build
|
||||||
|
# arg placed above the check steps in every check stage; passing a fresh
|
||||||
|
# value each run busts the cache for those steps (and nothing above them),
|
||||||
|
# so a green build means the checks actually ran. Dependency layers above
|
||||||
|
# the arg stay cached. The Gitea workflow runs this on push.
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
cd "$ROOT"
|
cd "$ROOT"
|
||||||
docker build .
|
docker build --build-arg CHECK_EPOCH="$(date +%s)" .
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|||||||
Reference in New Issue
Block a user