Skip to content

Commit

Permalink
Merge branch 'rust-update-helper'
Browse files Browse the repository at this point in the history
  • Loading branch information
obraunsdorf committed Mar 15, 2020
2 parents 5b245f9 + 5d2efe6 commit 575efb5
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 22 deletions.
19 changes: 14 additions & 5 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,29 @@ int main(int argc, char *argv[]) {
MainDialog w;
try {
std::cout << "Looking for updates..." << std::endl;
UpdateCheckingStatus ucs = updates_available(PBC_VERSION_MAJOR, PBC_VERSION_MINOR, PBC_VERSION_PATCH); // TODO: numeric conversions might be problematic here!
const uint32_t BUFF_LEN = 500;
uint8_t buffer[BUFF_LEN] = {0};
CBuffer desc_result_buf = CBuffer{buffer, BUFF_LEN};
UpdateCheckingStatus ucs = updates_available(PBC_VERSION_MAJOR, PBC_VERSION_MINOR, PBC_VERSION_PATCH, &desc_result_buf); // TODO: numeric conversions might be problematic here!
w.show();
switch (ucs.tag) {
case UpdateCheckingStatus::Tag::UpdatesAvailable:
{
unsigned major = ucs.updates_available._0;
uint64_t minor = ucs.updates_available._1;
uint64_t patch = ucs.updates_available._2;
const char* desc = (const char*) buffer;
std::string latest_version = "v" + std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(patch);
std::string msg = "A new version of PlaybookCreator is available (" + latest_version + "). "
"Please visit https://github.com/obraunsdorf/playbook-creator/releases";
std::string msg = "A new version of PlaybookCreator is available!"
"<br><br>Description of release " + latest_version + ":\n" + desc +
"<br><br>Please visit <a href='https://github.com/obraunsdorf/playbook-creator/releases'>https://github.com/obraunsdorf/playbook-creator/releases</a> "
"to update to the current version!";

QMessageBox::information(&w, "PBC Update Checker", QString::fromStdString(msg),
QMessageBox::Ok);
QMessageBox info;
info.setWindowTitle("PBC Update Checker");
info.setTextFormat(Qt::RichText);
info.setText(QString::fromStdString(msg));
info.exec();
}
break;

Expand Down
3 changes: 3 additions & 0 deletions updater/build.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
extern crate cbindgen;
use cbindgen::Language;
use std::env;

fn main() {
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();

cbindgen::Builder::new()
.with_crate(crate_dir)
.with_language(Language::Cxx)
.with_include_version(true)
.generate()
.expect("Unable to generate bindings")
.write_to_file("pbc_updater_bindings.h");
Expand Down
71 changes: 54 additions & 17 deletions updater/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use core::slice;
use semver;
use std::convert::TryFrom;
use std::ffi::CString;
use std::os::raw::c_char;

#[derive(Debug, Clone)]
enum MyError {
Expand All @@ -22,26 +23,45 @@ impl std::convert::From<semver::SemVerError> for MyError {

#[repr(C)]
pub enum UpdateCheckingStatus {
UpdatesAvailable(u64, u64, u64), // String = latest verison
UpdatesAvailable(u64, u64, u64), //major, minor, patch, release-text
UpToDate,
Error,
}

#[repr(C)]
pub struct CBuffer {
buf: *mut u8,
len: usize,
}

struct ReleaseWithBody {
version: semver::Version,
description: String,
}

#[no_mangle]
pub extern "C" fn updates_available(
current_pbc_version_major: u64,
current_pbc_version_minor: u64,
current_pbc_version_patch: u64,
description_result_buffer: &CBuffer,
) -> UpdateCheckingStatus {
let description_result: &mut [u8] = unsafe {
slice::from_raw_parts_mut(description_result_buffer.buf, description_result_buffer.len)
};
if let Ok(versions) = fetch_parse_and_filter_releases((
current_pbc_version_major,
current_pbc_version_minor,
current_pbc_version_patch,
)) {
if let Some(latest_version) = versions.first() {
let major = latest_version.major;
let minor = latest_version.minor;
let patch = latest_version.patch;
if let Some(latest_release) = versions.first() {
let major = latest_release.version.major;
let minor = latest_release.version.minor;
let patch = latest_release.version.patch;
// copy bytes from description into C-provided buffer
let mut description_result_slice =
&mut description_result[..latest_release.description.len()];
description_result_slice.clone_from_slice(latest_release.description.as_bytes());
UpdateCheckingStatus::UpdatesAvailable(major, minor, patch)
} else {
UpdateCheckingStatus::UpToDate
Expand All @@ -53,19 +73,23 @@ pub extern "C" fn updates_available(

fn fetch_parse_and_filter_releases(
current_pbc_version: (u64, u64, u64),
) -> Result<Vec<semver::Version>, MyError> {
) -> Result<Vec<ReleaseWithBody>, MyError> {
let releases = self_update::backends::github::ReleaseList::configure()
.repo_owner("obraunsdorf")
.repo_name("playbook-creator")
.build()?
.fetch()?;

let versions: Vec<semver::Version> = releases
let versions: Vec<ReleaseWithBody> = releases
.iter()
.map(|release| {
semver::Version::parse(release.version()).unwrap() // TODO: avoid unwrap!
// TODO: avoid unwrap!
ReleaseWithBody {
version: semver::Version::parse(release.version()).unwrap(),
description: release.body.clone(),
}
})
.filter(|version| {
.filter(|ReleaseWithBody { version, .. }| {
let (major, minor, patch) = current_pbc_version;
version.gt(&semver::Version::new(major, minor, patch))
})
Expand All @@ -79,20 +103,33 @@ mod tests {

#[test]
fn basic_test() {
let old_version = (0, 10, 0);
let old_version = (0, 13, 0);
let versions = fetch_parse_and_filter_releases(old_version).unwrap();
let latest_version = versions.first().unwrap();

match updates_available(old_version) {
UpdateCheckingStatus::UpdatesAvailable(..) => {}
let (major, minor, patch) = old_version;
let buf = CBuffer {
buf: [0u8; 500].as_mut_ptr(),
len: 500,
};
match updates_available(major, minor, patch, &buf) {
UpdateCheckingStatus::UpdatesAvailable(..) => {
let description: &[u8] = unsafe { slice::from_raw_parts(buf.buf, buf.len) };
let desc = String::from_utf8_lossy(description);
println!("description:\n{}", desc)
}
UpdateCheckingStatus::UpToDate => assert!(false),
UpdateCheckingStatus::Error => assert!(false),
}

let major = latest_version.major;
let minor = latest_version.minor;
let patch = latest_version.patch;
match updates_available((major, minor, patch)) {
let buf = CBuffer {
buf: [0u8; 500].as_mut_ptr(),
len: 500,
};
let major = latest_version.version.major;
let minor = latest_version.version.minor;
let patch = latest_version.version.patch;
match updates_available(major, minor, patch, &buf) {
UpdateCheckingStatus::UpdatesAvailable(..) => assert!(false),
UpdateCheckingStatus::UpToDate => {}
UpdateCheckingStatus::Error => assert!(false),
Expand Down

0 comments on commit 575efb5

Please sign in to comment.