valise 0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. data/doc/README +69 -0
  2. data/doc/Specification +72 -0
  3. data/doc/Specifications +81 -0
  4. data/doc/coverage/assets/0.5.3/app.js +88 -0
  5. data/doc/coverage/assets/0.5.3/fancybox/blank.gif +0 -0
  6. data/doc/coverage/assets/0.5.3/fancybox/fancy_close.png +0 -0
  7. data/doc/coverage/assets/0.5.3/fancybox/fancy_loading.png +0 -0
  8. data/doc/coverage/assets/0.5.3/fancybox/fancy_nav_left.png +0 -0
  9. data/doc/coverage/assets/0.5.3/fancybox/fancy_nav_right.png +0 -0
  10. data/doc/coverage/assets/0.5.3/fancybox/fancy_shadow_e.png +0 -0
  11. data/doc/coverage/assets/0.5.3/fancybox/fancy_shadow_n.png +0 -0
  12. data/doc/coverage/assets/0.5.3/fancybox/fancy_shadow_ne.png +0 -0
  13. data/doc/coverage/assets/0.5.3/fancybox/fancy_shadow_nw.png +0 -0
  14. data/doc/coverage/assets/0.5.3/fancybox/fancy_shadow_s.png +0 -0
  15. data/doc/coverage/assets/0.5.3/fancybox/fancy_shadow_se.png +0 -0
  16. data/doc/coverage/assets/0.5.3/fancybox/fancy_shadow_sw.png +0 -0
  17. data/doc/coverage/assets/0.5.3/fancybox/fancy_shadow_w.png +0 -0
  18. data/doc/coverage/assets/0.5.3/fancybox/fancy_title_left.png +0 -0
  19. data/doc/coverage/assets/0.5.3/fancybox/fancy_title_main.png +0 -0
  20. data/doc/coverage/assets/0.5.3/fancybox/fancy_title_over.png +0 -0
  21. data/doc/coverage/assets/0.5.3/fancybox/fancy_title_right.png +0 -0
  22. data/doc/coverage/assets/0.5.3/fancybox/fancybox-x.png +0 -0
  23. data/doc/coverage/assets/0.5.3/fancybox/fancybox-y.png +0 -0
  24. data/doc/coverage/assets/0.5.3/fancybox/fancybox.png +0 -0
  25. data/doc/coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.css +363 -0
  26. data/doc/coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.pack.js +44 -0
  27. data/doc/coverage/assets/0.5.3/favicon_green.png +0 -0
  28. data/doc/coverage/assets/0.5.3/favicon_red.png +0 -0
  29. data/doc/coverage/assets/0.5.3/favicon_yellow.png +0 -0
  30. data/doc/coverage/assets/0.5.3/highlight.css +129 -0
  31. data/doc/coverage/assets/0.5.3/highlight.pack.js +1 -0
  32. data/doc/coverage/assets/0.5.3/jquery-1.6.2.min.js +18 -0
  33. data/doc/coverage/assets/0.5.3/jquery.dataTables.min.js +152 -0
  34. data/doc/coverage/assets/0.5.3/jquery.timeago.js +141 -0
  35. data/doc/coverage/assets/0.5.3/jquery.url.js +174 -0
  36. data/doc/coverage/assets/0.5.3/loading.gif +0 -0
  37. data/doc/coverage/assets/0.5.3/magnify.png +0 -0
  38. data/doc/coverage/assets/0.5.3/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  39. data/doc/coverage/assets/0.5.3/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  40. data/doc/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  41. data/doc/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  42. data/doc/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  43. data/doc/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  44. data/doc/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  45. data/doc/coverage/assets/0.5.3/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  46. data/doc/coverage/assets/0.5.3/smoothness/images/ui-icons_222222_256x240.png +0 -0
  47. data/doc/coverage/assets/0.5.3/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  48. data/doc/coverage/assets/0.5.3/smoothness/images/ui-icons_454545_256x240.png +0 -0
  49. data/doc/coverage/assets/0.5.3/smoothness/images/ui-icons_888888_256x240.png +0 -0
  50. data/doc/coverage/assets/0.5.3/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  51. data/doc/coverage/assets/0.5.3/smoothness/jquery-ui-1.8.4.custom.css +295 -0
  52. data/doc/coverage/assets/0.5.3/stylesheet.css +383 -0
  53. data/doc/coverage/index.html +5843 -0
  54. data/doc/coverage/jquery-1.3.2.min.js +19 -0
  55. data/doc/coverage/jquery.tablesorter.min.js +15 -0
  56. data/doc/coverage/lib-fileset-errors_rb.html +231 -0
  57. data/doc/coverage/lib-fileset-item_rb.html +303 -0
  58. data/doc/coverage/lib-fileset-populator_rb.html +249 -0
  59. data/doc/coverage/lib-fileset-search-root_rb.html +1053 -0
  60. data/doc/coverage/lib-fileset-utils_rb.html +453 -0
  61. data/doc/coverage/lib-fileset_rb.html +789 -0
  62. data/doc/coverage/print.css +12 -0
  63. data/doc/coverage/rcov.js +42 -0
  64. data/doc/coverage/screen.css +270 -0
  65. data/lib/valise/errors.rb +30 -0
  66. data/lib/valise/item.rb +105 -0
  67. data/lib/valise/path-matcher.rb +113 -0
  68. data/lib/valise/search-root.rb +166 -0
  69. data/lib/valise/stack.rb +169 -0
  70. data/lib/valise/stem-decorator.rb +56 -0
  71. data/lib/valise/utils.rb +65 -0
  72. data/lib/valise.rb +219 -0
  73. data/spec/addable.rb +41 -0
  74. data/spec/dump_load.rb +32 -0
  75. data/spec/error_handling.rb +9 -0
  76. data/spec/fileset.rb +170 -0
  77. data/spec/glob_handling.rb +28 -0
  78. data/spec/item.rb +35 -0
  79. data/spec/merge_diff.rb +93 -0
  80. data/spec/population.rb +51 -0
  81. data/spec/search_root.rb +24 -0
  82. data/spec/stemming.rb +33 -0
  83. data/spec_help/file-sandbox.rb +164 -0
  84. data/spec_help/gem_test_suite.rb +17 -0
  85. data/spec_help/spec_helper.rb +3 -0
  86. data/spec_help/ungemmer.rb +37 -0
  87. metadata +220 -0
