revenc 0.1.3 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gemfiles +53 -0
- data/.gitignore +4 -8
- data/Gemfile.lock +42 -37
- data/HISTORY.markdown +9 -2
- data/LICENSE +1 -1
- data/README.markdown +33 -38
- data/Rakefile +24 -34
- data/TODO.markdown +3 -0
- data/VERSION +1 -1
- data/bin/revenc +30 -13
- data/config/cucumber.yml +4 -3
- data/examples/rsync/encrypted_data/key/encfs6.xml +27 -27
- data/examples/rsync/revenc.conf +2 -2
- data/examples/simple/encfs6.xml +27 -27
- data/features/app.feature +17 -17
- data/features/bin.feature +6 -6
- data/features/configuration.feature +9 -9
- data/features/copy.feature +15 -12
- data/features/generator.feature +1 -1
- data/features/mount.feature +14 -14
- data/features/settings.feature +119 -0
- data/features/step_definitions/revenc_steps.rb +1 -2
- data/features/support/aruba.rb +9 -9
- data/features/support/env.rb +8 -2
- data/features/unmount.feature +8 -8
- data/lib/revenc.rb +12 -3
- data/lib/revenc/app.rb +27 -53
- data/lib/revenc/core/array.rb +11 -0
- data/lib/revenc/core/hash.rb +45 -0
- data/lib/revenc/encfs_wrapper.rb +20 -24
- data/lib/revenc/errors.rb +3 -3
- data/lib/revenc/io.rb +13 -13
- data/lib/revenc/settings.rb +98 -0
- data/revenc.gemspec +28 -17
- data/spec/aruba_helper.rb +25 -0
- data/spec/basic_app/array_spec.rb +48 -0
- data/spec/basic_gem/aruba_helper_spec.rb +33 -0
- data/spec/basic_gem/basic_gem_spec.rb +71 -1
- data/spec/basic_gem/gemspec_spec.rb +68 -0
- data/spec/revenc/error_spec.rb +2 -2
- data/spec/revenc/io_spec.rb +12 -12
- data/spec/spec_helper.rb +4 -9
- data/spec/watchr.rb +48 -26
- metadata +120 -177
- data/.yardopts +0 -6
- 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
|
-
|
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
|
-
|
data/features/support/aruba.rb
CHANGED
@@ -1,21 +1,21 @@
|
|
1
|
-
require 'aruba'
|
1
|
+
require 'aruba/api'
|
2
2
|
require 'fileutils'
|
3
3
|
|
4
|
-
APP_BIN_PATH = File.join(
|
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 :
|
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
|
-
|
17
|
+
# run original aruba 'run'
|
18
|
+
old_run_simple(cmd, fail_on_error)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
data/features/support/env.rb
CHANGED
@@ -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 '
|
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
|
data/features/unmount.feature
CHANGED
@@ -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
|
18
|
-
|
17
|
+
And I successfully run `revenc mount unencrypted_source_folder encrypted_destination_folder`
|
18
|
+
|
19
19
|
Scenario: Successful unmount
|
20
|
-
When I run
|
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
|
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
|
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
|
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
|
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
|
"""
|
data/lib/revenc.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# require all files here
|
2
|
-
require '
|
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
|
|
data/lib/revenc/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 Revenc
|
|
11
10
|
|
12
11
|
class App
|
13
12
|
|
14
|
-
def initialize(
|
15
|
-
@
|
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 "
|
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
|
-
|
23
|
+
$stdout.sync = true
|
22
24
|
end
|
23
25
|
|
24
|
-
def
|
26
|
+
def execute
|
25
27
|
begin
|
26
28
|
|
27
29
|
if action_argument_required?
|
28
|
-
action =
|
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
|
-
|
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(
|
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(
|
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(
|
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,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
|