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.
- 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
|