braid 1.0.22 → 1.1.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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -2
  3. data/README.md +48 -0
  4. data/_config.yml +1 -0
  5. data/bin/braid +44 -7
  6. data/braid.gemspec +4 -0
  7. data/config_versions.md +58 -0
  8. data/lib/braid.rb +7 -0
  9. data/lib/braid/command.rb +7 -7
  10. data/lib/braid/commands/add.rb +3 -3
  11. data/lib/braid/commands/diff.rb +7 -14
  12. data/lib/braid/commands/push.rb +10 -4
  13. data/lib/braid/commands/setup.rb +5 -1
  14. data/lib/braid/commands/status.rb +5 -1
  15. data/lib/braid/commands/update.rb +6 -15
  16. data/lib/braid/commands/upgrade_config.rb +56 -0
  17. data/lib/braid/config.rb +166 -27
  18. data/lib/braid/mirror.rb +111 -11
  19. data/lib/braid/operations.rb +51 -35
  20. data/lib/braid/version.rb +1 -1
  21. data/spec/config_spec.rb +2 -2
  22. data/spec/fixtures/shiny-conf-1.0.9-lock/.braids.json +10 -0
  23. data/spec/fixtures/shiny-conf-1.0.9-lock/expected.braids.json +9 -0
  24. data/spec/fixtures/shiny-conf-1.0.9-lock/skit1/layouts/layout.liquid +219 -0
  25. data/spec/fixtures/shiny-conf-1.0.9-lock/skit1/preview.png +0 -0
  26. data/spec/fixtures/shiny-conf-breaking-changes/.braids +14 -0
  27. data/spec/fixtures/shiny-conf-breaking-changes/Spoon-Knife/README.md +9 -0
  28. data/spec/fixtures/shiny-conf-breaking-changes/Spoon-Knife/index.html +20 -0
  29. data/spec/fixtures/shiny-conf-breaking-changes/Spoon-Knife/styles.css +17 -0
  30. data/spec/fixtures/shiny-conf-breaking-changes/expected.braids.json +10 -0
  31. data/spec/fixtures/shiny-conf-breaking-changes/skit1/layouts/layout.liquid +219 -0
  32. data/spec/fixtures/shiny-conf-breaking-changes/skit1/preview.png +0 -0
  33. data/spec/fixtures/shiny-conf-future/.braids.json +10 -0
  34. data/spec/fixtures/shiny-conf-future/skit1/layouts/layout.liquid +219 -0
  35. data/spec/fixtures/shiny-conf-future/skit1/preview.png +0 -0
  36. data/spec/fixtures/shiny-conf-json-old-name/.braids +9 -0
  37. data/spec/fixtures/shiny-conf-json-old-name/expected.braids.json +10 -0
  38. data/spec/fixtures/shiny-conf-json-old-name/skit1/layouts/layout.liquid +219 -0
  39. data/spec/fixtures/shiny-conf-json-old-name/skit1/preview.png +0 -0
  40. data/spec/fixtures/shiny-conf-yaml/.braids +8 -0
  41. data/spec/fixtures/shiny-conf-yaml/expected.braids.json +10 -0
  42. data/spec/fixtures/shiny-conf-yaml/skit1/layouts/layout.liquid +219 -0
  43. data/spec/fixtures/shiny-conf-yaml/skit1/preview.png +0 -0
  44. data/spec/fixtures/shiny/skit-layout.liquid.test +2 -0
  45. data/spec/fixtures/shiny/skit1.test +2 -0
  46. data/spec/fixtures/skit1.1x/layouts/layout.liquid +219 -0
  47. data/spec/integration/adding_spec.rb +82 -34
  48. data/spec/integration/config_versioning_spec.rb +222 -0
  49. data/spec/integration/diff_spec.rb +173 -9
  50. data/spec/integration/integration_helper.rb +23 -5
  51. data/spec/integration/push_spec.rb +57 -4
  52. data/spec/integration/remove_spec.rb +27 -5
  53. data/spec/integration/updating_spec.rb +104 -19
  54. metadata +73 -2
@@ -247,21 +247,6 @@ module Braid
247
247
  true
248
248
  end
249
249
 
250
- # Implies no commit.
251
- def merge_ours(opt)
252
- invoke(:merge, '--allow-unrelated-histories -s ours --no-commit', opt)
253
- true
254
- end
255
-
256
- # Implies no commit.
257
- def merge_subtree(opt)
258
- # TODO which options are needed?
259
- invoke(:merge, '-s subtree --no-commit --no-ff', opt)
260
- true
261
- rescue ShellExecutionError => error
262
- raise MergeError, error.out
263
- end
264
-
265
250
  # Merge three trees (local_treeish should match the current state of the
