revenc 0.1.3 → 0.2.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.
Files changed (46) hide show
  1. data/.gemfiles +53 -0
  2. data/.gitignore +4 -8
  3. data/Gemfile.lock +42 -37
  4. data/HISTORY.markdown +9 -2
  5. data/LICENSE +1 -1
  6. data/README.markdown +33 -38
  7. data/Rakefile +24 -34
  8. data/TODO.markdown +3 -0
  9. data/VERSION +1 -1
  10. data/bin/revenc +30 -13
  11. data/config/cucumber.yml +4 -3
  12. data/examples/rsync/encrypted_data/key/encfs6.xml +27 -27
  13. data/examples/rsync/revenc.conf +2 -2
  14. data/examples/simple/encfs6.xml +27 -27
  15. data/features/app.feature +17 -17
  16. data/features/bin.feature +6 -6
  17. data/features/configuration.feature +9 -9
  18. data/features/copy.feature +15 -12
  19. data/features/generator.feature +1 -1
  20. data/features/mount.feature +14 -14
  21. data/features/settings.feature +119 -0
  22. data/features/step_definitions/revenc_steps.rb +1 -2
  23. data/features/support/aruba.rb +9 -9
  24. data/features/support/env.rb +8 -2
  25. data/features/unmount.feature +8 -8
  26. data/lib/revenc.rb +12 -3
  27. data/lib/revenc/app.rb +27 -53
  28. data/lib/revenc/core/array.rb +11 -0
  29. data/lib/revenc/core/hash.rb +45 -0
  30. data/lib/revenc/encfs_wrapper.rb +20 -24
  31. data/lib/revenc/errors.rb +3 -3
  32. data/lib/revenc/io.rb +13 -13
  33. data/lib/revenc/settings.rb +98 -0
  34. data/revenc.gemspec +28 -17
  35. data/spec/aruba_helper.rb +25 -0
  36. data/spec/basic_app/array_spec.rb +48 -0
  37. data/spec/basic_gem/aruba_helper_spec.rb +33 -0
  38. data/spec/basic_gem/basic_gem_spec.rb +71 -1
  39. data/spec/basic_gem/gemspec_spec.rb +68 -0
  40. data/spec/revenc/error_spec.rb +2 -2
  41. data/spec/revenc/io_spec.rb +12 -12
  42. data/spec/spec_helper.rb +4 -9
  43. data/spec/watchr.rb +48 -26
  44. metadata +120 -177
  45. data/.yardopts +0 -6
  46. data/spec/spec.opts +0 -2
