braid 1.0.22 → 1.1.0

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