ro 1.4.6 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +6 -14
  2. data/Gemfile +2 -0
  3. data/Gemfile.lock +43 -0
  4. data/LICENSE +1 -0
  5. data/README.md +120 -112
  6. data/README.md.erb +159 -0
  7. data/Rakefile +129 -78
  8. data/bin/ro +241 -68
  9. data/lib/ro/_lib.rb +95 -0
  10. data/lib/ro/asset.rb +45 -0
  11. data/lib/ro/collection/list.rb +23 -0
  12. data/lib/ro/collection.rb +168 -0
  13. data/lib/ro/config.rb +68 -0
  14. data/lib/ro/error.rb +8 -0
  15. data/lib/ro/klass.rb +25 -0
  16. data/lib/ro/methods.rb +238 -0
  17. data/lib/ro/model.rb +83 -114
  18. data/lib/ro/node.rb +177 -360
  19. data/lib/ro/pagination.rb +7 -4
  20. data/lib/ro/path.rb +225 -0
  21. data/lib/ro/root.rb +52 -31
  22. data/lib/ro/script/builder.rb +221 -0
  23. data/lib/ro/script/console.rb +47 -0
  24. data/lib/ro/script/server.rb +76 -0
  25. data/lib/ro/script.rb +189 -0
  26. data/lib/ro/slug.rb +19 -18
  27. data/lib/ro/template/rouge_formatter.rb +42 -0
  28. data/lib/ro/template.rb +104 -50
  29. data/lib/ro.rb +85 -317
  30. data/public/api/ro/index-1.json +147 -0
  31. data/public/api/ro/index.json +137 -0
  32. data/public/api/ro/posts/first_post/index.json +52 -0
  33. data/public/api/ro/posts/index-1.json +145 -0
  34. data/public/api/ro/posts/index.json +135 -0
  35. data/public/api/ro/posts/second_post/index.json +51 -0
  36. data/public/api/ro/posts/third_post/index.json +51 -0
  37. data/public/ro/posts/first_post/assets/foo/bar/baz.jpg +0 -0
  38. data/public/ro/posts/first_post/assets/foo.jpg +0 -0
  39. data/public/ro/posts/first_post/assets/src/foo/bar.rb +3 -0
  40. data/public/ro/posts/first_post/attributes.yml +2 -0
  41. data/public/ro/posts/first_post/blurb.erb.md +7 -0
  42. data/public/ro/posts/first_post/body.md +16 -0
  43. data/public/ro/posts/first_post/testing.txt +3 -0
  44. data/public/ro/posts/second_post/assets/foo/bar/baz.jpg +0 -0
  45. data/public/ro/posts/second_post/assets/foo.jpg +0 -0
  46. data/public/ro/posts/second_post/assets/src/foo/bar.rb +3 -0
  47. data/public/ro/posts/second_post/attributes.yml +2 -0
  48. data/public/ro/posts/second_post/blurb.erb.md +5 -0
  49. data/public/ro/posts/second_post/body.md +16 -0
  50. data/public/ro/posts/third_post/assets/foo/bar/baz.jpg +0 -0
  51. data/public/ro/posts/third_post/assets/foo.jpg +0 -0
  52. data/public/ro/posts/third_post/assets/src/foo/bar.rb +3 -0
  53. data/public/ro/posts/third_post/attributes.yml +2 -0
  54. data/public/ro/posts/third_post/blurb.erb.md +5 -0
  55. data/public/ro/posts/third_post/body.md +16 -0
  56. data/ro.gemspec +89 -29
  57. metadata +106 -90
  58. data/TODO.md +0 -50
  59. data/lib/ro/blankslate.rb +0 -7
  60. data/lib/ro/cache.rb +0 -26
  61. data/lib/ro/git.rb +0 -374
  62. data/lib/ro/initializers/env.rb +0 -5
  63. data/lib/ro/initializers/tilt.rb +0 -104
  64. data/lib/ro/lock.rb +0 -53
  65. data/lib/ro/node/list.rb +0 -142
  66. data/notes/ara.txt +0 -215