@@ -0,0 +1,166 @@
1
+ require 'valise/errors'
2
+ require 'valise/utils'
3
+ require 'valise/item'
4
+ require 'fileutils'
5
+ #require 'enum'
6
+
7
+ module Valise
8
+ class SearchRoot
9
+ include Unpath
10
+ include Enumerable
11
+
12
+ def initialize(path)
13
+ @segments = unpath(path)
14
+ end
15
+
16
+ attr_reader :segments
17
+
18
+ def each
19
+ paths = [[]]
20
+ until paths.empty?
21
+ rel = paths.shift
22
+ path = repath(@segments + rel)
23
+ #symlinks?
24
+ if(File::directory?(path))
25
+ Dir.entries(path).each do |entry|
26
+ next if entry == "."
27
+ next if entry == ".."
28
+ paths.push(rel + [entry])
29
+ end
30
+ elsif(File::file?(path))
31
+ yield(unpath(rel))
32
+ end
33
+ end
34
+ end
35
+
36
+ def inspect
37
+ "#{self.class.name.split(":").last}:#{[*@segments].join("/")}"
38
+ end
39
+
40
+ def full_path(segments)
41
+ repath(@segments + segments)
42
+ end
43
+
44
+ def write(item)
45
+ return if item.contents.nil?
46
+ FileUtils::mkdir_p(::File::dirname(item.full_path))
47
+ File::open(item.full_path, "w") do |file|
48
+ file.write(item.dump_contents)
49
+ end
50
+ item
51
+ end
52
+
53
+ def writable?(segments)
54
+ path = full_path(segments)
55
+ return (!File::exists?(path) or File::writable?(path))
56
+ end
57
+
58
+ def present?(segments)
59
+ return File::exists?(full_path(segments))
60
+ end
61
+
62
+ def insert(item)
63
+ if(File::exists?(item.full_path))
64
+ raise WouldClobber.new(Item.new(item.stack.segments, self, nil))
65
+ else
66
+ write(item)
67
+ return item
68
+ end
69
+ end
70
+
71
+ def get_from(item)
72
+ File::read(item.full_path)
73
+ end
74
+ end
75
+
76
+ class ReadOnlySearchRoot < SearchRoot
77
+ def writable?(segments)
78
+ false
79
+ end
80
+
81
+ def write(item)
82
+ raise ReadOnly
83
+ end
84
+
85
+ def insert(item)
86
+ raise ReadOnly
87
+ end
88
+ end
89
+
90
+ class DefinedDefaults < ReadOnlySearchRoot
91
+ def initialize
92
+ @files = {}
93
+ end
94
+
95
+ def segments
96
+ raise VirtualSearchPath, "does not have a real path"
97
+ end
98
+
99
+ def present?(segments)
100
+ @files.has_key?(segments)
101
+ end
102
+
103
+ def each
104
+ @files.each_key do |path|
105
+ yield(unpath(path))
106
+ end
107
+ end
108
+
109
+ def get_from(item)
110
+ return @files[item.segments]
111
+ end
112
+
113
+ def define(&block)
114
+ unless block.nil?
115
+ definer = DefinitionHelper.new(self)
116
+ definer.instance_eval &block
117
+ end
118
+ return self
119
+ end
120
+
121
+ def self.define(&block)
122
+ return self.new.define(&block)
123
+ end
124
+
125
+ def add_item(path, contents)
126
+ check_path = path[0..-2]
127
+ until check_path.empty?
128
+ if @files.has_key?(check_path)
129
+ raise MalformedTree, "Tried to add items below #{path[0..-2]} which is not a directory"
130
+ end
131
+ check_path.pop
132
+ end
133
+ @files[path] = contents
134
+ end
135
+
136
+ def add_dir(path)
137
+ #add_item(path, ValiseWorks::Directory.new(path))
138
+ end
139
+
140
+ def add_file(path, data = nil)
141
+ add_item(path, data)
142
+ end
143
+
144
+ class DefinitionHelper
145
+ def initialize(target)
146
+ @target = target
147
+ @prefix = []
148
+ end
149
+
150
+ def dir(name)
151
+ path = @prefix + [name]
152
+ @target.add_dir(path)
153
+ @prefix.push(name)
154
+ yield if block_given?
155
+ @prefix.pop
156
+ end
157
+
158
+ def file(name, data=nil)
159
+ path = @prefix + [name.to_s]
160
+ @target.add_file(path, data)
161
+ end
162
+
163
+ include StringTools
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,169 @@
1
+ # New plan here: Stack is returned by "find" and responds to many of the
2
+ # methods that Item current responds to. It caches results, essentially, of
3
+ # the find search - maybe at creation, with possiblity for reload/update.
4
+ # Also, makes possible use cases like file promotion, merging, etc.
5
+ #
6
+ # Still need to resolve the interface for parsing and merging files.
7
+ #
8
+ # * something from the Valise definition - would have to be part of defaults,
9
+ # which further is a problem if a file doesn't exist in the defaults
10
+ #
11
+ # * a filetype mapping
12
+ #
13
+ # * Is it a find-time user thing
14
+
15
+
16
+ module Valise
17
+ module ItemEnum
18
+ include Enumerable
19
+
20
+ class Enumerator
21
+ include ItemEnum
22
+
23
+ def initialize(list, &filter)
24
+ @list = list
25
+ @filter = proc(&filter)
26
+ end
27
+
28
+ def each
29
+ @list.each do |item|
30
+ next unless @filter[item]
31
+ yield(item)
32
+ end
33
+ end
34
+ end
35
+
36
+ def writable
37
+ Enumerator.new(self) do |item|
38
+ item.writable?
39
+ end
40
+ end
41
+
42
+ def absent
43
+ Enumerator.new(self) do |item|
44
+ not item.present?
45
+ end
46
+ end
47
+
48
+ def present
49
+ Enumerator.new(self) do |item|
50
+ item.present?
51
+ end
52
+ end
53
+ end
54
+
55
+ class MergeDiff
56
+ @@classes = {}
57
+ def self.[](index)
58
+ @@classes[index]
59
+ end
60
+
61
+ def self.register(index)
62
+ @@classes[index] = self
63
+ end
64
+
65
+ def initialize(stack)
66
+ @stack = stack
67
+ end
68
+
69
+ class TopMost < MergeDiff
70
+ register :topmost
71
+
72
+ def merge(item)
73
+ item.load_contents
74
+ end
75
+
76
+ def diff(item, value)
77
+ value
78
+ end
79
+ end
80
+
81
+ class HashMerge < MergeDiff
82
+ register :hash_merge
83
+
84
+ def merge(item)
85
+ merge_stack(@stack.not_above(item).reverse)
86
+ end
87
+
88
+ def merge_stack(stack)
89
+ stack.inject({}) do |hash, item|
90
+ deep_merge(hash, item.load_contents)
91
+ end
92
+ end
93
+
94
+ def deep_merge(collect, item)
95
+ item.each_pair do |key, value|
96
+ case value
97
+ when Hash
98
+ collect[key] ||= {}
99
+ deep_merge(collect[key], value)
100
+ else
101
+ collect[key] = value
102
+ end
103
+ end
104
+ collect
105
+ end
106
+
107
+ def diff(item, new_contents)
108
+ diff_with = merge_stack(@stack.below(item).reverse)
109
+ result = new_contents.dup
110
+
111
+ diff_with.each_pair do |key, value|
112
+ if result.has_key?(key)
113
+ if result[key] == value
114
+ result.delete(key)
115
+ end
116
+ else
117
+ result[key] = nil
118
+ end
119
+ end
120
+
121
+ result
122
+ end
123
+ end
124
+ end
125
+
126
+ class Stack
127
+ include Unpath
128
+ include ItemEnum
129
+
130
+ def inspect
131
+ "<default>:#{@segments.join "/"} #{@valise.inspect}"
132
+ end
133
+
134
+ def initialize(path, set, merge_class, dump_load)
135
+ @segments = unpath(path)
136
+ @valise = set
137
+ @merge_diff = (merge_class || MergeDiff::TopMost).new(self)
138
+ @dump_load = dump_load
139
+ end
140
+
141
+ attr_reader :segments
142
+
143
+ def merged(item)
144
+ @merge_diff.merge(item)
145
+ end
146
+
147
+ def diffed(item, value)
148
+ @merge_diff.diff(item, value)
149
+ end
150
+
151
+ def not_above(item)
152
+ Stack.new(@segments, @valise.not_above(item.root), @merge_diff.class, @dump_load)
153
+ end
154
+
155
+ def below(item)
156
+ Stack.new(@segments, @valise.below(item.root), @merge_diff.class, @dump_load)
157
+ end
158
+
159
+ def each
160
+ @valise.each do |root|
161
+ yield(Item.new(self, root, @dump_load))
162
+ end
163
+ end
164
+
165
+ def reverse
166
+ Stack.new(@segments, @valise.reverse, @merge_diff.class, @dump_load)
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,56 @@
1
+ module Valise
2
+ class StemDecorator < SearchRoot
3
+ def initialize(stem, search_root)
4
+ @stem, @search_root = stem, search_root
5
+ end
6
+
7
+ def under_stem(path)
8
+ segments = unpath(path)
9
+ top_part = segments[0...@stem.length]
10
+ if top_part == @stem
11
+ return segments[@stem.length..-1]
12
+ else
13
+ raise PathOutsideOfRoot
14
+ end
15
+ end
16
+
17
+ def inspect
18
+ "#{self.class.name.split(":").last}:[#{@stem.join("/")}]#{@search_root.inspect}"
19
+ end
20
+
21
+ def each
22
+ @search_root.each do |path|
23
+ yield(@stem + path)
24
+ end
25
+ end
26
+
27
+ def full_path(segments)
28
+ segments = under_stem(segments)
29
+ @search_root.full_path(segments)
30
+ end
31
+
32
+ def write(item)
33
+ @search_root.write(item)
34
+ end
35
+
36
+ def writable?(segments)
37
+ @search_root.writable?(under_stem(segments))
38
+ rescue PathOutsideOfRoot
39
+ return false
40
+ end
41
+
42
+ def present?(segments)
43
+ @search_root.present?(under_stem(segments))
44
+ rescue PathOutsideOfRoot
45
+ return false
46
+ end
47
+
48
+ def insert(item)
49
+ @search_root.insert(item)
50
+ end
51
+
52
+ def get_from(item)
53
+ @search_root.get_from(item)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,65 @@
1
+ module Valise
2
+ module StringTools
3
+ def align(string)
4
+ lines = string.split(/\n/)
5
+ first = lines.shift
6
+ match = /^(\s*)<<</.match(first)
7
+ unless(match.nil?)
8
+ catch(:haircut) do
9
+ return lines.map do |line|
10
+ raise line if /^#{match[1]}|^\s*$/ !~ line
11
+ throw :haircut if /^#{match[1]}|^\s*$/ !~ line
12
+ line.sub(/^#{match[1]}/, "")
13
+ end.join("\n")
14
+ end
15
+ end
16
+ return string
17
+ end
18
+ module_function :align
19
+ end
20
+
21
+ module Unpath
22
+ def unpath(parts)
23
+ if Array === parts and parts.length == 1
24
+ parts = parts[0]
25
+ end
26
+
27
+ case parts
28
+ when Array
29
+ if (parts.find{|part| not (String === part or Symbol === part)}.nil?)
30
+ parts = parts.map{|part| part.to_s}
31
+ else
32
+ raise "path must be composed of strings or symbols"
33
+ end
34
+ when String
35
+ parts = parts.split(::File::Separator)
36
+ when Symbol
37
+ parts = [parts.to_s]
38
+ when ::File
39
+ parts = parts.path
40
+ parts = parts.split(::File::Separator)
41
+ else
42
+ raise "path must be String, Array of Strings or File"
43
+ end
44
+
45
+ parts = parts.map do |part|
46
+ if /^~/ =~ part
47
+ ::File::expand_path(part).split(::File::Separator)
48
+ else
49
+ part
50
+ end
51
+ end.flatten
52
+
53
+ return parts
54
+ end
55
+
56
+ def repath(segments)
57
+ case segments
58
+ when Array
59
+ return segments.join(::File::Separator)
60
+ when String
61
+ return segments
62
+ end
63
+ end
64
+ end
65
+ end
data/lib/valise.rb ADDED
@@ -0,0 +1,219 @@
1
+ require 'valise/errors'
2
+ require 'valise/search-root'
3
+ require 'valise/utils'
4
+ require 'valise/stack'
5
+ require 'valise/path-matcher'
6
+ require 'valise/stem-decorator'
7
+
8
+ module Valise
9
+ module Debugging
10
+ def remark
11
+ end
12
+
13
+ class << self
14
+ attr_reader :remark_to
15
+
16
+ def enable(destination)
17
+ @remark_to = destination
18
+ class_eval do
19
+ def remark
20
+ self.class.remark_to.puts(yield)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ class Set
28
+ include Debugging
29
+ include Enumerable
30
+
31
+ class StemmedDefiner
32
+ include Unpath
33
+ def initialize(path, set)
34
+ @segments = unpath(path)
35
+ @target = set
36
+ end
37
+
38
+ def rw(name)
39
+ @target.add_search_root(
40
+ StemDecorator.new(@segments, SearchRoot.new(name)))
41
+ end
42
+
43
+ def ro(name)
44
+ @target.add_search_root(
45
+ StemDecorator.new(@segments, ReadOnlySearchRoot.new(name)))
46
+ end
47
+ end
48
+
49
+ class Definer
50
+ include Unpath
51
+ def initialize(set)
52
+ @target = set
53
+ end
54
+
55
+ def rw(name, path = nil)
56
+ @target.add_search_root(SearchRoot.new(name))
57
+ end
58
+
59
+ def ro(name, path = nil)
60
+ @target.add_search_root(ReadOnlySearchRoot.new(name))
61
+ end
62
+
63
+ def stemmed(path, &block)
64
+ definer = StemmedDefiner.new(path, @target)
65
+ definer.instance_eval(&block) unless block.nil?
66
+ return definer
67
+ end
68
+
69
+ def from_here(rel_path)
70
+ m = /(.*):\d+/.match(caller[0])
71
+ dir = ::File::dirname(::File::expand_path(m[1]))
72
+
73
+ unpath(dir) + unpath(rel_path)
74
+ end
75
+
76
+ def handle(path, serialization, merge_diff = nil)
77
+ @target.add_handler(unpath(path),
78
+ Valise::Serialization[serialization],
79
+ Valise::MergeDiff[merge_diff])
80
+ end
81
+
82
+ def defaults(name=nil, &block)
83
+ loc = DefinedDefaults.define(&block)
84
+ @target.add_search_root(loc)
85
+ end
86
+ end
87
+
88
+ def initialize
89
+ @search_roots = []
90
+ @merge_diff = PathMatcher.new
91
+ @serialization = PathMatcher.new
92
+ end
93
+
94
+ def inspect
95
+ @search_roots.inspect
96
+ end
97
+
98
+ def reverse
99
+ set = Set.new
100
+ set.search_roots = @search_roots.reverse
101
+ set
102
+ end
103
+
104
+ def define(&block)
105
+ definer = Definer.new(self)
106
+ definer.instance_eval(&block)
107
+ return self
108
+ end
109
+
110
+ def self.define(&block)
111
+ return self.new.define(&block)
112
+ end
113
+
114
+ def prepend_search_root(search_root)
115
+ @search_roots.unshift(search_root)
116
+ end
117
+
118
+ def add_search_root(search_root)
119
+ @search_roots << search_root
120
+ end
121
+
122
+ def add_handler(segments, serialization_class, merge_diff_class)
123
+ @merge_diff[segments] = merge_diff_class unless merge_diff_class.nil?
124
+ @serialization[segments] = serialization_class unless serialization_class.nil?
125
+ end
126
+
127
+ def +(other)
128
+ result = self.class.new
129
+ result.search_roots = @search_roots + other.search_roots
130
+ result.merge_handlers(*other.handler_lists)
131
+ result.merge_handlers(*handler_lists)
132
+ return result
133
+ end
134
+
135
+ attr_accessor :search_roots
136
+ protected :search_roots, :search_roots=
137
+
138
+ include Unpath
139
+ def get(path)
140
+ return Stack.new(path, self,
141
+ merge_diff(path),
142
+ serialization(path))
143
+ end
144
+
145
+ def merge_diff(path)
146
+ @merge_diff[unpath(path)]
147
+ end
148
+
149
+ def serialization(path)
150
+ @serialization[unpath(path)]
151
+ end
152
+
153
+ def merge_handlers(merge_diff, serialization)
154
+ @merge_diff.merge!(merge_diff)
155
+ @serialization.merge!(serialization)
156
+ end
157
+
158
+ def handler_lists
159
+ [@merge_diff, @serialization]
160
+ end
161
+
162
+ def find(path)
163
+ return get(path).present.first
164
+ end
165
+
166
+ def each(&block)
167
+ @search_roots.each(&block)
168
+ end
169
+
170
+ def files
171
+ unless block_given?
172
+ return self.enum_for(:files)
173
+ end
174
+
175
+ visited = {}
176
+ @search_roots.each do |root|
177
+ root.each do |segments|
178
+ unless visited.has_key?(segments)
179
+ item = find(segments)
180
+ visited[segments] = item
181
+ yield(item)
182
+ end
183
+ end
184
+ end
185
+ return visited
186
+ end
187
+
188
+ def not_above(root)
189
+ index = @search_roots.index(root)
190
+ raise RootNotInSet if index.nil?
191
+ set = self.class.new
192
+ set.search_roots = @search_roots[index..-1]
193
+ set
194
+ end
195
+
196
+ def below(root)
197
+ index = @search_roots.index(root)
198
+ raise RootNotInSet if index.nil?
199
+ set = self.class.new
200
+ set.search_roots = @search_roots[(index+1)..-1]
201
+ set
202
+ end
203
+
204
+ def [](index)
205
+ return @search_roots[index]
206
+ end
207
+
208
+ def populate(to = self)
209
+ files do |item|
210
+ contents = item.contents
211
+ to_stack = to.get(item.segments)
212
+ to_stack = yield(to_stack) if block_given?
213
+ target = to_stack.writable.first
214
+ next if target.present?
215
+ target.contents = contents
216
+ end
217
+ end
218
+ end
219
+ end
data/spec/addable.rb ADDED
@@ -0,0 +1,41 @@
1
+ require 'valise'
2
+ require 'file-sandbox'
3
+
4
+ describe Valise do
5
+ include FileSandbox
6
+
7
+ before do
8
+ sandbox.new :directory => "etc/conductor"
9
+ sandbox.new :directory => "home/.conductor"
10
+ sandbox.new :directory => ".conductor"
11
+ sandbox.new :directory => "spec"
12
+ sandbox.new :file => "home/.conductor/existed", :with_contents => "TEST"
13
+ one = Valise::Set.define do
14
+ handle "test", :yaml
15
+ rw ".conductor"
16
+ end
17
+
18
+ two = Valise::Set.define do
19
+ handle "test", nil, :hash_merge
20
+ defaults do
21
+ end
22
+ end
23
+
24
+ @sum = one + two
25
+ end
26
+
27
+
28
+ it "should be addable" do
29
+ @sum.should be_an_instance_of(Valise::Set)
30
+ end
31
+
32
+ it "should add in order" do
33
+ @sum[0].should be_an_instance_of(Valise::SearchRoot)
34
+ @sum[1].should be_an_instance_of(Valise::DefinedDefaults)
35
+ end
36
+
37
+ it "should combine file handlers" do
38
+ @sum.merge_diff("test").should == Valise::MergeDiff::HashMerge
39
+ @sum.serialization("test").should == Valise::Serialization::YAML
40
+ end
41
+ end