App-karr
view release on metacpan or search on metacpan
lib/App/karr/Cmd/Move.pm view on Meta::CPAN
# App::karr::Config/_usage_error prints for a rejected one.
die 'New status required (valid: ' . join( ', ', @statuses ) . "):\n"
. command_hint( 'move', $id, 'STATUS' ) . "\n"
unless $task_new_status;
# A move to the status the card already has, with no claim to hand over,
# changes nothing -- so it writes nothing: the write is what stamps
# `updated` and appends the activity-log entry, and both were saying a
# move happened when none did (#231). Assigned on every attempt rather
# than only in the branch where it is true: the callback re-runs on
# contention, and this answer belongs to the revision that attempt read.
#
# --claim is what makes it not this case: `move ID <same status> --claim
# NAME` writes claimed_by and a fresh claimed_at, which is how an agent
# takes over a card whose claim ran out without moving it, and dropping
# that silently would be this ticket's own bug pointing the other way.
# kanban-md short-circuits in front of its claim handling and does drop
# it; karr's claims expire and gate `pick`, so here the claim wins.
#
# After check_claim, not before it: whether somebody else's live claim
# blocks this command is a question about the card, not about the work,
# and kanban-md asks it in the same order.
$unchanged = $task->status eq $task_new_status
&& !( defined $claim && length $claim );
return $self->no_change if $unchanged;
if ( defined $claim && length $claim ) {
$task->claimed_by($claim);
$task->claimed_at(gmtime->datetime . 'Z');
}
$old_status = $self->apply_status_change($task, $task_new_status, $claim);
});
if ($unchanged) {
# The wording `karr archive` already uses for the same answer, and ADR
# 0002's exit 0: the card is where it was asked to be, which is success
# and not a failure to report.
printf "Task %d is already at %s: %s\n", $task->id, $task->status, $task->title
unless $self->json;
# `changed` is the field a --json reader keys on, and it is on both
# answers rather than only on this one: a key that appears only when
# nothing happened has to be tested for existence instead of for its
# value, and tells a reader nothing at all on the karr that never wrote
# it. old_status/new_status stay, holding the one status the card has, so
# the shape of a move result does not change with its outcome.
#
# Neither report is called here. Nothing was written, so nothing stepped
# over the expired claim this card may carry, and nothing took up work
# that its dependencies could still be waiting on -- and
# apply_status_change did not record either of them for this id.
return { id => $task->id, title => $task->title, old_status => $task->status,
new_status => $task->status, changed => JSON::MaybeXS::false() };
}
printf "Moved task %d: %s -> %s\n", $task->id, $old_status, $task->status unless $self->json;
# After the write, not inside the guarded callback that decided it: see
# App::karr::Role::DependencyCheck/dependency_report. Under --json the pair
# it returns lands in this hash instead of on STDERR. Same for the expired
# claim this move may have stepped over
# (App::karr::Role::ClaimTimeout/expired_claim_report, #177), which is
# reported first because it is about who held the card, not about the work.
return { id => $task->id, title => $task->title, old_status => $old_status,
new_status => $task->status, changed => JSON::MaybeXS::true(),
$self->expired_claim_report( $task->id ),
$self->dependency_report( $task->id ) };
});
$self->sync_after;
$self->print_json_results(@$results);
$self->report_batch_failure($failed, scalar @ids);
}
# The status looked up here is the card's own, not one the caller typed -- only
# --next/--prev come through -- so a miss means the card sits in a column this
# board does not configure and no relative move can be computed from it. The
# card is named, the board's vocabulary is printed, and the way out is the
# explicit form (ticket k263).
sub _status_index {
my ($self, $statuses, $status, $id) = @_;
for my $i (0..$#$statuses) {
return $i if $statuses->[$i] eq $status;
}
die "Task $id is at '$status', which this board does not configure (valid: "
. join( ', ', @$statuses ) . "):\n"
. command_hint( 'move', $id, 'STATUS' ) . "\n";
}
# App::karr::Role::TaskMutation raises the require_claim message and cannot know
# which command is running; its default names `karr edit ID --status STATUS`.
# Here the status is a positional and the caller has just typed it, so the
# suggestion is the caller's own command line with the one missing piece added.
sub claim_hint_tokens {
my ( $self, $task, $status ) = @_;
return ( 'move', $task->id, $status, '--claim', 'NAME' );
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
App::karr::Cmd::Move - Change a task's status
=head1 VERSION
version 0.601
=head1 SYNOPSIS
karr move 7 done
karr move 7 --next
karr move 7,8,9 in-progress --claim agent-fox
( run in 1.521 second using v1.01-cache-2.11-cpan-85d3896f969 )