App-karr

 view release on metacpan or  search on metacpan

lib/App/karr/BoardStore.pm  view on Meta::CPAN

=head1 NAME

App::karr::BoardStore - Ref-backed board storage for karr

=head1 VERSION

version 0.600

=head1 SYNOPSIS

    my $store = App::karr::BoardStore->new( git => $git );
    my $config = $store->load_config;
    my $id = $store->allocate_next_id;
    my @tasks = $store->load_tasks;

=head1 DESCRIPTION

L<App::karr::BoardStore> treats C<refs/karr/*> as the canonical board state.
It can merge sparse config overrides with code defaults, allocate numeric task
ids through a dedicated metadata ref, and materialize or serialize temporary
board views for command handlers that still work with files internally.

=head2 git

The L<App::karr::Git> instance this store reads and writes board refs
through. Required.

=head1 SEE ALSO

L<karr>, L<App::karr>, L<App::karr::Git>, L<App::karr::Task>,
L<App::karr::Config>

=head2 board_exists

True when this repository holds an initialized board, which means exactly one
thing: C<refs/karr/config> is there. It used to accept C<refs/karr/meta/next-id>
on its own as well, and that is how a stray C<karr create> in the wrong
directory produced a board that C<karr init> then refused to touch for good --
the half-board counted as existing, so the name, the statuses and the
F<.gitignore> entries could never be written (#62).

    my $whole = $store->board_exists;

Callers state the refusal through L<App::karr::Role::BoardDiscovery/require_board>
rather than testing this themselves: a repository that fails this check may
still hold a half-board's tasks, and the two cases need different words (#133).

=head2 has_board_refs

True when anything at all lives under C<refs/karr/>, initialized board or not.
This is the question the commands that clean up or read raw refs
(C<backup>, C<destroy>, C<materialize>, C<repair>) actually have: refusing them
on a half-board would strand the refs a pre-fix karr already left behind, with
no way to remove them from inside karr.

    my $anything_here = $store->has_board_refs;

=head2 load_config_overrides

Returns the board's raw config overrides -- whatever C<refs/karr/config>
currently holds, decoded but not merged with the code defaults. A board with
no config ref yet, or one whose ref does not decode to a mapping, answers
C<{}> rather than C<undef> or dying.

    my $overrides = $store->load_config_overrides;   # sparse, not effective

This is the input L</load_config> merges over
L<App::karr::Config/default_config>; see that method for the merged result,
and L</effective_config> for its cached form.

=head2 load_config

Reads L</load_config_overrides> and merges them over the code defaults via
L<App::karr::Config/effective_config>, returning a plain hash reference --
not a blessed L<App::karr::Config> object. Every call re-reads the config
ref; L</effective_config> is the cached wrapper most callers want instead.

    my $ec = $store->load_config;

=head2 effective_config

The board's merged config, cached for the lifetime of this C<$store>
instance. The first call runs L</load_config>; every call after returns the
same hash reference until L</save_config> invalidates the cache. This is the
entry point almost every command and role uses --
C<< App::karr::Config->from_merged( $store->effective_config ) >> is the
standard way to get a queryable L<App::karr::Config> object for the current
board (see L<App::karr::Config/from_merged>).

Not to be confused with the class method
L<App::karr::Config/effective_config>, which does the actual default/override
merge and takes no board at all; this method is the per-store cache built on
top of it.

    my $ec = $store->effective_config;
    my $config = App::karr::Config->from_merged($ec);

=head2 all_status_names

Returns a list of all status names from the effective config.

    my @statuses = $store->all_status_names;

=head2 status_requires_claim

Returns true if the given status requires a claim.

    if ($store->status_requires_claim('in-progress')) {
        # must use --claim to move here
    }

=head2 is_terminal_status

Returns true if the status is terminal for this board -- its final configured
status, or C<archived>.

    unless ($store->is_terminal_status($task->status)) {
        # task is still active
    }

=head2 foundation_enabled



( run in 1.233 second using v1.01-cache-2.11-cpan-364913b4093 )