oct 0.2.0 → 0.3.1

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.
@@ -1,5 +1,8 @@
1
- $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
- require 'rubygems'
3
1
  require 'oct'
4
- require 'aruba'
5
- require 'spec/expectations'
2
+ require 'aruba/cucumber'
3
+ require 'rspec/expectations'
4
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec/aruba_helper')
5
+
6
+ Before do
7
+ @aruba_timeout_seconds = 10
8
+ end
data/lib/oct/app.rb CHANGED
@@ -1,4 +1,3 @@
1
- require 'configatron'
2
1
  require 'term/ansicolor'
3
2
 
4
3
  class String
@@ -11,21 +10,26 @@ module Oct
11
10
 
12
11
  class App
13
12
 
14
- def initialize(base_dir, options={})
15
- @base_dir = base_dir
13
+ def initialize(working_dir, argv=[], options={})
14
+ @working_dir = working_dir
16
15
  @options = options
16
+ @argv = argv
17
17
  if @options[:verbose]
18
- puts "base_dir: #{@base_dir}".cyan
18
+ puts "working_dir: #{@working_dir}".cyan
19
19
  puts "options: #{@options.inspect}".cyan
20
+ puts "base_dir: #{@options[:base_dir]}".cyan if @options[:base_dir]
21
+ puts "config file: #{@options[:config]}".cyan if @options[:config]
20
22
  end
21
- configure(options)
23
+ $stdout.sync = true
22
24
  end
23
25
 
24
- def run
26
+ def execute
25
27
  begin
26
28
 
27
29
  if action_argument_required?
28
- action = ARGV.shift
30
+ action = @argv.shift
31
+ args = @argv
32
+
29
33
  unless AVAILABLE_ACTIONS.include?(action)
30
34
  if action.nil?
31
35
  puts "oct action required"
@@ -35,9 +39,9 @@ module Oct
35
39
  puts "oct --help for more information"
36
40
  exit 1
37
41
  end
38
- puts "oct run action: #{action}".cyan if @options[:verbose]
42
+ puts "oct run action: #{action} #{args.join(' ')}".cyan if @options[:verbose]
39
43
  raise "action #{action} not implemented" unless respond_to?(action)
40
- result = send(action)
44
+ result = send(action, args)
41
45
  else
42
46
  #
43
47
  # default action if action_argument_required? is false
@@ -46,7 +50,12 @@ module Oct
46
50
  result = Oct::FileStat.new.mode(files, @options)
47
51
  end
48
52
 
49
- exit(result ? 0 : 1)
53
+ if result.is_a?(Numeric)
54
+ exit(result)
55
+ else
56
+ # handle all other return types
57
+ exit(result ? 0 : 1)
58
+ end
50
59
 
51
60
  rescue SystemExit => e
52
61
  # This is the normal exit point, exit code from the send result
@@ -56,6 +65,7 @@ module Oct
56
65
  rescue Exception => e
57
66
  STDERR.puts("oct command failed, error(s) follow:")
58
67
  STDERR.puts("#{e.message}".red)
68
+ STDERR.puts("Use '--verbose' for backtrace.") unless @options[:verbose]
59
69
  STDERR.puts(e.backtrace.join("\n")) if @options[:verbose]
60
70
  exit(1)
61
71
  end
@@ -65,7 +75,7 @@ module Oct
65
75
  # app commands start
66
76
  #
67
77
 
68
-
78
+
69
79
  #
70
80
  # app commands end
71
81
  #
@@ -77,26 +87,5 @@ module Oct
77
87
  !AVAILABLE_ACTIONS.empty?
78
88
  end
79
89
 
80
- # read options for YAML config with ERB processing and initialize configatron
81
- def configure(options)
82
- config = @options[:config]
83
- config = File.join(@base_dir, 'oct.conf') unless config
84
- if File.exists?(config)
85
- # load configatron options from the config file
86
- puts "loading config file: #{config}".cyan if @options[:verbose]
87
- configatron.configure_from_yaml(config)
88
- else
89
- # user specified a config file?
90
- raise "config file not found" if @options[:config]
91
- # no error if user did not specify config file
92
- puts "#{config} not found".yellow if @options[:verbose]
93
- end
94
-
95
- #
96
- # set defaults, these will NOT override setting read from YAML
97
- #
98
-
99
- end
100
-
101
90
  end
