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
@@ -0,0 +1,2 @@
1
+ This file exists to test that `braid diff skit-layout.liquid` correctly limits
2
+ the diff to the single file and doesn't do a naive path prefix match.
@@ -0,0 +1,2 @@
1
+ This file exists to test that `braid diff skit1` correctly limits the diff to
2
+ the single directory and doesn't do a naive path prefix match.
@@ -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 green">
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>
@@ -20,18 +20,22 @@ describe 'Adding a mirror in a clean repository' do
20
20
  it 'should add the files and commit' do
21
21
  assert_no_diff("#{FIXTURE_PATH}/skit1/layouts/layout.liquid", "#{@repository_dir}/skit1/layouts/layout.liquid")
22
22
 
23
- assert_commit_subject(/Braid: Add mirror 'skit1' at '[0-9a-f]{7}'/)
24
- assert_commit_author('Some body')
25
- assert_commit_email('somebody@example.com')
23
+ in_dir(@repository_dir) do
24
+ assert_commit_subject(/Braid: Add mirror 'skit1' at '[0-9a-f]{7}'/)
25
+ assert_commit_author('Some body')
26
+ assert_commit_email('somebody@example.com')
27
+ end
26
28
  end
27
29
 
28
30
  it 'should create .braids.json and add the mirror to it' do
29
31
  braids = YAML::load_file("#{@repository_dir}/.braids.json")
30
- expect(braids['skit1']['url']).to eq(@vendor_repository_dir)
31
- expect(braids['skit1']['revision']).not_to be_nil
32
- expect(braids['skit1']['branch']).to eq('master')
33
- expect(braids['skit1']['tag']).to be_nil
34
- expect(braids['skit1']['path']).to be_nil
32
+ expect(braids['config_version']).to be_kind_of(Numeric)
33
+ mirror_obj = braids['mirrors']['skit1']
34
+ expect(mirror_obj['url']).to eq(@vendor_repository_dir)
35
+ expect(mirror_obj['revision']).not_to be_nil
36
+ expect(mirror_obj['branch']).to eq('master')
37
+ expect(mirror_obj['tag']).to be_nil
38
+ expect(mirror_obj['path']).to be_nil
35
39
  end
36
40
  end
37
41
 
@@ -41,25 +45,61 @@ describe 'Adding a mirror in a clean repository' do
41
45
  @vendor_repository_dir = create_git_repo_from_fixture('skit1')
42
46
 
43
47
  in_dir(@repository_dir) do
44
- run_command("#{BRAID_BIN} add --path layouts #{@vendor_repository_dir}")
48
+ run_command("#{BRAID_BIN} add --path layouts #{@vendor_repository_dir} skit-layouts")
45
49
  end
46
50
  end
47
51
 
48
52
  it 'should add the files and commit' do
49
- assert_no_diff("#{FIXTURE_PATH}/skit1/layouts/layout.liquid", "#{@repository_dir}/skit1/layout.liquid")
53
+ assert_no_diff("#{FIXTURE_PATH}/skit1/layouts/layout.liquid", "#{@repository_dir}/skit-layouts/layout.liquid")
54
+
55
+ in_dir(@repository_dir) do
56
+ assert_commit_subject(/Braid: Add mirror 'skit-layouts' at '[0-9a-f]{7}'/)
57
+ assert_commit_author('Some body')
58
+ assert_commit_email('somebody@example.com')
59
+ end
60
+ end
61
+
62
+ it 'should create .braids.json and add the mirror to it' do
63
+ braids = YAML::load_file("#{@repository_dir}/.braids.json")
64
+ expect(braids['config_version']).to be_kind_of(Numeric)
65
+ mirror_obj = braids['mirrors']['skit-layouts']
66
+ expect(mirror_obj['url']).to eq(@vendor_repository_dir)
67
+ expect(mirror_obj['revision']).not_to be_nil
68
+ expect(mirror_obj['branch']).to eq('master')
69
+ expect(mirror_obj['tag']).to be_nil
70
+ expect(mirror_obj['path']).to eq('layouts')
71
+ end
72
+ end
73
+
74
+ describe 'from a single file in a git repository' do
75
+ before do
76
+ @repository_dir = create_git_repo_from_fixture('shiny', :name => 'Some body', :email => 'somebody@example.com')
77
+ @vendor_repository_dir = create_git_repo_from_fixture('skit1')
50
78
 
