This commit is contained in:
Julian Ospald 2017-09-12 17:03:31 +02:00
parent 18c9a5ec7a
commit fc953316bf
4 changed files with 291 additions and 54 deletions

View File

@ -16,27 +16,6 @@
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="branch_tree">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
@ -65,6 +44,50 @@
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkComboBoxText" id="branch_select">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<placeholder/>
</child>

225
src/errors.rs Normal file
View File

@ -0,0 +1,225 @@
#![allow(missing_docs)]
use std::convert::From;
use libpijul;
error_chain! {
foreign_links {
Libpijul(libpijul::Error);
}
errors {
}
}
#[macro_export]
/// Try to unwrap a `Result<T, E>`. If there is a value `T`, yield it,
/// otherwise print a warning and `return ()` from the function.
macro_rules! try_w {
($expr:expr) => {
try_wr!($expr, ())
};
($expr:expr, $fmt:expr, $($arg:tt)+) => {
try_wr!($expr, (), $fmt, $(arg)+)
};
($expr:expr, $fmt:expr) => {
try_wr!($expr, (), $fmt)
}
}
#[macro_export]
/// Try to unwrap a `Result<T, E>`. If there is a value `T`, yield it,
/// otherwise print a warning and return from the function with the given value.
macro_rules! try_wr {
($expr:expr, $ret:expr) => (match $expr {
::std::result::Result::Ok(val) => val,
::std::result::Result::Err(err) => {
warn!("{:?}", err);
return $ret;
},
});
($expr:expr, $ret:expr, $fmt:expr) => (match $expr {
::std::result::Result::Ok(val) => val,
::std::result::Result::Err(err) => {
warn!("Original error: {:?}", err);
warn!($fmt);
return $ret;
},
});
($expr:expr, $ret:expr, $fmt:expr, $($arg:tt)+) => (match $expr {
::std::result::Result::Ok(val) => val,
::std::result::Result::Err(err) => {
warn!("Original error: {:?}", err);
warn!(format!($fmt, $(arg)+));
return $ret;
},
})
}
#[macro_export]
/// Try to unwrap a `Result<T, E>`. If there is a value `T`, yield it,
/// otherwise return from the function with the given value.
macro_rules! try_r {
($expr:expr, $ret:expr) => (match $expr {
::std::result::Result::Ok(val) => val,
::std::result::Result::Err(_) => {
return $ret;
},
});
}
#[macro_export]
/// Try to unwrap a `Result<T, E>`. If there is a value `T`, yield it,
/// otherwise print an error and exit the program.
macro_rules! try_e {
($expr:expr) => (match $expr {
::std::result::Result::Ok(val) => val,
::std::result::Result::Err(err) => {
error!("{:?}", err);
::std::process::exit(1);
},
});
($expr:expr, $fmt:expr) => (match $expr {
::std::result::Result::Ok(val) => val,
::std::result::Result::Err(err) => {
error!("Original error: {:?}", err);
error!($fmt);
std::process::exit(1);
},
});
($expr:expr, $fmt:expr, $($arg:tt)+) => (match $expr {
::std::result::Result::Ok(val) => val,
::std::result::Result::Err(err) => {
error!("Original error: {:?}", err);
error!(format!($fmt, $(arg)+));
std::process::exit(1);
},
})
}
#[macro_export]
/// Unwraps a `Result<T, E>` by yielding a value of the samet ype
/// for either case.
macro_rules! unwrap_any {
($expr:expr, $fmt_ok:expr, $fmt_err:expr) => (match $expr {
::std::result::Result::Ok(val) => $fmt_ok,
::std::result::Result::Err(err) => $fmt_err,
})
}
#[macro_export]
/// Warns on err and yields `()` without returning the function.
macro_rules! just_warn {
($expr:expr) => (match $expr {
::std::result::Result::Ok(_) => (),
::std::result::Result::Err(err) => {
warn!("{:?}", err);
()
},
});
}
#[macro_export]
/// Present a gtk error dialog with given message.
/// Provides only a close button.
macro_rules! error_dialog {
($msg:expr, $parent:expr) => {
{
use gtk::DialogExt;
use gtk::WidgetExt;
use gtk::WindowExt;
let parent: Option<&gtk::Window> = $parent;
let dialog = gtk::MessageDialog::new(parent,
gtk::DIALOG_DESTROY_WITH_PARENT,
gtk::MessageType::Error,
gtk::ButtonsType::Close,
$msg);
dialog.set_title("PNMixer-rs Error");
dialog.run();
dialog.destroy();
}
};
}
#[macro_export]
/// Present a gtk error dialog with the error from the `Result` type,
/// if any.
/// Provides only a close button.
macro_rules! result_warn {
($expr:expr, $parent:expr) => (match $expr {
::std::result::Result::Ok(v) => Ok(v),
::std::result::Result::Err(err) => {
use std::error::Error;
let warn_string = format!("{}{}", err.description(),
err.cause().map(|e| format!("\n\nCause: {}", e.description())).unwrap_or(String::from("")));
warn!("{}", warn_string);
error_dialog!(warn_string.as_str(), $parent);
Err(err)
},
});
}
#[macro_export]
/// Convert `WResult` to `Result`. All warnings are printed via the `log`
/// crate and are shown via Gtk dialogs.
macro_rules! wresult_warn {
($expr:expr, $parent:expr) => (match $expr {
::w_result::WResult::WOk(t, ws) => {
use std::error::Error;
for w in ws {
let warn_string = format!("{}{}", w.description(),
w.cause().map(|e| format!("\n\nCause: {}", e.description())).unwrap_or(String::from("")));
warn!("{}", warn_string);
error_dialog!(warn_string.as_str(), $parent);
}
Ok(t)
},
::w_result::WResult::WErr(err) => Err(err),
});
}
#[macro_export]
/// If there is an error in the expression, push it to
/// the given mutable warning vector.
macro_rules! push_warning {
($expr:expr, $vec:ident) => (match $expr {
Err(e) => $vec.push(e),
_ => ()
});
}
#[macro_export]
/// If there is a value in the Result type, unwrap it, otherwise error-log
/// the error, show it via gtk dialog and exit the whole program.
macro_rules! unwrap_error {
($expr:expr, $parent:expr) => (match $expr {
::std::result::Result::Ok(v) => v,
::std::result::Result::Err(err) => {
use std::error::Error;
let err_string = format!("{}{}", err.description(),
err.cause().map(|e| format!("\n\nCause: {}", e.description())).unwrap_or(String::from("")));
error!("{}", err_string);
error_dialog!(err_string.as_str(), $parent);
::std::process::exit(1);
},
});
}

