diff --git a/.travis.yml b/.travis.yml index ce909c6b..d3fd9427 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,23 +10,9 @@ language: rust matrix: include: - rust: 1.13.0 - env: IMAG_RUBY_VERSION=2.3.3 - - rust: 1.13.0 - env: IMAG_RUBY_VERSION=2.4.0 cache: cargo: true - directories: - - $TRAVIS_BUILD_DIR/libimagruby/vendor/bundle - -before_install: -- | - rvm install "$IMAG_RUBY_VERSION" - rvm use "$IMAG_RUBY_VERSION" - ruby --version - pushd libimagruby - bundle install --jobs=3 --retry=3 --path=$TRAVIS_BUILD_DIR/libimagruby/vendor/bundle - popd before_script: - | @@ -44,7 +30,6 @@ addons: - libcurl4-openssl-dev - libdw-dev - libelf-dev - - libruby - libzzip-dev - make - tree @@ -71,6 +56,3 @@ env: global: - THERMITE_DEBUG_FILENAME=/tmp/thermite-debug.log - secure: D+3exBnbvzFvk7fvLOxkF7UotCc4gBbvvOW4xGr9u6dDjEjV5y6CdDy/OQAkhfKhvSou+lIC22g5MuCBQXFEf/ua7A1XzwBAFeVLK4cWZSa7+ql6LdHKqOg3oF6pQlh095WeWr8S2PYJFFJFg8RGUPnbjqdu1J4KSXqe/7GoZ3lYS69mx7D5Hb93KEN084/KGfBuvyJtMjO1fK3spltL2zV8oqegFpv0gLG5GY4LsJ/7ij4Mc6wepXSyyQbaiA1eKMMwQZDvoi4V1mCulo/jeC3pucGxvgnMV5DZs8aa8R7votltGvSpHCgU78LW19dg8oZqwShQQ+XUYw27H+QK5V1lz1l1MaJLbwS3ySyZBPGH8qUuOzQ3bLp9xhAIRgCui3kX/UDhmeME7nJI6k3UZydh+/ydNB1BZHTKn76XS/yFj0Gcibxg7f5fcAYA6Ge5Sg+YPozuwbcKnKe6IpN2M7qNgWa+6MCSXJ1v4BgPb7kN74EynJUM8+yWEFN7MZtWEUQ4ZsHdCs8Pub4C/zHpYGV8qGenZwQzosAFq56YwoGCvJezz35yg4BDd3IMKenOzNnXLBrdxxqX8ySgwt5B3zBqwve/64Lx6OXjae2m8wZKlsmeqad/s6K7nx0zG15/qqRIzyvgcLXq3jwBaHkteq49FRFWvHQFpBQcsPZ2uH4= - matrix: - - IMAG_RUBY_VERSION=2.3.3 - - IMAG_RUBY_VERSION=2.4.0 diff --git a/Cargo.toml b/Cargo.toml index e2033577..dee38680 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,6 @@ members = [ "libimagnotes", "libimagref", "libimagrt", - "libimagruby", "libimagstore", "libimagstorestdhook", "libimagtimeui", diff --git a/Makefile b/Makefile index 838ba1cf..afc3e17a 100644 --- a/Makefile +++ b/Makefile @@ -47,18 +47,12 @@ bin: $(BIN_TARGETS) imag-bin bin-test: $(BIN_TARGET_TESTS) imag-bin -lib: $(LIB_TARGETS) lib-imag-ruby-tarball +lib: $(LIB_TARGETS) @$(ECHO) "\t[ALLLIB ]" lib-test: $(LIB_TARGETS_TEST) -lib-imag-ruby-tarball: - @$(MAKE) -C libimagruby tarball - -lib-imag-ruby-test: - @$(MAKE) -C libimagruby test - -test: bin-test lib-test lib-imag-ruby-test +test: bin-test lib-test install: $(INSTALL_TARGETS) imag-bin-install @$(ECHO) "\t[INSTALL]" diff --git a/default.nix b/default.nix index 5d8e76d5..70f6cb78 100644 --- a/default.nix +++ b/default.nix @@ -7,7 +7,6 @@ let ]; dependencies = with pkgs; [ - ruby bundler cmake curl diff --git a/libimagruby/.gitignore b/libimagruby/.gitignore deleted file mode 100644 index d76ba1ac..00000000 --- a/libimagruby/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -.bundle -Gemfile.lock -lib/liblibimagruby.so -vendor/bundle -libimagruby*.tar.gz diff --git a/libimagruby/Cargo.toml b/libimagruby/Cargo.toml deleted file mode 100644 index 2d98a086..00000000 --- a/libimagruby/Cargo.toml +++ /dev/null @@ -1,41 +0,0 @@ -[package] -name = "libimagruby" -version = "0.1.0" -authors = ["Matthias Beyer "] - -description = "Library for the imag core distribution" - -keywords = ["imag", "PIM", "personal", "information", "management"] -readme = "../README.md" -license = "LGPL-2.1" - -documentation = "https://matthiasbeyer.github.io/imag/imag_documentation/index.html" -repository = "https://github.com/matthiasbeyer/imag" -homepage = "http://imag-pim.org" - -[lib] -crate-type = ["dylib"] - -[dependencies] -ruru = "0.9" -lazy_static = "0.2" -log = "0.3" -env_logger = "0.3" -toml = "0.2" -uuid = { version = "0.3", features = ["v4"] } - -[dependencies.libimagerror] -path = "../libimagerror" - -[dependencies.libimagrt] -path = "../libimagrt" - -[dependencies.libimagstore] -path = "../libimagstore" - -[dependencies.libimagstorestdhook] -path = "../libimagstorestdhook" - -[dependencies.libimagutil] -path = "../libimagutil" - diff --git a/libimagruby/Gemfile b/libimagruby/Gemfile deleted file mode 100644 index aadb3470..00000000 --- a/libimagruby/Gemfile +++ /dev/null @@ -1,4 +0,0 @@ -# frozen_string_literal: true -source "https://rubygems.org" - -gemspec diff --git a/libimagruby/Makefile b/libimagruby/Makefile deleted file mode 100644 index bf023b98..00000000 --- a/libimagruby/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -ECHO=$(shell which echo) -e -RUBY=$(shell which ruby) -BUNDLE=$(shell which bundle) - -all: - @$(ECHO) "There is no default target here" - -bundle: - @$(ECHO) "[BUNDLE]" - @$(BUNDLE) install --path vendor/bundle - -tarball: bundle - @$(ECHO) "[RAKE ][thermite]" - @CARGO_TARGET=debug $(BUNDLE) exec rake thermite:tarball - -test: tarball - @$(ECHO) "[TEST ] Not yet implemented. :-(" - -.FORCE: - -.PHONY: all - diff --git a/libimagruby/README.md b/libimagruby/README.md deleted file mode 100644 index b11cc5cb..00000000 --- a/libimagruby/README.md +++ /dev/null @@ -1,85 +0,0 @@ -# imag-ruby - -A Ruby gem for scripting imag modules. - -## How does this work? - -Well, as we have some problems with lifetimes here, we have a fairly complex -codebase in this crate. - -### The Problem - -The Problem is, that `libimagstore::store::FileLockEntry<'a>` has a lifetime. If -we would wrap this object into a ruru wrapper and pass to the Ruby code, we -couldn't guarantee anymore that the lifetime holds. - -The problem is simple, you see... - -### The solution? - -Never pass anything to the Ruby code. - -Yes, exactly. The Ruby code only sees 'handles'. It never actually gets the -`Store` object either. -We move the `Store` Object into a `Cache` object (actually, the Ruby code could -have multiple `Store` objects to work with this way) and return a `StoreHandle` -to the Ruby code (which is a UUID underneath). - -Also, the Ruby code never actually touches a `FileLockEntry` - it only gets a -Handle for each `FileLockEntry` - which is a tuple of the `StoreHandle` and the -`libimagstore::storeid::StoreId` for the Entry. - -Each operation on a `FileLockEntry` is then wrapped by this very library. Each -time `FileLockEntry` is touched, this library fetches the appropriate `Store` -object from the static `Cache`, then fetches the `FileLockEntry` object from it, -does the operation and then drops the object (which implies that the actual -`FileLockEntry` is `update()`d!). - -### The Hell? - -Yes, I know this is a lot of overhead. But what are we talking about here? This -is Ruby code we're talking about here, so speed is not our concern. - -You could argue this is a hell of complexity introduced in this library and yes -it is. -If there are bugs (and I bet there are) they would be complex as hell. -But that's it... if you have a better approach, please file a PR. - -## Tests? - -We have tests Ruby scripts in `./test`, they are not executed by travis-ci, as -we need Ruby `2.3.0` for this and travis has `2.2.0` as latest version. -But I hope we get it in travis soonish. - -## Ruby gem? - -This crate will contain both the Rust bindings for imag using `ruru` and a bunch -of wrapper code for the actual `imag` gem. - -### Why another layer of indirection? - -As "ruru" does not yet support modules (which is sad btw) we would end up with -functions for all the things. - -E.G.: `imag_runtime_setup()` instead of `Imag::Runtime::setup()` - -I want to add a Ruby gem to wrap these things. - -So basically a piece of Ruby which uses the Rust code to build -`imag` as a gem which then exports a fine module system. - -### The module system: - -```text -Imag (Module) - EntryContent (Class (inherits from String)) - EntryHeader (Class) - FileLockEntryHandle (Class) - StoreHandle (Class) - StoreId (Class) -``` - -`libimagentrytag` and the other `libimagentry*` libraries will be pulled into -this library to support more advanced operations with the `FileLockEntryHandle` -type. - diff --git a/libimagruby/Rakefile b/libimagruby/Rakefile deleted file mode 100644 index a1397441..00000000 --- a/libimagruby/Rakefile +++ /dev/null @@ -1,5 +0,0 @@ -require "bundler/gem_tasks" -require 'thermite/tasks' - -Thermite::Tasks.new(cargo_project_path: "..", cargo_workspace_member: "libimagruby") - diff --git a/libimagruby/ext/Rakefile b/libimagruby/ext/Rakefile deleted file mode 100644 index 4e097360..00000000 --- a/libimagruby/ext/Rakefile +++ /dev/null @@ -1,5 +0,0 @@ -require 'thermite/tasks' - -Thermite::Tasks.new(cargo_project_path: "..", cargo_workspace_member: "libimagruby") -task default: %w(thermite:build) - diff --git a/libimagruby/imag.gemspec b/libimagruby/imag.gemspec deleted file mode 100644 index 5ffa7a62..00000000 --- a/libimagruby/imag.gemspec +++ /dev/null @@ -1,29 +0,0 @@ -# coding: utf-8 -lib = File.expand_path('../lib', __FILE__) -$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) -require 'imag/version' - -Gem::Specification.new do |spec| - spec.name = "imag" - spec.version = Imag::VERSION - spec.authors = ["Matthias Beyer"] - spec.email = ["mail@beyermatthias.de"] - - spec.summary = %q{A Ruby gem to script imag.} - spec.description = %q{A Ruby gem to script imag, the personal information management suite for the commandline} - spec.homepage = "http://imag-pim.org" - - spec.files = `git ls-files -z`.split("\x0").reject do |f| - f.match(%r{^(test|spec|features)/}) - end - - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } - spec.require_paths = ["lib"] - - spec.add_development_dependency "bundler", "~> 1.13" - spec.add_development_dependency "rake", "~> 10.0" - spec.add_development_dependency 'thermite', "~> 0.11", ">= 0.11.1" - - spec.extensions << 'ext/Rakefile' -end diff --git a/libimagruby/lib/imag.rb b/libimagruby/lib/imag.rb deleted file mode 100644 index 0938c50b..00000000 --- a/libimagruby/lib/imag.rb +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/env ruby - -# imag ruby interface module -# -# This module is created because the library which is used to write the Ruby -# bindings in Rust does not support modules. -# -# This is a wrapper to have nice Ruby-like things in the Ruby codebase and for -# beeing backwards compatible as soon as the Rust library gets module support. -# -# There will probably always be a wrapper for the Rust library, to be more -# flexible with the API, though. -module Imag - - # Function name of the function to call to initialize the Rust backend part. - # Do not use. - IMAG_INIT_FN_NAME = 'imag_ruby_initialize' - - # Setup method - # - # Call this method for initializing the library. - # It dynamically creates the classes for the imag library. - def self.setup binary_path - require binary_path - - self.core_setup - self.classes_setup - end - - # Abstraction over the logger frontend of the binary - # - # This is just a translation to nice Ruby code - module Logger - - def self.init cfg - debug = !!cfg[:debug] - verbose = !!cfg[:verbose] - color = !!cfg[:color] - ::RImag.init_logger debug, verbose, color - end - - # Log text with "trace" level in imag - def self.trace msg - ::RImag.trace msg - end - - # Log text with "debug" level in imag - def self.dbg msg - ::RImag.dbg msg - end - - # Log text with "debug" level in imag (alias for Imag::Logger::dbg) - def self.debug msg - ::RImag.debug msg - end - - # Log text with "info" level in imag - def self.info msg - ::RImag.info msg - end - - # Log text with "warning" level in imag - def self.warn msg - ::RImag.warn msg - end - - # Log text with "error" level in imag - def self.error msg - ::RImag.error msg - end - - end - - private - - # Class names of the Classes in the Ruby scope - # - # These classes are created by the Rust backend with an "R" prefix, and are - # here mapped to Ruby classes by inheriting from them. - # - # Addidional functionality and convenience methods can then be set up upon - # these pure Ruby classes. - def self.class_names - [ - :StoreId , - :StoreHandle , - :FileLockEntryHandle , - :EntryHeader , - :EntryContent , - ] - end - - # Do the core setup - # - # Maps the Rust classes to Ruby classes by inheriting from them - def self.core_setup - self.class_names.map {|n| [n, "R#{n}".to_sym ] }.each do |elem| - Imag.const_set elem.first, Kernel.const_get(elem.last) - end - end - - # Class setup - # - # Summarizing method for calling all the class-setup methods. - def self.classes_setup - self.class_storeid_setup - end - - # Class setup for the StoreId class - # - # Sets up additional methods for the Imag::StoreId class. - def self.class_storeid_setup - Imag::StoreId.class_exec do - def to_s - self.to_str - end - end - end - -end - -if __FILE__ == $0 - puts "Running some tests..." - puts "I hope you passed the library object as first argument..." - begin - Imag.setup ARGV.first - rescue Exception => e - puts "Seems not to be the case... or something else went wrong..." - puts e - exit 1 - end - - Imag::Logger.init debug: true, verbose: true, color: true - Imag::Logger.info "The Logger should work now" - - Imag::Logger.info "Lets see whether we have properly setup StoreId" - Imag::Logger.info Imag::StoreId::new_baseless("baselessId").to_s - Imag::Logger.info "Seems good." -end - diff --git a/libimagruby/lib/imag/version.rb b/libimagruby/lib/imag/version.rb deleted file mode 100644 index c2a2473f..00000000 --- a/libimagruby/lib/imag/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module Imag - VERSION = "0.1.0" -end diff --git a/libimagruby/src/cache.rs b/libimagruby/src/cache.rs deleted file mode 100644 index 94c2b869..00000000 --- a/libimagruby/src/cache.rs +++ /dev/null @@ -1,42 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer and contributors -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; version -// 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// - -use std::collections::BTreeMap; -use std::sync::Arc; -use std::sync::Mutex; - -use uuid::Uuid; - -use libimagstore::store::Store; - -#[derive(Clone, Debug, Ord, Hash, Eq, PartialOrd, PartialEq)] -pub struct StoreHandle(Uuid); - -impl StoreHandle { - pub fn new() -> StoreHandle { - StoreHandle(Uuid::new_v4()) - } -} - -lazy_static! { - pub static ref RUBY_STORE_CACHE: Arc>> = { - Arc::new(Mutex::new(BTreeMap::new())) - }; -} - diff --git a/libimagruby/src/entry.rs b/libimagruby/src/entry.rs deleted file mode 100644 index 9c55e72d..00000000 --- a/libimagruby/src/entry.rs +++ /dev/null @@ -1,276 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer and contributors -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; version -// 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// - -#[allow(unused_variables)] - -use std::error::Error; - -use ruru::{Class, Object, AnyObject, Boolean, RString, VM, Hash, NilClass, VerifiedObject}; -use toml::Value; - -use libimagstore::store::EntryContent; -use libimagstore::store::Entry; -use libimagstore::storeid::StoreId; -use libimagstore::toml_ext::TomlValueExt; - -use ruby_utils::IntoToml; -use toml_utils::IntoRuby; -use util::Wrap; -use util::Unwrap; -use cache::StoreHandle; - -pub struct FileLockEntryHandle(StoreHandle, StoreId); - -impl FileLockEntryHandle { - pub fn new(sh: StoreHandle, id: StoreId) -> FileLockEntryHandle { - FileLockEntryHandle(sh, id) - } - - pub fn store_handle(&self) -> &StoreHandle { - &self.0 - } - - pub fn fle_handle(&self) -> &StoreId { - &self.1 - } -} - -wrappable_struct!(FileLockEntryHandle, FileLockEntryWrapper, FLE_WRAPPER); -class!(RFileLockEntryHandle); -impl_wrap!(FileLockEntryHandle => FLE_WRAPPER); -impl_unwrap!(RFileLockEntryHandle => FileLockEntryHandle => FLE_WRAPPER); -impl_verified_object!(RFileLockEntryHandle); - -/// Helper macro for operating on RUBY_STORE_CACHE object -/// -/// This helps us calling operations on FileLockEntry objects. -/// -/// What I do here: Fetch the Store object from the cache, fetch the appropriate FileLockEntry and -/// call the operation on it. -/// -/// This could be improved with another cache, so not the store is cached but the FileLockEntry -/// only, but then we run into lifetime problems with the Store and its FileLockEntry objects. -/// Feel free to fix this, but for now, this is a workable solution. -/// -#[macro_export] -macro_rules! call_on_fle_from_store { - ($itself:ident ($wrapper:ident) -> $name:ident -> $operation:block) => {{ - let handle = $itself.get_data(&*$wrapper); - let store_handle = handle.store_handle(); - call_on_store_by_handle! { - store_handle named store inside { - match store.get(handle.fle_handle().clone()) { - Ok(Some(mut $name)) => { - $operation - }, - Ok(None) => { - VM::raise(Class::from_existing("RImagStoreReadError"), "Obj does not exist"); - NilClass::new().to_any_object() - }, - Err(e) => { - VM::raise(Class::from_existing("RImagStoreReadError"), e.description()); - NilClass::new().to_any_object() - }, - } - } - } - }}; - ($itself:ident ($wrapper:ident) -> $name:ident -> $operation: block on fail return $ex:expr) => {{ - let handle = $itself.get_data(&*$wrapper); - let store_handle = handle.store_handle(); - call_on_store_by_handle! { - store_handle named store inside { - match store.get(handle.fle_handle().clone()) { - Ok(Some(mut $name)) => { - $operation - }, - Ok(None) => { - VM::raise(Class::from_existing("RImagStoreReadError"), "Obj does not exist"); - $ex - }, - Err(e) => { - VM::raise(Class::from_existing("RImagStoreReadError"), e.description()); - $ex - }, - } - } on fail return $ex - } - }}; -} - - -methods!( - RFileLockEntryHandle, - itself, - - fn r_get_location() -> AnyObject { - call_on_fle_from_store!(itself (FLE_WRAPPER) -> fle -> { fle.get_location().clone().wrap() }) - } - - fn r_get_header() -> AnyObject { - call_on_fle_from_store!(itself (FLE_WRAPPER) -> fle -> { fle.get_header().clone().wrap() }) - } - - fn r_set_header(hdr: Hash) -> NilClass { - use ruby_utils::IntoToml; - use toml::Value; - - let entryheader = match typecheck!(hdr or return NilClass::new()).into_toml() { - Value::Table(t) => Value::Table(t), - _ => { - let ec = Class::from_existing("RImagEntryHeaderWriteError"); - VM::raise(ec, "Something weird happened. Hash seems to be not a Hash"); - return NilClass::new(); - }, - }; - - call_on_fle_from_store!(itself (FLE_WRAPPER) -> fle -> { - *fle.get_header_mut() = entryheader; - NilClass::new().to_any_object() - }); - - NilClass::new() - } - - fn r_get_content() -> AnyObject { - call_on_fle_from_store!(itself (FLE_WRAPPER) -> fle -> { - fle.get_content().clone().wrap() - } on fail return NilClass::new().to_any_object()) - } - - fn r_set_content(ctt: RString) -> NilClass { - use ruby_utils::IntoToml; - use toml::Value; - - let content = match typecheck!(ctt).into_toml() { - Value::String(s) => s, - _ => { - let ec = Class::from_existing("RImagEntryError"); - VM::raise(ec, "Something weird happened. String seems to be not a String"); - return NilClass::new(); - }, - }; - - call_on_fle_from_store!(itself (FLE_WRAPPER) -> fle -> { - *fle.get_content_mut() = content; - NilClass::new().to_any_object() - }); - - NilClass::new() - } - -); - -wrappable_struct!(Value, EntryHeaderWrapper, ENTRY_HEADER_WRAPPER); -class!(REntryHeader); -impl_wrap!(Value => ENTRY_HEADER_WRAPPER); -impl_unwrap!(REntryHeader => Value => ENTRY_HEADER_WRAPPER); -impl_verified_object!(REntryHeader); - -methods!( - REntryHeader, - itself, - - fn r_entry_header_new() -> AnyObject { - Entry::default_header().wrap() - } - - fn r_entry_header_insert(spec: RString, obj: AnyObject) -> Boolean { - let spec = typecheck!(spec or return Boolean::new(false)).to_string(); - let obj = obj.unwrap(); // possibly not safe... TODO - - match itself.get_data(&*ENTRY_HEADER_WRAPPER).insert(&spec, obj.into_toml()) { - Ok(b) => Boolean::new(b), - Err(e) => { - VM::raise(Class::from_existing("RImagEntryHeaderWriteError"), e.description()); - Boolean::new(false) - } - } - } - - fn r_entry_header_set(spec: RString, obj: AnyObject) -> AnyObject { - use ruru::NilClass; - - let spec = typecheck!(spec or return any Boolean::new(false)).to_string(); - let obj = obj.unwrap(); // possibly not safe... TODO - - match itself.get_data(&*ENTRY_HEADER_WRAPPER).set(&spec, obj.into_toml()) { - Ok(Some(v)) => v.into_ruby(), - Ok(None) => NilClass::new().to_any_object(), - Err(e) => { - VM::raise(Class::from_existing("RImagEntryHeaderWriteError"), e.description()); - return Boolean::new(false).to_any_object(); - } - } - } - - fn r_entry_header_get(spec: RString) -> AnyObject { - use ruru::NilClass; - - let spec = typecheck!(spec or return any Boolean::new(false)).to_string(); - - match itself.get_data(&*ENTRY_HEADER_WRAPPER).read(&spec) { - Ok(Some(v)) => v.into_ruby(), - Ok(None) => NilClass::new().to_any_object(), - Err(e) => { - VM::raise(Class::from_existing("RImagEntryHeaderReadError"), e.description()); - return Boolean::new(false).to_any_object(); - } - } - } - -); - -wrappable_struct!(EntryContent, EntryContentWrapper, ENTRY_CONTENT_WRAPPER); -class!(REntryContent); -impl_wrap!(EntryContent => ENTRY_CONTENT_WRAPPER); -impl_unwrap!(REntryContent => EntryContent => ENTRY_CONTENT_WRAPPER); - -wrappable_struct!(Entry, EntryWrapper, ENTRY_WRAPPER); -class!(REntry); -impl_unwrap!(REntry => Entry => ENTRY_WRAPPER); - -pub fn setup_filelockentry() -> Class { - let mut class = Class::new("RFileLockEntryHandle", None); - class.define(|itself| { - itself.def("location", r_get_location); - itself.def("header" , r_get_header); - itself.def("header=" , r_set_header); - itself.def("content" , r_get_content); - itself.def("content=", r_set_content); - }); - class -} - -pub fn setup_entryheader() -> Class { - let mut class = Class::new("REntryHeader", None); - class.define(|itself| { - itself.def("insert", r_entry_header_insert); - itself.def("set" , r_entry_header_set); - itself.def("[]=" , r_entry_header_set); - itself.def("read" , r_entry_header_get); - itself.def("[]" , r_entry_header_get); - }); - class -} - -pub fn setup_entrycontent() -> Class { - let string = Class::from_existing("String"); - Class::new("REntryContent", Some(&string)) -} diff --git a/libimagruby/src/error.rs b/libimagruby/src/error.rs deleted file mode 100644 index acd01d4e..00000000 --- a/libimagruby/src/error.rs +++ /dev/null @@ -1,52 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer and contributors -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; version -// 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// - -use ruru::Class; - -class!(RImagError); -class!(RImagObjDoesNotExistError); -class!(RImagStoreError); -class!(RImagStoreWriteError); -class!(RImagStoreReadError); -class!(RImagEntryError); -class!(RImagEntryHeaderError); -class!(RImagEntryHeaderReadError); -class!(RImagEntryHeaderWriteError); -class!(RImagTypeError); - -pub fn setup() { - let imag_error = Class::new("RImagError", Some(&Class::from_existing("RuntimeError"))); - Class::new("RImagObjDoesNotExistError" , Some(&imag_error)); - - { - let imag_store_error = Class::new("RImagStoreError", Some(&imag_error)); - Class::new("RImagStoreWriteError", Some(&imag_store_error)); - Class::new("RImagStoreReadError" , Some(&imag_store_error)); - } - - { - let imag_entry_error = Class::new("RImagEntryError" , Some(&imag_error)); - let imag_entry_header_error = Class::new("RImagEntryHeaderError", Some(&imag_entry_error)); - Class::new("RImagEntryHeaderReadError" , Some(&imag_entry_header_error)); - Class::new("RImagEntryHeaderWriteError", Some(&imag_entry_header_error)); - } - - Class::new("RImagTypeError", Some(&imag_error)); -} - diff --git a/libimagruby/src/imag.rs b/libimagruby/src/imag.rs deleted file mode 100644 index 8cec75ba..00000000 --- a/libimagruby/src/imag.rs +++ /dev/null @@ -1,148 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer and contributors -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; version -// 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// - -#[allow(unused_variables)] - -use std::error::Error; - -use ruru::{Class, Boolean, RString, NilClass, VM, Object}; - -use libimagrt::logger::ImagLogger; - -class!(RImag); - -methods!( - RImag, - itself, - - fn r_initialize_logger(debug: Boolean, verbose: Boolean, colored: Boolean) -> NilClass { - use std::env::var as env_var; - use env_logger; - use log; - use log::LogLevelFilter; - - let debug = match debug { - Ok(d) => d.to_bool(), - Err(ref e) => { - VM::raise(e.to_exception(), e.description()); - return NilClass::new(); - }, - }; - - let verbose = match verbose { - Ok(v) => v.to_bool(), - Err(ref e) => { - VM::raise(e.to_exception(), e.description()); - return NilClass::new(); - }, - }; - - let colored = match colored { - Ok(c) => c.to_bool(), - Err(ref e) => { - VM::raise(e.to_exception(), e.description()); - return NilClass::new(); - }, - }; - - if env_var("IMAG_LOG_ENV").is_ok() { - env_logger::init().unwrap(); - } else { - let lvl = if debug { - LogLevelFilter::Debug - } else if verbose { - LogLevelFilter::Info - } else { - LogLevelFilter::Warn - }; - - log::set_logger(|max_log_lvl| { - max_log_lvl.set(lvl); - debug!("Init logger with {}", lvl); - let lgr = ImagLogger::new(lvl.to_log_level().unwrap()) - .with_color(colored) - .with_prefix("[imag][ruby]".to_owned()) - .with_dbg_file_and_line(false); - Box::new(lgr) - }) - .map_err(|_| { - panic!("Could not setup logger"); - }) - .ok(); - } - - NilClass::new() - } - - fn r_log_trace(l: RString) -> NilClass { - match l { - Err(ref e) => VM::raise(e.to_exception(), e.description()), - Ok(s) => trace!("{}", s.to_string()), - } - NilClass::new() - } - - fn r_log_debug(l: RString) -> NilClass { - match l { - Err(ref e) => VM::raise(e.to_exception(), e.description()), - Ok(s) => debug!("{}", s.to_string()), - } - NilClass::new() - } - - fn r_log_info(l: RString) -> NilClass { - match l { - Err(ref e) => VM::raise(e.to_exception(), e.description()), - Ok(s) => info!("{}", s.to_string()), - } - NilClass::new() - } - - fn r_log_warn(l: RString) -> NilClass { - match l { - Err(ref e) => VM::raise(e.to_exception(), e.description()), - Ok(s) => warn!("{}", s.to_string()), - } - NilClass::new() - } - - fn r_log_error(l: RString) -> NilClass { - match l { - Err(ref e) => VM::raise(e.to_exception(), e.description()), - Ok(s) => error!("{}", s.to_string()), - } - NilClass::new() - } - -); - -pub fn setup() -> Class { - let mut class = Class::new("RImag", None); - class.define(|itself| { - itself.def_self("init_logger", r_initialize_logger); - itself.def_self("trace", r_log_trace); - itself.def_self("dbg", r_log_debug); - itself.def_self("debug", r_log_debug); - itself.def_self("info", r_log_info); - itself.def_self("warn", r_log_warn); - itself.def_self("error", r_log_error); - }); - class -} - diff --git a/libimagruby/src/lib.rs b/libimagruby/src/lib.rs deleted file mode 100644 index f26b6b1f..00000000 --- a/libimagruby/src/lib.rs +++ /dev/null @@ -1,55 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer and contributors -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; version -// 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// - -#[macro_use] extern crate ruru; -#[macro_use] extern crate lazy_static; -#[macro_use] extern crate log; -extern crate env_logger; -extern crate toml; -extern crate uuid; - -#[macro_use] extern crate libimagerror; -extern crate libimagstore; -extern crate libimagstorestdhook; -extern crate libimagrt; -#[macro_use] extern crate libimagutil; - -#[macro_use] mod util; -#[macro_use] pub mod store; -mod cache; - -pub mod error; -pub mod entry; -pub mod imag; -pub mod ruby_utils; -pub mod storeid; -pub mod toml_utils; - -#[no_mangle] -#[allow(non_snake_case)] -pub extern fn Init_liblibimagruby() { - self::error::setup(); - self::store::setup(); - self::storeid::setup(); - self::entry::setup_filelockentry(); - self::entry::setup_entryheader(); - self::entry::setup_entrycontent(); - self::imag::setup(); -} - diff --git a/libimagruby/src/ruby_utils.rs b/libimagruby/src/ruby_utils.rs deleted file mode 100644 index b40f684d..00000000 --- a/libimagruby/src/ruby_utils.rs +++ /dev/null @@ -1,210 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer and contributors -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; version -// 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// - -// Ruby -> Toml translation primitives - -use std::collections::BTreeMap; - -use ruru::{Object, AnyObject, Class, RString, Fixnum, Float, Symbol, Hash, Array, VM}; -use ruru::types::ValueType; -use toml::Value; - - -pub trait AsToml : Sized { - fn as_toml(&self) -> Value; -} - -pub trait IntoToml : AsToml { - fn into_toml(self) -> Value { - self.as_toml() - } -} -impl IntoToml for T { } - -impl AsToml for AnyObject { - - fn as_toml(&self) -> Value { - match self.value().ty() { - ValueType::None => { - Value::Boolean(false) - }, - ValueType::Object => { - let rte = Class::from_existing("TypeError"); - VM::raise(rte, "Cannot translate type '' to fit into TOML"); - Value::Boolean(false) - }, - ValueType::Class => { - let rte = Class::from_existing("TypeError"); - VM::raise(rte, "Cannot translate type '' to fit into TOML"); - Value::Boolean(false) - }, - ValueType::Module => { - let rte = Class::from_existing("TypeError"); - VM::raise(rte, "Cannot translate type '' to fit into TOML"); - Value::Boolean(false) - }, - ValueType::Float => self.try_convert_to::().unwrap().as_toml(), - ValueType::RString => self.try_convert_to::().unwrap().as_toml(), - ValueType::Regexp => { - let rte = Class::from_existing("TypeError"); - VM::raise(rte, "Cannot translate type '' to fit into TOML"); - Value::Boolean(false) - }, - ValueType::Array => self.try_convert_to::().unwrap().as_toml(), - ValueType::Hash => self.try_convert_to::().unwrap().as_toml(), - ValueType::Struct => { - let rte = Class::from_existing("TypeError"); - VM::raise(rte, "Cannot translate type '' to fit into TOML"); - Value::Boolean(false) - }, - ValueType::Bignum => { - let rte = Class::from_existing("TypeError"); - VM::raise(rte, "Cannot translate type '' to fit into TOML"); - Value::Boolean(false) - }, - ValueType::File => { - let rte = Class::from_existing("TypeError"); - VM::raise(rte, "Cannot translate type '' to fit into TOML"); - Value::Boolean(false) - }, - ValueType::Data => { - let rte = Class::from_existing("TypeError"); - VM::raise(rte, "Cannot translate type '' to fit into TOML"); - Value::Boolean(false) - }, - ValueType::Match => { - let rte = Class::from_existing("TypeError"); - VM::raise(rte, "Cannot translate type '' to fit into TOML"); - Value::Boolean(false) - }, - ValueType::Complex => { - let rte = Class::from_existing("TypeError"); - VM::raise(rte, "Cannot translate type '' to fit into TOML"); - Value::Boolean(false) - }, - ValueType::Rational => { - let rte = Class::from_existing("TypeError"); - VM::raise(rte, "Cannot translate type '' to fit into TOML"); - Value::Boolean(false) - }, - ValueType::Nil => Value::Boolean(false), - ValueType::True => Value::Boolean(true), - ValueType::False => Value::Boolean(false), - ValueType::Symbol => self.try_convert_to::().unwrap().as_toml(), - ValueType::Fixnum => self.try_convert_to::().unwrap().as_toml(), - ValueType::Undef => { - let rte = Class::from_existing("TypeError"); - VM::raise(rte, "Cannot translate type '' to fit into TOML"); - Value::Boolean(false) - }, - ValueType::Node => { - let rte = Class::from_existing("TypeError"); - VM::raise(rte, "Cannot translate type '' to fit into TOML"); - Value::Boolean(false) - }, - ValueType::IClass => { - let rte = Class::from_existing("TypeError"); - VM::raise(rte, "Cannot translate type '' to fit into TOML"); - Value::Boolean(false) - }, - ValueType::Zombie => { - let rte = Class::from_existing("TypeError"); - VM::raise(rte, "Cannot translate type '' to fit into TOML"); - Value::Boolean(false) - }, - ValueType::Mask => { - let rte = Class::from_existing("TypeError"); - VM::raise(rte, "Cannot translate type '' to fit into TOML"); - Value::Boolean(false) - }, - } - } - -} - -impl AsToml for Hash { - - fn as_toml(&self) -> Value { - let mut btm = BTreeMap::new(); - self.try_convert_to::() - .unwrap() - .each(|key, value| { - let key = match key.as_toml() { - Value::String(s) => s, - _ => { - let rte = Class::from_existing("TypeError"); - VM::raise(rte, "Can only have String or Symbol as Key for TOML maps"); - String::new() - } - }; - let value = value.as_toml(); - btm.insert(key, value); - }); - Value::Table(btm) - } - -} - -impl AsToml for Array { - - fn as_toml(&self) -> Value { - let vals = self - .try_convert_to::() - .unwrap() - .into_iter() - .map(|v| v.as_toml()) - .collect::>(); - - Value::Array(vals) - } - -} - -impl AsToml for RString { - - fn as_toml(&self) -> Value { - Value::String(self.try_convert_to::().unwrap().to_string()) - } - -} - -impl AsToml for Float { - - fn as_toml(&self) -> Value { - Value::Float(self.try_convert_to::().unwrap().to_f64()) - } - -} - -impl AsToml for Symbol { - - fn as_toml(&self) -> Value { - Value::String(self.try_convert_to::().unwrap().to_string()) - } - -} - -impl AsToml for Fixnum { - - fn as_toml(&self) -> Value { - Value::Integer(self.try_convert_to::().unwrap().to_i64()) - } - -} - diff --git a/libimagruby/src/store.rs b/libimagruby/src/store.rs deleted file mode 100644 index cc8a6626..00000000 --- a/libimagruby/src/store.rs +++ /dev/null @@ -1,578 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer and contributors -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; version -// 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// - -#[allow(unused_variables)] - -use libimagstore::store::Store; -use libimagerror::trace::trace_error; -use std::error::Error; - -use ruru::{Class, Object, AnyObject, Boolean, RString, VM, NilClass, VerifiedObject}; - -use util::Wrap; -use util::Unwrap; - -use storeid::RStoreId; -use entry::RFileLockEntryHandle; -use cache::StoreHandle; - -wrappable_struct!(StoreHandle, StoreWrapper, STORE_WRAPPER); -class!(RStoreHandle); -impl_wrap!(StoreHandle => STORE_WRAPPER); -impl_unwrap!(RStoreHandle => StoreHandle => STORE_WRAPPER); -impl_verified_object!(RStoreHandle); - -macro_rules! call_on_store_by_handle { - { - $store_handle:ident named $name:ident inside $operation:block - }=> {{ - call_on_store_by_handle! { - $store_handle - named $name - inside $operation - on fail return NilClass::new().to_any_object() - } - }}; - - { - $store_handle:ident named $name:ident inside $operation:block on fail return $ex:expr - } => {{ - use cache::RUBY_STORE_CACHE; - - let arc = RUBY_STORE_CACHE.clone(); - { - let lock = arc.lock(); - match lock { - Ok(mut hm) => { - match hm.get($store_handle) { - Some($name) => { $operation }, - None => { - VM::raise(Class::from_existing("RImagStoreReadError"), - "Tried to operate on non-existing object"); - $ex - } - } - }, - Err(e) => { - VM::raise(Class::from_existing("RImagError"), e.description()); - $ex - } - } - } - }}; -} - -macro_rules! call_on_store { - { - $store_name:ident <- $itself:ident wrapped inside $wrapper:ident, - $fle_name:ident <- fetch $fle_handle_name:ident - operation $operation:block - } => { - call_on_store! { - $store_name <- $itself wrapped inside $wrapper, - $fle_name <- fetch $fle_handle_name, - operation $operation, - on fail return NilClass::new() - } - }; - - { - $store_name:ident <- $itself:ident wrapped inside $wrapper:ident, - $fle_name:ident <- fetch $fle_handle_name:ident, - operation $operation:block, - on fail return $fail_expr:expr - } => { - let handle = $itself.get_data(&*$wrapper); - call_on_store_by_handle! { - handle named $store_name inside { - let $fle_name = match $store_name.get($fle_handle_name) { - Ok(Some(fle)) => fle, - Ok(None) => { - VM::raise(Class::from_existing("RImagStoreReadError"), "Obj does not exist"); - return $fail_expr - }, - Err(e) => { - VM::raise(Class::from_existing("RImagStoreReadError"), e.description()); - return $fail_expr - }, - }; - $operation - } - on fail return $fail_expr - } - }; - - { - $store_name:ident <- $itself:ident wrapped inside $wrapper:ident, - operation $operation:block, - on fail return $fail_expr:expr - } => { - let handle = $itself.get_data(&*$wrapper); - call_on_store_by_handle! { - handle named $store_name inside $operation on fail return $fail_expr - } - }; - - { - $store_name:ident <- $itself:ident wrapped inside $wrapper:ident, - operation $block - } => { - let handle = $itself.get_data(&*$wrapper); - call_on_store_by_handle! { handle named $name inside $operation } - }; -} - -methods!( - RStoreHandle, - itself, - - // Build a new Store object, return a handle to it. - // - // This function takes a boolean whether the store should include debugging functionality - // (namingly the debug hooks) and a runtimepath, where the store lifes. - // It then builds a Store object (raising errors on failure and returning Nil) and a handle for - // it. - // It puts the store object and the handle in the cache and returns the handle as object to the - // Ruby code. - // - // # Returns - // - // Nil on failure (including raising an error) - // StoreHandle on success - // - fn new(store_debugging: Boolean, rtp: RString) -> AnyObject { - use std::path::PathBuf; - use libimagerror::trace::trace_error; - use libimagerror::trace::trace_error_dbg; - use libimagrt::configuration::ConfigErrorKind; - use libimagrt::configuration::Configuration; - use libimagstore::error::StoreErrorKind; - use libimagstore::hook::Hook; - use libimagstore::hook::position::HookPosition as HP; - use libimagstorestdhook::debug::DebugHook; - use libimagstorestdhook::vcs::git::delete::DeleteHook as GitDeleteHook; - use libimagstorestdhook::vcs::git::store_unload::StoreUnloadHook as GitStoreUnloadHook; - use libimagstorestdhook::vcs::git::update::UpdateHook as GitUpdateHook; - - use cache::RUBY_STORE_CACHE; - - let store_debugging = typecheck!(store_debugging or return any NilClass::new()).to_bool(); - let rtp = PathBuf::from(typecheck!(rtp or return any NilClass::new()).to_string()); - - if !rtp.exists() || !rtp.is_dir() { - VM::raise(Class::from_existing("RImagError"), "Runtimepath not a directory"); - return NilClass::new().to_any_object(); - } - - let store_config = match Configuration::new(&rtp) { - Ok(mut cfg) => cfg.store_config().cloned(), - Err(e) => if e.err_type() != ConfigErrorKind::NoConfigFileFound { - VM::raise(Class::from_existing("RImagError"), e.description()); - return NilClass::new().to_any_object(); - } else { - warn!("No config file found."); - warn!("Continuing without configuration file"); - None - }, - }; - - let storepath = { - let mut spath = rtp.clone(); - spath.push("store"); - spath - }; - - let store = Store::new(storepath.clone(), store_config).map(|mut store| { - // If we are debugging, generate hooks for all positions - if store_debugging { - let hooks : Vec<(Box, &str, HP)> = vec![ - (Box::new(DebugHook::new(HP::PreCreate)) , "debug", HP::PreCreate), - (Box::new(DebugHook::new(HP::PostCreate)) , "debug", HP::PostCreate), - (Box::new(DebugHook::new(HP::PreRetrieve)) , "debug", HP::PreRetrieve), - (Box::new(DebugHook::new(HP::PostRetrieve)) , "debug", HP::PostRetrieve), - (Box::new(DebugHook::new(HP::PreUpdate)) , "debug", HP::PreUpdate), - (Box::new(DebugHook::new(HP::PostUpdate)) , "debug", HP::PostUpdate), - (Box::new(DebugHook::new(HP::PreDelete)) , "debug", HP::PreDelete), - (Box::new(DebugHook::new(HP::PostDelete)) , "debug", HP::PostDelete), - ]; - - // If hook registration fails, trace the error and warn, but continue. - for (hook, aspectname, position) in hooks { - if let Err(e) = store.register_hook(position, &String::from(aspectname), hook) { - if e.err_type() == StoreErrorKind::HookRegisterError { - trace_error_dbg(&e); - warn!("Registering debug hook with store failed"); - } else { - trace_error(&e); - }; - } - } - } - - let sp = storepath; - - let hooks : Vec<(Box, &str, HP)> = vec![ - (Box::new(GitDeleteHook::new(sp.clone(), HP::PostDelete)), "vcs", HP::PostDelete), - (Box::new(GitUpdateHook::new(sp.clone(), HP::PostUpdate)), "vcs", HP::PostUpdate), - (Box::new(GitStoreUnloadHook::new(sp)), "vcs", HP::StoreUnload), - ]; - - for (hook, aspectname, position) in hooks { - if let Err(e) = store.register_hook(position, &String::from(aspectname), hook) { - if e.err_type() == StoreErrorKind::HookRegisterError { - trace_error_dbg(&e); - warn!("Registering git hook with store failed"); - } else { - trace_error(&e); - }; - } - } - - store - }); - - let store = match store { - Ok(s) => s, - Err(e) => { - VM::raise(Class::from_existing("RImagStoreError"), e.description()); - return NilClass::new().to_any_object(); - }, - }; - - let store_handle = StoreHandle::new(); - - let arc = RUBY_STORE_CACHE.clone(); - { - let lock = arc.lock(); - match lock { - Ok(mut hm) => { - hm.insert(store_handle.clone(), store); - return store_handle.wrap().to_any_object(); - }, - Err(e) => { - VM::raise(Class::from_existing("RImagError"), e.description()); - return NilClass::new().to_any_object(); - } - } - } - - } - - - // Create an FileLockEntry in the store - // - // # Returns: - // - // On success: A RFileLockEntry - // On failure: Nil - // On error: Nil + Exception - // - fn create(id: RStoreId) -> AnyObject { - use entry::FileLockEntryHandle; - let sid = typecheck!(id or return any NilClass::new()).unwrap().clone(); - - call_on_store! { - store <- itself wrapped inside STORE_WRAPPER, - operation { - match store.create(sid.clone()) { - Err(e) => { - trace_error(&e); - VM::raise(Class::from_existing("RImagStoreWriteError"), e.description()); - NilClass::new().to_any_object() - }, - Ok(entry) => { - // Take the location (StoreId) of the entry (we know it exists... so this - // is fine) and wrap it into a RFileLockEntry which is then returned to the - // user (as handle) - let sid = entry.get_location().clone(); - let store_handle = itself.get_data(&*STORE_WRAPPER).clone(); - FileLockEntryHandle::new(store_handle, sid).wrap() - }, - } - }, - on fail return NilClass::new().to_any_object() - } - } - - // Retrieve an FileLockEntry from the store - // - // # Returns: - // - // On success: A RFileLockEntry - // On error: Nil + Exception - // - fn retrieve(id: RStoreId) -> AnyObject { - use entry::FileLockEntryHandle; - let sid = typecheck!(id or return any NilClass::new()).unwrap().clone(); - - call_on_store! { - store <- itself wrapped inside STORE_WRAPPER, - operation { - match store.retrieve(sid.clone()) { - Err(e) => { - trace_error(&e); - VM::raise(Class::from_existing("RImagStoreWriteError"), e.description()); - NilClass::new().to_any_object() - }, - Ok(entry) => { - // Take the location (StoreId) of the entry (we know it exists... so this - // is fine) and wrap it into a RFileLockEntry which is then returned to the - // user (as handle) - let sid = entry.get_location().clone(); - let store_handle = itself.get_data(&*STORE_WRAPPER).clone(); - FileLockEntryHandle::new(store_handle, sid).wrap() - }, - } - }, - on fail return NilClass::new().to_any_object() - } - } - - // Get an FileLockEntry from the store - // - // # Returns: - // - // On success, if there is some: A RFileLockEntry - // On success, if there is none: Nil - // On error: Nil + Exception - // - fn get(sid: RStoreId) -> AnyObject { - use entry::FileLockEntryHandle; - let sid = typecheck!(sid or return any NilClass::new()).unwrap().clone(); - - call_on_store! { - store <- itself wrapped inside STORE_WRAPPER, - operation { - match store.get(sid.clone()) { - Err(e) => { - trace_error(&e); - VM::raise(Class::from_existing("RImagStoreWriteError"), e.description()); - NilClass::new().to_any_object() - }, - Ok(None) => NilClass::new().to_any_object(), - Ok(Some(entry)) => { - // Take the location (StoreId) of the entry (we know it exists... so this - // is fine) and wrap it into a RFileLockEntry which is then returned to the - // user (as handle) - let sid = entry.get_location().clone(); - let store_handle = itself.get_data(&*STORE_WRAPPER).clone(); - FileLockEntryHandle::new(store_handle, sid).wrap() - }, - } - }, - on fail return NilClass::new().to_any_object() - } - } - - // Get all FileLockEntry of a module from the store - // - // # Returns: - // - // On success: A Array[RFileLockEntry] - // On error: Nil + Exception - // - fn retrieve_for_module(name: RString) -> AnyObject { - use entry::FileLockEntryHandle as FLEH; - use ruru::Array; - - let name = typecheck!(name or return any NilClass::new()).to_string(); - - call_on_store! { - store <- itself wrapped inside STORE_WRAPPER, - operation { - match store.retrieve_for_module(&name) { - Err(e) => { - trace_error(&e); - VM::raise(Class::from_existing("RImagStoreWriteError"), e.description()); - NilClass::new().to_any_object() - }, - Ok(iter) => { - let store_handle = itself.get_data(&*STORE_WRAPPER).clone(); - iter.map(|sid| FLEH::new(store_handle.clone(), sid).wrap()) - .fold(Array::new(), |mut a, e| a.push(e)) - .to_any_object() - }, - } - }, - on fail return NilClass::new().to_any_object() - } - } - - // Update a FileLockEntry in the store - // - // # Returns: - // - // On success: Nil - // On error: Nil + Exception - // - fn update(fle: RFileLockEntryHandle) -> NilClass { - let fle = typecheck!(fle).unwrap().fle_handle().clone(); - - call_on_store! { - store <- itself wrapped inside STORE_WRAPPER, - real_fle <- fetch fle, - operation { - let mut real_fle = real_fle; // rebind for mut - if let Err(e) = store.update(&mut real_fle) { - trace_error(&e); - VM::raise(Class::from_existing("RImagStoreWriteError"), e.description()); - } - NilClass::new() - }, - on fail return NilClass::new() - } - } - - // Delete a FileLockEntry from the store - // - // # Returns: - // - // On success: Nil - // On error: Nil + Exception - // - fn delete(sid: RStoreId) -> NilClass { - let sid = typecheck!(sid).unwrap().clone(); - - call_on_store! { - store <- itself wrapped inside STORE_WRAPPER, - operation { - if let Err(e) = store.delete(sid) { - trace_error(&e); - VM::raise(Class::from_existing("RImagStoreWriteError"), e.description()); - } - NilClass::new() - }, - on fail return NilClass::new() - } - } - - // Save a FileLockEntry in a new path inside the store, keep the RFileLockEntry - // - // # Returns: - // - // On success: Nil - // On error: Nil + Exception - // - fn save_to(fle: RFileLockEntryHandle, sid: RStoreId) -> NilClass { - let fle = typecheck!(fle).unwrap().fle_handle().clone(); - let sid = typecheck!(sid).unwrap().clone(); - - call_on_store! { - store <- itself wrapped inside STORE_WRAPPER, - real_fle <- fetch fle, - operation { - if let Err(e) = store.save_to(&real_fle, sid) { - trace_error(&e); - VM::raise(Class::from_existing("RImagStoreWriteError"), e.description()); - } - NilClass::new() - }, - on fail return NilClass::new() - } - } - - // Save a FileLockEntry in a new path inside the store, move the RFileLockEntry - // - // # Returns: - // - // On success: Nil - // On error: Nil + Exception - // - fn save_as(fle: RFileLockEntryHandle, sid: RStoreId) -> NilClass { - let fle = typecheck!(fle).unwrap().fle_handle().clone(); - let sid = typecheck!(sid).unwrap().clone(); - - call_on_store! { - store <- itself wrapped inside STORE_WRAPPER, - real_fle <- fetch fle, - operation { - if let Err(e) = store.save_as(real_fle, sid) { - trace_error(&e); - VM::raise(Class::from_existing("RImagStoreWriteError"), e.description()); - } - NilClass::new() - }, - on fail return NilClass::new() - } - } - - // Move one entry in the store to another place, by its ID - // - // # Returns: - // - // On success: Nil - // On error: Nil + Exception - // - fn move_by_id(old: RStoreId, nw: RStoreId) -> NilClass { - let old = typecheck!(old).unwrap().clone(); - let nw = typecheck!(nw).unwrap().clone(); - - call_on_store! { - store <- itself wrapped inside STORE_WRAPPER, - operation { - if let Err(e) = store.move_by_id(old, nw) { - trace_error(&e); - VM::raise(Class::from_existing("RImagStoreWriteError"), e.description()); - } - NilClass::new() - }, - on fail return NilClass::new() - } - } - - // Get the path of the store object - // - // # Returns: - // - // A RString - // - fn path() -> RString { - call_on_store! { - store <- itself wrapped inside STORE_WRAPPER, - operation { - store.path() - .clone() - .to_str() - .map(RString::new) - .unwrap_or(RString::new("")) - }, - on fail return RString::new("") - } - } - -); - -pub fn setup() -> Class { - let mut class = Class::new("RStoreHandle", None); - class.define(|itself| { - itself.def_self("new" , new); - itself.def("create" , create); - itself.def("retrieve" , retrieve); - itself.def("get" , get); - itself.def("retrieve_for_module" , retrieve_for_module); - itself.def("update" , update); - itself.def("delete" , delete); - itself.def("save_to" , save_to); - itself.def("save_as" , save_as); - itself.def("move_by_id" , move_by_id); - itself.def("path" , path); - }); - class -} - diff --git a/libimagruby/src/storeid.rs b/libimagruby/src/storeid.rs deleted file mode 100644 index a08787dd..00000000 --- a/libimagruby/src/storeid.rs +++ /dev/null @@ -1,164 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer and contributors -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; version -// 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// - -#[allow(unused_variables)] - -use std::path::PathBuf; - -use ruru::{Class, Object, AnyObject, Boolean, RString, NilClass, VerifiedObject, VM}; - -use libimagstore::storeid::StoreId; -use util::Unwrap; -use util::Wrap; - -wrappable_struct!(StoreId, StoreIdWrapper, STOREID_WRAPPER); -class!(RStoreId); -impl_wrap!(StoreId => STOREID_WRAPPER); -impl_unwrap!(RStoreId => StoreId => STOREID_WRAPPER); -impl_verified_object!(RStoreId); - - -methods!( - RStoreId, - itself, - - fn r_storeid_new(base: RString, id: RString) -> AnyObject { - let base = match base.map(|b| b.to_string()).map(PathBuf::from) { - Ok(base) => base, - Err(e) => { - // TODO: Exception! - error!("Building StoreId object failed: {:?}", e); - return AnyObject::from(NilClass::new().value()); - }, - }; - - let id = match id.map(|id| id.to_string()).map(PathBuf::from) { - Ok(id) => id, - Err(e) => { - // TODO: Exception! - error!("Building StoreId object failed: {:?}", e); - return AnyObject::from(NilClass::new().value()); - }, - }; - - match StoreId::new(Some(base), id) { - Ok(sid) => Class::from_existing("RStoreId").wrap_data(sid, &*STOREID_WRAPPER), - Err(e) => { - // TODO: Exception! - error!("Building StoreId object failed: {:?}", e); - return AnyObject::from(NilClass::new().value()); - }, - } - } - - fn r_storeid_new_baseless(id: RString) -> AnyObject { - let id = match id.map(|id| id.to_string()).map(PathBuf::from) { - Ok(id) => id, - Err(e) => { - // TODO: Exception! - error!("Building StoreId object failed: {:?}", e); - return AnyObject::from(NilClass::new().value()); - }, - }; - - match StoreId::new(None, id) { - Ok(sid) => Class::from_existing("RStoreId").wrap_data(sid, &*STOREID_WRAPPER), - Err(e) => { - // TODO: Exception! - error!("Building StoreId object failed: {:?}", e); - return AnyObject::from(NilClass::new().value()); - }, - } - } - - fn r_storeid_without_base() -> RStoreId { - let withoutbase : StoreId = itself.get_data(&*STOREID_WRAPPER).clone().without_base(); - Class::from_existing("RStoreId").wrap_data(withoutbase, &*STOREID_WRAPPER) - } - - fn r_storeid_with_base(base: RString) -> AnyObject { - let base : PathBuf = match base.map(|b| b.to_string()).map(PathBuf::from) { - Ok(pb) => pb, - Err(e) => { - // TODO: Exception! - error!("Error: {:?}", e); - return AnyObject::from(NilClass::new().value()); - }, - }; - let withoutbase : StoreId = itself.get_data(&*STOREID_WRAPPER).clone().with_base(base); - Class::from_existing("RStoreId").wrap_data(withoutbase, &*STOREID_WRAPPER) - } - - fn r_storeid_into_pathbuf() -> AnyObject { - itself.get_data(&*STOREID_WRAPPER) - .clone() - .into_pathbuf() - // TODO: No unwraps - .map(|pb| pb.to_str().map(String::from).unwrap()) - .as_ref() - .map(|s| AnyObject::from(RString::new(s).value())) - // TODO: Exception! - .unwrap_or(AnyObject::from(NilClass::new().value())) - } - - fn r_storeid_exists() -> Boolean { - use std::error::Error; - - match itself.get_data(&*STOREID_WRAPPER).exists() { - Ok(bool) => Boolean::new(bool), - Err(e) => { - VM::raise(Class::from_existing("RuntimeError"), e.description()); - Boolean::new(false) - } - } - } - - fn r_storeid_to_str() -> AnyObject { - itself.get_data(&*STOREID_WRAPPER) - .to_str() - .as_ref() - .map(|s| AnyObject::from(RString::new(s).value())) - // TODO: Exception! - .unwrap_or(AnyObject::from(NilClass::new().value())) - } - - fn r_storeid_local() -> RString { - let local = itself.get_data(&*STOREID_WRAPPER).local(); - let local = local.to_str().unwrap(); // TODO: No unwraps - RString::new(local) - } - -); - -pub fn setup() -> Class { - let mut class = Class::new("RStoreId", None); - class.define(|itself| { - itself.def_self("new" , r_storeid_new); - itself.def_self("new_baseless" , r_storeid_new_baseless); - - itself.def("without_base" , r_storeid_without_base); - itself.def("with_base" , r_storeid_with_base); - itself.def("into_pathbuf" , r_storeid_into_pathbuf); - itself.def("exists" , r_storeid_exists); - itself.def("to_str" , r_storeid_to_str); - itself.def("local" , r_storeid_local); - }); - class -} - diff --git a/libimagruby/src/toml_utils.rs b/libimagruby/src/toml_utils.rs deleted file mode 100644 index 85df9dde..00000000 --- a/libimagruby/src/toml_utils.rs +++ /dev/null @@ -1,65 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer and contributors -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; version -// 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// - -// Toml -> Ruby translation primitives - -use ruru::{Object, AnyObject, RString, Fixnum, Float, Boolean, Hash, Array}; -use toml::Value; - -pub trait AsRuby : Sized { - fn as_ruby(&self) -> AnyObject; -} - -pub trait IntoRuby : AsRuby { - fn into_ruby(self) -> AnyObject { - self.as_ruby() - } -} -impl IntoRuby for T { } - -impl AsRuby for Value { - - fn as_ruby(&self) -> AnyObject { - match *self { - Value::String(ref s) => RString::new(&s).to_any_object(), - Value::Integer(i) => Fixnum::new(i).to_any_object(), - Value::Float(f) => Float::new(f).to_any_object(), - Value::Boolean(b) => Boolean::new(b).to_any_object(), - Value::Datetime(ref s) => RString::new(&s).to_any_object(), - Value::Array(ref a) => { - let mut arr = Array::new(); - for obj in a.into_iter().map(AsRuby::as_ruby) { - arr.push(obj); - } - arr.to_any_object() - }, - Value::Table(ref t) => { - let mut h = Hash::new(); - for (k, v) in t.into_iter() { - let key = RString::new(k).to_any_object(); - let v = v.as_ruby(); - h.store(key, v); - } - h.to_any_object() - }, - } - } - -} - diff --git a/libimagruby/src/util.rs b/libimagruby/src/util.rs deleted file mode 100644 index 85813f29..00000000 --- a/libimagruby/src/util.rs +++ /dev/null @@ -1,102 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015, 2016 Matthias Beyer and contributors -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; version -// 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// - -use ruru::AnyObject; -pub trait Wrap { - fn wrap(self) -> AnyObject; -} - -#[macro_export] -macro_rules! impl_wrap { - ($target:ty => $wrapper:path) => { - impl Wrap for $target { - fn wrap(self) -> AnyObject { - Class::from_existing(concat!("R", stringify!($target))) - .wrap_data(self, &*($wrapper)) - } - } - } -} - -pub trait Unwrap { - type Target; - fn unwrap<'a>(&'a self) -> &'a mut Self::Target; -} - -#[macro_export] -macro_rules! impl_unwrap { - ($from:ty => $to:ty => $wrapper:path) => { - impl Unwrap for $from { - type Target = $to; - fn unwrap<'a>(&'a self) -> &'a mut $to { - self.get_data(&*($wrapper)) - } - } - } -} - -#[macro_export] -macro_rules! impl_verified_object { - ($objname: ty) => { - impl VerifiedObject for $objname { - fn is_correct_type(object: &T) -> bool { - object.class() == Class::from_existing(stringify!($objname)) - } - - fn error_message() -> &'static str { - concat!("Not a ", stringify!($objname), " object") - } - } - }; -} - -/// Helper macro to simplify type checking in the ruby-interfacing functions. -/// -/// # Return -/// -/// If called with only the object to check, this returns NIL after raising an exception. -/// If called with more arguments, the other things will be returned. -/// E.G.: -/// -/// ```ignore -/// let obj1 = typecheck!(obj1); // returns `obj` or raises exception -/// -/// // returns `obj` or raises exception and returns AnyObject (Boolean -> false): -/// let obj2 = typecheck!(obj2 or return any Boolean::new(false)); -/// -/// // returns `obj` or raises excpetion and returns Boolean -> false -/// let obj3 = typecheck!(obj3 or return Boolean::new(false)); -/// ``` -/// -#[macro_export] -macro_rules! typecheck { - ($obj: ident) => { typecheck!($obj or return NilClass::new()) }; - ($obj: ident or return any $els: expr) => { typecheck!($obj or return $els.to_any_object()) }; - ($obj: ident or return $els: expr) => { - match $obj { - Ok(o) => o, - Err(e) => { - VM::raise(e.to_exception(), e.description()); - return $els - }, - } - }; - -} -