51
- assert_commit_subject(/Braid: Add mirror 'skit1' at '[0-9a-f]{7}'/)
52
- assert_commit_author('Some body')
53
- assert_commit_email('somebody@example.com')
79
+ in_dir(@repository_dir) do
80
+ run_command("#{BRAID_BIN} add --path layouts/layout.liquid #{@vendor_repository_dir} skit-layout.liquid")
81
+ end
82
+ end
83
+
84
+ it 'should add the file and commit' do
85
+ assert_no_diff("#{FIXTURE_PATH}/skit1/layouts/layout.liquid", "#{@repository_dir}/skit-layout.liquid")
86
+
87
+ in_dir(@repository_dir) do
88
+ assert_commit_subject(/Braid: Add mirror 'skit-layout.liquid' at '[0-9a-f]{7}'/)
89
+ assert_commit_author('Some body')
90
+ assert_commit_email('somebody@example.com')
91
+ end
54
92
  end
55
93
 
56
94
  it 'should create .braids.json and add the mirror to it' do
57
95
  braids = YAML::load_file("#{@repository_dir}/.braids.json")
58
- expect(braids['skit1']['url']).to eq(@vendor_repository_dir)
59
- expect(braids['skit1']['revision']).not_to be_nil
60
- expect(braids['skit1']['branch']).to eq('master')
61
- expect(braids['skit1']['tag']).to be_nil
62
- expect(braids['skit1']['path']).to eq('layouts')
96
+ expect(braids['config_version']).to be_kind_of(Numeric)
97
+ mirror_obj = braids['mirrors']['skit-layout.liquid']
98
+ expect(mirror_obj['url']).to eq(@vendor_repository_dir)
99
+ expect(mirror_obj['revision']).not_to be_nil
100
+ expect(mirror_obj['branch']).to eq('master')
101
+ expect(mirror_obj['tag']).to be_nil
102
+ expect(mirror_obj['path']).to eq('layouts/layout.liquid')
63
103
  end
64
104
  end
65
105
 
@@ -79,18 +119,22 @@ describe 'Adding a mirror in a clean repository' do
79
119
  it 'should add the files and commit' do
80
120
  assert_no_diff("#{FIXTURE_PATH}/skit1/layouts/layout.liquid", "#{@repository_dir}/skit1/layouts/layout.liquid")
81
121
 
82
- assert_commit_subject(/Braid: Add mirror 'skit1' at '[0-9a-f]{7}'/)
83
- assert_commit_author('Some body')
84
- assert_commit_email('somebody@example.com')
122
+ in_dir(@repository_dir) do
123
+ assert_commit_subject(/Braid: Add mirror 'skit1' at '[0-9a-f]{7}'/)
124
+ assert_commit_author('Some body')
125
+ assert_commit_email('somebody@example.com')
126
+ end
85
127
  end
86
128
 
87
129
  it 'should create .braids.json and add the mirror to it' do
88
130
  braids = YAML::load_file("#{@repository_dir}/.braids.json")
89
- expect(braids['skit1']['url']).to eq(@vendor_repository_dir)
90
- expect(braids['skit1']['revision']).not_to be_nil
91
- expect(braids['skit1']['branch']).to be_nil
92
- expect(braids['skit1']['tag']).to eq('v1')
93
- expect(braids['skit1']['path']).to be_nil
131
+ expect(braids['config_version']).to be_kind_of(Numeric)
132
+ mirror_obj = braids['mirrors']['skit1']
133
+ expect(mirror_obj['url']).to eq(@vendor_repository_dir)
134
+ expect(mirror_obj['revision']).not_to be_nil
135
+ expect(mirror_obj['branch']).to be_nil
136
+ expect(mirror_obj['tag']).to eq('v1')
137
+ expect(mirror_obj['path']).to be_nil
94
138
  end
95
139
  end
96
140
 
@@ -111,18 +155,22 @@ describe 'Adding a mirror in a clean repository' do
111
155
  it 'should add the files and commit' do
