alki 0.9.0 → 0.9.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 30b3e6d184beebdc00446b13b4930d47d32151df
4
- data.tar.gz: 98249b15e58962ab44737b9e54199f8690938407
3
+ metadata.gz: bc1b79ca08e965916ecbd78625d9635f9b11868c
4
+ data.tar.gz: 7d847de049a43edefa043d07ef4d64160c625407
5
5
  SHA512:
6
- metadata.gz: df40acd78708b8a0371f5191f1b5160c4d09e9348e92c237791761528a22552f3212c7dd14759c555b20d5364def4cd1976eaa12ad90690d3d9b81a7c5e27670
7
- data.tar.gz: 24bc23ef4c32c0b16a6e63a0386c3a767bcc9fc0a2393b8197c9d942e4f9ebad6bc97b394d1d142c060cc39371e42d6fc2edeb6d72a51035fd12dad836babc8c
6
+ metadata.gz: 05ffaa08ff5d51121f127ee2db0cc01238031b1b0ff6f7e0c1a95eedab5cd551e6733c991ea54a7058cc308468843b97591e40fdbac5c19b005317fbaddd5614
7
+ data.tar.gz: a1db4bc72926268f1d1ccb789215c903bfd83a0e165816a98777fa15bf5ab70f230a2a35854f94ebf62df8cb0810f9f7b3a2c1fc09bc1cd3cac0d468964b148b
data/exe/alki CHANGED
@@ -2,8 +2,9 @@
2
2
  require 'fileutils'
3
3
  require 'optparse'
4
4
  require 'alki/support'
5
+ require 'alki/generator'
5
6
 
6
- valid_addons = ["console"]
7
+ valid_addons = ["console","reload"]
7
8
 