102
91
  end
@@ -0,0 +1,11 @@
1
+ class Array
2
+ def recursively_symbolize_keys!
3
+ self.each do |item|
4
+ if item.is_a? Hash
5
+ item.recursively_symbolize_keys!
6
+ elsif item.is_a? Array
7
+ item.recursively_symbolize_keys!
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,45 @@
1
+ class Hash
2
+
3
+ # sorted yaml
4
+ def to_yaml( opts = {} )
5
+ YAML::quick_emit( object_id, opts ) do |out|
6
+ out.map( taguri, to_yaml_style ) do |map|
7
+ sorted_keys = keys
8
+ sorted_keys = begin
9
+ sorted_keys.sort
10
+ rescue
11
+ sorted_keys.sort_by {|k| k.to_s} rescue sorted_keys
12
+ end
13
+
14
+ sorted_keys.each do |k|
15
+ map.add( k, fetch(k) )
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ # active_support hash key functions
22
+ def symbolize_keys!
23
+ self.replace(self.symbolize_keys)
24
+ end
25
+
26
+ def symbolize_keys
27
+ inject({}) do |options, (key, value)|
28
+ options[(key.to_sym rescue key) || key] = value
29
+ options
30
+ end
31
+ end
32
+
33
+ def recursively_symbolize_keys!
34
+ self.symbolize_keys!
35
+ self.values.each do |v|
36
+ if v.is_a? Hash
37
+ v.recursively_symbolize_keys!
38
+ elsif v.is_a? Array
39
+ v.recursively_symbolize_keys!
40
+ end
41
+ end
42
+ self
43
+ end
44
+
45
+ end
data/lib/oct/oct.rb CHANGED
@@ -9,7 +9,7 @@ module Oct
9
9
  puts "oct mode files: #{files.inspect}".cyan if options[:verbose]
10
10
  files.sort.each do |file|
11
11
  stat = File.stat(file)
12
- printf("%04o ", stat.mode & 07777)
12
+ printf("%04o ", stat.mode & 07777)
13
13
  if stat.directory?
14
14
  puts file.blue
15
15
  elsif stat.executable?
@@ -19,7 +19,7 @@ module Oct
19
19
  else
20
20
  puts file
21
21
  end
22
- end
22
+ end
23
23
  end
24
24
 
25
25
  end
@@ -0,0 +1,60 @@
1
+ require 'yaml'
2
+
3
+ module Oct
4
+
5
+ class Settings
6
+
7
+ def initialize(working_dir, options={})
8
+ @working_dir = working_dir
9
+ @options = options
10
+ configure
11
+ end
12
+
13
+ def options
14
+ @options
15
+ end
16
+
17
+ private
18
+
19
+ # read options from YAML config
20
+ def configure
21
+
22
+ # config file default options
23
+ configuration = {
24
+ :options => {
25
+ :verbose => false,
26
+ :color => 'AUTO'
27
+ }
28
+ }
29
+
30
+ # set default config if not given on command line
31
+ config = @options[:config]
32
+ unless config
33
+ config = [
34
+ File.join(@working_dir, "oct.conf"),
35
+ File.join(@working_dir, ".oct.conf"),
36
+ File.join(@working_dir, "config", "oct.conf"),
37
+ File.expand_path(File.join("~", ".oct.conf"))
38
+ ].detect { |filename| File.exists?(filename) }
39
+ end
40
+
41
+ if config && File.exists?(config)
42
+ # rewrite options full path for config for later use
43
+ @options[:config] = config
44
+
45
+ # load options from the config file, overwriting hard-coded defaults
46
+ config_contents = YAML::load(File.open(config))
47
+ configuration.merge!(config_contents.symbolize_keys!) if config_contents && config_contents.is_a?(Hash)
48
+ else
49
+ # user specified a config file?, no error if user did not specify config file
50
+ raise "config file not found" if @options[:config]
51
+ end
52
+
53
+ # the command line options override options read from the config file
54
+ @options = configuration[:options].symbolize_keys!.merge!(@options)
55
+
56
+ end
57
+
58
+ end
59
+
60
+ end
data/lib/oct.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  # require all files here
2
2
  require 'rbconfig'
