berkshelf-bzr 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a32783d27faa3200825c6150cccbf2b9fd58d4ec
4
+ data.tar.gz: 9c9f7a9e5c6bff4b34fed0de388fe5ac5ed5cb01
5
+ SHA512:
6
+ metadata.gz: fec4113c7f74f9ca90f03b49f506f8561c63f4a51f7837aa7cebf4aa90e99634880b608ee8e4741028f86b80cc723189be1334d23cd32c9b3c44ca44039ed990
7
+ data.tar.gz: c700762902ba61b8d7a4586597e79cd21c029b7751ad26b2f102ec7439af74a04ead8fcae5169b9dce79b8eee3bfb2bf100a443a219111fafdfc647a2dd4f749
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .rspec
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
@@ -0,0 +1,13 @@
1
+ before_install:
2
+ - sudo apt-get update -qq
3
+ - sudo apt-get install bzr
4
+ - bzr whoami 'Test <test@test.net>'
5
+
6
+ rvm:
7
+ - 1.9.3
8
+ - 2.0.0
9
+ - 2.1.0
10
+
11
+ bundler_args: --jobs 7
12
+
13
+ script: bundle exec rake travis:ci
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'berkshelf', github: 'berkshelf/berkshelf'
4
+
5
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
@@ -0,0 +1,65 @@
1
+ Berkshelf Bzr
2
+ ============
3
+ [![Gem Version](https://badge.fury.io/rb/berkshelf-bzr.png)](http://badge.fury.io/rb/berkshelf-bzr)
4
+ [![Build Status](https://travis-ci.org/berkshelf/berkshelf-bzr.png?branch=master)](https://travis-ci.org/berkshelf/berkshelf-bzr)
5
+ [![Code Climate](https://codeclimate.com/github/berkshelf/berkshelf-bzr.png)](https://codeclimate.com/github/berkshelf/berkshelf-bzr)
6
+
7
+ Berkshelf Bzr is a Berkshelf extension that adds support for downloading cookbooks from Bazaar locations.
8
+
9
+ Installation
10
+ ------------
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'berkshelf-bzr'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install berkshelf-bzr
22
+
23
+ Usage
24
+ -----
25
+ Activate the extension in your `Berksfile`:
26
+
27
+ ```ruby
28
+ source 'https://api.berkshelf.com'
29
+ extension 'bzr'
30
+ ```
31
+
32
+ Use the exposed `:bzr` key to define your sources:
33
+
34
+ ```ruby
35
+ cookbook 'mycookbook', bzr: 'lp:mycookbook'
36
+ ```
37
+
38
+ You may also specify a `ref` (see output of bzr help revisionspec):
39
+
40
+ ```ruby
41
+ cookbook 'mycookbook', bzr: 'lp:mycookbook', ref: 'revno:7'
42
+ ```
43
+
44
+ License & Authors
45
+ -----------------
46
+ The code is an adaptation of Mercurial berkshelf's extension
47
+ (https://github.com/berkshelf/berkshelf-hg)
48
+
49
+ - Author: David Chauviere (d_chauviere@yahoo.fr)
50
+
51
+ ```text
52
+ Copyright 2014 David Chauviere
53
+
54
+ Licensed under the Apache License, Version 2.0 (the "License");
55
+ you may not use this file except in compliance with the License.
56
+ You may obtain a copy of the License at
57
+
58
+ http://www.apache.org/licenses/LICENSE-2.0
59
+
60
+ Unless required by applicable law or agreed to in writing, software
61
+ distributed under the License is distributed on an "AS IS" BASIS,
62
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
63
+ See the License for the specific language governing permissions and
64
+ limitations under the License.
65
+ ```
@@ -0,0 +1,12 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new(:unit)
5
+
6
+ require 'cucumber/rake/task'
7
+ Cucumber::Rake::Task.new(:integration)
8
+
9
+ namespace :travis do
10
+ desc 'Run the tests on Travis'
11
+ task :ci => [:unit, :integration]
12
+ end
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'berkshelf/bzr/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'berkshelf-bzr'
8
+ spec.version = Berkshelf::Bzr::VERSION
9
+ spec.authors = [ 'David Chauviere' ]
10
+ spec.email = [ 'd_chauviere@yahoo.fr' ]
11
+ spec.summary = 'Bazaar support for Berkshelf'
12
+ spec.description = 'A Berkshelf plugin that adds support for downloading ' \
13
+ 'Chef cookbooks from Bazaar locations.'
14
+ spec.homepage = 'https://github.com/Da-Wei/berkshelf-bzr'
15
+ spec.license = 'Apache 2.0'
16
+
17
+ spec.files = `git ls-files`.split($/)
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ['lib']
21
+
22
+ # Runtime dependencies
23
+ spec.add_dependency 'berkshelf', '~> 3.0'
24
+
25
+ # Development dependencies
26
+ spec.add_development_dependency 'aruba', '~> 0.5'
27
+ spec.add_development_dependency 'rspec', '~> 2.14'
28
+
29
+ spec.add_development_dependency 'bundler', '~> 1.5'
30
+ spec.add_development_dependency 'rake', '~> 0.9'
31
+ end
@@ -0,0 +1,69 @@
1
+ Feature: Installing from a bazaar location
2
+
3
+ Scenario: installing a demand from a Bzr location
4
+ Given a remote bazaar cookbook named "fake"
5
+ And I write a Berksfile with:
6
+ """
7
+ source 'https://api.berkshelf.com'
8
+ extension 'bzr'
9
+
10
+ cookbook 'fake', bzr: "#{Dir.pwd}/bzr-cookbooks/fake"
11
+ """
12
+ When I successfully run `berks install`
13
+ Then the cookbook store should have the bzr cookbooks:
14
+ | fake | 1.0.0 | 14ff121c2fd9f70f1db9fe0824a5880b6f91da20 |
15
+ And the output should contain:
16
+ """
17
+ Using fake (1.0.0)
18
+ """
19
+
20
+ Scenario: installing a demand from a Bzr location that has already been installed
21
+ Given a remote bazaar cookbook named "fake"
22
+ Given I write a Berksfile with:
23
+ """
24
+ source 'https://api.berkshelf.com'
25
+ extension 'bzr'
26
+
27
+ cookbook 'fake', bzr: "#{Dir.pwd}/bzr-cookbooks/fake"
28
+ """
29
+ And the cookbook store has the bzr cookbooks:
30
+ | fake | 1.0.0 | 14ff121c2fd9f70f1db9fe0824a5880b6f91da20 |
31
+ When I successfully run `berks install`
32
+ Then the output should contain:
33
+ """
34
+ Using fake (1.0.0)
35
+ """
36
+
37
+ Scenario: installing a Berksfile that contains a Bzr location with a ref
38
+ Given a remote bazaar cookbook named "fake" with a ref named "revno:1"
39
+ Given I write a Berksfile with:
40
+ """
41
+ source 'https://api.berkshelf.com'
42
+ extension 'bzr'
43
+
44
+ cookbook 'fake', bzr: "#{Dir.pwd}/bzr-cookbooks/fake", ref: 'revno:1'
45
+ """
46
+ When I successfully run `berks install`
47
+ Then the cookbook store should have the bzr cookbooks:
48
+ | fake | 1.0.0 | 14ff121c2fd9f70f1db9fe0824a5880b6f91da20 |
49
+ And the output should contain:
50
+ """
51
+ Using fake (1.0.0)
52
+ """
53
+
54
+ Scenario: with a bzr error during download
55
+ Given a remote bazaar cookbook named "fake" with a ref named "revno:1"
56
+ Given I write a Berksfile with:
57
+ """
58
+ source 'https://api.berkshelf.com'
59
+ extension 'bzr'
60
+
61
+ cookbook 'fake', bzr: "#{Dir.pwd}/bzr-cookbooks/fake", ref: 'revno:1'
62
+ cookbook "doesntexist", bzr: "asdjhfkljashflkjashfakljsf"
63
+ """
64
+ When I run `berks install`
65
+ Then the output should contain:
66
+ """
67
+ Bzr error
68
+ """
69
+ And the exit status should be "BzrLocation::BzrError"
@@ -0,0 +1,76 @@
1
+ Given(/^I write a Berksfile with:$/) do |string|
2
+ File.open(File.join(tmp_path, 'Berksfile'), 'w') do |f|
3
+ f.write string
4
+ end
5
+ end
6
+
7
+
8
+ Then(/^the cookbook store should have the bzr cookbooks:$/) do |cookbooks|
9
+ cookbooks.raw.each do |name, version, sha1|
10
+ Berkshelf.cookbook_store.storage_path.join("#{name}-#{sha1}").exist?
11
+ end
12
+ end
13
+
14
+ Given(/^the cookbook store has the bzr cookbooks:$/) do |cookbooks|
15
+ cookbooks.raw.each do |name, version, sha|
16
+ folder = "#{name}-#{sha}"
17
+ metadata = File.join(folder, 'metadata.rb')
18
+
19
+ create_dir(folder)
20
+ write_file(metadata, [
21
+ "name '#{name}'",
22
+ "version '#{version}'"
23
+ ].join("\n"))
24
+ end
25
+ end
26
+
27
+ Then /^the exit status should be "(.+)"$/ do |name|
28
+ error = name.split('::').reduce(Berkshelf) { |klass, id| klass.const_get(id) }
29
+ assert_exit_status(error.status_code)
30
+ end
31
+
32
+ Given /^a remote bazaar cookbook named "(\w+)"$/ do |name|
33
+ path = File.join(tmp_path, 'bzr-cookbooks', name)
34
+ FileUtils.mkdir_p(path)
35
+
36
+ Dir.chdir(path) do
37
+ bzr('init')
38
+
39
+ File.open('metadata.rb', 'w') do |f|
40
+ f.write <<-EOH
41
+ name '#{name}'
42
+ version '1.0.0'
43
+ EOH
44
+ end
45
+
46
+ bzr('add')
47
+ bzr_commit('Initial commit')
48
+ end
49
+ end
50
+
51
+ Given(/^a remote bazaar cookbook named "(.*?)" with a ref named "(.*?)"$/) do |name, ref|
52
+ path = File.join(tmp_path, 'bzr-cookbooks', name)
53
+ steps %Q|Given a remote bazaar cookbook named "#{name}"|
54
+
55
+ Dir.chdir(path) do
56
+ File.open('metadata.rb', 'w') do |f|
57
+ f.write <<-EOH
58
+ name '#{name}'
59
+ version '2.3.4'
60
+ EOH
61
+ end
62
+
63
+ bzr('add')
64
+ bzr_commit('More changes')
65
+ end
66
+ end
67
+
68
+ def bzr(command)
69
+ %x|bzr #{command}|
70
+ end
71
+
72
+ def bzr_commit(message)
73
+ bzr %|commit -m "#{message}"|
74
+ end
75
+
76
+
@@ -0,0 +1,23 @@
1
+ require 'aruba/cucumber'
2
+ require 'aruba/in_process'
3
+ require 'berkshelf'
4
+
5
+ Before do
6
+ Aruba::InProcess.main_class = Berkshelf::Cli::Runner
7
+ Aruba.process = Aruba::InProcess
8
+
9
+ @aruba_timeout_seconds = 30
10
+
11
+ ENV['BERKSHELF_PATH'] = tmp_path
12
+
13
+ ENV['BERKSHELF_CONFIG'] = Berkshelf.config.path.to_s
14
+ # clean_tmp_path
15
+ Berkshelf.initialize_filesystem
16
+ Berkshelf::CookbookStore.instance.initialize_filesystem
17
+ # reload_configs
18
+ Berkshelf::CachedCookbook.instance_variable_set(:@loaded_cookbooks, nil)
19
+ end
20
+
21
+ def tmp_path
22
+ File.expand_path('tmp/aruba')
23
+ end
@@ -0,0 +1,5 @@
1
+ require 'berkshelf/bzr/version'
2
+
3
+ module Berkshelf
4
+ autoload :BzrLocation, 'berkshelf/locations/bzr'
5
+ end
@@ -0,0 +1,5 @@
1
+ module Berkshelf
2
+ module Bzr
3
+ VERSION = '0.3.0'
4
+ end
5
+ end
@@ -0,0 +1,177 @@
1
+ require 'buff/shell_out'
2
+ require 'digest/sha1'
3
+ require 'pathname'
4
+ require 'berkshelf'
5
+
6
+ module Berkshelf
7
+ class BzrLocation < BaseLocation
8
+ class BzrError < BerkshelfError; status_code(600); end
9
+
10
+ class BzrNotInstalled < BzrError
11
+ def initialize
12
+ super 'You need to install Bazaar before you can download ' \
13
+ 'cookbooks from bzr repositories. For more information, please ' \
14
+ 'see the Bazaar docs: http://bazaar.canonical.com.'
15
+ end
16
+ end
17
+
18
+ class BzrCommandError < BzrError
19
+ def initialize(command, path = nil, stderr = nil)
20
+ out = "Bzr error: command `bzr #{command}` failed. If this error "
21
+ out << "persists, try removing the cache directory at `#{path}'."
22
+
23
+ if stderr
24
+ out << "Output from the command:\n\n"
25
+ out << stderr
26
+ end
27
+ super(out)
28
+ end
29
+ end
30
+
31
+ attr_reader :uri
32
+ attr_reader :revision
33
+ attr_reader :ref
34
+
35
+ def initialize(dependency, options = {})
36
+ super
37
+
38
+ @uri = options[:bzr]
39
+ @revision = options[:revision]
40
+ @ref = options[:ref] || 'last:'
41
+ end
42
+
43
+ # Determine if this revision is installed.
44
+ #
45
+ # @return [Boolean]
46
+ def installed?
47
+ revision && install_path.exist?
48
+ end
49
+
50
+ # Install this bzr cookbook into the cookbook store. This method leverages
51
+ # a cached bzr copy and a scratch directory to prevent bad cookbooks from
52
+ # making their way into the cookbook store.
53
+ #
54
+ # @see BaseLocation#install
55
+ def install
56
+
57
+ if cached?
58
+ Dir.chdir(cache_path) do
59
+ bzr %|pull|
60
+ end
61
+ else
62
+ FileUtils.mkdir_p(cache_path.dirname)
63
+ bzr %|branch #{uri} #{cache_path}|
64
+ end
65
+
66
+ Dir.chdir(cache_path) do
67
+ bzr %|update -r #{@revision || @ref}|
68
+ end
69
+ @revision ||= revid(cache_path)
70
+
71
+ # Validate the scratched path is a valid cookbook
72
+ validate_cached!(cache_path)
73
+
74
+ # If we got this far, we should copy
75
+ FileUtils.rm_rf(install_path) if install_path.exist?
76
+ FileUtils.cp_r(cache_path, install_path)
77
+ install_path.chmod(0777 & ~File.umask)
78
+ end
79
+
80
+ # @see BaseLocation#cached_cookbook
81
+ def cached_cookbook
82
+ if installed?
83
+ @cached_cookbook ||= CachedCookbook.from_path(install_path)
84
+ else
85
+ nil
86
+ end
87
+ end
88
+
89
+ def ==(other)
90
+ other.is_a?(BzrLocation) &&
91
+ other.uri == uri &&
92
+ other.ref == ref
93
+ end
94
+
95
+ def to_s
96
+ "#{uri} (at ref: #{ref})"
97
+ end
98
+
99
+ def to_lock
100
+ out = " bzr: #{uri}\n"
101
+ out << " revision: #{revision}\n"
102
+ out << " ref: #{ref}\n" if ref
103
+ out
104
+ end
105
+
106
+ private
107
+
108
+ # Perform a bazaar command.
109
+ #
110
+ # @param [String] command
111
+ # the command to run
112
+ # @param [Boolean] error
113
+ # whether to raise error if the command fails
114
+ #
115
+ # @raise [String]
116
+ # the +$stdout+ from the command
117
+ def bzr(command, error = true)
118
+ unless Berkshelf.which('bzr') || Berkshelf.which('bzr.exe')
119
+ raise BzrNotInstalled.new
120
+ end
121
+
122
+ response = Buff::ShellOut.shell_out(%|bzr #{command}|)
123
+
124
+ if error && !response.success?
125
+ # All bzr output is on stdout, not stderr
126
+ raise BzrCommandError.new(command, cache_path, stderr = response.stdout)
127
+ end
128
+
129
+ response.stdout.strip
130
+ end
131
+
132
+ # Get revid from bazaar repository.
133
+ # @param [String] path
134
+ # the path to the bazaar repository
135
+ # @return [String | nil]
136
+ # the bazaar revid
137
+ def revid(path)
138
+ Dir.chdir(path) do
139
+ stdout = bzr %|testament --strict|
140
+ if stdout
141
+ testament = stdout.match(/revision-id: (.*)/)
142
+ unless testament[1]
143
+ raise BazaarError.new('Unable to find bazaar revid')
144
+ end
145
+ 'revid:' + testament[1]
146
+ end
147
+ end
148
+ end
149
+
150
+
151
+ # Determine if this bazaar repo has already been downloaded.
152
+ #
153
+ # @return [Boolean]
154
+ def cached?
155
+ cache_path.exist?
156
+ end
157
+
158
+
159
+ # The path where this cookbook would live in the store, if it were
160
+ # installed.
161
+ #
162
+ # @return [Pathname, nil]
163
+ def install_path
164
+ Berkshelf.cookbook_store.storage_path
165
+ .join("#{dependency.name}-#{revision.gsub('-', '_')}")
166
+ end
167
+
168
+ # The path where this bazaar repository is cached.
169
+ #
170
+ # @return [Pathname]
171
+ def cache_path
172
+ Pathname.new(Berkshelf.berkshelf_path)
173
+ .join('.cache', 'bzr', Digest::SHA1.hexdigest(uri))
174
+ end
175
+
176
+ end
177
+ end
@@ -0,0 +1,13 @@
1
+ require 'berkshelf/bzr'
2
+
3
+ RSpec.configure do |config|
4
+ config.treat_symbols_as_metadata_keys_with_true_values = true
5
+ config.run_all_when_everything_filtered = true
6
+ config.filter_run :focus
7
+
8
+ # Run specs in random order to surface order dependencies. If you find an
9
+ # order dependency and want to debug it, you can fix the order by providing
10
+ # the seed, which is printed after each run.
11
+ # --seed 1234
12
+ config.order = 'random'
13
+ end
@@ -0,0 +1,150 @@
1
+ require 'spec_helper'
2
+
3
+ module Berkshelf
4
+ describe BzrLocation do
5
+ let(:dependency) { double(name: 'bacon') }
6
+
7
+ subject do
8
+ described_class.new(dependency, bzr: 'https://repo.com',
9
+ ref: 'revno:2', revision: 'revid:test@test.net-20140320213448-r0103d8bgjlu5jyz')
10
+ end
11
+
12
+ describe '.initialize' do
13
+ it 'sets the uri' do
14
+ instance = described_class.new(dependency, bzr: 'https://repo.com')
15
+ expect(instance.uri).to eq('https://repo.com')
16
+ end
17
+
18
+ it 'sets the ref' do
19
+ instance = described_class.new(dependency,
20
+ bzr: 'https://repo.com', ref: 'revno:1')
21
+ expect(instance.ref).to eq('revno:1')
22
+ end
23
+
24
+ it 'sets the revision' do
25
+ instance = described_class.new(dependency,
26
+ bzr: 'https://repo.com', revision: 'revid:test@test.net-20140320213448-r0103d8bgjlu5jyz')
27
+ expect(instance.revision).to eq('revid:test@test.net-20140320213448-r0103d8bgjlu5jyz')
28
+ end
29
+
30
+ end
31
+
32
+ describe '#installed?' do
33
+ it 'returns false when there is no revision' do
34
+ subject.stub(:revision).and_return(nil)
35
+ expect(subject.installed?).to be_false
36
+ end
37
+ it 'returns false when the install_path does not exist' do
38
+ subject.stub(:revision).and_return('abcd1234')
39
+ subject.stub(:install_path).and_return(double(exist?: false))
40
+ expect(subject.installed?).to be_false
41
+ end
42
+
43
+ it 'returns true when the location is installed' do
44
+ subject.stub(:revision).and_return('abcd1234')
45
+ subject.stub(:install_path).and_return(double(exist?: true))
46
+ expect(subject.installed?).to be_true
47
+ end
48
+ end
49
+
50
+ describe '#install' do
51
+ before do
52
+ CachedCookbook.stub(:from_store_path)
53
+ FileUtils.stub(:cp_r)
54
+ File.stub(:chmod)
55
+ subject.stub(:validate_cached!)
56
+ subject.stub(:validate_cookbook!)
57
+ subject.stub(:bzr)
58
+ end
59
+
60
+ context 'when the repository is cached' do
61
+ it 'pulls a new version' do
62
+ Dir.stub(:chdir).and_yield
63
+ subject.stub(:cached?).and_return(true)
64
+ expect(subject).to receive(:bzr).with('pull')
65
+ subject.install
66
+ end
67
+ end
68
+
69
+ context 'when the revision is not cached' do
70
+ it 'clones the repository' do
71
+ Dir.stub(:chdir).and_yield
72
+ subject.stub(:cached?).and_return(false)
73
+ FileUtils.stub(:mkdir_p)
74
+ expect(subject).to receive(:bzr).with(/branch https:\/\/repo.com .*/)
75
+ subject.install
76
+ end
77
+ end
78
+ end
79
+
80
+ describe '#cached_cookbook' do
81
+ it 'returns nil if the cookbook is not installed' do
82
+ subject.stub(:installed?).and_return(false)
83
+ expect(subject.cached_cookbook).to be_nil
84
+ end
85
+
86
+ it 'returns the cookbook at the install_path' do
87
+ subject.stub(:installed?).and_return(true)
88
+ CachedCookbook.stub(:from_path)
89
+
90
+ expect(CachedCookbook).to receive(:from_path).once
91
+ subject.cached_cookbook
92
+ end
93
+ end
94
+
95
+ describe '#==' do
96
+ let(:other) { subject.dup }
97
+
98
+ it 'returns true when everything matches' do
99
+ expect(subject).to eq(other)
100
+ end
101
+
102
+ it 'returns false when the other location is not an BzrLocation' do
103
+ other.stub(:is_a?).and_return(false)
104
+ expect(subject).to_not eq(other)
105
+ end
106
+
107
+ it 'returns false when the uri is different' do
108
+ other.stub(:uri).and_return('different')
109
+ expect(subject).to_not eq(other)
110
+ end
111
+
112
+ it 'returns false when the ref is different' do
113
+ other.stub(:ref).and_return('different')
114
+ expect(subject).to_not eq(other)
115
+ end
116
+ end
117
+
118
+ describe '#to_s' do
119
+ it 'gives the ref' do
120
+ expect(subject.to_s).to eq('https://repo.com (at ref: revno:2)')
121
+ end
122
+ end
123
+
124
+ describe '#to_lock' do
125
+ it 'includes all the information' do
126
+ expect(subject.to_lock).to eq <<-EOH.gsub(/^ {8}/, '')
127
+ bzr: https://repo.com
128
+ revision: revid:test@test.net-20140320213448-r0103d8bgjlu5jyz
129
+ ref: revno:2
130
+ EOH
131
+ end
132
+ end
133
+
134
+ describe '#bzr' do
135
+ before { described_class.send(:public, :bzr) }
136
+
137
+ it 'raises an error if Bazaar is not installed' do
138
+ Berkshelf.stub(:which).and_return(false)
139
+ expect { subject.bzr('foo') }.to raise_error(BzrLocation::BzrNotInstalled)
140
+ end
141
+
142
+ it 'raises an error if the command fails' do
143
+
144
+ shell_out = double('shell_out', success?: false, stdout: 'bzr: ERROR: Not a branch: "foo".', stderr: nil)
145
+ Buff::ShellOut.stub(:shell_out).and_return(shell_out)
146
+ expect { subject.bzr('foo') }.to raise_error(BzrLocation::BzrCommandError)
147
+ end
148
+ end
149
+ end
150
+ end
metadata ADDED
@@ -0,0 +1,135 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: berkshelf-bzr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - David Chauviere
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: berkshelf
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: aruba
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.5'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.14'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.14'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.5'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.5'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.9'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.9'
83
+ description: A Berkshelf plugin that adds support for downloading Chef cookbooks from
84
+ Bazaar locations.
85
+ email:
86
+ - d_chauviere@yahoo.fr
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - ".travis.yml"
93
+ - Gemfile
94
+ - LICENSE
95
+ - README.md
96
+ - Rakefile
97
+ - berkshelf-bzr.gemspec
98
+ - features/bzr.feature
99
+ - features/step_definitions/remote_steps.rb
100
+ - features/support/env.rb
101
+ - lib/berkshelf/bzr.rb
102
+ - lib/berkshelf/bzr/version.rb
103
+ - lib/berkshelf/locations/bzr.rb
104
+ - spec/spec_helper.rb
105
+ - spec/unit/locations/bzr_spec.rb
106
+ homepage: https://github.com/Da-Wei/berkshelf-bzr
107
+ licenses:
108
+ - Apache 2.0
109
+ metadata: {}
110
+ post_install_message:
111
+ rdoc_options: []
112
+ require_paths:
113
+ - lib
114
+ required_ruby_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ required_rubygems_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ requirements: []
125
+ rubyforge_project:
126
+ rubygems_version: 2.2.2
127
+ signing_key:
128
+ specification_version: 4
129
+ summary: Bazaar support for Berkshelf
130
+ test_files:
131
+ - features/bzr.feature
132
+ - features/step_definitions/remote_steps.rb
133
+ - features/support/env.rb
134
+ - spec/spec_helper.rb
135
+ - spec/unit/locations/bzr_spec.rb