View File

@ -1,7 +1,6 @@
#![feature(alloc_system)]
extern crate alloc_system;
extern crate gdk;
extern crate glib;
extern crate glib_sys;
@ -19,6 +18,7 @@ extern crate log;
extern crate error_chain;
mod ui;
mod errors;
use ui::entry::*;
use std::rc::Rc;

View File

@ -5,6 +5,7 @@ use gtk::WidgetExt;
use libpijul;
use libpijul::fs_representation::*;
use std::path::Path;
use errors::*;
pub struct AppS {
@ -28,7 +29,7 @@ impl AppS {
pub struct Gui {
_cant_construct: (),
pub window: gtk::Window,
pub branch_tree: gtk::TreeView,
pub branch_select: gtk::ComboBoxText,
pub patch_tree: gtk::TreeView,
}
@ -37,7 +38,7 @@ impl Gui {
return Gui {
_cant_construct: (),
window: builder.get_object("main").unwrap(),
branch_tree: builder.get_object("branch_tree").unwrap(),
branch_select: builder.get_object("branch_select").unwrap(),
patch_tree: builder.get_object("patch_tree").unwrap(),
}
}
@ -46,33 +47,19 @@ impl Gui {
pub fn init(appstate: Rc<AppS>) {
{
let ls = gtk::ListStore::new(&[gtk::Type::String]);
let branches = get_branches("/home/hasufell/git/pijul");
for branch in branches {
ls.insert_with_values(None, &[0], &[&branch.as_str()]);
for branch in branches.unwrap() {
appstate.gui.branch_select.append_text(branch.as_str())
}
let renderer = gtk::CellRendererText::new();
let col = gtk::TreeViewColumn::new();
col.set_title("Branch");
col.set_resizable(true);
col.pack_start(&renderer, true);
col.add_attribute(&renderer, "text", 0);
col.set_clickable(true);
col.set_sort_column_id(0);
appstate.gui.branch_tree.append_column(&col);
appstate.gui.branch_tree.set_model(Some(&ls));
appstate.gui.branch_select.set_active(0);
}
{
let ls = gtk::ListStore::new(&[gtk::Type::String]);
let patches = get_patches("/home/hasufell/git/pijul",
"master");
for patch in patches {
for patch in patches.unwrap() {
ls.insert_with_values(None, &[0], &[&patch.as_str()]);
}
@ -94,7 +81,7 @@ pub fn init(appstate: Rc<AppS>) {
fn get_branches(path: &str) -> Vec<String> {
fn get_branches(path: &str) -> Result<Vec<String>> {
let mut vec = Vec::new();
let repo = libpijul::Repository::open(pristine_dir(path), None).unwrap();
@ -103,25 +90,27 @@ fn get_branches(path: &str) -> Vec<String> {
let branches = txn.iter_branches(None).map(|x| String::from(x.name.as_str()));
vec.extend(branches);
return vec;
return Ok(vec);
}
fn get_patches(path: &str, branch: &str) -> Vec<String> {
fn get_patches(path: &str, branch: &str) -> Result<Vec<String>> {
let mut vec = Vec::new();
let repo = libpijul::Repository::open(pristine_dir(path), None).unwrap();
let repo = libpijul::Repository::open(pristine_dir(path), None)?;
let txn = repo.txn_begin().unwrap();
let branch = txn.get_branch(branch).unwrap();
let patches = txn.iter_patches(&branch, None).map(|x| {
let p = libpijul::fs_representation::read_patch(Path::new(path),
txn.external_hash(x.0)).unwrap();
p.header().name.clone()
});
let patches_ids = txn.iter_patches(&branch, None).map(|x| x.0);
for pid in patches_ids {
let mp = libpijul::fs_representation::read_patch(Path::new(path),
txn.external_hash(pid));
match mp {
Ok(p) => vec.push(p.header().name.clone()),
Err(e) => warn!("Could not get patch for patch_id {:?}\nError: {:?}", pid, e),
}
}
vec.extend(patches);
return vec;
return Ok(vec);
}