112
156
  assert_no_diff("#{FIXTURE_PATH}/skit1/layouts/layout.liquid", "#{@repository_dir}/skit1/layouts/layout.liquid")
113
157
 
114
- assert_commit_subject(/Braid: Add mirror 'skit1' at '[0-9a-f]{7}'/)
115
- assert_commit_author('Some body')
116
- assert_commit_email('somebody@example.com')
158
+ in_dir(@repository_dir) do
159
+ assert_commit_subject(/Braid: Add mirror 'skit1' at '[0-9a-f]{7}'/)
160
+ assert_commit_author('Some body')
161
+ assert_commit_email('somebody@example.com')
162
+ end
117
163
  end
118
164
 
119
165
  it 'should create .braids.json and add the mirror to it' do
120
166
  braids = YAML::load_file("#{@repository_dir}/.braids.json")
121
- expect(braids['skit1']['url']).to eq(@vendor_repository_dir)
122
- expect(braids['skit1']['revision']).not_to be_nil
123
- expect(braids['skit1']['branch']).to be_nil
124
- expect(braids['skit1']['tag']).to be_nil
125
- expect(braids['skit1']['path']).to be_nil
167
+ expect(braids['config_version']).to be_kind_of(Numeric)
168
+ mirror_obj = braids['mirrors']['skit1']
169
+ expect(mirror_obj['url']).to eq(@vendor_repository_dir)
170
+ expect(mirror_obj['revision']).not_to be_nil
171
+ expect(mirror_obj['branch']).to be_nil
172
+ expect(mirror_obj['tag']).to be_nil
173
+ expect(mirror_obj['path']).to be_nil
126
174
  end
127
175
  end
128
176
 