data/lib/ro/git.rb DELETED
@@ -1,374 +0,0 @@
1
- module Ro
2
- class Git
3
- attr_accessor :root
4
- attr_accessor :branch
5
- attr_accessor :patching
6
-
7
- def initialize(root, options = {})
8
- options = Map.for(options)
9
-
10
- @root = root
11
- @branch = options[:branch] || 'master'
12
- end
13
-
14
- # patch takes a block, allows abitrary edits (additions, modifications,
15
- # deletions) to be performed by it, and then computes a single, atomic patch
16
- # that is applied to the repo and pushed. the patch is returned. if the
17
- # patch was not applied then patch.applied==false and it's up to client code
18
- # to decide how to proceed, perhaps retrying or saving the patchfile for
19
- # later manual application
20
- #
21
- def patch(*args, &block)
22
- options = Map.options_for!(args)
23
-
24
- user = options[:user] || ENV['USER'] || 'ro'
25
- msg = options[:message] || "#{ user } edits on #{ File.basename(@root).inspect }"
26
- add = options.has_key?(:add) ? options[:add] : true
27
-
28
- patch = nil
29
-
30
- Thread.exclusive do
31
- @root.lock do
32
- Dir.chdir(@root) do
33
- # ensure .git-ness
34
- #
35
- status, stdout, stderr = spawn("git rev-parse --git-dir", :raise => true, :capture => true)
36
-
37
- git_root = stdout.to_s.strip
38
-
39
- dot_git = File.expand_path(git_root)
40
-
41
- unless test(?d, dot_git)
42
- raise Error.new("missing .git directory #{ dot_git }")
43
- end
44
-
45
- # calculate a tmp branch name
46
- #
47
- time = Coerce.time(options[:time] || Time.now).utc.iso8601(2).gsub(/[^\w]/, '')
48
- branch = "#{ user }-#{ time }-#{ rand.to_s.gsub(/^0./, '') }"
49
-
50
- # allow block to edit, compute the patch, attempt to apply it
51
- #
52
- begin
53
- # get pristine
54
- #
55
- spawn("git checkout -f master", :raise => true)
56
- spawn("git fetch --all", :raise => true)
57
- spawn("git reset --hard origin/master", :raise => true)
58
-
59
- # pull recent changes
60
- #
61
- trying('to pull'){ spawn("git pull origin master") }
62
-
63
- # create a new temporary branch
64
- #
65
- spawn("git checkout -b #{ branch.inspect }", :raise => true)
66
-
67
- # the block can perform arbitrary edits
68
- #
69
- block.call
70
-
71
- # add all changes - additions, deletions, or modifications - unless :add => false was specified
72
- #
73
- if add
74
- spawn("git add . --all", :raise => true)
75
- end
76
-
77
- # commit if anything changed
78
- #
79
- changes_to_apply =
80
- spawn("git commit -m #{ msg.inspect }")
81
-
82
- if changes_to_apply
83
- # create the patch
84
- #
85
- status, stdout, stderr =
86
- spawn("git format-patch master --stdout", :raise => true, :capture => true)
87
-
88
- patch = Patch.new(:data => stdout, :name => branch)
89
-
90
- unless stdout.to_s.strip.empty?
91
- # apply the patch
92
- #
93
- spawn("git checkout master", :raise => true)
94
-
95
- #
96
- spawn("git rebase --abort")
97
- spawn("git am --abort")
98
-
99
- spawn("git am --abort")
100
- spawn("git rebase --abort")
101
-
102
- #
103
- status, stdout, stderr =
104
- spawn("git am --signoff --3way --ignore-space-change --ignore-whitespace", :capture => true, :stdin => patch.data)
105
-
106
- #
107
- patch.applied = !!(status == 0)
108
-
109
- # commit the patch back to the repo
110
- #
111
- patch.committed =
112
- begin
113
- trying('to pull'){ spawn("git pull origin master") }
114
- trying('to push'){ spawn("git push origin master") }
115
- true
116
- rescue Object
117
- false
118
- end
119
- end
120
- end
121
- ensure
122
- # get pristine
123
- #
124
- spawn("git checkout -f master", :raise => true)
125
- spawn("git fetch --all", :raise => true)
126
- spawn("git reset --hard origin/master", :raise => true)
127
-
128
- spawn("git am --abort")
129
- spawn("git rebase --abort")
130
-
131
- # get changes
132
- #
133
- trying('to pull'){ spawn("git pull") }
134
-
135
- # nuke the tmp branch
136
- #
137
- if patch and patch.applied and patch.committed
138
- spawn("git branch -D #{ branch.inspect }")
139
- end
140
- end
141
- end
142
- end
143
- end
144
-
145
- patch
146
- end
147
-
148
- #
149
- class Patch
150
- fattr :data
151
- fattr :name
152
- fattr :applied
153
- fattr :committed
154
- fattr :status
155
- fattr :stdout
156
- fattr :stderr
157
-
158
- def initialize(*args)
159
- options = Map.options_for!(args)
160
-
161
- self.class.fattrs.each do |key|
162
- send(key, options.get(key)) if options.has?(key)
163
- end
164
-
165
- unless args.empty?
166
- self.data = args.join
167
- end
168
- end
169
-
170
- def save(path)
171
- return false unless data
172
- path = path.to_s
173
- FileUtils.mkdir_p(File.dirname(path))
174
- IO.binwrite(path, data)
175
- end
176
-
177
- %w( to_s to_str ).each do |method|
178
- class_eval <<-__, __FILE__, __LINE__
179
- def #{ method }
180
- data
181
- end
182
- __
183
- end
184
-
185
- %w( filename pathname basename ).each do |method|
186
- class_eval <<-__, __FILE__, __LINE__
187
- def #{ method }
188
- name
189
- end
190
- __
191
- end
192
-
193
- %w( success success? applied applied? ).each do |method|
194
- class_eval <<-__, __FILE__, __LINE__
195
- def #{ method }
196
- status && status == 0
197
- end
198
- __
199
- end
200
- end
201
-
202
-
203
-
204
- def save(directory, options = {})
205
- if directory.is_a?(Node)
206
- directory = directory.path
207
- end
208
-
209
- options = Map.for(options)
210
-
211
- dir = File.expand_path(directory.to_s)
212
-
213
- relative_path = Ro.relative_path(dir, :from => @root)
214
-
215
- exists = test(?d, dir)
216
-
217
- action = exists ? 'edited' : 'created'
218
-
219
- msg = options[:message] || "#{ ENV['USER'] } #{ action } #{ relative_path }"
220
-
221
- @root.lock do
222
- FileUtils.mkdir_p(dir) unless exists
223
-
224
- Dir.chdir(dir) do
225
- # .git
226
- #
227
- status, stdout, stderr = spawn("git rev-parse --git-dir", :raise => true, :capture => true)
228
-
229
- git_root = stdout.to_s.strip
230
-
231
- dot_git = File.expand_path(git_root)
232
-
233
- unless test(?d, dot_git)
234
- raise Error.new("missing .git directory #{ dot_git }")
235
- end
236
-
237
- # correct branch
238
- #
239
- spawn("git checkout #{ @branch.inspect }", :raise => true)
240
-
241
- # return if nothing to do...
242
- #
243
- if `git status --porcelain`.strip.empty?
244
- return true
245
- end
246
-
247
- # commit the work
248
- #
249
- trying "to commit" do
250
-
251
- committed =
252
- spawn("git add --all . && git commit -m #{ msg.inspect } -- .")
253
-
254
- =begin
255
- unless committed
256
- spawn "git reset --hard"
257
- end
258
- =end
259
-
260
- #require 'pry'
261
- #binding.pry
262
- =begin
263
- retried = false
264
- begin
265
- spawn "git add --all . && git commit -m #{ msg.inspect } -- ."
266
- committed = true
267
- rescue
268
- raise if retried
269
- spawn "git reset --hard", :raise => false
270
- retry
271
- end
272
- =end
273
- end
274
-
275
-
276
- trying "to push" do
277
- pushed = nil
278
-
279
- unless spawn("git push origin master")
280
- # merge
281
- #
282
- unless spawn("git pull")
283
- spawn("git checkout --ours -- .")
284
- spawn("git add --all .")
285
- spawn("git commit -F #{ dot_git }/MERGE_MSG")
286
- else
287
- raise 'wtf!?'
288
- end
289
-
290
- pushed = spawn("git push origin master")
291
- else
292
- pushed = true
293
- end
294
-
295
- pushed
296
- end
297
-
298
- =begin
299
- git push
300
-
301
- git pull
302
-
303
- # publish
304
- git checkout --ours -- .
305
- git add --all .
306
- git commit -F .git/MERGE_MSG
307
- git push
308
- =end
309
-
310
-
311
-
312
- end
313
- end
314
- end
315
-
316
- class Error < ::StandardError;end
317
-
318
- def trying(*args, &block)
319
- options = Map.options_for!(args)
320
- label = ['trying', *args].join(' - ')
321
-
322
- n = Integer(options[:n] || 3)
323
- timeout = options[:timeout]
324
- e = nil
325
- done = nil
326
- not_done = Object.new.freeze
327
-
328
- result =
329
- catch(:trying) do
330
- n.times do |i|
331
- done = block.call
332
- if done
333
- throw(:trying, done)
334
- else
335
- unless timeout == false
336
- sleep( (i + 1) * (timeout || (1 + rand)) )
337
- end
338
- end
339
- end
340
-
341
- not_done
342
- end
343
-
344
- if result == not_done
345
- raise(Error.new("#{ label } failed #{ n } times"))
346
- else
347
- done
348
- end
349
- end
350
-
351
- def spawn(command, options = {})
352
- options = Map.for(options)
353
-
354
- status, stdout, stderr = systemu(command, :stdin => options[:stdin])
355
-
356
- Ro.log(:debug, "command: #{ command }")
357
- Ro.log(:debug, "status: #{ status }")
358
- Ro.log(:debug, "stdout:\n#{ stdout }")
359
- Ro.log(:debug, "stderr:\n#{ stderr }")
360
-
361
- if options[:raise] == true
362
- unless status == 0
363
- raise "command (#{ command }) failed with #{ status }"
364
- end
365
- end
366
-
367
- if options[:capture]
368
- [status, stdout, stderr]
369
- else
370
- status == 0
371
- end
372
- end
373
- end
374
- end
@@ -1,5 +0,0 @@
1
- module Ro
2
- if ENV['RO_DEBUG']
3
- Ro.debug!
4
- end
5
- end
@@ -1,104 +0,0 @@
1
- require 'tilt'
2
-
3
- module Tilt
4
- class SyntaxHighlightingRedcarpetTemplate < Template
5
- self.default_mime_type = 'text/html'
6
-
7
- def self.engine_initialized?
8
- defined?(::Redcarpet) && defined?(::Pygments) && defined?(::ERB)
9
- end
10
-
11
- def initialize_engine
12
- require_template_library('redcarpet')
13
- require_template_library('pygments')
14
- require_template_library('erb')
15
- end
16
-
17
- def prepare
18
- @engine =
19
- Redcarpet::Markdown.new(
20
- syntax_highlighting_renderer,
21
-
22
- :no_intra_emphasis => true,
23
- :tables => true,
24
- :fenced_code_blocks => true,
25
- :autolink => true,
26
- :disable_indented_code_blocks => true,
27
- :strikethrough => true,
28
- :lax_spacing => true,
29
- :space_after_headers => false,
30
- :superscript => true,
31
- :underline => true,
32
- :highlight => true,
33
- :quote => true,
34
-
35
- :with_toc_data => true,
36
- :hard_wrap => true,
37
- )
38
-
39
- @output = nil
40
- end
41
-
42
- def syntax_highlighting_renderer
43
- Class.new(Redcarpet::Render::HTML) do
44
- def block_code(code, language)
45
- language = 'ruby' if language.to_s.strip.empty?
46
- ::Pygments.highlight(code, :lexer => language, :options => {:encoding => 'utf-8'})
47
- end
48
- end
49
- end
50
-
51
- def evaluate(scope, locals, &block)
52
- binding =
53
- if scope.is_a?(::Binding)
54
- scope
55
- else
56
- scope.instance_eval{ ::Kernel.binding }
57
- end
58
-
59
- @engine.render(erb(data, binding))
60
- end
61
-
62
- def erb(string, binding)
63
- string
64
- end
65
-
66
- def allows_script?
67
- true
68
- end
69
- end
70
-
71
- class ERBSyntaxHighlightingRedcarpetTemplate < SyntaxHighlightingRedcarpetTemplate
72
- def erb(string, binding)
73
- ::ERB.new(string).result(binding)
74
- end
75
- end
76
- end
77
-
78
- Tilt.prefer(Tilt::SyntaxHighlightingRedcarpetTemplate, 'md')
79
- Tilt.prefer(Tilt::SyntaxHighlightingRedcarpetTemplate, 'markdown')
80
- Tilt.prefer(Tilt::ERBSyntaxHighlightingRedcarpetTemplate, 'md.erb')
81
- Tilt.prefer(Tilt::ERBSyntaxHighlightingRedcarpetTemplate, 'markdown.erb')
82
-
83
-
84
- if $0 == __FILE__
85
-
86
- markdown = <<-__
87
- * one
88
- * two
89
- * <%= :three %>
90
- * <%= @x %>
91
-
92
- ```rb
93
- @a = 42
94
- yield
95
- ```
96
- __
97
-
98
- template = Tilt['md.erb'].new{ markdown }
99
-
100
- object = Object.new.instance_eval{ @x = :four; self }
101
-
102
- puts template.render(object)
103
-
104
- end
data/lib/ro/lock.rb DELETED
@@ -1,53 +0,0 @@
1
- module Ro
2
- class Lock
3
- def initialize(path)
4
- @path = path.to_s
5
- @fd = false
6
- end
7
-
8
- def lock(&block)
9
- open!
10
-
11
- if block
12
- begin
13
- lock!
14
- block.call
15
- ensure
16
- unlock!
17
- end
18
- else
19
- self
20
- end
21
- end
22
-
23
- def open!
24
- @fd ||= (
25
- fd =
26
- begin
27
- open(@path, 'ab+')
28
- rescue
29
- unless test(?e, @path)
30
- FileUtils.mkdir_p(@path)
31
- FileUtils.touch(@path)
32
- end
33
-
34
- open(@path, 'ab+')
35
- end
36
-
37
- fd.close_on_exec = true
38
-
39
- fd
40
- )
41
- end
42
-
43
- def lock!
44
- open!
45
- @fd.flock File::LOCK_EX
46
- end
47
-
48
- def unlock!
49
- open!
50
- @fd.flock File::LOCK_UN
51
- end
52
- end
53
- end
data/lib/ro/node/list.rb DELETED
@@ -1,142 +0,0 @@
1
- module Ro
2
- class Node
3
- class List < ::Array
4
- fattr :root
5
- fattr :type
6
- fattr :index
7
-
8
- def initialize(*args, &block)
9
- options = Map.options_for!(args)
10
-
11
- root = args.shift || options[:root]
12
- type = args.shift || options[:type]
13
-
14
- @root = Root.new(root)
15
- @type = type.nil? ? nil : String(type)
16
- @index = {}
17
-
18
- block.call(self) if block
19
- end
20
-
21
- def nodes
22
- self
23
- end
24
-
25
- def load(path)
26
- add( node = Node.new(path) )
27
- end
28
-
29
- def add(node)
30
- return nil if node.nil?
31
-
32
- unless index.has_key?(node.identifier)
33
- push(node)
34
- index[node.identifier] = node
35
- node
36
- else
37
- false
38
- end
39
- end
40
-
41
- def related(*args, &block)
42
- related = List.new(root)
43
-
44
- each do |node|
45
- node.related(*args, &block).each do |related_node|
46
- related.add(related_node)
47
- end
48
- end
49
-
50
- related
51
- end
52
-
53
- def [](*args, &block)
54
- key = args.first
55
-
56
- case key
57
- when String, Symbol
58
- if @type.nil?
59
- type = key.to_s
60
- list = select{|node| type == node._type}
61
- list.type = type
62
- list
63
- else
64
- id = Slug.for(key.to_s)
65
- detect{|node| id == node.id}
66
- end
67
- else
68
- super(*args, &block)
69
- end
70
- end
71
-
72
- def select(*args, &block)
73
- List.new(root){|list| list.replace(super)}
74
- end
75
-
76
- def where(*args, &block)
77
- case
78
- when !args.empty? && block
79
- raise ArgumentError.new
80
-
81
- when args.empty? && block
82
- select{|node| node.instance_eval(&block)}
83
-
84
- when !args.empty?
85
- ids = args.flatten.compact.uniq.map{|arg| Slug.for(arg.to_s)}
86
- index = ids.inject(Hash.new){|h,id| h.update(id => id)}
87
- select{|node| index[node.id]}
88
-
89
- else
90
- raise ArgumentError.new
91
- end
92
- end
93
-
94
- def find(*args, &block)
95
- case
96
- when !args.empty? && block
97
- raise ArgumentError.new
98
- when args.empty? && block
99
- detect{|node| node.instance_eval(&block)}
100
-
101
- when args.size == 1
102
- id = args.first.to_s
103
- detect{|node| node.id == id}
104
-
105
- when args.size > 1
106
- where(*args, &block)
107
-
108
- else
109
- raise ArgumentError.new
110
- end
111
- end
112
-
113
- def identifier
114
- [root, type].compact.join('/')
115
- end
116
-
117
- include Pagination
118
-
119
- def method_missing(method, *args, &block)
120
- Ro.log "Ro::List(#{ identifier })#method_missing(#{ method.inspect }, #{ args.inspect })"
121
-
122
- if @type.nil?
123
- type = method.to_s
124
- list = self[type]
125
- super unless list
126
- list.empty? ? super : list
127
- else
128
- node = self[Slug.for(method, :join => '-')] || self[Slug.for(method, :join => '_')]
129
- node.nil? ? super : node
130
- end
131
- end
132
-
133
- def binding
134
- Kernel.binding
135
- end
136
-
137
- def _binding
138
- Kernel.binding
139
- end
140
- end
141
- end
142
- end