@@ -0,0 +1,119 @@
1
+ @announce
2
+ Feature: Configuration via yaml file
3
+
4
+ In order to configure options, as an interactive user or automated script,
5
+ the program should process configuration options via yaml. These options
6
+ should override hard coded defaults but not command line options.
7
+
8
+ Config files are read from multiple locations in order of priority. Once a
9
+ config file is found, all other config files are ignored.
10
+
11
+ All command line options can be read from the config file from the "options:"
12
+ block. The "options" block is optional.
13
+
14
+ NOTE: All file system testing is done via the Aruba gem. The home folder
15
+ config file is stubbed to prevent testing contamination in case it exists.
16
+
17
+
18
+ Scenario: Specified config file exists
19
+ Given an empty file named "config.conf"
20
+ When I run `revenc action --verbose --config config.conf`
21
+ Then the output should contain:
22
+ """
23
+ config file: config.conf
24
+ """
25
+
26
+ Scenario: Specified config file option but not given on command line
27
+ When I run `revenc action --verbose --config`
28
+ Then the exit status should be 1
29
+ And the output should contain:
30
+ """
31
+ missing argument: --config
32
+ """
33
+
34
+ Scenario: Specified config file not found
35
+ When I run `revenc path --verbose --config config.conf`
36
+ Then the exit status should be 1
37
+ And the output should contain:
38
+ """
39
+ config file not found
40
+ """
41
+
42
+ Scenario: Reading options from specified config file, ignoring the
43
+ default config file
44
+ Given a file named "revenc.conf" with:
45
+ """
46
+ ---
47
+ options:
48
+ coloring: true
49
+ """
50
+ And a file named "no_coloring.conf" with:
51
+ """
52
+ ---
53
+ options:
54
+ coloring: false
55
+ """
56
+ When I run `revenc action --verbose --config no_coloring.conf`
57
+ Then the output should contain:
58
+ """
59
+ :coloring=>false
60
+ """
61
+ And the output should not contain:
62
+ """
63
+ :coloring=>true
64
+ """
65
+
66
+ Scenario: Reading options from specified config file, ignoring the
67
+ default config file with override on command line
68
+ Given a file named "revenc.conf" with:
69
+ """
70
+ ---
71
+ options:
72
+ coloring: true
73
+ """
74
+ And a file named "no_coloring.conf" with:
75
+ """
76
+ ---
77
+ options:
78
+ coloring: false
79
+ """
80
+ When I run `revenc action --verbose --config no_coloring.conf --coloring`
81
+ Then the output should contain:
82
+ """
83
+ :coloring=>"AUTO"
84
+ """
85
+ And the output should not contain:
86
+ """
87
+ :coloring=>false
88
+ """
89
+ And the output should not contain:
90
+ """
91
+ :coloring=>true
92
+ """
93
+
94
+ Scenario: Reading options from config file with negative override on command line
95
+ And a file named "with_coloring.conf" with:
96
+ """
97
+ ---
98
+ options:
99
+ coloring: true
100
+ """
101
+ When I run `revenc action --verbose --config with_coloring.conf --no-coloring`
102
+ Then the output should contain:
103
+ """
104
+ :coloring=>false
105
+ """
106
+
107
+ Scenario: Reading text options from config file
108
+ Given a file named "with_always_coloring.conf" with:
109
+ """
110
+ ---
111
+ options:
112
+ coloring: ALWAYS
113
+ """
114
+ When I run `revenc action --verbose --config with_always_coloring.conf`
115
+ Then the output should contain:
116
+ """
117
+ :coloring=>"ALWAYS"
118
+ """
119
+
@@ -47,7 +47,7 @@
47
47
  When /^I run with a lock file present "(.*)"$/ do |cmd|
48
48
  lockfile = File.join(current_dir, 'revenc.lck')
49
49
  Mutagem::Mutex.new(lockfile).execute do
50
- run(unescape(cmd), false)
50
+ run_simple(unescape(cmd), false)
51
51
  end
52
52
  end
53
53
 
@@ -62,4 +62,3 @@
62
62
  folder.exists?.should be_true
63
63
  folder.should_not be_empty
64
64
  end
65
-
@@ -1,21 +1,21 @@
1
- require 'aruba'
1
+ require 'aruba/api'
2
2
  require 'fileutils'
3
3
 
4
- APP_BIN_PATH = File.join(ENV['PWD'], 'bin', 'revenc')
4
+ APP_BIN_PATH = File.join(FileUtils.pwd, 'bin', 'revenc')
5
5
 
6
6
  module Aruba
7
7
  module Api
8
8
 
9
- alias_method :old_run, :run
9
+ alias_method :old_run_simple, :run_simple
10
+
11
+ # override aruba
12
+ def run_simple(cmd, fail_on_error=true)
10
13
 
11
- # override aruba
12
- def run(cmd, fail_on_error=true)
13
-
14
14
  # run development version in verbose mode
15
- cmd = cmd.gsub(/^revenc/, "#{APP_BIN_PATH} --verbose")
15
+ cmd = cmd.gsub(/^revenc/, "ruby -S #{APP_BIN_PATH} --verbose")
16
16
 
17
- # run original aruba 'run'
18
- old_run(cmd, fail_on_error)
17
+ # run original aruba 'run'
18
+ old_run_simple(cmd, fail_on_error)
19
19
  end
