Skip to main content

Store

Struct Store 

Source
pub struct Store {
    pub issues_dir: PathBuf,
    pub config: Config,
}

Fields§

§issues_dir: PathBuf§config: Config

Implementations§

Source§

impl Store

Source

pub fn open(config: &Config) -> Result<Store>

Source

pub fn list(&self) -> Result<Vec<Issue>>

Source

pub fn get(&self, selector: IssueSelector) -> Result<Issue>

Source

pub fn create( &self, issue: &mut Issue, body: &str, filename_stem: Option<&str>, ) -> Result<PathBuf>

Create an issue file atomically and assign its number by scanning the live issue set (issue #52): the highest existing number plus one, with a floor of 0 for an empty store.

The number is resolved at creation time rather than read from a persisted [state].next_number counter, so tix.toml is never rewritten by create. A deleted high-numbered issue’s number can be reused by a later create; the frontmatter number stays stable for every surviving issue (C-007).

The file is written into the assignee segment derived from issue.assignee (unassigned/ fallback, FR-029/FR-030), creating the segment directory as needed, and issue.filename is set to the relative path so create output and later edits agree. Atomic-write discipline (temp + rename, NFR-006) is preserved.

Source

pub fn config_path(&self) -> Result<PathBuf>

Source

pub fn update(&self, filename: &str, issue: &Issue) -> Result<()>

Source

pub fn add_asset( &self, filename: &str, source_path: &Path, ) -> Result<AssetAdded>

Copy an asset into the issue’s <slug>-assets/ directory (FR-006) and insert a relative markdown link at the end of the body, persisted via Store::update (NFR-004).

The asset dir is derived from the issue filename per contracts/comments-format.md: <slug>-assets/ where <slug> is the basename stem minus the leading YYYY-MM-DD- date prefix. The copy is atomic (temp + rename, NFR-004); on a name collision the file is stored as <stem>-<n>.<ext> (first free n) and the inserted link points at the actual written name. Image extensions (.png .jpg .jpeg .gif .svg .webp .bmp) get the ![…](…) form, everything else the […](…) form. The link path is relative to the issue file, so the segment prefix is never part of it.

Source

pub fn delete(&self, filename: &str) -> Result<()>

Source

pub fn set_status(&self, filename: &str, new_status: &str) -> Result<Issue>

Symmetrically link two issues by their selectors (D2).

Both selectors are resolved with the same grammar and errors as the selector-taking commands (tix edit/tix move, parse_selector); linking an issue to itself is InvalidInput. The two identifiers are number-based, so self-links are detected by comparing resolved numbers. Each issue gains the other’s number in its links list if absent (idempotent). Both files are written atomically with updated bumped.

Symmetrically remove the link between two issues (D2).

Both selectors are resolved like Store::link. Removing a pair that was never linked is a no-op: neither file is written. Each issue drops the other’s number from its links list and gets updated bumped when something actually changed.

Replace one issue’s links list and reconcile back-references (D2).

Only numeric targets are accepted; every referenced number must already exist (NotFound otherwise) and a self-link is InvalidInput. Numbers newly added get this issue’s number appended to their links; numbers dropped have it removed. Each touched issue is written exactly once with updated bumped; the target issue itself always wins on the default non-numeric tolerance (hand-edited values untouched by this path).

Source

pub fn reassign( &self, filename: &str, new_assignee: Option<&str>, ) -> Result<PathBuf>

Physically move an issue file into the assignee segment of a new assignee (FR-031, contracts/file-format.md rule 9).

filename is a path relative to the issues dir: either a legacy flat basename (2026-05-10-fix-login.md, C-010) or a grouped path (alice/2026-05-10-fix-login.md). It is validated via the relaxed [validate_filename] before anything touches the filesystem, so traversal attempts are refused here as everywhere else.

The old assignee segment is read from the current relative path, the new one derived with derive_segment; equal segments are a no-op. The target filename keeps the original created-slug stem; when the target already holds <stem>.md, a deterministic -1, -2, … suffix is appended by testing existence — an existing file is never overwritten or deleted. number/created live in the frontmatter and are untouched, so issue-number stability is guaranteed by construction (C-007).

The move is a single std::fs::rename (atomic-ish, same filesystem). Returns the new relative path (matching how issue.filename is stored) on success, including the unchanged relative path for the equal-segment no-op.

Auto Trait Implementations§

§

impl Freeze for Store

§

impl RefUnwindSafe for Store

§

impl Send for Store

§

impl Sync for Store

§

impl Unpin for Store

§

impl UnsafeUnpin for Store

§

impl UnwindSafe for Store

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.