266
251
  # index) and update the index and working tree.
267
252
  #
@@ -282,17 +267,56 @@ module Braid
282
267
  invoke('ls-files', prefix)
283
268
  end
284
269
 
285
- # Read tree into the index and working tree.
286
- def read_tree_prefix_u(treeish, prefix)
287
- invoke(:read_tree, "--prefix=#{prefix}/ -u", treeish)
288
- true
270
+ class BlobWithMode
271
+ def initialize(hash, mode)
272
+ @hash = hash
273
+ @mode = mode
274
+ end
275
+ attr_reader :hash, :mode
276
+ end
277
+ # Allow the class to be referenced as `git.BlobWithMode`.
278
+ def BlobWithMode
279
+ Git::BlobWithMode
289
280
  end
290
281
 
291
- # Read tree into the index, regardless of the state of the working tree.
292
- # Most useful with a temporary index file.
293
- def read_tree_prefix_i(treeish, prefix)
294
- invoke(:read_tree, "--prefix=#{prefix}/ -i", treeish)
295
- true
282
+ # Get the item at the given path in the given tree. If it's a tree, just
283
+ # return its hash; if it's a blob, return a BlobWithMode object. (This is
284
+ # how we remember the mode for single-file mirrors.)
285
+ def get_tree_item(tree, path)
286
+ if path.nil? || path == ''
287
+ tree
288
+ else
289
+ m = /^([^ ]*) ([^ ]*) ([^\t]*)\t.*$/.match(invoke(:ls_tree, tree, path))
290
+ mode = m[1]
291
+ type = m[2]
292
+ hash = m[3]
293
+ if type == 'tree'
294
+ hash
295
+ elsif type == 'blob'
296
+ return BlobWithMode.new(hash, mode)
297
+ else
298
+ raise ShellExecutionError, 'Tree item is not a tree or a blob'
299
+ end
300
+ end
301
+ end
302
+
303
+ # Add the item (as returned by get_tree_item) to the index at the given
304
+ # path. If update_worktree is true, then update the worktree, otherwise
305
+ # disregard the state of the worktree (most useful with a temporary index
306
+ # file).
307
+ def add_item_to_index(item, path, update_worktree)
308
+ if item.is_a?(BlobWithMode)
309
+ # Our minimum git version is 1.6.0 and the new --cacheinfo syntax
310
+ # wasn't added until 2.0.0.
311
+ invoke(:update_index, '--add', '--cacheinfo', item.mode, item.hash, path)
312
+ if update_worktree
313
+ # XXX If this fails, we've already updated the index.
314
+ invoke(:checkout_index, path)
315
+ end
316
+ else
317
+ # Yes, if path == '', "git read-tree --prefix=/" works. :/
318
+ invoke(:read_tree, "--prefix=#{path}/", update_worktree ? '-u' : '-i', item)
319
+ end
296
320
  end
297
321
 
298
322
  # Read tree into the root of the index. This may not be the preferred way
@@ -317,14 +341,13 @@ module Braid
317
341
  end
318
342
  end
319
343
 
320
- def make_tree_with_subtree(main_content, subtree_path, subtree_content)
344
+ def make_tree_with_item(main_content, item_path, item)
321
345
  with_temporary_index do
322
346
  if main_content
323
347
  read_tree_im(main_content)
324
- rm_r_cached(subtree_path)
348
+ rm_r_cached(item_path)
325
349
  end
326
- # Yes, if subtree_path == '', "git read-tree --prefix=/" works. :/
327
- read_tree_prefix_i(subtree_content, subtree_path)
350
+ add_item_to_index(item, item_path, false)
328
351
  write_tree
329
352
  end
330
353
  end
@@ -349,13 +372,6 @@ module Braid
349
372
  out.split[2]
350
373
  end
351
374
 
352
- def diff_tree(src_tree, dst_tree, prefix = nil)
353
- cmd = "git diff-tree -p --binary #{src_tree} #{dst_tree}"
354
- cmd << " --src-prefix=a/#{prefix}/ --dst-prefix=b/#{prefix}/" if prefix
355
- status, out, err = exec!(cmd)
356
- out
357
- end
358
-
359
375
  def diff_to_stdout(*args)
360
376
  # For now, ignore the exit code. It can be 141 (SIGPIPE) if the user
361
377
  # quits the pager before reading all the output.
@@ -1,3 +1,3 @@
1
1
  module Braid
