# hx/backend/hobix - Hobix filesystem backend for Hx # # Copyright (c) 2009-2010 MenTaLguY # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. require 'rubygems' require 'time' require 'pathname' require 'yaml' require 'hx' module Hx module Backend class Hobix include Hx::Source def initialize(source, options) @entry_dir = Hx.get_pathname(options, :entry_dir) end def yaml_repr(value) YAML.parse(YAML.dump(value)) end private :yaml_repr def edit_entry(path, prototype=nil) entry_filename = @entry_dir + "#{path}.yaml" begin text = entry_filename.read previous_mtime = entry_filename.mtime rescue Errno::ENOENT raise Hx::NoSuchEntryError, path unless prototype prototype = prototype.dup prototype['content'] = (prototype['content'] || "").dup content = prototype['content'] def content.to_yaml_style ; :literal ; end native = YAML::DomainType.new('hobix.com,2004', 'entry', prototype) text = YAML.dump(native) previous_mtime = nil end text = yield text repr = YAML.parse(text) keys = {} repr.value.each_key { |key| keys[key.value] = key } %w(created updated).each { |name| keys[name] ||= yaml_repr(name) } update_time = Time.now update_time_repr = yaml_repr(update_time) previous_mtime ||= update_time previous_mtime_repr = yaml_repr(previous_mtime) repr.add(keys['created'], previous_mtime_repr) unless repr['created'] repr.add(keys['updated'], update_time_repr) entry_filename.parent.mkpath() entry_filename.open('w') { |stream| stream << repr.emit } self end def each_entry Pathname.glob(@entry_dir + '**/*.yaml') do |entry_filename| path = entry_filename.relative_path_from(@entry_dir).to_s path.sub!(/\.yaml$/, '') entry = entry_filename.open('r') do |stream| YAML.load(stream).value end entry['updated'] ||= entry_filename.mtime entry['created'] ||= entry['updated'] yield path, entry end self end end end end