commit method
Dispatches the queued ops to an InstallTransaction and returns its result.
@param dryRun When true, the transaction prints staged ops and returns
DryRun without writing to disk.
@param force When true, the transaction bypasses the conflict
pre-flight and overwrites user-modified files.
@return The TransactionResult surfaced by the underlying transaction.
@throws StateError When invoked more than once on the same instance.
Implementation
Future<TransactionResult> commit({
bool dryRun = false,
bool force = false,
}) async {
// 1. One-shot guard. Reject the second call regardless of the first
// call's outcome (Success / DryRun / Conflict / Error all flip the
// guard so the queue can never be replayed against stale state).
if (_committed) {
throw StateError(
'PluginInstaller.commit() called twice on the same instance; '
'installers are one-shot. Construct a new PluginInstaller for each '
'install pass.',
);
}
_committed = true;
// 2. Fire the pre-commit hook (when registered). Runs before the dispatch
// attempt so setup work happens regardless of the eventual outcome.
_startWith?.call(_ctx);
// 3. Build an InstallTransaction bound to the same context and plugin
// identifier so the install record file path stays consistent.
final tx = InstallTransaction(_ctx, pluginName: _pluginName);
for (final op in _ops) {
tx.stage(op);
}
// 4. Delegate the actual write / dry-run / conflict pre-flight to the
// transaction. Forwarding the two flags keeps the boolean surface flat.
final result = await tx.commit(dryRun: dryRun, force: force);
// 5. Post-commit hook fires only when the transaction reported Success.
// DryRun / Conflict / Error short-circuit the endWith so callers can
// safely use it for "next steps" banners that would mislead the user
// if printed after a failed or previewed run.
if (result is Success) {
_endWith?.call(_ctx);
}
return result;
}