ro 1.1.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|