Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
name: Bug report
about: Report incorrect behaviour in the FAT12 engine
title: ''
labels: bug
assignees: ''
---

## Summary

A clear, concise description of the bug.

## To reproduce

Steps or a minimal code snippet that triggers the problem. If you can, drive it through
the in-memory device fixture (`InMemoryBlockDevice`) so it's runnable in a unit test:

```kotlin
// e.g. format -> writeFile -> readFile, and what you observed
```

## Expected behaviour

What you expected to happen.

## Actual behaviour

What actually happened — include the exception/stack trace or the wrong bytes/result.

## Environment

- fat12-engine version / commit:
- JDK version (`java -version`):
- OS:

## Correctness-contract impact

Does this involve a write/`mkdir`/`rename`/`delete`/set-label/set-attributes path, i.e.
the verify-after-write + rollback contract? (yes / no / unsure)

## Additional context

Anything else that might help — volume geometry, file names, image dumps, etc.
42 changes: 42 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
name: Feature request
about: Suggest an addition or improvement to the FAT12 engine
title: ''
labels: enhancement
assignees: ''
---

## Summary

A clear, concise description of the feature or improvement.

## Motivation

What problem does this solve? What can't you do today, or what's awkward about the
current API?

## Proposed API / change

If you have a concrete shape in mind, sketch it:

```kotlin
// proposed signatures / constants / behaviour
```

## Scope check

This repo is the `:core` engine only (the Android demonstrator is separate). Is the
request in scope for `:core`?

## Correctness-contract impact

Would this touch a write/rollback path, or is it additive (new pure helpers, constants,
read-only accessors)? Additive changes are the easiest to land.

## Alternatives considered

Any other approaches you thought about.

## Additional context

Links to the FAT spec, related issues, or examples from other tools.
31 changes: 31 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!--
Thanks for contributing! Please fill in the sections below and tick the checklist.
See CONTRIBUTING.md for build/test instructions and the correctness contract.
-->

## What

Briefly describe what this PR changes and why.

Closes #<!-- issue number -->

## How

Key implementation notes a reviewer should know (design decisions, trade-offs, anything
non-obvious).

## Correctness contract

- [ ] This change does **not** touch a write / `mkdir` / `rename` / `delete` /
set-label / set-attributes path, **or** it does and I've explained below why the
verify-after-write + rollback contract is preserved.

<!-- If it touches a write/rollback path, explain here: -->

## Checklist

- [ ] Tests added or updated for the change.
- [ ] `./gradlew :core:test` passes locally.
- [ ] Change is scoped to the `:core` engine (the Android demonstrator is separate and not part of this repository).
- [ ] Golden images under `core/src/testFixtures/resources/golden/` are unchanged (or the PR explains why they were regenerated, per `testdata/README.md`).
- [ ] PR is focused on one logical change.
78 changes: 78 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Contributing to fat12-engine

Thanks for your interest in contributing! This document covers how to build and test
the engine, what's in scope, and the one invariant every change must preserve.

## Build and test

```bash
./gradlew :core:test
```

This compiles the engine and runs the full headless suite on JDK 17. You don't need to
install a JDK yourself — the Gradle `foojay-resolver` toolchain plugin auto-provisions a
matching JDK 17 if one isn't already present. There is **no Android SDK, no device, and
no network access** required at test time.

## Scope

This repository is the engine `:core` module only — a dependency-free, pure-JVM FAT12
read/write layer. The Android application that drives the engine over USB-OTG storage is
a separate demonstrator and is **not** part of this repo. Please keep PRs focused on the
`:core` engine.

## The correctness contract (read before changing any write path)

The engine's reason for existing is an atomic **verify-after-write + rollback** contract.
Every multi-step mutation (file write, `mkdir`, `rename`, recursive `delete`, set-label,
set-attributes) goes through a per-operation undo log:

- each touched sector is captured **before** it is written,
- every data cluster is read back and byte-compared **after** it is written, and
- on **any** failure (write error, verify mismatch, or disk-full) the whole operation is
rolled back to a byte-for-byte identical pre-operation state.

A PR **must not weaken this contract**. If a change touches a write/rollback path, say so
explicitly in the PR description and explain why it's still safe. The full test suite and
the CI `fsck.fat -n` oracle must stay green.

## CI

Two jobs run on every pull request (see [`.github/workflows/ci.yml`](.github/workflows/ci.yml)):

1. **`core-test`** — the full `:core` suite on a clean, pinned JDK 17.
2. **`fsck-oracle`** — an independent [dosfstools](https://github.com/dosfstools/dosfstools)
check: the engine emits FAT12 images and CI runs `fsck.fat -n` on them (both must exit
0). This validates the engine's writes against a real third-party FAT checker, not just
against our own expectations.

Run `./gradlew :core:test` locally and make sure it's green before opening a PR.

## Tests

New behaviour should come with tests. Mirror the style of the existing tests under
`core/src/test/kotlin/com/ams/fat12ex/core/` — many of them use the in-memory device
fixture (`InMemoryBlockDevice`) and the `Fat12ImageBuilder` test fixture, so you rarely
need to touch real media. Pure-logic additions (decoders, constants, accessors) just need
a focused unit test asserting exact values.

## Golden images

The reference FAT12 images under `core/src/testFixtures/resources/golden/` are committed,
read-only inputs — **not** regenerated by the build. Their provenance and the exact,
version-pinned (`dosfstools 4.2`, `SOURCE_DATE_EPOCH`) regeneration procedure are
documented in [`testdata/README.md`](testdata/README.md). Don't regenerate or replace them
without a clear reason.

## Commit and PR style

- Keep PRs small and focused — one logical change per PR.
- Write a clear PR description: what changed, why, and (if relevant) why the
write/rollback contract is preserved.
- Reference the issue you're closing (e.g. `Fixes #123`).

## License

This project is licensed under **Apache-2.0**. By contributing, you agree that your
contributions will be licensed under the same terms. See [`LICENSE`](LICENSE),
[`NOTICE`](NOTICE), and [`PROVENANCE.md`](PROVENANCE.md) for details.
Loading