# layout — guide
> **Class:** `guide` · audience: a techie provisioning a target's directories. The *what* is in
> [`layout-design.md`](layout-design.md).
## Lay out a target
```rust
use skidbladnir::layout::Layout;
let layout = Layout::dated("/var/lib/nordisk", "/var/log/nordisk", "/opt/nordisk");
let (software, data, log) = layout.prepare_product("holger")?; // creates all three, idempotent
// software = /opt/nordisk/<YYYYMMDD>/holger data = /var/lib/nordisk/holger log = /var/log/nordisk/holger
```
`prepare_product` is safe to call again on an update — it never clobbers existing `data/` or
`log/`.
## Activate a generation (atomic upgrade)
```rust
// after unpacking this generation's files under software/<version>/…
layout.activate()?; // atomic: current → <version>
assert_eq!(layout.active_version().as_deref(), Some(layout.version.as_str()));
```
The service's unit points through `current`, so activation is the instant the new generation goes
live — no daemon churn, no path rewrite.
## Upgrade to a new generation
```rust
let next = Layout::dated("/var/lib/nordisk", "/var/log/nordisk", "/opt/nordisk"); // new YYYYMMDD
let (sw, _data, _log) = next.prepare_product("holger")?; // data/log preserved from before
// … unpack the new files under sw …
next.activate()?; // current now points at the new version
```
## Roll back
Rollback is just re-activating an older layout — the previous generation was never deleted:
```rust
old_layout.activate()?; // current → the previous <version>
```
## Gotchas
- `activate()` needs the temp symlink and `current` to be on the **same filesystem** — the atomic
`rename(2)` is what makes the swap tear-free.
- The symlink target is the **relative** version name, so you can move the whole `software_dir`
without breaking `current`.
- `data/` and `log/` live *outside* the versioned `software/` tree on purpose — that is why an
update swaps binaries while state survives.