SelfUpdater

Struct SelfUpdater 

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

Core self-update manager for AGPM binary upgrades.

SelfUpdater handles the entire process of checking for and installing AGPM updates from GitHub releases. It provides a safe, reliable way to upgrade the running binary with proper error handling and version management.

§Features

  • GitHub Integration: Fetches releases from the official AGPM repository
  • Version Comparison: Uses semantic versioning for intelligent update detection
  • Force Updates: Allows forcing updates even when already on latest version
  • Target Versions: Supports upgrading to specific versions or latest
  • Progress Tracking: Shows download progress during updates
  • Security: URL validation, path traversal protection, configurable checksum verification

§Safety

The updater itself only handles the download and binary replacement. For full safety, it should be used in conjunction with BackupManager to create backups before updates.

§Examples

§Check for Updates

use agpm_cli::upgrade::SelfUpdater;

let updater = SelfUpdater::new();

if let Some(latest_version) = updater.check_for_update().await? {
    println!("Update available: {} -> {}",
             updater.current_version(), latest_version);
} else {
    println!("Already on latest version: {}", updater.current_version());
}

§Update to Latest Version

use agpm_cli::upgrade::SelfUpdater;

let updater = SelfUpdater::new();

match updater.update_to_latest().await? {
    true => println!("Successfully updated to latest version"),
    false => println!("Already on latest version"),
}

§Force Update with Required Checksums

use agpm_cli::upgrade::{SelfUpdater, ChecksumPolicy};

let updater = SelfUpdater::new()
    .force(true)
    .checksum_policy(ChecksumPolicy::Required);

// This will update even if already on the latest version
// and require checksum verification
updater.update_to_latest().await?;

§Repository Configuration

By default, updates are fetched from aig787/agpm on GitHub. This is configured in the Default implementation and targets the official AGPM repository.

§Error Handling

All methods return Result<T, anyhow::Error> for comprehensive error handling:

  • Network errors during GitHub API calls
  • Version parsing errors for invalid semver
  • File system errors during binary replacement
  • Permission errors on locked or protected files
  • Security validation failures

Implementations§

Source§

impl SelfUpdater

Source

pub fn new() -> Self

Create a new SelfUpdater with default settings.

This is equivalent to Default::default() but provides a more conventional constructor-style interface.

§Examples
use agpm_cli::upgrade::SelfUpdater;

let updater = SelfUpdater::new();
assert_eq!(updater.current_version(), env!("CARGO_PKG_VERSION"));
Source

pub fn with_repo(repo_owner: &str, repo_name: &str) -> Result<Self>

Create a new SelfUpdater with custom repository settings.

This constructor allows specifying a custom GitHub repository for updates, with security validation to prevent URL injection attacks.

§Arguments
  • repo_owner - GitHub repository owner (e.g., “aig787”)
  • repo_name - GitHub repository name (e.g., “agpm”)
§Errors

Returns an error if the repository identifiers contain invalid characters that could be used for URL injection or other attacks.

§Examples
use agpm_cli::upgrade::SelfUpdater;

// Valid repository identifiers
let updater = SelfUpdater::with_repo("aig787", "agpm")?;
let custom = SelfUpdater::with_repo("my-org", "my_fork")?;

// This would fail due to invalid characters
// let bad = SelfUpdater::with_repo("../evil", "repo");
Source

pub const fn force(self, force: bool) -> Self

Configure whether to force updates regardless of version comparison.

When force mode is enabled, the updater will attempt to download and install updates even if the current version is already the latest or newer than the target version.

§Use Cases
  • Reinstalling: Fix corrupted binary installations
  • Downgrading: Install older versions for compatibility
  • Testing: Verify update mechanism functionality
  • Recovery: Restore from problematic versions
§Arguments
  • force - true to enable force mode, false to respect version comparisons
§Examples
use agpm_cli::upgrade::SelfUpdater;

// Normal update (respects versions)
let updater = SelfUpdater::new();

// Force update (ignores version comparison)
let force_updater = SelfUpdater::new().force(true);
Source

pub const fn checksum_policy(self, policy: ChecksumPolicy) -> Self

Configure the checksum verification policy for downloads.

This setting controls how the updater handles checksum verification during binary downloads, allowing you to balance security with usability.

§Security Implications
  • Required: Maximum security, but updates may fail if checksums are unavailable
  • WarnOnFailure: Good balance of security and usability (default)
  • Skip: Least secure, not recommended for production use
§Arguments
  • policy - The checksum verification policy to use
§Examples
use agpm_cli::upgrade::{SelfUpdater, ChecksumPolicy};

// Require checksum verification (most secure)
let secure_updater = SelfUpdater::new()
    .checksum_policy(ChecksumPolicy::Required);

// Skip checksum verification (least secure)
let fast_updater = SelfUpdater::new()
    .checksum_policy(ChecksumPolicy::Skip);
Source

pub fn current_version(&self) -> &str

Get the current version of the running AGPM binary.

This version is determined at compile time from the crate’s Cargo.toml and represents the version of the currently executing binary.