20
20
  end
21
21
  end
@@ -1,4 +1,10 @@
1
1
  $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
+ require 'rubygems'
2
3
  require 'revenc'
3
- require 'aruba'
4
- require 'spec/expectations'
4
+ require 'aruba/cucumber'
5
+ require 'rspec/expectations'
6
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec/aruba_helper')
7
+
8
+ Before do
9
+ @aruba_timeout_seconds = 10
10
+ end
@@ -14,21 +14,21 @@ Feature: Unmounting a reverse mounted encrypted folder using encfs
14
14
  """
15
15
  test
16
16
  """
17
- And I successfully run "revenc mount unencrypted_source_folder encrypted_destination_folder"
18
-
17
+ And I successfully run `revenc mount unencrypted_source_folder encrypted_destination_folder`
18
+
19
19
  Scenario: Successful unmount
20
- When I run "revenc unmount encrypted_destination_folder"
20
+ When I run `revenc unmount encrypted_destination_folder`
21
21
  Then the exit status should be 0
22
22
  And the folder "encrypted_destination_folder" should not be mounted
23
-
23
+
24
24
 
25
25
  Scenario: Successful unmount dry run
26
- When I run "revenc --dry-run unmount encrypted_destination_folder"
26
+ When I run `revenc --dry-run unmount encrypted_destination_folder`
27
27
  Then the exit status should be 0
28
28
  And the folder "encrypted_destination_folder" should be mounted
29
29
 
30
30
  Scenario: Unmount folder not specified
31
- When I run "revenc unmount"
31
+ When I run `revenc unmount`
32
32
  Then the exit status should be 1
33
33
  And the output should contain:
34
34
  """
@@ -37,7 +37,7 @@ Feature: Unmounting a reverse mounted encrypted folder using encfs
37
37
 
38
38
  Scenario: Unmount folder doesn't exist
39
39
  Given a directory named "encrypted_destination_folder"
40
- When I run "revenc unmount unencrypted_source_folder"
40
+ When I run `revenc unmount unencrypted_source_folder`
41
41
  Then the exit status should be 1
42
42
  And the output should contain:
43
43
  """
@@ -50,7 +50,7 @@ Feature: Unmounting a reverse mounted encrypted folder using encfs
50
50
  unmount:
51
51
  executable: missing_bin_file
52
52
  """
53
- When I run "revenc unmount unencrypted_source_folder"
53
+ When I run `revenc unmount unencrypted_source_folder`
54
54
  Then the exit status should be 1
55
55
  And the output should contain:
56
56
  """
@@ -1,6 +1,9 @@
1
1
  # require all files here
2
- require 'rubygems'
2
+ require 'rbconfig'
3
+ require 'revenc/core/hash'
4
+ require 'revenc/core/array'
3
5
  require 'revenc/app'
6
+ require 'revenc/settings'
4
7
  require 'revenc/io'
5
8
  require 'revenc/errors'
6
9
  require 'revenc/encfs_wrapper'
@@ -16,9 +19,15 @@ module Revenc
16
19
  def self.version
17
20
  version_info_file = File.join(File.dirname(__FILE__), *%w[.. VERSION])
18
21
  File.open(version_info_file, "r") do |f|
19
- f.read
22
+ f.read.strip
20
23
  end
21
24
  end
22
-
25
+
26
+ # Platform constants
27
+ unless defined?(Revenc::WINDOWS)
28
+ WINDOWS = RbConfig::CONFIG['host_os'] =~ /mswin|mingw/i
29
+ CYGWIN = RbConfig::CONFIG['host_os'] =~ /cygwin/i
30
+ end
31
+
23
32
  end
24
33
 
@@ -1,4 +1,3 @@
1
- require 'configatron'
2
1
  require 'term/ansicolor'
3
2
 
4
3
  class String
@@ -11,21 +10,26 @@ module Revenc
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 "revenc action required"
@@ -35,9 +39,9 @@ def run
35
39
  puts "revenc --help for more information"