3
+ require 'oct/core/hash'
4
+ require 'oct/core/array'
3
5
  require 'oct/app'
6
+ require 'oct/settings'
4
7
  require 'oct/oct'
5
8
 
6
9
  # Master namespace
@@ -20,8 +23,8 @@ module Oct
20
23
 
21
24
  # Platform constants
22
25
  unless defined?(BasicGem::WINDOWS)
23
- WINDOWS = Config::CONFIG['host_os'] =~ /mswin|mingw/i
24
- CYGWIN = Config::CONFIG['host_os'] =~ /cygwin/i
26
+ WINDOWS = RbConfig::CONFIG['host_os'] =~ /mswin|mingw/i
27
+ CYGWIN = RbConfig::CONFIG['host_os'] =~ /cygwin/i
25
28
  end
26
29
 
27
30
  end
data/oct.gemspec CHANGED
@@ -1,30 +1,25 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  #
3
3
  #
4
-
5
4
  Gem::Specification.new do |s|
6
- # wrap 'git' so we can get gem files even on systems without 'git'
5
+
6
+ # avoid shelling out to run git every time the gemspec is evaluated
7
7
  #
8
8
  # @see spec/gemspec_spec.rb
9
9
  #
10
- @gemfiles ||= begin
11
- filename = File.join(File.dirname(__FILE__), '.gemfiles')
12
- # backticks blows up on Windows w/o valid binary, use system instead
13
- if File.directory?('.git') && system('git ls-files bogus-filename')
14
- files = `git ls-files`
15
- cached_files = File.exists?(filename) ? File.open(filename, "r") {|f| f.read} : nil
16
- # maintain EOL
17
- files.gsub!(/\n/, "\r\n") if cached_files && cached_files.match("\r\n")
18
- File.open(filename, 'wb') {|f| f.write(files)} if cached_files != files
19
- else
20
- files = File.open(filename, "r") {|f| f.read}
21
- end
22
- raise "unable to process gemfiles" unless files
23
- files.gsub(/\r\n/, "\n")
10
+ gemfiles_cache = File.join(File.dirname(__FILE__), '.gemfiles')
11
+ if File.exists?(gemfiles_cache)
12
+ gemfiles = File.open(gemfiles_cache, "r") {|f| f.read}
13
+ # normalize EOL
14
+ gemfiles.gsub!(/\r\n/, "\n")
15
+ else
16
+ # .gemfiles missing, run 'rake gemfiles' to create it
17
+ # falling back to 'git ls-files'"
18
+ gemfiles = `git ls-files`
24
19
  end
25
20
 
26
21
  s.name = "oct"
27
- s.version = File.open(File.join(File.dirname(__FILE__), 'VERSION'), "r") { |f| f.read }
22
+ s.version = File.open(File.join(File.dirname(__FILE__), 'VERSION'), "r") { |f| f.read }
28
23
  s.platform = Gem::Platform::RUBY
29
24
  s.authors = ["Robert Wahler"]
30
25
  s.email = ["robert@gearheadforhire.com"]
@@ -36,31 +31,25 @@ Gem::Specification.new do |s|
36
31
  s.rubyforge_project = "oct"
37
32
 
38
33
  s.add_dependency 'term-ansicolor', '>= 1.0.4'
39
- s.add_dependency 'configatron', '>= 2.5.1'
40
34
 
