Skip to main content

RepoScopes

Struct RepoScopes 

Source
pub struct RepoScopes { /* private fields */ }
Expand description

Buffer name → the repository that buffer acts on.

The DocumentId index is not redundant with the name map: Event::DocumentClosed carries a DocumentId, and the two are not interchangeable — the same reason ProjectDiffService keeps its own by_document.

Implementations§

Source§

impl RepoScopes

Source

pub fn set_resolver(&self, resolver: ProjectResolverHandle)

PR.5: hand the resolver over at boot.

Separate from construction because RepoScopes is built in magit’s install, and the resolver is a service looked up from the same boot — a constructor argument would just move the Option to the call site.

Source

pub fn discovery_start(&self) -> Option<PathBuf>

PR.5: where step 3 starts discovering from.

The bug this fixes: magit’s fallback was Repository::discover(".") — the process’s working directory. :cd sets editor.current_dir and never calls set_current_dir, so after :cd /other/repo a fresh C-x g still opened the repository the editor was launched in.

Returns a directory to discover from, not an answer: magit needs a git worktree specifically, and the project root may not be one. gix walking up from here preserves “None when not in a repository” exactly as before.

Source

pub fn record(&self, name: impl Into<String>, workdir: PathBuf)

Record (or re-point) the repository name acts on.

Overwrites rather than accumulating: re-triggering C-x g for a repository must find the buffer you already have, not stack a second record behind it.

Source

pub fn workdir_for(&self, name: &str) -> Option<PathBuf>

The repository name acts on, if one was recorded.

None is a real answer, not a bug: a magit buffer reopened by :b after a restart has a name but no record, and the view falls back to resolving from scratch.

Source

pub fn workdir_for_label(&self, label: &str) -> Option<PathBuf>

MR.3b: the repository behind a label, recovered from any magit buffer already recorded against it.

This is what lets a view opened from inside another magit buffer — <CR> on a commit in the log, a file at a revision — name itself correctly without reaching for services it does not have. Those producers sit in helpers holding only their own buffer’s state, so all they can carry across is the label their own name already spells; this turns that label back into a path.

Sound because labels are unique among open magit buffers by construction: two checkouts sharing a basename qualify at the trigger (RepoScopes::collides) precisely so that one label never names two repositories at once.

Source

pub fn collides(&self, name: &str, workdir: &Path) -> bool

Is name already recorded against a different repository?

The collision question, asked by the trigger before it settles on a name. Merging two repositories into one buffer is the worst outcome available here — the staging chords would act on whichever was recorded last (design §3.1).

Source

pub fn index_document(&self, document: DocumentId, name: impl Into<String>)

Index the document behind name, so closing the buffer drops the record. Called by the view when it activates — the first moment the document exists.

Source

pub fn forget_by_document_id(&self, document: DocumentId) -> bool

Cleanup entry point for the DocumentClosed subscriber.

Returns whether anything was dropped, which is what makes the wiring testable without reaching into the maps.

Source

pub fn tracked(&self) -> usize

How many buffers have a recorded repository. For tests and Debug; the accumulation failure mode is only visible as a count.

Trait Implementations§

Source§

impl BufferScopeSource for RepoScopes

PR.6: RepoScopes already answers “which repository is the buffer called this acting on” — which is exactly what the editor’s generic project resolution needs from a buffer that has no path.

Implementing the trait rather than having the host read RepoScopesHandle keeps a magit-specific service out of generic host code: the host learns a directory and never learns whose, or that git was involved.

It works for every magit view at once — status, diff, log, stash, blame — because they all record through the same map.

Source§

fn scope_dir_for_name(&self, buffer_name: &str) -> Option<PathBuf>

The directory a buffer named buffer_name is about, if this source knows. None for a name it does not recognise — every source is asked and most will not know.
Source§

impl Debug for RepoScopes

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for RepoScopes

Source§

fn default() -> RepoScopes

Returns the “default value” for a type. Read more

Auto Trait Implementations§

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.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

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

Source§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more