Search by

rmb32 / barn-paths

rogerbarnfather

Finds or makes a barn (a project with a .barn/ folder) and says where each app keeps its files inside it

Package info

bitbucket.org/rmb32/barn-paths/

Homepage

pkg:composer/rmb32/barn-paths

Statistics

Installs: 77

Dependents: 15

Suggesters: 0

v3.0.0 2026-11-05 21:02 UTC

This package is auto-updated.

Last update: 2026-11-06 09:59:35 UTC


README

Find the barn a directory belongs to, make a new one, and say where each app keeps its files inside it.

A barn is any project with a .barn/ folder at its root. Each app that works in a barn keeps its settings and records in a folder of its own inside it, whether one app is used or all of them, and adds nothing else to the project's root:

my-shop/
  .barn/
    barn/
      settings.json              # the project's name
    barnspec/
      settings.json              # the requirements app's settings
      ...                        # and its records
    barnark/                     # the architecture app's records
    barncept/
      concepts/                  # saved concepts
  composer.json
  src/
  tests/

An app with nothing to keep has no folder. Every path stored inside those files stays relative to the barn's root (my-shop/), not to .barn/.

Requirements

  • PHP 8.5+

Installation

composer require rmb32/barn-paths

Finding a barn

locate() walks up from a directory to the nearest one holding a .barn/ folder, so it works from anywhere inside the project. It returns null outside a barn:

use Rmb32\BarnPaths\Api\Factory\BarnLocatorFactory;

$barn = new BarnLocatorFactory()->create()->locate(getcwd());

if ($barn === null) {
    // say so, and offer to make one
}

The root it returns is a real path, with symlinks and .. resolved. The walk doesn't stop at a git repository's root.

Making a barn

create() makes the .barn/ folder in an existing directory and nothing else; each app makes its own folder inside when it first writes:

use Rmb32\BarnPaths\Api\Exception\InsideAnotherBarn;
use Rmb32\BarnPaths\Api\Factory\BarnCreatorFactory;

$creator = new BarnCreatorFactory()->create();

try {
    $barn = $creator->create('/home/sam/my-shop');
} catch (InsideAnotherBarn $refusal) {
    // ask whether to make a separate barn inside $refusal->enclosingBarn->root, and if so:
    $barn = $creator->create('/home/sam/my-shop', insideAnotherBarn: true);
}

It refuses with a checked exception, so the caller can say why:

ExceptionWhenCarries
BarnAlreadyTherethe directory already has .barn/barn
InsideAnotherBarna barn was found further up, and insideAnotherBarn wasn't setroot, enclosingBarn
BarnNotCreatedthe directory doesn't exist or is a file, or .barn/ couldn't be made in itroot

The paths

BarnPaths holds absolute paths for one barn:

PropertyPath
rootthe project root
directory.barn
barnSettings.barn/barn/settings.json
barnspecData.barn/barnspec
barnspecSettings.barn/barnspec/settings.json
barnarkDirectory.barn/barnark
barnceptConcepts.barn/barncept/concepts

Its constants (BarnPaths::BARN_SETTINGS, BarnPaths::BARNSPEC_DATA and so on) hold the same paths relative to the root, for messages and for writing paths into files.

BarnPaths::at() gives the paths for a root you already know, and exists() says whether its .barn/ folder is there.

Used in Barn

Barn builds barns; its apps read and write their files at the paths this package gives them.

Internals · History · Known issues

License

Proprietary. See LICENSE. Copyright (c) Roger Barnfather.