Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ fn update() -> Result<(), Box<dyn std::error::Error>> {
}
```

Amazon S3, Google GCS, and DigitalOcean Spaces are also supported through the `S3` backend to check for new releases. Provided a `bucket_name`
Amazon S3, Google GCS, and DigitalOcean Spaces, as well as any S3 compatible server are also supported
through the `S3` backend to check for new releases. Provided a `bucket_name`
and `asset_prefix` string, `self_update` will look up all matching files using the following format
as a convention for the filenames: `[directory/]<asset name>-<semver>-<platform/target>.<extension>`.
Leading directories will be stripped from the file name allowing the use of subdirectories in the S3 bucket,
Expand All @@ -71,6 +72,8 @@ use self_update::cargo_crate_version;

fn update() -> Result<(), Box<::std::error::Error>> {
let status = self_update::backends::s3::Update::configure()
// .end_point(self_update::backends::s3::EndPoint::GCS)
// .end_point("https://s3.example.com")
.bucket_name("self_update_releases")
.asset_prefix("something/self_update")
.region("eu-west-2")
Expand Down
58 changes: 44 additions & 14 deletions src/backends/s3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,41 @@ const MAX_KEYS: u8 = 100;

/// The service end point.
///
/// Currently S3, GCS, and DigitalOcean Spaces supported.
#[allow(clippy::upper_case_acronyms)]
#[derive(Clone, Copy, Debug, Default)]
#[derive(Clone, Debug, Default)]
Comment thread
mat813 marked this conversation as resolved.
#[non_exhaustive]
pub enum EndPoint {
/// Short for `https://<bucket>.s3.<region>.amazonaws.com/`
#[default]
S3,
/// Short for `https://<bucket>.s3.dualstack.<region>.amazonaws.com/`
S3DualStack,
/// Short for `https://storage.googleapis.com/<bucket>/`
GCS,
/// Short for `https://<bucket>.<region>.digitaloceanspaces.com/`
DigitalOceanSpaces,
/// Generic, for other s3 compatible providers
Generic {
/// The full URL of the end point. For example:
///
/// - `https://bucket.s3.example.com/`
/// - `https://s3.example.com/bucket/`
end_point: String,
},
}

impl From<&str> for EndPoint {
fn from(value: &str) -> Self {
Self::Generic {
end_point: value.to_owned(),
}
}
}

impl From<String> for EndPoint {
fn from(value: String) -> Self {
Self::Generic { end_point: value }
}
}

/// `ReleaseList` Builder
Expand Down Expand Up @@ -63,8 +89,8 @@ impl ReleaseListBuilder {
}

/// Set the end point
pub fn end_point(&mut self, end_point: EndPoint) -> &mut Self {
self.end_point = end_point;
pub fn end_point(&mut self, end_point: impl Into<EndPoint>) -> &mut Self {
self.end_point = end_point.into();
self
}

Expand All @@ -77,7 +103,7 @@ impl ReleaseListBuilder {
/// Verify builder args, returning a `ReleaseList`
pub fn build(&self) -> Result<ReleaseList> {
Ok(ReleaseList {
end_point: self.end_point,
end_point: self.end_point.clone(),
bucket_name: if let Some(ref name) = self.bucket_name {
name.to_owned()
} else {
Expand Down Expand Up @@ -117,7 +143,7 @@ impl ReleaseList {
/// If specified, filter for those containing a specified `target`
pub fn fetch(&self) -> Result<Vec<Release>> {
let releases = fetch_releases_from_s3(
self.end_point,
&self.end_point,
&self.bucket_name,
&self.region,
&self.asset_prefix,
Expand Down Expand Up @@ -192,8 +218,8 @@ impl UpdateBuilder {
}

/// Set the end point
pub fn end_point(&mut self, end_point: EndPoint) -> &mut Self {
self.end_point = end_point;
pub fn end_point(&mut self, end_point: impl Into<EndPoint>) -> &mut Self {
self.end_point = end_point.into();
self
}

Expand Down Expand Up @@ -356,7 +382,7 @@ impl UpdateBuilder {
};

Ok(Box::new(Update {
end_point: self.end_point,
end_point: self.end_point.clone(),
bucket_name: if let Some(ref name) = self.bucket_name {
name.to_owned()
} else {
Expand Down Expand Up @@ -431,7 +457,7 @@ impl Update {
impl ReleaseUpdate for Update {
fn get_latest_release(&self) -> Result<Release> {
let releases = fetch_releases_from_s3(
self.end_point,
&self.end_point,
&self.bucket_name,
&self.region,
&self.asset_prefix,
Expand Down Expand Up @@ -460,7 +486,7 @@ impl ReleaseUpdate for Update {

fn get_latest_releases(&self, current_version: &str) -> Result<Vec<Release>> {
let releases = fetch_releases_from_s3(
self.end_point,
&self.end_point,
&self.bucket_name,
&self.region,
&self.asset_prefix,
Expand Down Expand Up @@ -491,7 +517,7 @@ impl ReleaseUpdate for Update {

fn get_release_version(&self, ver: &str) -> Result<Release> {
let releases = fetch_releases_from_s3(
self.end_point,
&self.end_point,
&self.bucket_name,
&self.region,
&self.asset_prefix,
Expand Down Expand Up @@ -566,7 +592,7 @@ impl ReleaseUpdate for Update {
///
/// This will strip the prefix from provided file names, allowing use with subdirectories
fn fetch_releases_from_s3(
end_point: EndPoint,
end_point: &EndPoint,
bucket_name: &str,
region: &Option<String>,
asset_prefix: &Option<String>,
Expand All @@ -591,10 +617,14 @@ fn fetch_releases_from_s3(
bucket_name, region?
),
EndPoint::GCS => format!("https://storage.googleapis.com/{}/", bucket_name),
EndPoint::Generic { ref end_point } => end_point.clone(),
};

let api_url = match end_point {
EndPoint::S3 | EndPoint::S3DualStack | EndPoint::DigitalOceanSpaces => format!(
EndPoint::S3
| EndPoint::S3DualStack
| EndPoint::DigitalOceanSpaces
| EndPoint::Generic { .. } => format!(
"{}?list-type=2&max-keys={}{}",
download_base_url, MAX_KEYS, prefix
),
Expand Down
5 changes: 4 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ fn update() -> Result<(), Box<dyn std::error::Error>> {
}
```

Amazon S3, Google GCS, and DigitalOcean Spaces are also supported through the `S3` backend to check for new releases. Provided a `bucket_name`
Amazon S3, Google GCS, and DigitalOcean Spaces, as well as any S3 compatible server are also supported
through the `S3` backend to check for new releases. Provided a `bucket_name`
and `asset_prefix` string, `self_update` will look up all matching files using the following format
as a convention for the filenames: `[directory/]<asset name>-<semver>-<platform/target>.<extension>`.
Leading directories will be stripped from the file name allowing the use of subdirectories in the S3 bucket,
Expand All @@ -70,6 +71,8 @@ use self_update::cargo_crate_version;

fn update() -> Result<(), Box<::std::error::Error>> {
let status = self_update::backends::s3::Update::configure()
// .end_point(self_update::backends::s3::EndPoint::GCS)
// .end_point("https://s3.example.com")
.bucket_name("self_update_releases")
.asset_prefix("something/self_update")
.region("eu-west-2")
Expand Down
Loading