2
- VERSION = '1.0.22'.freeze
2
+ VERSION = '1.1.0'.freeze
3
3
  end
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/test_helper'
2
2
 
3
3
  describe 'Braid::Config, when empty' do
4
4
  before(:each) do
5
- @config = Braid::Config.new('tmp.yml')
5
+ @config = Braid::Config.new({'config_file' => 'tmp.yml'})
6
6
  end
7
7
 
8
8
  after(:each) do
@@ -23,7 +23,7 @@ end
23
23
 
24
24
  describe 'Braid::Config, with one mirror' do
25
25
  before(:each) do
26
- @config = Braid::Config.new('tmp.yml')
26
+ @config = Braid::Config.new({'config_file' => 'tmp.yml'})
27
27
  @mirror = build_mirror
28
28
  @config.add(@mirror)
29
29
  end
@@ -0,0 +1,10 @@
1
+ {
2
+ "skit1": {
3
+ "url": "file:///path/to/braid/spec/fixtures/skit1",
4
+ "remote": "master/braid/skit1",
5
+ "branch": "master",
6
+ "squashed": true,
7
+ "revision": "6d3aeac08f9f4f9689d367fc771f5f1c90496176",
8
+ "lock": "6d3aeac08f9f4f9689d367fc771f5f1c90496176"
9
+ }
10
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "config_version": 1,
3
+ "mirrors": {
4
+ "skit1": {
5
+ "url": "file:///path/to/braid/spec/fixtures/skit1",
6
+ "revision": "6d3aeac08f9f4f9689d367fc771f5f1c90496176"
7
+ }
8
+ }
9
+ }
@@ -0,0 +1,219 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html xmlns="http://www.w3.org/1999/xhtml">
3
+ {{ '/feed/atom.xml' | assign_to: 'global_feed' }}
4
+ {{ '/feed/all_comments.xml' | assign_to: 'global_comments_feed' }}
5
+ <head>
6
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7
+ <title>
8
+ {{ site.title }}
9
+ {% if site.current_section %}
10
+ - {{ site.current_section.name }}
11
+ {% endif %}
12
+ {% if article %}
13
+ - {{ article.title }}
14
+ {% endif %}
15
+ </title>
16
+ <link rel="alternate" type="application/atom+xml" title="{{ site.title }} feed" href="{{ global_feed }}"/>
17
+ <link rel="alternate" type="application/atom+xml" title="{{ site.title }} comments feed" href="{{ global_comments_feed }}"/>
18
+ {{ 'base' | stylesheet }}
19
+ {{ 'app' | javascript }}
20
+ <!--[if IE]>
21
+ {{ 'base_ie' | stylesheet }}
22
+ <![endif]-->
23
+ </head>
24
+
25
+ <body class="fixed orange">
26
+ <script type="text/javascript">loadPreferences()</script>
27
+
28
+ <div id="wrapper">
29
+
30
+ <div id="header" class="clearfix">
31
+ <div id="title" class="clearfix">
32
+ <h1><a href="/">{{ site.title }}</a></h1>
33
+ </div>
34
+ <h2>Sections</h2>
35
+ <ul id="menu">
36
+ {% for section in site.sections %}
37
+ {% if section.articles_count > 0 %}
38
+ {% if section.is_home %}
39
+ <li{% if section.current %} class="selected"{% endif %}>{{ section | link_to_section }}</li>
40
+ {% else %}
41
+ {% if section.is_paged %}
42
+ <li{% if section.current %} class="selected"{% endif %}>{{ section | link_to_section }}</li>
43
+ {% endif %}
44
+ {% endif %}
45
+ {% endif %}
46
+ {% endfor %}
47
+ </ul>
48
+ </div>
49
+
50
+ <div id="contentwrapper" class="clearfix">
51
+
52
+ <div id="content">
53
+
54
+ <div id="innerwrapper">
55
+
56
+ <div class="article">
57
+ <div class="body">
58
+ <h2>Skittlish Tips'n'Tricks</h2>
59
+ <ul>
60
+ <li>Change the classes for the body tag to set your default site style. also change these in the app.js file (line 66).</li>
61
+ <li>Remove the scripts and the #options div if you don't want the option switcher.</li>
62
+ <li>The top menu shows the home section and the sections that are not blogs.</li>
63
+ <li>Email me at <a href="mailto:evil@che.lu">evil@che.lu</a> if you have any questions.</li>
64
+ <li>Happy hacking!</li>
65
+ </ul>
66
+ </div>
67
+ </div>
68
+
69
+ {{ content_for_layout }}
70
+
71
+ </div>
72
+
73
+ </div>
74
+
75
+ <div id="sidebar">
76
+
77
+ <div class="boxy short">
78
+ <h3>boxy short</h3>
79
+
80
+ <p>You can have, boxes with a short, tall or no background shade, just change the class of the containing div.</p>
81
+
82
+ <p>Have boxes with smaller text with the class "minor". See the "Recent" boxy below.</p>
83
+
84
+ </div>
85
+
86
+ <div id="search" class="boxy short">
87
+ <h3>Search</h3>
88
+ <form method="get" action="/search">
89
+ <fieldset>
90
+ <input class="text" type="text" id="q" value="" name="q"/>
91
+ </fieldset>
92
+ </form>
93
+ </div>
94
+
95
+ <div class="boxy tall minor">
96
+ <h3>Recent</h3>
97
+
98
+ <dl>
99
+ <dt>Articles <a class="feed" href="{{ global_feed }}"><span>feed</span></a></dt>
100
+ <dd>
101
+ <ul>
102
+ {% for article in site.latest_articles %}
103
+ <li>{{ article | link_to_article }} <em>({{ article.published_at | format_date: 'stub', true }})</em></li>
104
+ {% endfor %}
105
+ </ul>
106
+ </dd>
107
+
108
+ <dt>Comments <a class="feed" href="{{ global_comments_feed }}"><span>feed</span></a></dt>
109
+ <dd>
110
+ <ul>
111
+ {% for comment in site.latest_comments %}
112
+ <li>{{ comment.author_link }} on <a href="{{ comment.url }}#comment-{{ comment.id }}">{{ comment.title }}</a></li>
113
+ {% endfor %}
114
+ </ul>
115
+ </dd>
116
+ </dl>
117
+ </div>
118
+
119
+ <div class="boxy short">
120
+ <h3>Archives</h3>
121
+ <p>This would be much nicer with jamis' month_drop thingy.</p>
122
+ {{ '' | section | months | assign_to: 'home_section' }}
123
+ <ul>
124
+ {% for month in home_section.months %}
125
+ {{ home_section | monthly_articles: month | size | assign_to: 'articles_count' }}
126
+ {% if articles_count > 0 %}
127
+ <li>{{ home_section | link_to_month: month }} ({{ articles_count }})</li>
128
+ {% endif %}
129
+ {% endfor %}
130
+ </ul>
131
+ </div>
132
+
133
+ {% if site.blog_sections.size > 1 %}
134
+ <div class="boxy short">
135
+ <h3>Categories</h3>
136
+ <p>Lists only blog type categories with at least one article.</p>
137
+ <p>This list uses an ul. You could use a dl with only dd's in it for the same effect. Wouldn't be semantic tho.</p>
138
+ <ul class="sections">
139
+ {% for section in site.blog_sections %}
140
+ {% if section.articles_count > 0 %}
141
+ {% unless section.is_home %}
142
+ <li>{{ section | link_to_section }} ({{ section.articles_count }})</li>
143
+ {% endunless %}
144
+ {% endif %}
145
+ {% endfor %}
146
+ </ul>
147
+ </div>
148
+
149
+ {% endif %}
150
+ {% unless site.tags == empty %}
151
+ <div class="boxy short">
152
+ <p>This would be nicer if we could get the number of articles for each tag.</p>
153
+ <h3>tags: </h3>
154
+ <ul>
155
+ {% for tag in site.tags %}
156
+ <li>{{ tag | link_to_tag }}</li>
157
+ {% endfor %}
158
+ </ul>
159
+ </div>
160
+
161
+ {% endunless %}
162
+ <div class="boxy tall">
163
+ <h3>boxy tall</h3>
164
+ <p>When using a tall box, make sure it's got plenty of content or that it's immediately followed by a short boxy. It might look a bit chopped off otherwise.</p>
165
+ <dl>
166
+ <dt>thing 1</dt>
167
+ <dd><a href="#">value 1</a></dd>
168
+ <dd><a href="#">value 2</a></dd>
169
+ <dd><a href="#">value 3</a></dd>
170
+ <dd><a href="#">value 4</a></dd>
171
+ <dd><a href="#">value 5</a></dd>
172
+ <dd><a href="#">value 6</a></dd>
173
+ <dd><a href="#">value 6</a></dd>
174
+
175
+ <dt>thing 1</dt>
176
+ <dd><a href="#">value 1</a></dd>
177
+ <dd><a href="#">value 2</a></dd>
178
+ <dd><a href="#">value 3</a></dd>
179
+ <dd>value 4</dd>
180
+ <dd>value 5</dd>
181
+ <dd><a href="#">value 6</a></dd>
182
+ <dd><a href="#">value 6</a></dd>
183
+
184
+ </dl>
185
+ </div>
186
+
187
+ </div>
188
+
189
+ </div>
190
+
191
+ <div id="options">
192
+ <h2>Options:</h2>
193
+ <h3>Size</h3>
194
+ <ul id="option_size">
195
+ <li id="option_size_fixed" class="fixed" ><a><span>fixed </span></a></li>
196
+ <li id="option_size_fluid" class="fluid" ><a><span>fluid </span></a></li>
197
+ </ul>
198
+ <h3>Colors</h3>
199
+ <ul id="option_color">
200
+ <li id="option_color_orange" class="orange"><a><span>orange</span></a></li>
201
+ <li id="option_color_blue" class="blue" ><a><span>blue </span></a></li>
202
+ <li id="option_color_green" class="green" ><a><span>green </span></a></li>
203
+ <li id="option_color_pink" class="pink" ><a><span>pink </span></a></li>
204
+ <li id="option_color_cyan" class="cyan" ><a><span>cyan </span></a></li>
205
+ <li id="option_color_red" class="red" ><a><span>red </span></a></li>
206
+ <li id="option_color_violet" class="violet"><a><span>violet</span></a></li>
207
+ </ul>
208
+ </div>
209
+
210
+ <div id="footer">
211
+ <p>Copyright &copy; 2006, Your Name. Valid <a href="http://validator.w3.org/check/referer">XHTML</a> and <a href="http://jigsaw.w3.org/css-validator/check/referer">CSS</a>.</p>
212
+ <p>Using <a href="http://evil.che.lu/projects/skittlish">skittlish</a> on <a href="http://publishwithimpunity.com/">mephisto</a>.</p>
213
+ </div>
214
+
215
+ </div>
216
+
217
+ </body>
218
+
219
+ </html>
@@ -0,0 +1,14 @@
1
+ --- !ruby/object:Hash
2
+ Spoon-Knife: !ruby/object:Hash
3
+ remote: master/braid/Spoon-Knife
4
+ revision: 18
5
+ squashed: true
6
+ type: svn
7
+ url: https://github.com/octocat/Spoon-Knife.git/trunk
8
+ skit1: !ruby/object:Hash
9
+ branch: master
10
+ remote: master/braid/skit1
11
+ revision: 6d3aeac08f9f4f9689d367fc771f5f1c90496176
12
+ squashed: false
13
+ type: git
14
+ url: file:///path/to/braid/spec/fixtures/skit1/.git
@@ -0,0 +1,9 @@
1
+ ### Well hello there!
2
+
3
+ This repository is meant to provide an example for *forking* a repository on GitHub.
4
+
5
+ Creating a *fork* is producing a personal copy of someone else's project. Forks act as a sort of bridge between the original repository and your personal copy. You can submit *Pull Requests* to help make other people's projects better by offering your changes up to the original project. Forking is at the core of social coding at GitHub.
6
+
7
+ After forking this repository, you can make some changes to the project, and submit [a Pull Request](https://github.com/octocat/Spoon-Knife/pulls) as practice.
8
+
9
+ For some more information on how to fork a repository, [check out our guide, "Forking Projects""](http://guides.github.com/overviews/forking/). Thanks! :sparkling_heart:
@@ -0,0 +1,20 @@
1
+ <!DOCTYPE html>
2
+
3
+ <html>
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
6
+ <title>Spoon-Knife</title>
7
+ <LINK href="styles.css" rel="stylesheet" type="text/css">
8
+ </head>
9
+
10
+ <body>
11
+
12
+ <img src="forkit.gif" id="octocat" alt="" />
13
+
14
+ <!-- Feel free to change this text here -->
15
+ <p>
16
+ Fork me? Fork you, @octocat!
17
+ </p>
18
+
19
+ </body>
20
+ </html>
@@ -0,0 +1,17 @@
1
+ * {
2
+ margin:0px;
3
+ padding:0px;
4
+ }
5
+
6
+ #octocat {
7
+ display: block;
8
+ width:384px;
9
+ margin: 50px auto;
10
+ }
11
+
12
+ p {
13
+ display: block;
14
+ width: 400px;
15
+ margin: 50px auto;
16
+ font: 30px Monaco,"Courier New","DejaVu Sans Mono","Bitstream Vera Sans Mono",monospace;
17
+ }