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
sourceimpl Updater<GithubReleaser>
impl Updater<GithubReleaser>
sourcepub fn gh<S>(repo_name: S) -> Result<Self> where
S: Into<String>,
pub fn gh<S>(repo_name: S) -> Result<Self> where
S: Into<String>,
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.
sourceimpl<T> Updater<T> where
T: Releaser + Send + 'static,
impl<T> Updater<T> where
T: Releaser + Send + 'static,
sourcepub fn new<S>(repo_name: S) -> Result<Updater<T>> where
S: Into<String>,
pub fn new<S>(repo_name: S) -> Result<Updater<T>> where
S: Into<String>,
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.
sourcepub fn init(&self) -> Result<()>
pub fn init(&self) -> Result<()>
Initializes Updater
to fetch latest release information.
-
If it has been more than
UPDATE_INTERVAL
seconds (seeset_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 ifUPDATE_INTERVAL
seconds has passed since the last network call. -
All calls, which happen before the
UPDATE_INTERVAL
seconds, will initialize theUpdater
by using a local cache to report metadata about a release.
For Updater
s 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
sourcepub fn update_ready(&self) -> Result<bool>
pub fn update_ready(&self) -> Result<bool>
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
sourcepub fn try_update_ready(&self) -> Result<bool>
pub fn try_update_ready(&self) -> Result<bool>
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
sourcepub fn set_version<S: AsRef<str>>(&mut self, version: S)
pub fn set_version<S: AsRef<str>>(&mut self, version: S)
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.
sourcepub fn set_interval(&mut self, tick: i64)
pub fn set_interval(&mut self, tick: i64)
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);
sourcepub fn due_to_check(&self) -> bool
pub fn due_to_check(&self) -> bool
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());
sourcepub fn download_latest(&self) -> Result<PathBuf>
pub fn download_latest(&self) -> Result<PathBuf>
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.
sourcepub fn latest_avail_version(&self) -> Option<Version>
pub fn latest_avail_version(&self) -> Option<Version>
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.
sourcepub fn current_version(&self) -> &Version
pub fn current_version(&self) -> &Version
Get workflow’s current version
Auto Trait Implementations
impl<T> !RefUnwindSafe for Updater<T>
impl<T> Send for Updater<T> where
T: Send,
impl<T> !Sync for Updater<T>
impl<T> Unpin for Updater<T> where
T: Unpin,
impl<T> !UnwindSafe for Updater<T>
Blanket Implementations
sourceimpl<T> BorrowMut<T> for T where
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
const: unstable · sourcefn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
sourceimpl<T> Instrument for T
impl<T> Instrument for T
sourcefn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
sourcefn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
sourceimpl<T> WithSubscriber for T
impl<T> WithSubscriber for T
sourcefn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> where
S: Into<Dispatch>,
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
sourcefn with_current_subscriber(self) -> WithDispatch<Self>
fn with_current_subscriber(self) -> WithDispatch<Self>
Attaches the current default Subscriber
to this type, returning a
WithDispatch
wrapper. Read more