41
- s.add_development_dependency "bundler", ">= 1.0.7"
42
- s.add_development_dependency "rspec", "= 1.3.1"
43
- s.add_development_dependency "cucumber", ">= 0.9.4"
44
- s.add_development_dependency "aruba", ">= 0.2.2"
35
+ s.add_development_dependency "bundler", ">= 1.0.14"
36
+ s.add_development_dependency "rspec", ">= 2.6.0"
37
+ s.add_development_dependency "cucumber", "~> 1.0"
38
+ s.add_development_dependency "aruba", "~> 0.4.3"
45
39
  s.add_development_dependency "rake", ">= 0.8.7"
46
- s.add_development_dependency "yard", ">= 0.6.2"
47
-
48
- # Specify a markdown gem for rake doc:generate
49
- #
50
- # Without the development dependency, running yard rake
51
- # tasks will fail. Kramdown chosen to provide a pure Ruby solution.
52
- s.add_development_dependency "kramdown", ">= 0.12.0"
53
40
 
54
- s.files = @gemfiles.split("\n")
55
- s.executables = @gemfiles.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
41
+ # doc generation
42
+ s.add_development_dependency "yard", ">= 0.7.2"
43
+ s.add_development_dependency "redcarpet", ">= 1.17.2"
56
44
 
57
- s.require_path = 'lib'
45
+ s.files = gemfiles.split("\n")
46
+ s.executables = gemfiles.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
47
+ s.require_paths = ["lib"]
58
48
 