@@ -0,0 +1,222 @@
1
+ require File.dirname(__FILE__) + '/integration_helper'
2
+
3
+ describe 'Config versioning:' do
4
+
5
+ before do
6
+ FileUtils.rm_rf(TMP_PATH)
7
+ FileUtils.mkdir_p(TMP_PATH)
8
+ end
9
+
10
+ # Workaround for Braid writing .braids.json with LF line endings on Windows,
11
+ # while the .braids.json files in the fixtures get converted to CRLF under Git
12
+ # for Windows recommended settings.
13
+ # https://github.com/cristibalan/braid/issues/77
14
+ def assert_no_diff_in_braids(file1, file2)
15
+ # --ignore-trailing-space is not present in the platform diff command under osx so only use it when needed
16
+ assert_no_diff(file1, file2, Gem.win_platform? ? '--ignore-trailing-space' : '')
17
+ end
18
+
19
+ describe 'read-only command' do
20
+
21
+ it 'from future config version should fail' do
22
+ @repository_dir = create_git_repo_from_fixture('shiny-conf-future')
23
+
24
+ in_dir(@repository_dir) do
25
+ output = run_command_expect_failure("#{BRAID_BIN} diff skit1")
26
+ expect(output).to match(/is too old to understand/)
27
+ end
28
+ end
29
+
30
+ it 'from old config version with no breaking changes should work' do
31
+ @repository_dir = create_git_repo_from_fixture('shiny-conf-yaml')
32
+ @vendor_repository_dir = create_git_repo_from_fixture('skit1')
33
+
34
+ vendor_revision = nil
35
+ in_dir(@vendor_repository_dir) do
36
+ vendor_revision = run_command('git rev-parse HEAD')
37
+ end
38
+
39
+ in_dir(@repository_dir) do
40
+ # For a real command to work, we have to substitute the URL and revision
41
+ # of the real vendor repository we created on this run of the test. The
42
+ # below looks marginally easier than using the real YAML parser.
43
+ braids_content = nil
44
+ File.open('.braids', 'rb') do |f|
45
+ braids_content = f.read
46
+ end
47
+ braids_content = braids_content.sub(/revision:.*$/, "revision: #{vendor_revision}")
48
+ braids_content = braids_content.sub(/url:.*$/, "url: file://#{@vendor_repository_dir}")
49
+ File.open('.braids', 'wb') do |f|
50
+ f.write braids_content
51
+ end
52
+
53
+ output = run_command("#{BRAID_BIN} diff skit1")
54
+ expect(output).to eq('') # no diff
55
+ end
56
+ end
57
+
58
+ it 'from old config version with breaking changes should fail' do
59
+ @repository_dir = create_git_repo_from_fixture('shiny-conf-breaking-changes')
60
+
61
+ in_dir(@repository_dir) do
62
+ output = run_command_expect_failure("#{BRAID_BIN} diff skit1")
63
+ expect(output).to match(/no longer supports a feature/)
64
+ end
65
+ end
66
+
67
+ end
68
+
69
+ describe 'write command' do
70
+
71
+ it 'from future config version should fail' do
72
+ @repository_dir = create_git_repo_from_fixture('shiny-conf-future')
73
+
74
+ in_dir(@repository_dir) do
75
+ output = run_command_expect_failure("#{BRAID_BIN} update skit1")
76
+ expect(output).to match(/is too old to understand/)
77
+ end
78
+ end
79
+
80
+ it 'from old config version with no breaking changes should fail' do
81
+ @repository_dir = create_git_repo_from_fixture('shiny-conf-yaml')
82
+
83
+ in_dir(@repository_dir) do
84
+ output = run_command_expect_failure("#{BRAID_BIN} update skit1")
85
+ expect(output).to match(/force other developers on your project to upgrade Braid/)
86
+ end
87
+ end
88
+
89
+ it 'from old config version with breaking changes should fail' do
90
+ @repository_dir = create_git_repo_from_fixture('shiny-conf-breaking-changes')
91
+
92
+ in_dir(@repository_dir) do
93
+ output = run_command_expect_failure("#{BRAID_BIN} update skit1")
94
+ expect(output).to match(/no longer supports a feature/)
95
+ end
96
+ end
97
+
98
+ end
99
+
100
+ describe '"braid upgrade-config"' do
101
+
102
+ it 'from Braid 0.7.1 (.braids YAML) should produce the expected configuration' do
103
+ @repository_dir = create_git_repo_from_fixture('shiny-conf-yaml')
104
+
105
+ in_dir(@repository_dir) do
106
+ output = run_command("#{BRAID_BIN} upgrade-config")
107
+ # Check this on one of the test cases.
108
+ expect(output).to match(/Configuration upgrade complete\./)
109
+ expect(File.exists?('.braids')).to eq(false)
110
+ assert_no_diff_in_braids('.braids.json', 'expected.braids.json')
111
+ end
112
+ end
113
+
114
+ it 'from Braid 1.0.0 (.braids JSON) should produce the expected configuration' do
115
+ @repository_dir = create_git_repo_from_fixture('shiny-conf-json-old-name')
116
+
117
+ in_dir(@repository_dir) do
118
+ run_command("#{BRAID_BIN} upgrade-config")
119
+ expect(File.exists?('.braids')).to eq(false)
120
+ assert_no_diff_in_braids('.braids.json', 'expected.braids.json')
121
+ end
122
+ end
123
+
124
+ it 'from Braid 1.0.9 (.braids.json) with old-style lock should produce the expected configuration' do
125
+ @repository_dir = create_git_repo_from_fixture('shiny-conf-1.0.9-lock')
126
+
127
+ in_dir(@repository_dir) do
128
+ run_command("#{BRAID_BIN} upgrade-config")
129
+ assert_no_diff_in_braids('.braids.json', 'expected.braids.json')
130
+ end
131
+ end
132
+
133
+ it 'from Braid 1.0.9 (.braids.json) with old-style lock with --dry-run should print info without performing the upgrade' do
134
+ @repository_dir = create_git_repo_from_fixture('shiny-conf-1.0.9-lock')
135
+
136
+ in_dir(@repository_dir) do
137
+ output = run_command("#{BRAID_BIN} upgrade-config --dry-run")
138
+ expect(output).to match(/Your configuration file will be upgraded from configuration version 0 to 1\./)
139
+ expect(output).not_to match(/The following breaking changes/)
140
+ # Instructions should not include --allow-breaking-changes if it isn't necessary.
141
+ expect(output).to match(/Run 'braid upgrade-config'/)
142
+ assert_no_diff_in_braids('.braids.json', "#{FIXTURE_PATH}/shiny-conf-1.0.9-lock/.braids.json")
143
+ end
144
+ end
145
+
146
+ it 'with breaking changes and --dry-run should print info without performing the upgrade' do
147
+ @repository_dir = create_git_repo_from_fixture('shiny-conf-breaking-changes')
148
+
149
+ in_dir(@repository_dir) do
150
+ output = run_command("#{BRAID_BIN} upgrade-config --dry-run")
151
+ expect(output).to match(/The following breaking changes/)
152
+ expect(output).to match(/Spoon-Knife.*Subversion/)
153
+ expect(output).to match(/skit1.*full-history/)
154
+ expect(output).to match(/Run 'braid upgrade-config --allow-breaking-changes'/)
155
+ assert_no_diff('.braids', "#{FIXTURE_PATH}/shiny-conf-breaking-changes/.braids")
156
+ expect(File.exists?('.braids.json')).to eq(false)
157
+ end
158
+ end
159
+
160
+ it 'with breaking changes should fail' do
161
+ @repository_dir = create_git_repo_from_fixture('shiny-conf-breaking-changes')
162
+
163
+ in_dir(@repository_dir) do
164
+ output = run_command_expect_failure("#{BRAID_BIN} upgrade-config")
165
+ expect(output).to match(/The following breaking changes/)
166
+ expect(output).to match(/Spoon-Knife.*Subversion/)
167
+ expect(output).to match(/skit1.*full-history/)
168
+ expect(output).to match(/You must pass --allow-breaking-changes/)
169
+ # `braid upgrade-config` should not have changed any files.
170
+ assert_no_diff('.braids', "#{FIXTURE_PATH}/shiny-conf-breaking-changes/.braids")
171
+ expect(File.exists?('.braids.json')).to eq(false)
172
+ end
173
+ end
174
+
175
+ it 'with breaking changes and --allow-breaking-changes should produce the expected configuration' do
176
+ @repository_dir = create_git_repo_from_fixture('shiny-conf-breaking-changes')
177
+
178
+ in_dir(@repository_dir) do
179
+ output = run_command("#{BRAID_BIN} upgrade-config --allow-breaking-changes")
180
+ expect(output).to match(/The following breaking changes/)
181
+ expect(output).to match(/Spoon-Knife.*Subversion/)
182
+ expect(output).to match(/skit1.*full-history/)
183
+ expect(output).to match(/Configuration upgrade complete\./)
184
+ expect(File.exists?('.braids')).to eq(false)
185
+ assert_no_diff_in_braids('.braids.json', 'expected.braids.json')
186
+ end
187
+ end
188
+
189
+ it 'from future config version should fail' do
190
+ @repository_dir = create_git_repo_from_fixture('shiny-conf-future')
191
+
192
+ in_dir(@repository_dir) do
193
+ output = run_command_expect_failure("#{BRAID_BIN} upgrade-config")
194
+ expect(output).to match(/is too old to understand/)
195
+ end
196
+ end
197
+
198
+ it 'from current config version should do nothing and print expected message' do
199
+ # Generate a current-version configuration by adding a mirror.
200
+ @repository_dir = create_git_repo_from_fixture('shiny')
201
+ @vendor_repository_dir = create_git_repo_from_fixture('skit1')
202
+
203
+ in_dir(@repository_dir) do
204
+ run_command("#{BRAID_BIN} add #{@vendor_repository_dir}")
205
+ output = run_command("#{BRAID_BIN} upgrade-config")
206
+ expect(output).to match(/already at the current configuration version/)
207
+ end
208
+ end
209
+
210
+ it 'with no Braid configuration should do nothing and print expected message' do
211
+ @repository_dir = create_git_repo_from_fixture('shiny')
212
+
213
+ in_dir(@repository_dir) do
214
+ output = run_command("#{BRAID_BIN} upgrade-config")
215
+ expect(output).to match(/has no Braid configuration file/)
216
+ expect(File.exists?('.braids.json')).to eq(false)
217
+ end
218
+ end
219
+
220
+ end
221
+
222
+ end