36
40
  exit 1
37
41
  end
38
- puts "revenc run action: #{action}".cyan if @options[:verbose]
42
+ puts "revenc 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
@@ -45,7 +49,12 @@ def run
45
49
  result = 0
46
50
  end
47
51
 
48
- exit(result ? 0 : 1)
52
+ if result.is_a?(Numeric)
53
+ exit(result)
54
+ else
55
+ # handle all other return types
56
+ exit(result ? 0 : 1)
57
+ end
49
58
 
50
59
  rescue SystemExit => e
51
60
  # This is the normal exit point, exit code from the send result
@@ -55,6 +64,7 @@ def run
55
64
  rescue Exception => e
56
65
  STDERR.puts("revenc command failed, error(s) follow:")
57
66
  STDERR.puts("#{e.message}".red)
67
+ STDERR.puts("Use '--verbose' for backtrace.") unless @options[:verbose]
58
68
  STDERR.puts(e.backtrace.join("\n")) if @options[:verbose]
59
69
  exit(1)
60
70
  end
@@ -65,18 +75,18 @@ def run
65
75
  #
66
76
  # TODO: Add status command, use encfsctl
67
77
 
68
- def mount
69
- EncfsWrapper.new(@base_dir, @options).mount(ARGV.shift, ARGV.shift)
78
+ def mount(args)
79
+ EncfsWrapper.new(@base_dir, @options).mount(args.shift, args.shift)
70
80
  end
71
81
 
72
- def unmount
73
- EncfsWrapper.new(@base_dir, @options).unmount(ARGV.shift)
82
+ def unmount(args)
83
+ EncfsWrapper.new(@base_dir, @options).unmount(args.shift)
74
84
  end
75
85
 
76
- def copy
77
- EncfsWrapper.new(@base_dir, @options).copy(ARGV.shift, ARGV.shift)
86
+ def copy(args)
87
+ EncfsWrapper.new(@base_dir, @options).copy(args.shift, args.shift)
78
88
  end
79
-
89
+
80
90
  #
81
91
  # app commands end
82
92
  #
@@ -88,41 +98,5 @@ def action_argument_required?
88
98
  !AVAILABLE_ACTIONS.empty?
89
99
  end
90
100
 
91
- # read options for YAML config with ERB processing and initialize configatron
92
- def configure(options)
93
- # TODO: read ~/.revenc.conf before looking in the current folder for revenc.conf, read BOTH files
94
- config = @options[:config]
95
- config = File.join(@base_dir, 'revenc.conf') unless config
96
- if File.exists?(config)
97
- # load configatron options from the config file
98
- puts "loading config file: #{config}".cyan if @options[:verbose]
99
- configatron.configure_from_yaml(config)
100
- else
101
- # user specified a config file?
102
- raise "config file not found" if @options[:config]
103
- # no error if user did not specify config file
104
- puts "#{config} not found".yellow if @options[:verbose]
105
- end
106
-
107
- #
108
- # set defaults, these will NOT override setting read from YAML
109
- #
110
- configatron.mount.source.set_default(:name, nil)
111
- configatron.mount.mountpoint.set_default(:name, nil)
112
- configatron.mount.passphrasefile.set_default(:name, 'passphrase')
113
- configatron.mount.keyfile.set_default(:name, 'encfs6.xml')
114
- configatron.mount.set_default(:cmd, nil)
115
- configatron.mount.set_default(:executable, nil)
116
-
117
- configatron.unmount.mountpoint.set_default(:name, nil)
118
- configatron.unmount.set_default(:cmd, nil)
119
- configatron.unmount.set_default(:executable, nil)
120
-
121
- configatron.copy.source.set_default(:name, nil)
122
- configatron.copy.destination.set_default(:name, nil)
123
- configatron.copy.set_default(:cmd, nil)
124
- configatron.copy.set_default(:executable, nil)
125
- end
126
-
127
101
  end
128
102
  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