ro 1.1.1 → 1.2.0
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 +8 -8
- data/README.md +26 -1
- data/Rakefile +1 -1
- data/TODO.md +50 -0
- data/bin/ro +13 -3
- data/lib/ro.rb +75 -26
- data/lib/ro/cache.rb +10 -4
- data/lib/ro/git.rb +359 -0
- data/lib/ro/initializers/tilt.rb +15 -8
- data/lib/ro/lock.rb +53 -0
- data/lib/ro/model.rb +150 -0
- data/lib/ro/node.rb +66 -17
- data/lib/ro/node/list.rb +87 -11
- data/lib/ro/root.rb +22 -0
- data/lib/ro/slug.rb +1 -0
- data/lib/ro/template.rb +15 -3
- data/notes/ara.txt +119 -0
- data/ro.gemspec +14 -40
- metadata +50 -19
- data/: +0 -9
- data/:w +0 -29
- data/lib/co/db.rb +0 -4
- data/lib/co/node.rb +0 -4
- data/lib/co/node/list.rb +0 -16
- data/lib/co/util.rb +0 -5
- data/ro/people/ara/assets/ara-glacier.jpg +0 -0
- data/ro/people/ara/assets/source/a.rb +0 -5
- data/ro/people/ara/attributes.yml +0 -12
- data/ro/people/ara/bio.md.erb +0 -18
- data/ro/people/noah/attributes.yml +0 -5
- data/ro/posts/hello-world/attributes.yml +0 -3
- data/ro/posts/hello-world/body.md +0 -3
- data/ro/posts/second-awesome-post/attributes.yml +0 -1
- data/ro/posts/second-awesome-post/body.md +0 -3
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NjU3NjMzOGVkNmQyZDFmNzk0MjBlOTc1MjRiYTFjYzhhOTFjM2E3NA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZWNmMmIyZjcwNTJkYmU0ZDJkZTYwZGYwYjE4MWEyZDdiMmM5Y2ZkMQ==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NjUxM2JkYjg5OTMxODM3ZGVmYjBhYjgwOTc3ZTFlYjY4N2FiNTQyMDc3ZDUz
|
10
|
+
M2FmNWQxMTMzYjk4NjlhYzIxYTcwYTQ3MTM2ODA0NDEwNzY2YjI2YWJiM2Ey
|
11
|
+
MzQzMTI5ZTE2MjZhMTE0Mjg0ZTNiZWY3OTdiNWYzYzk4ODA4MDA=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NWRkODVlNDYzY2I4NzA4N2Q1ZDM5MTNhYzc1OTU1YWE5MjQ5NWMxZGUwOTZk
|
14
|
+
YzA0MmJhNjdmNjg1ZjBhNTIxN2QwNzA1M2Q4ZWZkMmQ3ZDJlYjFmYmYwZjA4
|
15
|
+
M2VmZDlkZjY2ZWMyMTBhYjdlYzI0NTU2NWE5MDg5MTE4OTIwYmY=
|
data/README.md
CHANGED
@@ -5,7 +5,7 @@ ro
|
|
5
5
|
|
6
6
|
|
7
7
|
TL;DR
|
8
|
-
|
8
|
+
-----
|
9
9
|
|
10
10
|
<pre>
|
11
11
|
|
@@ -139,6 +139,31 @@ INSTALL
|
|
139
139
|
gem install ro
|
140
140
|
|
141
141
|
|
142
|
+
CONFIG
|
143
|
+
------
|
144
|
+
|
145
|
+
if you are using the url methods you'll need to make sure your application can
|
146
|
+
route to the assets. by default ro assumes that the urls it generates are
|
147
|
+
routeable under '/ro' so it is up to you to make sure this works.
|
148
|
+
|
149
|
+
for a rails app this might mean writing a 'RoController' or, more simply, just
|
150
|
+
putting your ro data in ./public/ro.
|
151
|
+
|
152
|
+
for a middleman app this might mean putting your ro data in ./source/ro.
|
153
|
+
|
154
|
+
if you choose a non-standard approach you'll need to
|
155
|
+
|
156
|
+
```
|
157
|
+
|
158
|
+
Ro.route = '/my-custom-route'
|
159
|
+
|
160
|
+
|
161
|
+
```
|
162
|
+
|
163
|
+
in all cases ro urls will be prefixed by the route, so be sure that this prefix
|
164
|
+
is either automatically, or manually, exposed.
|
165
|
+
|
166
|
+
|
142
167
|
DOCS
|
143
168
|
----
|
144
169
|
|
data/Rakefile
CHANGED
@@ -84,7 +84,7 @@ task :gemspec do
|
|
84
84
|
lib = This.lib
|
85
85
|
object = This.object
|
86
86
|
version = This.version
|
87
|
-
files = shiteless[Dir::glob("**/**")]
|
87
|
+
files = shiteless[Dir::glob("**/**")].select{|path| test(?f, path)}
|
88
88
|
executables = shiteless[Dir::glob("bin/*")].map{|exe| File.basename(exe)}
|
89
89
|
#has_rdoc = true #File.exist?('doc')
|
90
90
|
test_files = test(?e, "test/#{ lib }.rb") ? "test/#{ lib }.rb" : nil
|
data/TODO.md
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
todo:
|
2
|
+
|
3
|
+
Model[id]
|
4
|
+
Model.select
|
5
|
+
Model.where
|
6
|
+
|
7
|
+
- reconsider using active_model...
|
8
|
+
|
9
|
+
- with ro, do we/should we need to expand assets?
|
10
|
+
- posts
|
11
|
+
- body.md -> html -> expand_asset_urls?
|
12
|
+
|
13
|
+
- https://github.com/rails/rails/blob/master/activemodel/lib/active_model/model.rb
|
14
|
+
|
15
|
+
- track where shit comes from...
|
16
|
+
|
17
|
+
- custom ui better?
|
18
|
+
- chiclets
|
19
|
+
- posts
|
20
|
+
|
21
|
+
done:
|
22
|
+
|
23
|
+
- expand relative asset links in html
|
24
|
+
|
25
|
+
- patch based transactions
|
26
|
+
|
27
|
+
- http://ariejan.net/2009/10/26/how-to-create-and-apply-a-patch-with-git/
|
28
|
+
|
29
|
+
- git checkout -b test-branch
|
30
|
+
- add, commit, etc
|
31
|
+
- add assets last
|
32
|
+
|
33
|
+
- git format-patch master --stdout > p.patch
|
34
|
+
|
35
|
+
- actor.date.uuid
|
36
|
+
|
37
|
+
-
|
38
|
+
a:~/git/ahoward/ro $ git apply --stat p.patch
|
39
|
+
tmp/coat.zip | Bin
|
40
|
+
tmp/a.txt | 1 +
|
41
|
+
2 files changed, 1 insertion(+)
|
42
|
+
|
43
|
+
- git apply --check p.patch
|
44
|
+
|
45
|
+
- git am --signoff < fix_empty_poster.patch
|
46
|
+
|
47
|
+
- iff fail: sorry, your edits conflict with another user!
|
48
|
+
- because they need to review new content ;-)
|
49
|
+
|
50
|
+
- git branch -D test-branch
|
data/bin/ro
CHANGED
@@ -2,14 +2,24 @@
|
|
2
2
|
|
3
3
|
Main {
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
argument('root'){
|
6
|
+
optional
|
7
7
|
}
|
8
8
|
|
9
|
+
def run
|
10
|
+
help!
|
11
|
+
end
|
12
|
+
|
9
13
|
mode(:console){
|
10
14
|
def run
|
11
|
-
if params['root'].given?
|
15
|
+
if params['root'].given?
|
12
16
|
Ro.root = params['root'].value
|
17
|
+
else
|
18
|
+
if ENV['RO_ROOT']
|
19
|
+
Ro.root = ENV['RO_ROOT']
|
20
|
+
else
|
21
|
+
Ro.root = './ro'
|
22
|
+
end
|
13
23
|
end
|
14
24
|
|
15
25
|
basename = File.basename(Ro.root)
|
data/lib/ro.rb
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
|
11
11
|
#
|
12
12
|
module Ro
|
13
|
-
Version = '1.
|
13
|
+
Version = '1.2.0' unless defined?(Version)
|
14
14
|
|
15
15
|
def version
|
16
16
|
Ro::Version
|
@@ -20,17 +20,13 @@
|
|
20
20
|
{
|
21
21
|
'map' => [ 'map' , ' >= 6.5.1' ] ,
|
22
22
|
'fattr' => [ 'fattr' , ' >= 2.2.1' ] ,
|
23
|
-
'tilt' => [ 'tilt' , ' >= 1.
|
23
|
+
'tilt' => [ 'tilt' , ' >= 1.3.1' ] ,
|
24
24
|
'pygments' => [ 'pygments.rb' , ' >= 0.5.0' ] ,
|
25
25
|
'coerce' => [ 'coerce' , ' >= 0.0.4' ] ,
|
26
26
|
'stringex' => [ 'stringex' , ' >= 2.1.0' ] ,
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
# 'uuidtools' => [ 'uuidtools' , ' >= 2.1.2' ] ,
|
31
|
-
# 'wrap' => [ 'wrap' , ' >= 1.5.0' ] ,
|
32
|
-
# 'rails_current' => [ 'rails_current' , ' >= 1.8.0' ] ,
|
33
|
-
# 'rails_errors2html' => [ 'rails_errors2html' , ' >= 1.3.0' ] ,
|
27
|
+
'systemu' => [ 'systemu' , ' >= 2.5.2' ] ,
|
28
|
+
'nokogiri' => [ 'nokogiri' , ' >= 1.6.1' ] ,
|
29
|
+
'main' => [ 'main' , ' >= 5.2.0' ] ,
|
34
30
|
}
|
35
31
|
end
|
36
32
|
|
@@ -80,22 +76,26 @@
|
|
80
76
|
#
|
81
77
|
|
82
78
|
module Ro
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
when defined?(Rails.root)
|
87
|
-
root = Rails.root.to_s
|
88
|
-
File.join(root, 'public', 'ro')
|
79
|
+
def Ro.default_root
|
80
|
+
[ ENV['RO_ROOT'], "./public/ro", "./source/ro" ].compact.detect{|d| test(?d, d)} || "./ro"
|
81
|
+
end
|
89
82
|
|
90
|
-
|
91
|
-
|
92
|
-
|
83
|
+
def Ro.root=(root)
|
84
|
+
@root = Root.new(root.to_s)
|
85
|
+
end
|
93
86
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
87
|
+
def Ro.root(*args)
|
88
|
+
Ro.root = args.first unless args.empty?
|
89
|
+
@root ||= Root.new(Ro.default_root)
|
90
|
+
end
|
91
|
+
|
92
|
+
def Ro.git
|
93
|
+
root.git
|
94
|
+
end
|
95
|
+
|
96
|
+
def Ro.patch(*args, &block)
|
97
|
+
git.patch(*args, &block)
|
98
|
+
end
|
99
99
|
|
100
100
|
Fattr(:cache){
|
101
101
|
Cache.new
|
@@ -105,7 +105,7 @@
|
|
105
105
|
nil
|
106
106
|
}
|
107
107
|
|
108
|
-
Fattr(:
|
108
|
+
Fattr(:route){
|
109
109
|
'/ro'
|
110
110
|
}
|
111
111
|
|
@@ -155,14 +155,18 @@
|
|
155
155
|
|
156
156
|
def Ro.slug_for(*args, &block)
|
157
157
|
options = Map.options_for!(args)
|
158
|
-
options
|
158
|
+
unless options.has_key?(:join)
|
159
|
+
options[:join] = '-'
|
160
|
+
end
|
159
161
|
args.push(options)
|
160
162
|
Slug.for(*args, &block)
|
161
163
|
end
|
162
164
|
|
163
165
|
def Ro.name_for(*args, &block)
|
164
166
|
options = Map.options_for!(args)
|
165
|
-
options
|
167
|
+
unless options.has_key?(:join)
|
168
|
+
options[:join] = '_'
|
169
|
+
end
|
166
170
|
args.push(options)
|
167
171
|
Slug.for(*args, &block)
|
168
172
|
end
|
@@ -191,6 +195,49 @@
|
|
191
195
|
Template.render_source(*args, &block)
|
192
196
|
end
|
193
197
|
|
198
|
+
def Ro.expand_asset_urls(html, node)
|
199
|
+
begin
|
200
|
+
accurate_expand_asset_urls(html, node)
|
201
|
+
rescue Object
|
202
|
+
sloppy_expand_asset_urls(html, node)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def Ro.accurate_expand_asset_urls(html, node)
|
207
|
+
doc = Nokogiri::HTML(html)
|
208
|
+
|
209
|
+
doc.traverse do |element|
|
210
|
+
if element.respond_to?(:attributes)
|
211
|
+
element.attributes.each do |attr, attribute|
|
212
|
+
value = attribute.value
|
213
|
+
if value =~ %r{(?:./)?assets/(.+)$}
|
214
|
+
begin
|
215
|
+
base, ext = $1.split('.', 2)
|
216
|
+
url = node.url_for(base)
|
217
|
+
attribute.value = url
|
218
|
+
rescue Object
|
219
|
+
next
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
doc.xpath('//body').inner_html.strip
|
227
|
+
end
|
228
|
+
|
229
|
+
def Ro.sloppy_expand_asset_urls(html, node)
|
230
|
+
html.to_s.gsub(%r{['"]assets/([^'"]+)['"]}) do |match|
|
231
|
+
base, ext = $1.split('.', 2)
|
232
|
+
|
233
|
+
begin
|
234
|
+
node.url_for(base).inspect
|
235
|
+
rescue Object
|
236
|
+
match
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
194
241
|
def Ro.paths_for(*args)
|
195
242
|
path = args.flatten.compact.join('/')
|
196
243
|
path.gsub!(%r|[.]+/|, '/')
|
@@ -262,6 +309,8 @@
|
|
262
309
|
blankslate.rb
|
263
310
|
|
264
311
|
root.rb
|
312
|
+
lock.rb
|
313
|
+
git.rb
|
265
314
|
|
266
315
|
cache.rb
|
267
316
|
|
data/lib/ro/cache.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
module Ro
|
2
|
-
class Cache < ::
|
2
|
+
class Cache < ::Map
|
3
3
|
def write(key, value)
|
4
|
-
|
4
|
+
invalidate(key)
|
5
|
+
set(key => value)
|
5
6
|
end
|
6
7
|
|
7
8
|
def read(key, &block)
|
8
|
-
if
|
9
|
-
|
9
|
+
if has?(key)
|
10
|
+
get(key)
|
10
11
|
else
|
11
12
|
if block
|
12
13
|
value = block.call
|
@@ -16,5 +17,10 @@ module Ro
|
|
16
17
|
end
|
17
18
|
end
|
18
19
|
end
|
20
|
+
|
21
|
+
def invalidate(key)
|
22
|
+
prefix = Array(key).dup.tap{|array| array.pop}
|
23
|
+
set(prefix, {})
|
24
|
+
end
|
19
25
|
end
|
20
26
|
end
|
data/lib/ro/git.rb
ADDED
@@ -0,0 +1,359 @@
|
|
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
|
+
|
27
|
+
patch = nil
|
28
|
+
|
29
|
+
Thread.exclusive do
|
30
|
+
@root.lock do
|
31
|
+
Dir.chdir(@root) do
|
32
|
+
# ensure .git-ness
|
33
|
+
#
|
34
|
+
status, stdout, stderr = spawn("git rev-parse --git-dir", :raise => true, :capture => true)
|
35
|
+
|
36
|
+
git_root = stdout.to_s.strip
|
37
|
+
|
38
|
+
dot_git = File.expand_path(git_root)
|
39
|
+
|
40
|
+
unless test(?d, dot_git)
|
41
|
+
raise Error.new("missing .git directory #{ dot_git }")
|
42
|
+
end
|
43
|
+
|
44
|
+
# calculate a tmp branch name
|
45
|
+
#
|
46
|
+
time = Coerce.time(options[:time] || Time.now).utc.iso8601(2).gsub(/[^\w]/, '')
|
47
|
+
branch = "#{ user }-#{ time }-#{ rand.to_s.gsub(/^0./, '') }"
|
48
|
+
|
49
|
+
# allow block to edit, compute the patch, attempt to apply it
|
50
|
+
#
|
51
|
+
begin
|
52
|
+
# get pristine
|
53
|
+
#
|
54
|
+
spawn("git checkout -f master", :raise => true)
|
55
|
+
spawn("git fetch --all", :raise => true)
|
56
|
+
spawn("git reset --hard origin/master", :raise => true)
|
57
|
+
|
58
|
+
# pull recent changes
|
59
|
+
#
|
60
|
+
trying('to pull'){ spawn("git pull origin master") }
|
61
|
+
|
62
|
+
# create a new temporary branch
|
63
|
+
#
|
64
|
+
spawn("git checkout -b #{ branch.inspect }", :raise => true)
|
65
|
+
|
66
|
+
# the block can perform arbitrary edits
|
67
|
+
#
|
68
|
+
block.call
|
69
|
+
|
70
|
+
# add all changes - additions, deletions, or modifications
|
71
|
+
#
|
72
|
+
spawn("git add . --all", :raise => true)
|
73
|
+
|
74
|
+
# commit if anything changed
|
75
|
+
#
|
76
|
+
changes_to_apply =
|
77
|
+
spawn("git commit -am #{ msg.inspect }")
|
78
|
+
|
79
|
+
if changes_to_apply
|
80
|
+
# create the patch
|
81
|
+
#
|
82
|
+
status, stdout, stderr =
|
83
|
+
spawn("git format-patch master --stdout", :raise => true, :capture => true)
|
84
|
+
|
85
|
+
patch = Patch.new(:data => stdout, :name => branch)
|
86
|
+
|
87
|
+
unless stdout.to_s.strip.empty?
|
88
|
+
# apply the patch
|
89
|
+
#
|
90
|
+
spawn("git checkout master", :raise => true)
|
91
|
+
|
92
|
+
status, stdout, stderr =
|
93
|
+
spawn("git am --signoff --3way", :capture => true, :stdin => patch.data)
|
94
|
+
|
95
|
+
patch.applied = !!(status == 0)
|
96
|
+
|
97
|
+
# commit the patch back to the repo
|
98
|
+
#
|
99
|
+
patch.committed =
|
100
|
+
begin
|
101
|
+
trying('to pull'){ spawn("git pull origin master") }
|
102
|
+
trying('to push'){ spawn("git push origin master") }
|
103
|
+
true
|
104
|
+
rescue Object
|
105
|
+
false
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
ensure
|
110
|
+
# get pristine
|
111
|
+
#
|
112
|
+
spawn("git checkout -f master", :raise => true)
|
113
|
+
spawn("git fetch --all", :raise => true)
|
114
|
+
spawn("git reset --hard origin/master", :raise => true)
|
115
|
+
|
116
|
+
# get changes
|
117
|
+
#
|
118
|
+
trying('to pull'){ spawn("git pull") }
|
119
|
+
|
120
|
+
# nuke the tmp branch
|
121
|
+
#
|
122
|
+
spawn("git branch -D #{ branch.inspect }")
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
patch
|
129
|
+
end
|
130
|
+
|
131
|
+
#
|
132
|
+
class Patch
|
133
|
+
fattr :data
|
134
|
+
fattr :name
|
135
|
+
fattr :applied
|
136
|
+
fattr :committed
|
137
|
+
fattr :status
|
138
|
+
fattr :stdout
|
139
|
+
fattr :stderr
|
140
|
+
|
141
|
+
def initialize(*args)
|
142
|
+
options = Map.options_for!(args)
|
143
|
+
|
144
|
+
self.class.fattrs.each do |key|
|
145
|
+
send(key, options.get(key)) if options.has?(key)
|
146
|
+
end
|
147
|
+
|
148
|
+
unless args.empty?
|
149
|
+
self.data = args.join
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def save(path)
|
154
|
+
return false unless data
|
155
|
+
path = path.to_s
|
156
|
+
FileUtils.mkdir_p(File.dirname(path))
|
157
|
+
IO.binwrite(path, data)
|
158
|
+
end
|
159
|
+
|
160
|
+
%w( to_s to_str ).each do |method|
|
161
|
+
class_eval <<-__, __FILE__, __LINE__
|
162
|
+
def #{ method }
|
163
|
+
data
|
164
|
+
end
|
165
|
+
__
|
166
|
+
end
|
167
|
+
|
168
|
+
%w( filename pathname basename ).each do |method|
|
169
|
+
class_eval <<-__, __FILE__, __LINE__
|
170
|
+
def #{ method }
|
171
|
+
name
|
172
|
+
end
|
173
|
+
__
|
174
|
+
end
|
175
|
+
|
176
|
+
%w( success success? applied applied? ).each do |method|
|
177
|
+
class_eval <<-__, __FILE__, __LINE__
|
178
|
+
def #{ method }
|
179
|
+
status && status == 0
|
180
|
+
end
|
181
|
+
__
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
|
187
|
+
def save(directory, options = {})
|
188
|
+
if directory.is_a?(Node)
|
189
|
+
directory = directory.path
|
190
|
+
end
|
191
|
+
|
192
|
+
options = Map.for(options)
|
193
|
+
|
194
|
+
dir = File.expand_path(directory.to_s)
|
195
|
+
|
196
|
+
relative_path = Ro.relative_path(dir, :from => @root)
|
197
|
+
|
198
|
+
exists = test(?d, dir)
|
199
|
+
|
200
|
+
action = exists ? 'edited' : 'created'
|
201
|
+
|
202
|
+
msg = options[:message] || "#{ ENV['USER'] } #{ action } #{ relative_path }"
|
203
|
+
|
204
|
+
@root.lock do
|
205
|
+
FileUtils.mkdir_p(dir) unless exists
|
206
|
+
|
207
|
+
Dir.chdir(dir) do
|
208
|
+
# .git
|
209
|
+
#
|
210
|
+
git_root = `git rev-parse --git-dir`.strip
|
211
|
+
|
212
|
+
if git_root.empty?
|
213
|
+
git_root = '.'
|
214
|
+
end
|
215
|
+
|
216
|
+
dot_git = File.expand_path(File.join(git_root, '.git'))
|
217
|
+
|
218
|
+
unless test(?d, dot_git)
|
219
|
+
raise Error.new("missing .git directory #{ dot_git }")
|
220
|
+
end
|
221
|
+
|
222
|
+
# correct branch
|
223
|
+
#
|
224
|
+
spawn("git checkout #{ @branch.inspect }", :raise => true)
|
225
|
+
|
226
|
+
# return if nothing to do...
|
227
|
+
#
|
228
|
+
if `git status --porcelain`.strip.empty?
|
229
|
+
return true
|
230
|
+
end
|
231
|
+
|
232
|
+
# commit the work
|
233
|
+
#
|
234
|
+
trying "to commit" do
|
235
|
+
|
236
|
+
committed =
|
237
|
+
spawn("git add --all . && git commit -m #{ msg.inspect } -- .")
|
238
|
+
|
239
|
+
=begin
|
240
|
+
unless committed
|
241
|
+
spawn "git reset --hard"
|
242
|
+
end
|
243
|
+
=end
|
244
|
+
|
245
|
+
#require 'pry'
|
246
|
+
#binding.pry
|
247
|
+
=begin
|
248
|
+
retried = false
|
249
|
+
begin
|
250
|
+
spawn "git add --all . && git commit -m #{ msg.inspect } -- ."
|
251
|
+
committed = true
|
252
|
+
rescue
|
253
|
+
raise if retried
|
254
|
+
spawn "git reset --hard", :raise => false
|
255
|
+
retry
|
256
|
+
end
|
257
|
+
=end
|
258
|
+
end
|
259
|
+
|
260
|
+
|
261
|
+
trying "to push" do
|
262
|
+
pushed = nil
|
263
|
+
|
264
|
+
unless spawn("git push origin master")
|
265
|
+
# merge
|
266
|
+
#
|
267
|
+
unless spawn("git pull")
|
268
|
+
spawn("git checkout --ours -- .")
|
269
|
+
spawn("git add --all .")
|
270
|
+
spawn("git commit -F #{ dot_git }/MERGE_MSG")
|
271
|
+
else
|
272
|
+
raise 'wtf!?'
|
273
|
+
end
|
274
|
+
|
275
|
+
pushed = spawn("git push origin master")
|
276
|
+
else
|
277
|
+
pushed = true
|
278
|
+
end
|
279
|
+
|
280
|
+
pushed
|
281
|
+
end
|
282
|
+
|
283
|
+
=begin
|
284
|
+
git push
|
285
|
+
|
286
|
+
git pull
|
287
|
+
|
288
|
+
# publish
|
289
|
+
git checkout --ours -- .
|
290
|
+
git add --all .
|
291
|
+
git commit -F .git/MERGE_MSG
|
292
|
+
git push
|
293
|
+
=end
|
294
|
+
|
295
|
+
|
296
|
+
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
class Error < ::StandardError;end
|
302
|
+
|
303
|
+
def trying(*args, &block)
|
304
|
+
options = Map.options_for!(args)
|
305
|
+
label = ['trying', *args].join(' - ')
|
306
|
+
|
307
|
+
n = Integer(options[:n] || 3)
|
308
|
+
timeout = options[:timeout]
|
309
|
+
e = nil
|
310
|
+
done = nil
|
311
|
+
not_done = Object.new.freeze
|
312
|
+
|
313
|
+
result =
|
314
|
+
catch(:trying) do
|
315
|
+
n.times do |i|
|
316
|
+
done = block.call
|
317
|
+
if done
|
318
|
+
throw(:trying, done)
|
319
|
+
else
|
320
|
+
unless timeout == false
|
321
|
+
sleep( (i + 1) * (timeout || (1 + rand)) )
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
not_done
|
327
|
+
end
|
328
|
+
|
329
|
+
if result == not_done
|
330
|
+
raise(Error.new("#{ label } failed #{ n } times"))
|
331
|
+
else
|
332
|
+
done
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
def spawn(command, options = {})
|
337
|
+
options = Map.for(options)
|
338
|
+
|
339
|
+
status, stdout, stderr = systemu(command, :stdin => options[:stdin])
|
340
|
+
|
341
|
+
Ro.log(:debug, "command: #{ command }")
|
342
|
+
Ro.log(:debug, "status: #{ status }")
|
343
|
+
Ro.log(:debug, "stdout:\n#{ stdout }")
|
344
|
+
Ro.log(:debug, "stderr:\n#{ stderr }")
|
345
|
+
|
346
|
+
if options[:raise] == true
|
347
|
+
unless status == 0
|
348
|
+
raise "command (#{ command }) failed with #{ status }"
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
if options[:capture]
|
353
|
+
[status, stdout, stderr]
|
354
|
+
else
|
355
|
+
status == 0
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
359
|
+
end
|