§Returns

A string slice containing the semantic version (e.g., “0.3.14”).

§Examples
use agpm_cli::upgrade::SelfUpdater;

let updater = SelfUpdater::new();
println!("Current AGPM version: {}", updater.current_version());
Source

pub async fn check_for_update(&self) -> Result<Option<String>>

Check if a newer version is available on GitHub.

Queries the GitHub API to fetch the latest release information and compares it with the current version using semantic versioning rules. This method does not download or install anything.

§Returns
  • Ok(Some(version)) - A newer version is available
  • Ok(None) - Already on the latest version or no releases found
  • Err(error) - Network error, API failure, or version parsing error
§Errors

This method can fail if:

  • Network connectivity issues prevent GitHub API access
  • GitHub API rate limiting is exceeded
  • Release version tags are not valid semantic versions
  • Repository is not found or access is denied
§Examples
use agpm_cli::upgrade::SelfUpdater;

let updater = SelfUpdater::new();

match updater.check_for_update().await? {
    Some(latest) => {
        println!("Update available: {} -> {}",
                 updater.current_version(), latest);
    }
    None => {
        println!("Already on latest version: {}",
                 updater.current_version());
    }
}
Source

pub async fn update(&self, target_version: Option<&str>) -> Result<bool>

Update the AGPM binary to a specific version or latest.

Downloads and installs the specified version from GitHub releases, replacing the current binary. This is the core update method used by both version-specific and latest update operations.

§Arguments
  • target_version - Specific version to install (e.g., “0.4.0”), or None for latest
§Returns
  • Ok(true) - Successfully updated to the target version
  • Ok(false) - Already on target version (no update needed)
  • Err(error) - Update failed due to download, permission, or file system error
§Force Mode Behavior

When force mode is enabled via force():

  • Bypasses version comparison checks
  • Downloads and installs even if already on target version
  • Useful for reinstalling or recovery scenarios
§Errors

This method can fail if:

  • Network issues prevent downloading the release
  • Insufficient permissions to replace the binary
  • Target version doesn’t exist or has no binary assets
  • File system errors during binary replacement
  • The downloaded binary is corrupted or invalid
§Platform Considerations
  • Windows: May require retries due to file locking
  • Unix: Preserves executable permissions
  • macOS: Works with both Intel and Apple Silicon binaries
§Examples
use agpm_cli::upgrade::SelfUpdater;

let updater = SelfUpdater::new();

// Update to latest version
if updater.update(None).await? {
    println!("Successfully updated!");
} else {
    println!("Already on latest version");
}

// Update to specific version
if updater.update(Some("0.4.0")).await? {
    println!("Successfully updated to v0.4.0!");
}
Source

pub async fn update_to_latest(&self) -> Result<bool>

Update to the latest available version from GitHub releases.

This is a convenience method that calls update() with None as the target version, instructing it to find and install the most recent release.

§Returns
  • Ok(true) - Successfully updated to a newer version
  • Ok(false) - Already on the latest version (no update performed)
  • Err(error) - Update failed (see update() for error conditions)
§Examples
use agpm_cli::upgrade::SelfUpdater;

let updater = SelfUpdater::new();

match updater.update_to_latest().await? {
    true => println!("Successfully updated to latest version!"),
    false => println!("Already on the latest version"),
}
§See Also
Source

pub async fn update_to_version(&self, version: &str) -> Result<bool>

Update to a specific version from GitHub releases.

Downloads and installs the specified version, regardless of whether it’s newer or older than the current version. The version string will be automatically prefixed with ‘v’ if not already present.

§Arguments
  • version - The target version string (e.g., “0.4.0” or “v0.4.0”)
§Returns
  • Ok(true) - Successfully updated to the specified version
  • Ok(false) - Already on the specified version (no update needed)
  • Err(error) - Update failed (see update() for error conditions)
§Version Format

The version parameter accepts multiple formats:

  • "0.4.0" - Semantic version number
  • "v0.4.0" - Version with ‘v’ prefix (GitHub tag format)
  • "0.4.0-beta.1" - Pre-release versions
§Examples
use agpm_cli::upgrade::SelfUpdater;

let updater = SelfUpdater::new();

// Update to specific stable version
updater.update_to_version("0.4.0").await?;

// Update to pre-release version
updater.update_to_version("v0.5.0-beta.1").await?;

// Force downgrade to older version
let force_updater = updater.force(true);
force_updater.update_to_version("0.3.0").await?;
§See Also

Trait Implementations§

Source§

impl Default for SelfUpdater

Source§

fn default() -> Self

Create a new SelfUpdater with default configuration.

§Default Configuration
  • Repository: aig787/agpm (official AGPM repository)
  • Binary Name: agpm
  • Current Version: Detected from build-time crate version
  • Force Mode: Disabled (respects version comparisons)
§Examples
use agpm_cli::upgrade::SelfUpdater;

let updater = SelfUpdater::default();
println!("Current version: {}", updater.current_version());

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