Ragex.Editor.Transaction (Ragex v0.10.0)

View Source

Multi-file atomic edit transactions.

Provides transaction-like semantics for editing multiple files:

  • All-or-nothing atomicity
  • Coordinated backups across files
  • Validation of all files before committing
  • Automatic rollback on any failure

Summary

Types

A single file edit within a transaction.

t()

A transaction containing multiple file edits.

Result of a transaction commit.

Functions

Adds a file edit to the transaction.

Commits the transaction, applying all edits atomically.

Creates a new empty transaction.

Validates all edits in the transaction without applying them.

Types

file_edit()

@type file_edit() :: %{
  path: String.t(),
  changes: [Ragex.Editor.Types.change()],
  opts: keyword()
}

A single file edit within a transaction.

t()

@type t() :: %Ragex.Editor.Transaction{edits: [file_edit()], opts: keyword()}

A transaction containing multiple file edits.

transaction_result()

@type transaction_result() :: %{
  status: :success | :failure,
  files_edited: non_neg_integer(),
  results: [Ragex.Editor.Types.edit_result()],
  errors: [term()],
  rolled_back: boolean()
}

Result of a transaction commit.

Functions

add(transaction, path, changes, opts \\ [])

@spec add(t(), String.t(), [Ragex.Editor.Types.change()], keyword()) :: t()

Adds a file edit to the transaction.

Parameters

  • transaction: The transaction to add to
  • path: Path to the file
  • changes: List of changes to apply
  • opts: Per-file options (override transaction defaults)

Examples

iex> txn = Transaction.new()
iex> txn = Transaction.add(txn, "lib/file1.ex", [Types.replace(1, 1, "new")])
iex> txn = Transaction.add(txn, "lib/file2.ex", [Types.replace(2, 2, "new")])

commit(transaction)

@spec commit(t()) :: {:ok, transaction_result()} | {:error, transaction_result()}

Commits the transaction, applying all edits atomically.

If any edit fails (including validation), all changes are rolled back and the transaction returns an error.

Process

  1. Validate all edits
  2. Create backups for all files
  3. Apply all edits
  4. If any step fails, rollback all changes

Returns

  • {:ok, result} if all edits succeeded
  • {:error, result} if any edit failed (includes rollback status)

Examples

iex> txn = Transaction.new()
iex>   |> Transaction.add("lib/file1.ex", changes1)
iex>   |> Transaction.add("lib/file2.ex", changes2)
iex> Transaction.commit(txn)
{:ok, %{status: :success, files_edited: 2, ...}}

new(opts \\ [])

@spec new(keyword()) :: t()

Creates a new empty transaction.

Examples

iex> Transaction.new()
%Transaction{edits: [], opts: []}

iex> Transaction.new(validate: false)
%Transaction{edits: [], opts: [validate: false]}

validate(transaction)

@spec validate(t()) :: {:ok, :valid} | {:error, [{String.t(), term()}]}

Validates all edits in the transaction without applying them.

Returns {:ok, :valid} if all edits are valid, or {:error, errors} with details about which files failed validation.

Examples

iex> txn = Transaction.new() |> Transaction.add("lib/file.ex", changes)
iex> Transaction.validate(txn)
{:ok, :valid}