pub struct Updater<T> where
    T: Releaser
{ /* private fields */ }
Expand description

Struct to check for & download the latest release of workflow from a remote server.

Implementations

Create an Updater object that will interface with a github repository.

The repo_name should be in user_name/repository_name form. See the module level documentation for full example and description.

use alfred_rs::Updater;

let updater = Updater::gh("spamwax/alfred-pinboard-rs").expect("cannot initiate Updater");

This only creates an Updater without performing any network operations. To check availability of a new release, launch and check for updates by using init() and update_ready() or try_update_ready() methods.

To download an available release use download_latest() method afterwards.

Errors

Error will happen during calling this method if:

  • Updater state cannot be read/written during instantiation, or
  • The workflow version cannot be parsed as semantic version compatible identifier.

Create an Updater object that will interface with a remote repository for updating operations.

repo_name is an arbitrary tag/identifier associated with the remote repository.

How the Updater interacts with the remote server should be implemented using the Releaser trait. This crate provides a default implementation for interacting with github.com repositories, see gh() and GithubReleaser.

Example

use url::Url;
use semver::Version;

use alfred_rs::Updater;
use alfred_rs::updater::Releaser;

#[derive(Clone)]
struct MyPrivateHost {/* inner */};

// You need to actually implement the trait, following is just a mock.
impl Releaser for MyPrivateHost {
    type SemVersion = Version;
    type DownloadLink = Url;

    fn new<S: Into<String>>(project_id: S) -> Self {
        MyPrivateHost {}
    }

    fn fetch_latest_release(&self) -> Result<(Version, Url)> {
        let version = Version::new(1, 0, 12);
        let url = Url::parse("https://ci.remote.cc/release/latest")?;
        Ok((version, url))
    }
}

let updater: Updater<MyPrivateHost> =
    Updater::new("my_hidden_proj").expect("cannot initiate Updater");

This only creates an Updater without performing any network operations. To check availability of a new release, launch and check for updates by using init() and update_ready() or try_update_ready() methods.

To check availability of a new release use update_ready() method.

To download an available release use download_latest() method afterwards.

Errors

Error will happen during calling this method if:

  • Updater state cannot be read/written during instantiation, or
  • The workflow version cannot be parsed as a semantic version compatible identifier.

Initializes Updater to fetch latest release information.

  • If it has been more than UPDATE_INTERVAL seconds (see set_interval()) since last check, the method will spawn a worker thread. In the background, the spawned thread will attempt to make a network call to fetch metadata of releases only if UPDATE_INTERVAL seconds has passed since the last network call.

  • All calls, which happen before the UPDATE_INTERVAL seconds, will initialize the Updater by using a local cache to report metadata about a release.

For Updaters talking to github.com, the worker thread will only fetch a small metadata information to extract the version of the latest release.

To check on status of worker thread and to get latest release status, use either of update_ready() or try_update_ready() methods.

Example
let updater = Updater::gh("spamwax/alfred-pinboard-rs")?;

let rx = updater.init().expect("Error in starting updater.");

// We'll do some other work that's related to our workflow while waiting
do_some_other_stuff();

// We can now check if update is ready using two methods:
// 1- Block and wait until we receive results or errors
let update_status = updater.update_ready();

// 2- Or without blocking, check if the worker thread sent the results.
//    If the worker thread is still busy, we'll get an `Err`
let update_status = updater.try_update_ready();

if let Ok(is_ready) = update_status {
    // Everything went ok:
    // No error happened during operation of worker thread
    // and we received release info
    if is_ready {
        // there is an update available.
    }
} else {
    /* either the worker thread wasn't successful or we couldn't get its results */
}
Errors

Followings can cause the method return an error:

  • A worker thread cannot be spawned
  • Alfred environment variable error
  • File IO error

Checks if a new update is available by waiting for the background thread to finish fetching release info (blocking).

In practice, this method will block if it has been more than UPDATE_INTERVAL seconds since last check. In any other instance the updater will return the update status that was cached since last check.

This method will wait for worker thread (spawned by calling init()) to deliver release information from remote server. Upon successful retrieval, this method will compare release information to the current vertion of the workflow. The remote repository should tag each release according to semantic version scheme for this to work.

You should use this method after calling init(), preferably after your workflow is done with other tasks and now wants to get information about the latest release.

Note
  • Since this method may block the current thread until a response is received from remote server, workflow authors should consider scenarios where network connection is poor and the block can take a long time (>1 second), and devise their workflow around it. An alternative to this method is the non-blocking try_update_ready().
  • The very first call to this method will always return false since it is assumed that user has just downloaded and installed the workflow.
Example
use alfred_rs::Updater;

let updater =
    Updater::gh("spamwax/alfred-pinboard-rs").expect("cannot initiate Updater");
updater.init().expect("cannot start the worker thread");

// Perform other workflow related tasks...

assert_eq!(true, updater.update_ready().expect("cannot get update information"));
Errors

Error will be returned :

  • If worker thread has been interrupted
  • If init() method has not been called successfully before this method
  • If worker could not communicate with server
  • If any file error or Alfred environment variable error happens

