VersionResolver

Struct VersionResolver 

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

Centralized version resolver for batch SHA resolution.

The VersionResolver manages the collection and resolution of all dependency versions in a single batch operation, enabling optimal Git repository access patterns and maximum worktree reuse.

Implementations§

Source§

impl VersionResolver

Source

pub fn new(cache: Cache) -> Self

Creates a new version resolver with the given cache and default concurrency

Uses the same default concurrency as installation: max(10, 2 × CPU cores)

Source

pub fn with_concurrency(cache: Cache, max_concurrency: usize) -> Self

Creates a new version resolver with explicit concurrency limit

Source

pub fn add_version( &self, source: &str, url: &str, version: Option<&str>, resolution_mode: ResolutionMode, )

Adds a version to be resolved

Multiple calls with the same (source, version) pair will be deduplicated.

§Arguments
  • source - Source name from manifest
  • url - Git repository URL
  • version - Version specification (tag, branch, commit, or None for HEAD)
  • resolution_mode - The resolution mode to use for this entry
Source

pub async fn resolve_all( &self, progress: Option<Arc<MultiPhaseProgress>>, ) -> Result<()>

Resolves all collected versions to their commit SHAs using cached repositories.

This is the second phase of AGPM’s two-phase resolution architecture. Call after pre_sync_sources(). See documentation for detailed resolution process and performance characteristics.

§Prerequisites

CRITICAL: pre_sync_sources() must be called first to populate the cache.

§Performance

Uses batch git rev-parse --stdin to resolve multiple refs in a single process, reducing process spawn overhead from O(n) to O(1) per source. This is especially impactful on Windows where process spawning is expensive.

§Example
let cache = Cache::new()?;
let mut resolver = VersionResolver::new(cache);
resolver.add_version("source", "https://github.com/org/repo.git", Some("v1.2.3"), ResolutionMode::Version);

resolver.pre_sync_sources(None).await?;  // Pass None for no progress tracking
resolver.resolve_all(None).await?;  // Pass None for no progress tracking
§Errors

Returns an error if:

  • Repository not pre-synced (call pre_sync_sources() first)
  • Version/tag/branch not found or constraint unsatisfied
  • Git operations fail or repository inaccessible
Source

pub async fn resolve_single( &self, source: &str, url: &str, version: Option<&str>, ) -> Result<String>

Resolves a single version to SHA without affecting the batch

This is useful for incremental resolution or testing.

Source

pub fn get_resolved_sha(&self, source: &str, version: &str) -> Option<String>

Gets the resolved SHA for a given source and version

Returns None if the version hasn’t been resolved yet.

§Arguments
  • source - Source name
  • version - Version specification (use “HEAD” for None)
Source

pub fn get_all_resolved(&self) -> HashMap<(String, String), String>

Gets all resolved SHAs as a HashMap

Useful for bulk operations or debugging.

Source

pub fn get_all_resolved_full( &self, ) -> HashMap<(String, String), ResolvedVersion>

Gets all resolved versions with both SHA and resolved reference

Returns a HashMap with (source, version) -> ResolvedVersion

Source

pub fn is_resolved(&self, source: &str, version: &str) -> bool

Checks if a specific version has been resolved

Source

pub async fn pre_sync_sources( &self, progress: Option<Arc<MultiPhaseProgress>>, ) -> Result<()>

Pre-syncs all unique sources to ensure repositories are cloned/fetched.

This is the first phase of AGPM’s two-phase resolution architecture. Performs all Git network operations upfront before resolve_all(). Automatically deduplicates by source URL for efficiency.

§Prerequisites

Call this method after adding versions via add_version() calls.

§Example
use agpm_cli::resolver::version_resolver::VersionResolver;
use agpm_cli::resolver::types::ResolutionMode;
use agpm_cli::cache::Cache;

let cache = Cache::new()?;
let mut resolver = VersionResolver::new(cache);
resolver.add_version("source", "https://github.com/org/repo.git", Some("v1.0.0"), ResolutionMode::Version);

// Phase 1: Sync repositories (parallel network operations with progress)
resolver.pre_sync_sources(None).await?;  // Pass None for no progress tracking

// Phase 2: Resolve versions to SHAs (local operations)
resolver.resolve_all(None).await?;  // Pass None for no progress tracking
§Arguments
  • progress - Optional progress tracker. Pass None to disable progress tracking. When provided, displays real-time sync status with windowed updates showing which sources are being synced. The progress tracker automatically calculates window size based on the number of concurrent operations.
§Errors

Returns an error if:

  • Repository cloning or fetching fails (network, auth, invalid URL)
  • Authentication fails for private repositories
  • Insufficient disk space or repository corruption
Source

pub fn get_bare_repo_path(&self, source: &str) -> Option<PathBuf>

Gets the bare repository path for a source

Returns None if the source hasn’t been processed yet.

Source

pub fn register_bare_repo(&self, source: String, repo_path: PathBuf)

Registers a bare repository path for a source

This is used when manually ensuring a repository exists without clearing all state.

Source

pub fn clear(&self)

Clears all resolved versions and cached data

Useful for testing or when starting a fresh resolution.

Source

pub fn pending_count(&self) -> usize

Returns the number of unique versions to resolve

Source

pub fn has_entries(&self) -> bool

Checks if the resolver has any entries to resolve.

This is a convenience method to determine if the resolver has been populated with version entries via add_version() calls. It’s useful for conditional logic to avoid unnecessary operations when no versions need resolution.

§Returns

Returns true if there are entries that need resolution, false if the resolver is empty.

§Example
let mut resolver = VersionResolver::new(cache);
assert!(!resolver.has_entries()); // Initially empty

resolver.add_version("source", "https://github.com/org/repo.git", Some("v1.0.0"), ResolutionMode::Version);
assert!(resolver.has_entries()); // Now has entries
Source

pub fn resolved_count(&self) -> usize

Returns the number of successfully resolved versions

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.

Source§

impl<T> Instrument for T

Source§

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

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

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

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

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

Initializes a with the given initializer. Read more
Source§

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

Dereferences the given pointer. Read more
Source§

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

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

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

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

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. 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.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

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

fn with_current_subscriber(self) -> WithDispatch<Self>

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