Minga.Buffer.Fork (Minga v0.1.0)

Copy Markdown View Source

A forked copy of a buffer for concurrent agent editing.

When an agent session starts editing a file, a fork is created from the parent Buffer.Server. The fork holds a snapshot of the parent's Document at fork time (the common ancestor) and its own Document that the agent edits. The user continues editing the parent buffer independently.

When the agent finishes, merge/1 computes a three-way merge: common ancestor, fork changes, and current parent changes. Non-overlapping changes merge automatically. Overlapping changes are returned as conflicts for resolution.

The fork exposes the same GenServer call messages as Buffer.Server for the editing subset (content, find_and_replace, replace_content, etc.), so agent tools can call it without knowing whether they're talking to a fork or a real buffer.

Lifecycle

parent_pid  Fork.create(parent_pid)  fork_pid
                                              
                            agent edits 
                                              
                          Fork.merge(fork_pid)  {:ok, merged} | {:conflict, hunks}

Summary

Types

Fork creation options.

Internal fork state.

Functions

Returns the ancestor (snapshot at fork time) content.

Returns a specification to start this module under a supervisor.

Returns the full text content of the fork.

Creates a fork from an existing buffer.

Whether the fork has been edited since creation.

Finds and replaces text in the fork. Returns {:ok, msg} or {:error, reason}.

Computes a three-way merge between the ancestor, fork, and current parent.

Replaces the entire content of the fork.

Monotonic version counter.

Types

create_opt()

@type create_opt() :: {:parent, pid()} | {:content, String.t()}

Fork creation options.

state()

@type state() :: %{
  ancestor: Minga.Buffer.Document.t(),
  document: Minga.Buffer.Document.t(),
  parent: pid(),
  parent_monitor: reference(),
  parent_alive: boolean(),
  version: non_neg_integer(),
  dirty: boolean()
}

Internal fork state.

Functions

ancestor_content(server)

@spec ancestor_content(GenServer.server()) :: String.t()

Returns the ancestor (snapshot at fork time) content.

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

content(server)

@spec content(GenServer.server()) :: String.t()

Returns the full text content of the fork.

create(parent_pid)

@spec create(pid()) :: {:ok, pid()} | {:error, term()}

Creates a fork from an existing buffer.

Snapshots the parent's current Document as the common ancestor and creates an independent copy for editing. The fork monitors the parent buffer.

dirty?(server)

@spec dirty?(GenServer.server()) :: boolean()

Whether the fork has been edited since creation.

find_and_replace(server, old_text, new_text)

@spec find_and_replace(GenServer.server(), String.t(), String.t()) ::
  {:ok, String.t()} | {:error, String.t()}

Finds and replaces text in the fork. Returns {:ok, msg} or {:error, reason}.

merge(server)

@spec merge(GenServer.server()) ::
  {:ok, String.t()}
  | {:conflict, [Minga.Core.Diff.merge_hunk()]}
  | {:error, term()}

Computes a three-way merge between the ancestor, fork, and current parent.

Returns {:ok, merged_text} when all changes merge cleanly, or {:conflict, merge_hunks} when overlapping changes exist. Returns {:error, reason} if the parent buffer is dead.

replace_content(server, content)

@spec replace_content(GenServer.server(), String.t()) :: :ok

Replaces the entire content of the fork.

start_link(opts)

@spec start_link([create_opt()]) :: GenServer.on_start()

version(server)

@spec version(GenServer.server()) :: non_neg_integer()

Monotonic version counter.