59
- s.has_rdoc = 'yard'
60
- s.rdoc_options = [
61
- '--title', 'Oct Documentation',
62
- '--main', 'README.markdown',
49
+ s.rdoc_options = [
50
+ '--title', 'Oct Documentation',
51
+ '--main', 'README.markdown',
63
52
  '--line-numbers',
64
- '--inline-source'
53
+ '--inline-source'
65
54
  ]
66
55
  end
@@ -0,0 +1,25 @@
1
+ module Aruba
2
+ module Api
3
+
4
+ # @return full path to files in the aruba tmp folder
5
+ def fullpath(filename)
6
+ path = File.expand_path(File.join(current_dir, filename))
7
+ if path.match(/^\/cygdrive/)
8
+ # match /cygdrive/c/path/to and return c:\\path\\to
9
+ path = `cygpath -w #{path}`.chomp
10
+ elsif path.match(/.\:/)
11
+ # match c:/path/to and return c:\\path\\to
12
+ path = path.gsub(/\//, '\\')
13
+ end
14
+ path
15
+ end
16
+
17
+ # @return the contents of "filename" in the aruba tmp folder
18
+ def get_file_contents(filename)
19
+ in_current_dir do
20
+ IO.read(filename)
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe Array do
4
+
5
+ describe 'recursively_symbolize_keys!' do
6
+
7
+ it "should recursively convert a hash with string keys to a hash with symbol keys" do
8
+ hash_symbols = {
9
+ :options => {
10
+ :verbose => false,
11
+ },
12
+ :repos => {
13
+ :repo1 => {:path => "something"}
14
+ }
15
+ }
16
+
17
+ hash_strings = {
18
+ 'options' => {
19
+ 'verbose' => false,
20
+ },
21
+ 'repos' => {
22
+ 'repo1' => {'path' => "something"}
23
+ }
24
+ }
25
+
26
+ hash_symbols.should == hash_strings.recursively_symbolize_keys!
27
+ end
28
+
29
+ it "should should handle hashes that are already symbolized" do
30
+ hash_symbols = {
31
+ :options => {
32
+ :verbose => false,
33
+ },
34
+ :repos => {
35
+ :repo1 => {:path => "something"}
36
+ }
37
+ }
38
+
39
+ hash_copy = hash_symbols.dup
40
+
41
+ hash_copy.should == hash_symbols.recursively_symbolize_keys!
42
+ hash_symbols[:repos][:repo1].should == {:path => "something"}
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+
@@ -1,10 +1,10 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe Oct do
4
-
4
+
5
5
  before(:each) do
6
6
  @filename = 'input.txt'
7
- create_file(@filename, "the quick brown fox")
7
+ write_file(@filename, "the quick brown fox")
8
8
  end
9
9
 
10
10
  describe 'Aruba::API.current_dir' do
@@ -1,7 +1,7 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe Oct do
4
-
4
+
5
5
  describe 'version' do
6
6
 
7
7
  it "should return a string formatted '#.#.#'" do
@@ -10,4 +10,75 @@ describe Oct do
10
10
 
11
11
  end
12
12
 
13
+ # VIM autocmd to remove trailing whitespace
14
+ # autocmd BufWritePre * :%s/\s\+$//e
15
+ #
16
+ describe "code" do
17
+
18
+ before(:each) do
19
+ @gemfiles_filename = File.expand_path(File.dirname(__FILE__) + '/../../.gemfiles')
20
+ raise ".gemfiles not found. Please run 'rake gemfiles'" unless File.exists?(@gemfiles_filename)
21
+ @gemfiles = File.open(@gemfiles_filename, "rb") {|f| f.read}
22
+ @eol = @gemfiles.match("\r\n") ? "\r\n" : "\n"
23
+ end
24
+
25
+ def binary?(filename)
26
+ open filename do |f|
27
+ f.each_byte { |x|
28
+ x.nonzero? or return true
29
+ }
30
+ end
31
+ false
32
+ end
33
+
34
+ def check_for_tab_characters(filename)
35
+ failing_lines = []
36
+ File.readlines(filename).each_with_index do |line,number|
37
+ failing_lines << number + 1 if line =~ /\t/
38
+ end
39
+
40
+ unless failing_lines.empty?
41
+ "#{filename} has tab characters on lines #{failing_lines.join(', ')}"
42
+ end
43
+ end
44
+
45
+ def check_for_extra_spaces(filename)
46
+ failing_lines = []
47
+ File.readlines(filename).each_with_index do |line,number|
48
+ next if line =~ /^\s+#.*\s+#{@eol}$/
49
+ failing_lines << number + 1 if line =~ /\s+#{@eol}$/
50
+ end
51
+
52
+ unless failing_lines.empty?
53
+ "#{filename} has spaces on the EOL on lines #{failing_lines.join(', ')}"
54
+ end
55
+ end
56
+
57
+ RSpec::Matchers.define :be_well_formed do
58
+ failure_message_for_should do |actual|
59
+ actual.join("\n")
60
+ end
61
+
62
+ match do |actual|
63
+ actual.empty?
64
+ end
65
+ end
66
+
67
+ it "has no malformed whitespace" do
68
+ error_messages = []
69
+ @gemfiles.split(@eol).each do |filename|
70
+ filename = File.expand_path(File.join(File.dirname(__FILE__), ["..", "..", filename]))
71
+ unless File.exists?(filename)
72
+ puts "WARNING: .gemfiles out-of-date, #{filename} not found. Edit .gemfiles or run 'rake gemfiles' after committing changes."
73
+ next
74
+ end
75
+ next if filename =~ /\.gitmodules/
76
+ next if binary?(filename)
77
+ error_messages << check_for_tab_characters(filename)
78
+ error_messages << check_for_extra_spaces(filename)
79
+ end
80
+ error_messages.compact.should be_well_formed
81
+ end
82
+
83
+ end
13
84
  end
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe Oct do
4
4
 
@@ -6,7 +6,7 @@ describe Oct do
6
6
  filename = File.expand_path('../../../oct.gemspec', __FILE__)
7
7
  eval(File.read(filename), nil, filename)
8
8
  end
9
-
9
+
10
10
  describe 'gemspec' do
11
11
 
12
12
  it "should return the gem VERSION" do
@@ -27,31 +27,19 @@ describe Oct do
27
27
  @gemspec.executables.is_a?(Array).should == true
28
28
  end
29
29
 
30
- describe 'without an existing cache' do
30
+ describe 'without .gemfiles cache' do
31
31
  before(:each) do
32
32
  File.stub!('exists?').and_return false
33
33
  @gemspec = load_gemspec
34
34
  end
35
35
 
36
- it "should not blow up" do
37
- @gemspec.files.is_a?(Array).should == true
38
- @gemspec.files.include?('VERSION').should == true
39
- end
40
- end
41
-
42
- describe 'without a git repo' do
43
- before(:each) do
44
- File.stub!('directory?').and_return false
45
- @gemspec = load_gemspec
46
- end
47
-
48
- it "should return 'files' from cache" do
49
- File.directory?(File.expand_path('../../../.git', __FILE__)).should == false
36
+ it "should return 'files' from using 'git ls-files" do
37
+ File.exists?(File.expand_path('../../../.gemfiles', __FILE__)).should == false
50
38
  @gemspec.files.is_a?(Array).should == true
51
39
  @gemspec.files.include?('VERSION').should == true
52
40
  end
53
- it "should return 'executables' from cache" do
54
- File.directory?(File.expand_path('../../../.git', __FILE__)).should == false
41
+ it "should return 'executables' from 'git ls-files" do
42
+ File.exists?(File.expand_path('../../../.gemfiles', __FILE__)).should == false
55
43
  @gemspec.executables.is_a?(Array).should == true
56
44
  end
57
45
  end
@@ -64,12 +52,12 @@ describe Oct do
64
52
  end
65
53
 
66
54
  it "should return 'files' from cache" do
67
- system('git --version').should == false
55
+ system('git --version').should == false
68
56
  @gemspec.files.is_a?(Array).should == true
69
57
  @gemspec.files.include?('VERSION').should == true
70
58
  end
71
59
  it "should return 'executables' from cache" do
72
- system('git --version').should == false
60
+ system('git --version').should == false
73
61
  @gemspec.executables.is_a?(Array).should == true
74
62
  end
75
63
 
data/spec/spec_helper.rb CHANGED
@@ -1,35 +1,11 @@
1
- $LOAD_PATH.unshift File.expand_path('..', __FILE__) unless
2
- $LOAD_PATH.include? File.expand_path('..', __FILE__)
3
- $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) unless
4
- $LOAD_PATH.include? File.expand_path('../../lib', __FILE__)
5
-
6
- require 'rubygems'
7
1
  require 'oct'
8
- require 'spec'
9
- require 'spec/autorun'
2
+ require 'rspec/core'
10
3
  require 'aruba/api'
4
+ require 'aruba_helper'
11
5
 
12
- # aruba helpers
13
- #
14
- # @return full path to files in the aruba tmp folder
15
- def fullpath(filename)
16
- path = File.expand_path(File.join(current_dir, filename))
17
- if path.match(/^\/cygdrive/)
18
- # match /cygdrive/c/path/to and return c:\\path\\to
19
- path = `cygpath -w #{path}`.chomp
20
- elsif path.match(/.\:/)
21
- # match c:/path/to and return c:\\path\\to
22
- path = path.gsub(/\//, '\\')
23
- end
24
- path
25
- end
26
- # @return the contents of "filename" in the aruba tmp folder
27
- def get_file_contents(filename)
28
- in_current_dir do
29
- IO.read(filename)
30
- end
31
- end
32
-
33
- Spec::Runner.configure do |config|
34
- config.include Aruba::Api
6
+ RSpec.configure do |config|
7
+ config.include Aruba::Api
8
+ config.filter_run :focus => true
9
+ config.run_all_when_everything_filtered = true
10
+ config.treat_symbols_as_metadata_keys_with_true_values = true
35
11
  end
data/spec/watchr.rb CHANGED
@@ -44,13 +44,15 @@ end
44
44
 
45
45
  def run(cmd)
46
46
 
47
+ cmd = 'bundle exec ' + cmd unless cmd.match(/^bundle exec/)
48
+
47
49
  pid = fork do
48
50
 
49
51
  puts "\n"
50
52
  if $c
51
53
  print $c.cyan, cmd, $c.clear, "\n"
52
54
  else
53
- puts cmd
55
+ puts cmd
54
56
  end
55
57
 
56
58
  exec(cmd)