readorder 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,58 @@
1
+ require 'logging'
2
+ require 'readorder'
3
+
4
+ module Readorder
5
+ ::Logging::Logger[self].level = :info
6
+
7
+ def self.logger
8
+ ::Logging::Logger[self]
9
+ end
10
+
11
+ module Log
12
+ def self.init( options = {} )
13
+ appender = Logging.appenders.stderr
14
+ appender.layout = self.console_layout
15
+ if options['log-file'] then
16
+ appender = ::Logging::Appenders::File.new(
17
+ 'readorder',
18
+ :filename => options['log-file'],
19
+ :layout => self.layout
20
+ )
21
+ end
22
+
23
+ Readorder.logger.add_appenders( appender )
24
+ self.level = options['log-level'] || :info
25
+ end
26
+
27
+ def self.console
28
+ Logging.appenders.stderr.level
29
+ end
30
+
31
+ def self.console=( level )
32
+ Logging.appenders.stderr.level = level
33
+ end
34
+
35
+ def self.level
36
+ ::Logging::Logger[Readorder].level
37
+ end
38
+
39
+ def self.level=( l )
40
+ ::Logging::Logger[Readorder].level = l
41
+ end
42
+
43
+ def self.layout
44
+ @layout ||= Logging::Layouts::Pattern.new(
45
+ :pattern => "[%d] %5l %6p %c : %m\n",
46
+ :date_pattern => "%Y-%m-%d %H:%M:%S"
47
+ )
48
+ end
49
+
50
+ def self.console_layout
51
+ @console_layout ||= Logging::Layouts::Pattern.new(
52
+ :pattern => "%d %5l : %m\n",
53
+ :date_pattern => "%H:%M:%S"
54
+ )
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,69 @@
1
+ module Readorder
2
+ module Paths
3
+ # The root directory of the project is considered to be the parent directory
4
+ # of the 'lib' directory.
5
+ #
6
+ def root_dir
7
+ @root_dir ||= (
8
+ path_parts = ::File.expand_path(__FILE__).split(::File::SEPARATOR)
9
+ lib_index = path_parts.rindex("lib")
10
+ path_parts[0...lib_index].join(::File::SEPARATOR) + ::File::SEPARATOR
11
+ )
12
+ end
13
+
14
+ def root_path( sub, *args )
15
+ sub_path( root_dir, sub, *args )
16
+ end
17
+
18
+ def bin_path( *args )
19
+ root_path( 'bin', *args )
20
+ end
21
+
22
+ def lib_path( *args )
23
+ root_path( "lib", *args )
24
+ end
25
+
26
+ def spec_path( *args )
27
+ root_path( "spec", *args )
28
+ end
29
+
30
+ # The home dir is the home directory of the project while it is running
31
+ # by default, this the same as the root_dir. But if this value is set
32
+ # then it affects other paths
33
+ def home_dir
34
+ @home_dir ||= root_dir
35
+ end
36
+
37
+ def home_dir=( other )
38
+ @home_dir = File.expand_path( other )
39
+ end
40
+
41
+ def home_path( sub, *args )
42
+ sub_path( home_dir, sub, *args )
43
+ end
44
+
45
+ def config_path( *args )
46
+ home_path( "config", *args )
47
+ end
48
+
49
+ def data_path( *args )
50
+ home_path( "data", *args )
51
+ end
52
+
53
+ def log_path( *args )
54
+ home_path( "log", *args )
55
+ end
56
+
57
+ def tmp_path( *args )
58
+ home_path( "tmp", *args )
59
+ end
60
+
61
+ def sub_path( parent, sub, *args )
62
+ sp = ::File.join( parent, sub ) + File::SEPARATOR
63
+ sp = ::File.join( sp, *args ) if args
64
+ end
65
+
66
+ extend self
67
+ end
68
+ extend Paths
69
+ end
@@ -0,0 +1,48 @@
1
+ require 'readorder/log'
2
+ require 'readorder/command'
3
+
4
+ module Readorder
5
+ class Runner
6
+ attr_reader :options
7
+
8
+ def initialize( opts = {} )
9
+ @options = opts.dup
10
+ initialize_logging
11
+ end
12
+
13
+ def logger
14
+ @logger ||= ::Logging::Logger[self]
15
+ end
16
+
17
+ def setup_signal_handling( cmd )
18
+ %w[ INT QUIT TERM ].each do |s|
19
+ Signal.trap( s ) do
20
+ logger.info "received signal #{s} -- shutting down"
21
+ cmd.shutdown
22
+ exit 1
23
+ end
24
+ end
25
+ end
26
+
27
+ def initialize_logging
28
+ Readorder::Log.init( options )
29
+ end
30
+
31
+ def run( command_name )
32
+ cmd = Command.find( command_name ).new( @options )
33
+ begin
34
+ setup_signal_handling( cmd )
35
+ cmd.before
36
+ cmd.run
37
+ rescue => e
38
+ logger.error "while running #{command_name} : #{e.message}"
39
+ e.backtrace.each do |l|
40
+ logger.debug l
41
+ end
42
+ cmd.error
43
+ ensure
44
+ cmd.after
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,30 @@
1
+ #--
2
+ # Copyright (c) 2009 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details
4
+ #++
5
+
6
+ module Readorder
7
+ module Version
8
+ MAJOR = 1
9
+ MINOR = 0
10
+ BUILD = 0
11
+
12
+ def to_a
13
+ [MAJOR, MINOR, BUILD]
14
+ end
15
+
16
+ def to_s
17
+ to_a.join(".")
18
+ end
19
+
20
+ def to_hash
21
+ { :major => MAJOR, :minor => MINOR, :build => BUILD }
22
+ end
23
+
24
+ STRING = Version.to_s
25
+ extend self
26
+
27
+ end
28
+ VERSION = Version.to_s
29
+ extend Version
30
+ end
data/lib/readorder.rb ADDED
@@ -0,0 +1,24 @@
1
+ #--
2
+ # Copyright (c) 2009 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+
6
+ #
7
+ # Take a look in the README and the Analyzer and Datum classes. That is where
8
+ # all the real work is done.
9
+ #
10
+ module Readorder
11
+ #
12
+ # root Error class for Readorder
13
+ #
14
+ class Error < StandardError; end
15
+ end
16
+
17
+ require 'rubygems'
18
+ require 'logging'
19
+ require 'readorder/version'
20
+ require 'readorder/paths'
21
+ require 'readorder/cli'
22
+ require 'readorder/filelist'
23
+ require 'readorder/datum'
24
+ require 'readorder/analyzer'
@@ -0,0 +1,51 @@
1
+ require File.expand_path( File.join( File.dirname( __FILE__ ),"spec_helper.rb"))
2
+
3
+ require 'readorder/analyzer'
4
+
5
+ describe Readorder::Analyzer do
6
+ before( :each ) do
7
+ s = StringIO.new
8
+ fl = Dir.glob("#{Readorder::Paths.spec_path}/*_spec.rb")
9
+ s.puts fl.to_a.join("\n")
10
+ s.rewind
11
+ @filelist = Readorder::Filelist.new( s )
12
+ @analyzer = Readorder::Analyzer.new( @filelist, false )
13
+ end
14
+
15
+ it "collects data about files" do
16
+ @analyzer.collect_data
17
+ @analyzer.good_data.size.should > 0
18
+ @analyzer.inode_order.size.should > 0
19
+ @analyzer.physical_order.size.should == 0
20
+ end
21
+
22
+ it "logs a summary report" do
23
+ @analyzer.collect_data
24
+ @analyzer.log_summary_report
25
+ spec_log.should =~ /Collection Rate/
26
+ end
27
+
28
+ it "can have bad data and dump it to a file" do
29
+ s = StringIO.new
30
+ s.puts "/a/nonexistent/file"
31
+ s.rewind
32
+ analyzer = Readorder::Analyzer.new( Readorder::Filelist.new( s ) )
33
+ analyzer.collect_data
34
+ analyzer.bad_data.size.should > 0
35
+
36
+ s2 = StringIO.new
37
+ analyzer.dump_bad_data_to( s2 )
38
+ s2.rewind
39
+ s2.gets.should == "error_reason,filename\n"
40
+ s2.gets.should == "No such file or directory - /a/nonexistent/file,/a/nonexistent/file\n"
41
+ end
42
+
43
+ it "can dump good data to a csv" do
44
+ @analyzer.collect_data
45
+ s = StringIO.new
46
+ @analyzer.dump_good_data_to( s )
47
+ s.rewind
48
+ s.gets.should == "filename,size,inode_number\n"
49
+ s.read.split("\n").size.should == @analyzer.good_data.size
50
+ end
51
+ end
@@ -0,0 +1,37 @@
1
+ require File.expand_path( File.join( File.dirname( __FILE__ ),"spec_helper.rb"))
2
+
3
+ require 'readorder/command'
4
+
5
+ class Readorder::Junk < Readorder::Command; end
6
+
7
+ describe Readorder::Command do
8
+ before( :each ) do
9
+ @cmd = Readorder::Command.new
10
+ end
11
+
12
+ it "has a command name" do
13
+ @cmd.command_name.should == "command"
14
+ end
15
+
16
+ it "can log" do
17
+ @cmd.logger.info "this is a log statement"
18
+ spec_log.should =~ /this is a log statement/
19
+ end
20
+
21
+ it "cannot be run" do
22
+ lambda { @cmd.run }.should raise_error( Readorder::Command::Error, /Unknown command `command`/ )
23
+ end
24
+
25
+ it "registers inherited classes" do
26
+ Readorder::Command.commands.should be_include( Readorder::Junk )
27
+ Readorder::Command.commands.delete( Readorder::Junk )
28
+ Readorder::Command.commands.should_not be_include(Readorder::Junk)
29
+ end
30
+
31
+ it "classes cannot be run without implementing 'run'" do
32
+ j = Readorder::Junk.new
33
+ j.respond_to?(:run).should == true
34
+ lambda { j.run }.should raise_error( Readorder::Command::Error, /Unknown command `junk`/)
35
+ end
36
+
37
+ end
@@ -0,0 +1,53 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),"spec_helper.rb"))
2
+
3
+ require 'stringio'
4
+ require 'readorder/filelist'
5
+
6
+ describe ::Readorder::Filelist do
7
+ it "can read from an object that responds to gets" do
8
+ s = StringIO.new
9
+ files = %w[ /tmp/here /tmp/there ]
10
+ files.each { |f| s.puts f }
11
+ s.rewind
12
+
13
+ fl = ::Readorder::Filelist.new( s )
14
+ fl.gets.should == "/tmp/here\n"
15
+ fl.gets.should == "/tmp/there\n"
16
+ end
17
+
18
+ it "raises an error if given a filename and it cannot open or read from the file" do
19
+ lambda { ::Readorder::Filelist.new( "/does/not/exist" ) }.should raise_error( Readorder::Filelist::Error, /does not exist/ )
20
+ end
21
+
22
+ it "raises an error if given something that is not a string that does not respond to gets" do
23
+ x = Object.new
24
+ def x.close
25
+ true
26
+ end
27
+ lambda { ::Readorder::Filelist.new( x ) }.should raise_error( Readorder::Filelist::Error, /does not respond to 'gets'/ )
28
+ end
29
+
30
+ it "raises an error if given something that is not a string that does not respond to close" do
31
+ x = Object.new
32
+ def x.gets
33
+ true
34
+ end
35
+ lambda { ::Readorder::Filelist.new( x ) }.should raise_error( Readorder::Filelist::Error, /does not respond to 'close'/ )
36
+ end
37
+
38
+ it "can be iterated over with each_line" do
39
+ s = StringIO.new
40
+ files = [ "/tmp/here\n", "/tmp/there\n" ]
41
+
42
+ files.each { |f| s.print f }
43
+ s.rewind
44
+
45
+ fl = ::Readorder::Filelist.new( s )
46
+ out = []
47
+ fl.each_line do |l|
48
+ out << l
49
+ end
50
+ out.size.should == 2
51
+ out.should == files
52
+ end
53
+ end
data/spec/log_spec.rb ADDED
@@ -0,0 +1,13 @@
1
+ require File.expand_path( File.join( File.dirname( __FILE__ ),"spec_helper.rb"))
2
+
3
+ require 'readorder/log'
4
+
5
+ describe Readorder::Log do
6
+ it "creates its own layout" do
7
+ Readorder::Log.layout.should be_instance_of(Logging::Layouts::Pattern)
8
+ end
9
+
10
+ it "can retrieves its level" do
11
+ Readorder::Log.level.should == 0
12
+ end
13
+ end
@@ -0,0 +1,45 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),"spec_helper.rb"))
2
+
3
+ describe Readorder::Paths do
4
+ before(:each) do
5
+ @root_dir = File.expand_path(File.join(File.dirname(__FILE__), ".."))
6
+ @root_dir += "/"
7
+ end
8
+
9
+ it "root dir should be correct" do
10
+ Readorder.root_dir.should == @root_dir
11
+ end
12
+
13
+ it "home dir should be correct" do
14
+ Readorder.home_dir.should == @root_dir
15
+ end
16
+
17
+ %w[ bin lib spec config data log tmp ].each do |d|
18
+ it "#{d} path should be correct" do
19
+ Readorder.send( "#{d}_path" ).should == File.join(@root_dir, "#{d}/" )
20
+ end
21
+ end
22
+
23
+ describe "setting home_dir" do
24
+ before( :each ) do
25
+ @tmp_dir = "/some/location/#{Process.pid}"
26
+ Readorder.home_dir = @tmp_dir
27
+ end
28
+
29
+ %w[ config data log tmp ].each do |d|
30
+ check_path = "#{d}_path"
31
+ it "affects the location of #{check_path}" do
32
+ p = Readorder.send( check_path )
33
+ p.should == ( File.join( @tmp_dir, d ) + File::SEPARATOR )
34
+ end
35
+ end
36
+
37
+ %w[ bin lib spec ].each do |d|
38
+ check_path = "#{d}_path"
39
+ it "does not affect the location of #{check_path}" do
40
+ p = Readorder.send( check_path )
41
+ p.should == ( File.join( @root_dir, d ) + File::SEPARATOR )
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,46 @@
1
+ require File.expand_path( File.join( File.dirname( __FILE__ ),"spec_helper.rb"))
2
+
3
+ require 'readorder/runner'
4
+
5
+ class Readorder::Junk4Runner < Readorder::Command
6
+ def self.command_name
7
+ 'junk4runner'
8
+ end
9
+
10
+ def run
11
+ logger.info "doing junk, as instructed #{options['foo']}"
12
+ if options['boom'] then
13
+ raise options['boom']
14
+ end
15
+ end
16
+ end
17
+
18
+ describe Readorder::Runner do
19
+ before(:each) do
20
+ @old_level = ::Readorder::Log.console
21
+ ::Readorder::Log.console = :off
22
+ end
23
+
24
+ after(:each) do
25
+ ::Readorder::Log.console = @old_level
26
+ end
27
+
28
+ it "can log" do
29
+ r = Readorder::Runner.new
30
+ r.logger.info "log statement from Runner"
31
+ spec_log.should =~ /log statement from Runner/
32
+ end
33
+
34
+ it "runs a command" do
35
+ r = Readorder::Runner.new( "foo" => "bar" )
36
+ r.run( 'junk4runner' )
37
+ spec_log.should =~ /doing junk, as instructed bar/
38
+ end
39
+
40
+ it "logs an exception raised by a Command" do
41
+ r = Readorder::Runner.new( 'boom' => 'a big kaboom!' )
42
+ r.run( 'junk4runner' )
43
+ spec_log.should =~ /doing junk, as instructed/
44
+ spec_log.should =~ /a big kaboom!/
45
+ end
46
+ end
@@ -0,0 +1,57 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ $: << File.expand_path(File.join(File.dirname(__FILE__),"..","lib"))
5
+ require 'readorder'
6
+
7
+ Logging::Logger['Readorder'].level = :all
8
+ module Spec
9
+ module Log
10
+ def self.io
11
+ @io ||= StringIO.new
12
+ end
13
+ def self.appender
14
+ @appender ||= Logging::Appenders::IO.new( "speclog", io )
15
+ end
16
+
17
+ Logging::Logger['Readorder'].add_appenders( Log.appender )
18
+
19
+ def self.layout
20
+ @layout ||= Logging::Layouts::Pattern.new(
21
+ :pattern => "[%d] %5l %6p %c : %m\n",
22
+ :date_pattern => "%Y-%m-%d %H:%M:%S"
23
+ )
24
+ end
25
+
26
+ Log.appender.layout = layout
27
+
28
+ end
29
+
30
+ module Helpers
31
+ require 'tmpdir'
32
+ def make_temp_dir( unique_id = $$ )
33
+ dirname = File.join( Dir.tmpdir, "snipe-#{unique_id}" )
34
+ FileUtils.mkdir_p( dirname ) unless File.directory?( dirname )
35
+ return dirname
36
+ end
37
+
38
+ # the logging output from the test, if that class has any logging
39
+ def spec_log
40
+ Log.io.string
41
+ end
42
+ end
43
+ end
44
+
45
+ Spec::Runner.configure do |config|
46
+ config.include Spec::Helpers
47
+
48
+ config.before do
49
+ Spec::Log.io.rewind
50
+ Spec::Log.io.truncate( 0 )
51
+ end
52
+
53
+ config.after do
54
+ Spec::Log.io.rewind
55
+ Spec::Log.io.truncate( 0 )
56
+ end
57
+ end
@@ -0,0 +1,16 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),"spec_helper.rb"))
2
+
3
+ describe "Readorder::Version" do
4
+
5
+ it "should have a version string" do
6
+ Readorder::Version.to_s.should =~ /\d+\.\d+\.\d+/
7
+ Readorder::VERSION.should =~ /\d+\.\d+\.\d+/
8
+ end
9
+
10
+ it "should have a version hash" do
11
+ h = Readorder::Version.to_hash
12
+ [ :major, :minor, :build ].each do |k|
13
+ h[k].should_not be_nil
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,39 @@
1
+ require 'tasks/config'
2
+ #-------------------------------------------------------------------------------
3
+ # announcement methods
4
+ #-------------------------------------------------------------------------------
5
+
6
+ proj_config = Configuration.for('project')
7
+ namespace :announce do
8
+ desc "create email for ruby-talk"
9
+ task :email do
10
+ info = Utils.announcement
11
+
12
+ File.open("email.txt", "w") do |mail|
13
+ mail.puts "From: #{proj_config.author} <#{proj_config.email}>"
14
+ mail.puts "To: ruby-talk@ruby-lang.org"
15
+ mail.puts "Date: #{Time.now.rfc2822}"
16
+ mail.puts "Subject: [ANN] #{info[:subject]}"
17
+ mail.puts
18
+ mail.puts info[:title]
19
+ mail.puts
20
+ mail.puts " gem install #{Readorder::GEM_SPEC.name}"
21
+ mail.puts
22
+ mail.puts info[:urls]
23
+ mail.puts
24
+ mail.puts info[:description]
25
+ mail.puts
26
+ mail.puts "{{ Release notes for Version #{Readorder::VERSION} }}"
27
+ mail.puts
28
+ mail.puts info[:release_notes]
29
+ mail.puts
30
+ end
31
+ puts "Created the following as email.txt:"
32
+ puts "-" * 72
33
+ puts File.read("email.txt")
34
+ puts "-" * 72
35
+ end
36
+
37
+ CLOBBER << "email.txt"
38
+ end
39
+