8
9
  options = {
9
10
  config_dir: nil,
@@ -14,12 +15,14 @@ options = {
14
15
  parser = OptionParser.new do |opts|
15
16
  opts.banner = "Usage: alki init PROJECT_NAME [options]"
16
17
 
17
- opts.on("-a", "--add[=ADDON]", "Add addon to project. Valid addons: #{valid_addons.join(', ')}") do |v|
18
- unless valid_addons.include? v
19
- puts "Invalid addon: #{v}"
20
- exit 1
18
+ opts.on("-a", "--addons=ADDONS", Array, "Add addon to project. Valid addons: #{valid_addons.join(', ')}") do |vs|
19
+ vs.each do |v|
20
+ unless valid_addons.include? v
21
+ puts "Invalid addon: #{v}"
22
+ exit 1
23
+ end
24
+ options[:addons] |= [v]
21
25
  end
22
- options[:addon] |= [v]
23
26
  end
24
27
 
25
28
  opts.on('-d','--directory=DIRECTORY', 'Project root, defaults to the current working directory') do |v|
@@ -47,187 +50,9 @@ unless ARGV[1] =~ %r{^[a-z0-9_]+(/[a-z0-9_]+)*$}
47
50
  exit 1
48
51
  end
49
52
 
50
-
51
-
52
- class AlkiFileWriter
53
- def initialize(root_dir)
54
- @root_dir = root_dir
55
- @changes = []
56
- @triggers = []
57
- end
58
-
59
- def create(file,contents)
60
- @changes << [:create,file: file,contents: contents,opts: {}]
61
- end
62
-
63
- def create_exec(file,contents)
64
- @changes << [:create,file: file,contents: contents,opts: {exec: true}]
65
- end
66
-
67
- def check_create(file:, contents:, opts:)
68
- path = abs_path( file)
69
- if File.exists? path
70
- if File.read(path) == contents
71
- :skip
72
- end
73
- end
74
- end
75
-
76
- def desc_create(file:, contents:, opts: {})
77
- path = abs_path( file)
78
- if opts[:exec]
79
- adj = "executable "
80
- end
81
- if File.exists? path
82
- "Overwriting #{adj}#{file}!"
83
- else
84
- "Create #{adj}#{file}"
85
- end
86
- end
87
-
88
- def do_create(file:, contents:, opts: {})
89
- path = abs_path( file)
90
- FileUtils.mkdir_p File.dirname(path)
91
- File.write path, contents
92
- FileUtils.chmod '+x', path if opts[:exec]
93
- end
94
-
95
- def opt_create(file,contents)
96
- @changes << [:opt_create,file: file,contents: contents]
97
- end
98
-
99
- def check_opt_create(file:, contents:)
100
- if File.exists? abs_path( file)
101
- :skip
102
- end
103
- end
104
-
105
- def desc_opt_create(opts)
106
- desc_create opts
107
- end
108
-
109
- def do_opt_create(opts)
110
- do_create opts
111
- end
112
-
113
- def add_line(file,line,opts={})
114
- @changes << [:add_line,file: file,line: line,opts: opts]
115
- end
116
-
117
- def check_add_line(file:,line:,opts:)
118
- if File.exists? abs_path(file)
119
- File.open(file) do |f|
120
- if opts[:after]
121
- found = until f.eof?
122
- break true if f.readline.chomp == opts[:after]
123
- end
124
- unless found
125
- puts "File \"#{file}\" doesn't contain required line #{opts[:after]}"
126
- return :abort
127
- end
128
- end
129
- until f.eof?
130
- l = f.readline
131
- if opts[:match] ? l.chomp.match(opts[:match]) : (l.chomp == line)
132
- return :skip
133
- end
134
- end
135
- end
136
- else
137
- unless @changes.find {|c| [:create,:opt_create].include?(c[0]) && c[1][:file] == file}
138
- puts "File \"#{file}\" doesn't exist!"
139
- return :abort
140
- end
141
- end
142
- end
143
-
144
- def desc_add_line(file:,line:,opts:)
145
- "Add line \"#{line}\" to #{file}"
146
- end
147
-
148
- def do_add_line(file:,line:,opts:)
149
- if opts[:after]
150
- File.write file, File.read(file).sub(/^#{Regexp.quote(opts[:after])}\n/){|m| m + line + "\n"}
151
- else
152
- File.open(file,'a') do |f|
153
- f.puts line
154
- end
155
- end
156
- end
157
-
158
- def trigger(file,cmd)
159
- @triggers << [file, cmd]
160
- end
161
-
162
- def check_trigger(changes,file)
163
- changes.find {|c| c[1][:file] == file}
164
- end
165
-
166
- def desc_trigger(cmd:)
167
- "Run \"#{cmd}\""
168
- end
169
-
170
- def do_trigger(cmd:)
171
- system cmd
172
- end
173
-
174
- def check_changes
175
- puts "Checking preconditions..."
176
- abort = false
177
- unless Dir.exists?(@root_dir)
178
- puts "Root dir doesn't exist"
179
- exit 1
180
- end
181
- do_changes = []
182
- @changes.each do |(type,args)|
183
- res = send "check_#{type}", args
184
- abort = true if res == :abort
185
- do_changes << [type,args] unless res == :skip
186
- end
187
- @triggers.each do |(file,cmd)|
188
- if check_trigger do_changes, file
189
- do_changes << [:trigger,cmd: cmd]
190
- end
191
- end
192
- exit 1 if abort
193
- do_changes
194
- end
195
-
196
- def print_overview(changes)
197
- puts "Overview of changes to be made:"
198
-
199
- changes.each do |(type,args)|
200
- desc = send "desc_#{type}", args
201
- puts " #{desc}" if desc
202
- end
203
- print "Proceed? "
204
- resp = STDIN.gets.chomp
205
- unless resp =~ /^y(es?)?/i
206
- puts "Aborting"
207
- exit
208
- end
209
- end
210
-
211
- def write
212
- puts "Using project root: #{@root_dir}\n"
213
- do_changes = check_changes
214
- print_overview do_changes
215
-
216
- puts "Writing changes..."
217
- do_changes.each do |(type,args)|
218
- send "do_#{type}", args
219
- end
220
- puts "Done"
221
- end
222
-
223
- def abs_path(p)
224
- File.expand_path(p,@root_dir)
225
- end
226
- end
227
-
228
53
  project_name = ARGV[1]
229
54
 
230
- fw = AlkiFileWriter.new config[:project_dir]
55
+ fw = Alki::Generator.new options[:project_dir]
231
56
 
232
57
  config_dir = options[:config_dir] || 'config'
233
58
  primary_config = options[:primary_config] || 'assembly'
@@ -261,7 +86,7 @@ if options[:addons].include? "console"
261
86
  fw.add_line "Gemfile", "gem 'alki-console'", match: /^gem ['"]alki-console['"]/
262
87
 
263
88
  name = project_name.tr('/','-')
264
- fw.add_line primary_config_path, " mount :console, 'alki/console', name: '#{name}'", match: /^\s*assembly :console/, after: 'Alki do'
89
+ fw.add_line primary_config_path, " mount :console, 'alki/console', name: '#{name}'", match: /^\s*mount\( *:console/, after: 'Alki do'
265
90
 
266
91
  fw.create_exec 'bin/console', <<END
267
92
  #!/usr/bin/env ruby
@@ -272,4 +97,12 @@ require '#{project_name}'
272
97
  END
273
98
  end
274
99
 
100
+ if options[:addons].include? "reload"
101
+ fw.add_line "Gemfile", "gem 'alki-reload'", match: /^gem ['"]alki-reload['"]/
102
+
103
+ env_name = project_name.tr('a-z/','A-Z_')+"_ENV"
104
+ fw.add_line primary_config_path, " mount(:reloader, 'alki/reload'){ set(:watch) { development? } }", match: /^\s*mount\(? *:reloader/, after: 'Alki do'
105
+ fw.add_line primary_config_path, " set(:development?){ ENV['#{env_name}'] == 'development' }", match: /^\s*set :development?/, after: 'Alki do'
106
+ end
107
+
275
108
  fw.write
@@ -10,6 +10,7 @@ module Alki
10
10
  @config_dir = nil
11
11
  @assembly_name = nil
12
12
  @definition = nil
13
+ @load_mode = :direct
13
14
  end
14
15
 
15
16
  attr_reader :config_dir, :assembly_name, :definition
@@ -19,6 +20,7 @@ module Alki
19
20
  end
20
21
 
21
22
  def build(opts={},&blk)
23
+ @load_mode = opts[:load_mode] if opts[:load_mode]
22
24
  build_assembly blk if blk
23
25
  if opts[:config_dir]
24
26
  context = if opts[:project_assembly]
@@ -68,9 +70,7 @@ module Alki
68
70
  end
69
71
 
70
72
  def register_config_directory
71
- opts = {config_dir: @config_dir}
72
- opts[:prefix] = File.join(@assembly_name,'alki_config') if @assembly_name
73
- Alki::Dsl.register_dir @config_dir, 'alki/dsls/assembly', opts
73
+ Alki::Dsl.register_dir @config_dir, 'alki/dsls/assembly', dsl_opts
74
74
  end
75
75
 
76
76
  def load_assembly_file(name = nil)
@@ -78,7 +78,7 @@ module Alki
78
78
  if @config_dir
79
79
  assembly_config_path = File.join(@config_dir,"#{name}.rb")
80
80
  if File.exists? assembly_config_path
81
- @definition = Alki::Dsl.load(assembly_config_path)[:class]
81
+ @definition = assembly_config_path
82
82
  true
83
83
  end
84
84
  end
@@ -89,22 +89,47 @@ module Alki
89
89
  end
90
90
 
91
91
  def build_assembly(blk)
92
- @definition = Alki::Dsl.build('alki/dsls/assembly', config_dir: @config_dir, &blk)[:class]
92
+ @definition = Alki::Dsl.build('alki/dsls/assembly', dsl_opts, &blk)[:class]
93
+ end
94
+
95
+ def dsl_opts
96
+ opts = {config_dir: @config_dir}
97
+ if @assembly_name
98
+ opts[:prefix] = File.join(@assembly_name,'alki_config')
99
+ opts[:assembly_name] = @assembly_name
100
+ end
101
+ opts
93
102
  end
94
103
 
95
104
  def build_class
96
105
  definition = @definition
106
+ name = @assembly_name
107
+ load_class = if @load_mode == :require
108
+ ->{ name }
109
+ else
110
+ ->{ self }
111
+ end
97
112
  Alki::ClassBuilder.build(
98
113
  prefix: '',
99
114
  name: @assembly_name,
100
115
  class_modules: [Alki::Assembly],
101
116
  type: :module,
102
117
  class_methods: {
118
+ assembly_name: {
119
+ body: ->{
120
+ name
121
+ }
122
+ },
103
123
  definition: {
104
124
  body: ->{
105
- definition
125
+ definition.is_a?(String) ?
126
+ Alki::Dsl.load(definition)[:class] :
127
+ definition
106
128
  }
107
129
  },
130
+ load_class: {
131
+ body: load_class
132
+ }
108
133
  }
109
134
  )
110
135
  end
@@ -11,16 +11,18 @@ module Alki
11
11
  @overlays = overlays
12
12
  @data = {}
13
13
  @semaphore = Monitor.new
14
- clear
15
- end
16
-
17
- def clear
18
14
  @lookup_cache = {}
19
15
  @call_cache = {}
20
16
  @context_cache = {}
21
17
  @processed_overlays = false
22
18
  end
23
19
 
20
+ def synchronize
21
+ @semaphore.synchronize do
22
+ yield
23
+ end
24
+ end
25
+
24
26
  def call(path,*args,&blk)
25
27
  execute({},path,args,blk)
26
28
  end
@@ -29,7 +31,7 @@ module Alki
29
31
  cache_entry = @call_cache[path]
30
32
  if cache_entry
31
33
  if cache_entry.status == :building
32
- raise "Circular element reference found"
34
+ raise "Circular element reference found: #{path.join(".")}"
33
35
  end
34
36
  else
35
37
  @semaphore.synchronize do
@@ -49,6 +51,15 @@ module Alki
49
51
  call_value(cache_entry.type,cache_entry.value,meta,args,blk)
50
52
  end
51
53
 
54
+ def canonical_path(from,path)
55
+ from_elem = lookup(from)
56
+ scope = from_elem[:full_scope] || from_elem[:scope]
57
+ path.inject(nil) do |p,elem|
58
+ scope = lookup(p)[:scope] if p
59
+ scope[elem]
60
+ end
61
+ end
62
+
52
63
  private
53
64
 
54
65
  def process_overlays
@@ -58,8 +69,11 @@ module Alki
58
69
  @overlays.each do |(from,info)|
59
70
  target = canonical_path(from,info.target) or
60
71
  raise InvalidPathError.new("Invalid overlay target #{info.target.join('.')}")
61
- overlay = canonical_path(from,info.overlay) or
62
- raise InvalidPathError.new("Invalid overlay path #{info.overlay.join('.')}")
72
+ overlay = info.overlay
73
+ if overlay.is_a?(Array)
74
+ overlay = canonical_path(from,info.overlay) or
75
+ raise InvalidPathError.new("Invalid overlay path #{info.overlay.join('.')}")
76
+ end
63
77
  (@data[:overlays][target]||=[]) << [overlay,info.args]
64
78
  end
65
79
  end
@@ -84,15 +98,6 @@ module Alki
84
98
  elem.output data
85
99
  end
86
100
 
87
-
88
- def canonical_path(from,path)
89
- scope = lookup(from)[:full_scope]
90
- path.inject(nil) do |p,elem|
91
- scope = lookup(p)[:scope] if p
92
- scope[elem]
93
- end
94
- end
95
-
96
101
  def process_action(action)
97
102
  if action.key?(:value)
98
103
  [:value,action[:value]]
@@ -1,20 +1,37 @@
1
+ require 'delegate'
2
+ require 'alki/support'
3
+
1
4
  module Alki
2
5
  module Assembly
3
- class Instance
4
- def initialize(executor)
5
- @executor = executor
6
+ class Instance < Delegator
7
+ def initialize(assembly_module,args)
8
+ @assembly_module = assembly_module
9
+ @args = args
6
10
  end
7
11
 
8
- def root
9
- @root ||= @executor.call []
12
+ def __reload__
13
+ if @obj.respond_to? :__reload__
14
+ did_something = @obj.__reload__
15
+ end
16
+ if did_something != false && @obj
17
+ @obj = nil
18
+ did_something = true
19
+ end
20
+ if did_something
21
+ GC.start
22
+ end
23
+ !!did_something
10
24
  end
11
25
 
12
- def respond_to_missing?(name,include_all)
13
- root.respond_to? name
26
+ def __setobj__(obj)
27
+ @obj = obj
14
28
  end
15
29
 
16
- def method_missing(name,*args,&blk)
17
- root.send name, *args, &blk
30
+ def __getobj__
31
+ unless @obj
32
+ Alki::Support.load_class(@assembly_module).raw_instance self, *@args
33
+ end
34
+ @obj
18
35
  end
19
36
  end
20
37
  end
@@ -12,7 +12,7 @@ Alki do
12
12
  },
13
13
  proc: -> (elem) {
14
14
  elem[:value] = overlays.inject(__build__) do |val,(overlay,args)|
15
- overlay = root.lookup(overlay)
15
+ overlay = root.lookup(overlay) if overlay.is_a?(Array)
16
16
  if !overlay.respond_to?(:call) && overlay.respond_to?(:new)
17
17
  overlay = overlay.method(:new)
18
18
  end
data/lib/alki/assembly.rb CHANGED
@@ -3,26 +3,34 @@ require 'alki/assembly/types/assembly'
3
3
  require 'alki/assembly/types/group'
4
4
  require 'alki/assembly/instance'
5
5
  require 'alki/assembly/executor'
6
+ require 'alki/overlay_info'
6
7
 
7
8
  module Alki
8
9
  module Assembly
9
10
  def new(overrides={},&blk)
11
+ Instance.new load_class, [overrides, blk]
12
+ end
13
+
14
+ def raw_instance(instance,overrides,blk)
10
15
  overrides_info = OverrideBuilder.build(overrides,&blk)
11
16
  override_root = overrides_info[:root] || build(:group)
12
17
 
13
18
  assembly = build :assembly, root, override_root
14
- executor = Executor.new(assembly, overlays+overrides_info[:overlays])
19
+ update_instance_overlay = [[],OverlayInfo.new(
20
+ [:assembly_instance],
21
+ ->obj{instance.__setobj__ obj; instance},
22
+ []
23
+ )]
24
+ all_overlays = overlays+overrides_info[:overlays]+[update_instance_overlay]
25
+ executor = Executor.new(assembly, all_overlays)
15
26
 
16
27
  override_root.children[:assembly_instance] = build(:service,->{
17
- Instance.new(executor)
28
+ root
18
29
  })
30
+ override_root.children[:assembly_executor] = build(:value,executor)
19
31
  executor.call [:assembly_instance]
20
32
  end
21
33
 
22
- def build(type,*args)
23
- Alki::Support.load_class("alki/assembly/types/#{type}").new *args
24
- end
25
-
26
34
  def root
27
35
  self.definition.root
28
36
  end
@@ -30,5 +38,11 @@ module Alki
30
38
  def overlays
31
39
  self.definition.overlays
32
40
  end
41
+
42
+ private
43
+
44
+ def build(type,*args)
45
+ Alki::Support.load_class("alki/assembly/types/#{type}").new *args
46
+ end
33
47
  end
34
48
  end
@@ -4,6 +4,7 @@ Alki do
4
4
 
5
5
  finish do
6
6
  add :config_dir, build(:value, ctx[:config_dir])
7
+ add :assembly_name, build(:value, ctx[:assembly_name])
7
8
  prefix_overlays :original, ctx[:overlays]
8
9
 
9
10
  root = ctx[:root]
@@ -1,5 +1,6 @@
1
1
  require 'alki/execution/context'
2
2
  require 'alki/overlay_delegator'
3
+ require 'alki/reloadable_delegator'
3
4
 
4
5
  module Alki
5
6
  module Execution
@@ -9,6 +10,14 @@ module Alki
9
10
  def delegate_overlay(obj,overlay,**args)
10
11
  Alki::OverlayDelegator.new(obj,overlay,args)
11
12
  end
13
+
14
+ def entrypoint(klass,*args, reloadable: false)
15
+ klass.new *args.map {|a| reloadable ? self.reloadable(a) : lookup(a) }
16
+ end
17
+
18
+ def reloadable(path)
19
+ Alki::ReloadableDelegator.new(root.assembly_instance,meta[:building],path)
20
+ end
12
21
  end
13
22
  end
14
23
  end
@@ -0,0 +1,177 @@
1
+ module Alki
2
+ class Generator
3
+ def initialize(root_dir)
4
+ @root_dir = root_dir
5
+ @changes = []
6
+ @triggers = []
7
+ end
8
+
9
+ def create(file,contents)
10
+ @changes << [:create,file: file,contents: contents,opts: {}]
11
+ end
12
+
13
+ def create_exec(file,contents)
14
+ @changes << [:create,file: file,contents: contents,opts: {exec: true}]
15
+ end
16
+
17
+ def check_create(file:, contents:, opts:)
18
+ path = abs_path( file)
19
+ if File.exists? path
20
+ if File.read(path) == contents
21
+ :skip
22
+ end
23
+ end
24
+ end
25
+
26
+ def desc_create(file:, contents:, opts: {})
27
+ path = abs_path( file)
28
+ if opts[:exec]
29
+ adj = "executable "
30
+ end
31
+ if File.exists? path
32
+ "Overwriting #{adj}#{file}!"
33
+ else
34
+ "Create #{adj}#{file}"
35
+ end
36
+ end
37
+
38
+ def do_create(file:, contents:, opts: {})
39
+ path = abs_path( file)
40
+ FileUtils.mkdir_p File.dirname(path)
41
+ File.write path, contents
42
+ FileUtils.chmod '+x', path if opts[:exec]
43
+ end
44
+
45
+ def opt_create(file,contents)
46
+ @changes << [:opt_create,file: file,contents: contents]
47
+ end
48
+
49
+ def check_opt_create(file:, contents:)
50
+ if File.exists? abs_path( file)
51
+ :skip
52
+ end
53
+ end
54
+
55
+ def desc_opt_create(opts)
56
+ desc_create opts
57
+ end
58
+
59
+ def do_opt_create(opts)
60
+ do_create opts
61
+ end
62
+
63
+ def add_line(file,line,opts={})
64
+ @changes << [:add_line,file: file,line: line,opts: opts]
65
+ end
66
+
67
+ def check_add_line(file:,line:,opts:)
68
+ if File.exists? abs_path(file)
69
+ File.open(file) do |f|
70
+ if opts[:after]
71
+ found = until f.eof?
72
+ break true if f.readline.chomp == opts[:after]
73
+ end
74
+ unless found
75
+ puts "File \"#{file}\" doesn't contain required line #{opts[:after]}"
76
+ return :abort
77
+ end
78
+ end
79
+ until f.eof?
80
+ l = f.readline
81
+ if opts[:match] ? l.chomp.match(opts[:match]) : (l.chomp == line)
82
+ return :skip
83
+ end
84
+ end
85
+ end
86
+ else
87
+ unless @changes.find {|c| [:create,:opt_create].include?(c[0]) && c[1][:file] == file}
88
+ puts "File \"#{file}\" doesn't exist!"
89
+ return :abort
90
+ end
91
+ end
92
+ end
93
+
94
+ def desc_add_line(file:,line:,opts:)
95
+ "Add line \"#{line}\" to #{file}"
96
+ end
97
+
98
+ def do_add_line(file:,line:,opts:)
99
+ if opts[:after]
100
+ File.write file, File.read(file).sub(/^#{Regexp.quote(opts[:after])}\n/){|m| m + line + "\n"}
101
+ else
102
+ File.open(file,'a') do |f|
103
+ f.puts line
104
+ end
105
+ end
106
+ end
107
+
108
+ def trigger(file,cmd)
109
+ @triggers << [file, cmd]
110
+ end
111
+
112
+ def check_trigger(changes,file)
113
+ changes.find {|c| c[1][:file] == file}
114
+ end
115
+
116
+ def desc_trigger(cmd:)
117
+ "Run \"#{cmd}\""
118
+ end
119
+
120
+ def do_trigger(cmd:)
121
+ system cmd
122
+ end
123
+
124
+ def check_changes
125
+ puts "Checking preconditions..."
126
+ abort = false
127
+ unless Dir.exists?(@root_dir)
128
+ puts "Root dir doesn't exist"
129
+ exit 1
130
+ end
131
+ do_changes = []
132
+ @changes.each do |(type,args)|
133
+ res = send "check_#{type}", args
134
+ abort = true if res == :abort
135
+ do_changes << [type,args] unless res == :skip
136
+ end
137
+ @triggers.each do |(file,cmd)|
138
+ if check_trigger do_changes, file
139
+ do_changes << [:trigger,cmd: cmd]
140
+ end
141
+ end
142
+ exit 1 if abort
143
+ do_changes
144
+ end
145
+
146
+ def print_overview(changes)
147
+ puts "Overview of changes to be made:"
148
+
149
+ changes.each do |(type,args)|
150
+ desc = send "desc_#{type}", args
151
+ puts " #{desc}" if desc
152
+ end
153
+ print "Proceed? "
154
+ resp = STDIN.gets.chomp
155
+ unless resp =~ /^y(es?)?/i
156
+ puts "Aborting"
157
+ exit
158
+ end
159
+ end
160
+
161
+ def write
162
+ puts "Using project root: #{@root_dir}\n"
163
+ do_changes = check_changes
164
+ print_overview do_changes
165
+
166
+ puts "Writing changes..."
167
+ do_changes.each do |(type,args)|
168
+ send "do_#{type}", args
169
+ end
170
+ puts "Done"
171
+ end
172
+
173
+ def abs_path(p)
174
+ File.expand_path(p,@root_dir)
175
+ end
176
+ end
177
+ end
@@ -0,0 +1,17 @@
1
+ require 'delegate'
2
+
3
+ module Alki
4
+ class ReloadableDelegator < Delegator
5
+ def initialize(instance,from,path)
6
+ @instance = instance
7
+ @from = from.to_s.split('.').map(&:to_sym)
8
+ @path = path.to_s.split('.').map(&:to_sym)
9
+ end
10
+
11
+ def __getobj__
12
+ @instance.assembly_executor.call(
13
+ @instance.assembly_executor.canonical_path(@from,@path)
14
+ )
15
+ end
16
+ end
17
+ end
data/lib/alki/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Alki
2
- VERSION = "0.9.0"
2
+ VERSION = "0.9.1"
3
3
  end
data/lib/alki.rb CHANGED
@@ -5,6 +5,7 @@ module Alki
5
5
  class << self
6
6
  def project_assembly!(opts={},&blk)
7
7
  opts[:project_assembly] ||= caller_locations(1,1)[0].absolute_path
8
+ opts[:load_mode] = :require
8
9
  Assembly::Builder.build(opts,&blk)
9
10
  end
10
11
 
@@ -210,16 +210,18 @@ describe 'Overlays' do
210
210
 
211
211
  it 'should allow setting overlays on assembly_instance' do
212
212
  values = []
213
+ mock = Minitest::Mock.new
213
214
  assembly = Alki.create_assembly do
214
215
  overlay :assembly_instance, :test_overlay
215
-
216
+ set :val, 1
216
217
  set :test_overlay, ->(value) {
217
218
  values << value
218
- :transformed
219
+ mock
219
220
  }
220
221
  end
221
- assembly.new.must_equal :transformed
222
+ mock.expect :val, 2
223
+ assembly.new.val.must_equal 2
222
224
  values.size.must_equal 1
223
- values[0].must_be_instance_of Alki::Assembly::Instance
225
+ values[0].val.must_equal 1
224
226
  end
225
227
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alki
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Edlefsen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-12-17 00:00:00.000000000 Z
11
+ date: 2016-12-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -138,9 +138,11 @@ files:
138
138
  - lib/alki/execution/context_class_builder.rb
139
139
  - lib/alki/execution/value_context.rb
140
140
  - lib/alki/feature_test.rb
141
+ - lib/alki/generator.rb
141
142
  - lib/alki/overlay_delegator.rb
142
143
  - lib/alki/overlay_info.rb
143
144
  - lib/alki/override_builder.rb
145
+ - lib/alki/reloadable_delegator.rb
144
146
  - lib/alki/service_delegator.rb
145
147
  - lib/alki/test.rb
146
148
  - lib/alki/version.rb
@@ -186,7 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
186
188
  version: '0'
187
189
  requirements: []
188
190
  rubyforge_project:
189
- rubygems_version: 2.5.1
191
+ rubygems_version: 2.5.2
190
192
  signing_key:
191
193
  specification_version: 4
192
194
  summary: Base library for building applications.