Try to get release info from background worker and see if a new update is available (non-blocking).

This method will attempt to receive release information from worker thread (spawned by calling init()). Upon successful retrieval, this method will compare release information to the current vertion of the workflow. The remote repository should tag each release according to semantic version scheme for this to work.

If communication with worker thread is not successful or if the worker thread could not fetch release information, this method will return an error.

You should use this method after calling init(), preferably after your workflow is done with other tasks and now wants to get information about the latest release.

Note
  • To wait for the worker thread to deliver its release information you can use the blocking update_ready() method.
  • The very first call to this method will always return false since it is assumed that user has just downloaded and installed the workflow.
Example
extern crate alfred_rs;

use alfred_rs::Updater;



fn main() {
let updater =
    Updater::gh("spamwax/alfred-pinboard-rs").expect("cannot initiate Updater");
updater.init().expect("cannot start the worker thread");

// Perform other workflow related tasks...
do_some_other_stuff();

assert_eq!(true, updater.try_update_ready().expect("cannot get update information"));

// Execution of program will immediately follow to here since this method is non-blocking.

}
Errors

Error will be returned :

  • If worker thread is not ready to send information or it has been interrupted
  • If init() method has not been called successfully before this method
  • If worker could not communicate with server
  • If any file error or Alfred environment variable error happens

Set workflow’s version to version.

Content of version needs to follow semantic versioning.

This method is provided so workflow authors can set the version from within the Rust code.

Example
let mut updater = Updater::gh("spamwax/alfred-pinboard-rs")?;
updater.set_version("0.23.3");

An alternative (recommended) way of setting version is through Alfred’s preferences window.

Panics

The method will panic if the passed value version cannot be parsed as a semantic version compatible string.

Set the interval between checks for a newer release (in seconds)

Default value is 86,400 seconds (24 hrs).

Example

Set interval to be 7 days

let mut updater =
    Updater::gh("spamwax/alfred-pinboard-rs").expect("cannot initiate Updater");
updater.set_interval(7 * 24 * 60 * 60);

Check if it is time to ask remote server for latest updates.

It returns true if it has been more than UPDATE_INTERVAL seconds since we last checked with server (i.e. ran update_ready()), otherwise returns false.

Example
let mut updater = Updater::gh("spamwax/alfred-pinboard-rs")?;

// Assuming it is has been UPDATE_INTERVAL seconds since last time we ran the
// `update_ready()` and there actually exists a new release:
assert_eq!(true, updater.due_to_check());

Method to download and save the latest release into workflow’s cache dir.

If the download and save operations are both successful, it returns name of file in which the downloaded Alfred workflow bundle is saved.

The downloaded workflow will be saved in dedicated cache folder of the workflow, and it will be always renamed to latest_release_WORKFLOW-NAME.alfredworkflow

To install the downloaded release, your workflow needs to somehow open the saved file.

Within shell, it can be installed by issuing something like:

open -b com.runningwithcrayons.Alfred latest_release_WORKFLOW-NAME.alfredworkflow

Or you can add “Run script” object to your workflow and use environment variables set by Alfred to automatically open the downloaded release:

open -b com.runningwithcrayons.Alfred "$alfred_workflow_cache/latest_release_$alfred_workflow_name.alfredworkflow"
Note

The method may take longer than other Alfred-based actions to complete. Workflow authors using this crate should implement strategies to prevent unpleasant long blocks of user’s typical work flow.

One option to initiate the download and upgrade process is to invoke your executable with a different argument. The following snippet can be tied to a dedicated Alfred Hotkey or Script Filter so that it is only executed when user explicitly asks for it:

Example
use alfred_rs::Updater;
use alfred::{ItemBuilder, json};

if cmd_line_download_flag && updater.update_ready().unwrap() {
    match updater.download_latest() {
        Ok(downloaded_fn) => {
            json::write_items(io::stdout(), &[
                ItemBuilder::new("New version of workflow is available!")
                             .subtitle("Click to upgrade!")
                             .arg(downloaded_fn.to_str().unwrap())
                             .variable("update_ready", "yes")
                             .valid(true)
                             .into_item()
            ]);
        },
        Err(e) => {
            // Show an error message to user or log it.
        }
    }
}

For the above example to automatically work, you then need to connect the output of the script to an Open File action so that Alfred can install/upgrade the new version.

As suggested in above example, you can add an Alfred variable to the item so that your workflow can use it for further processing.

Errors

Downloading latest workflow can fail if network error, file error or Alfred environment variable errors happen, or if Releaser cannot produce a usable download url.

Returns the version for the latest downloadable workflow from Releaser. None is returned if no release info has yet been fetched from server.

Note

This method does not perform any network or disk IO. It merely returns the cached version info based on last successful communication with the remote server. So it is possible the method will return a version different than server’s version if:

  • It’s been less than UPDATE_INTERVAL seconds since last check, or
  • Worker thread is busy checking and you called this method before it finishes.

Get workflow’s current version

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

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

Instruments this type with the current Span, returning an Instrumented wrapper. Read more

Calls U::from(self).

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

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.

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

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