berkshelf 3.0.0.beta7 → 3.0.0.beta8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +4 -1
  4. data/CONTRIBUTING.md +1 -1
  5. data/Gemfile +0 -1
  6. data/Guardfile +0 -8
  7. data/README.md +33 -13
  8. data/berkshelf.gemspec +3 -3
  9. data/features/commands/install.feature +16 -88
  10. data/features/commands/search.feature +15 -0
  11. data/features/commands/shelf/show.feature +2 -2
  12. data/features/commands/shelf/uninstall.feature +1 -1
  13. data/features/commands/show.feature +3 -3
  14. data/features/commands/update.feature +29 -1
  15. data/features/commands/upload.feature +172 -7
  16. data/features/commands/vendor.feature +32 -0
  17. data/features/json_formatter.feature +26 -24
  18. data/features/lifecycle.feature +285 -0
  19. data/features/lockfile.feature +9 -7
  20. data/features/step_definitions/chef_server_steps.rb +1 -0
  21. data/features/step_definitions/cli_steps.rb +2 -2
  22. data/features/step_definitions/filesystem_steps.rb +2 -4
  23. data/gem_graph.png +0 -0
  24. data/generator_files/chefignore +0 -2
  25. data/lib/berkshelf.rb +39 -14
  26. data/lib/berkshelf/berksfile.rb +161 -113
  27. data/lib/berkshelf/cached_cookbook.rb +2 -2
  28. data/lib/berkshelf/cli.rb +15 -3
  29. data/lib/berkshelf/commands/shelf.rb +3 -7
  30. data/lib/berkshelf/community_rest.rb +9 -9
  31. data/lib/berkshelf/config.rb +3 -3
  32. data/lib/berkshelf/cookbook_generator.rb +0 -8
  33. data/lib/berkshelf/cookbook_store.rb +1 -2
  34. data/lib/berkshelf/dependency.rb +25 -138
  35. data/lib/berkshelf/downloader.rb +41 -7
  36. data/lib/berkshelf/errors.rb +113 -214
  37. data/lib/berkshelf/formatters/base.rb +42 -0
  38. data/lib/berkshelf/formatters/human.rb +145 -0
  39. data/lib/berkshelf/formatters/json.rb +149 -133
  40. data/lib/berkshelf/formatters/null.rb +8 -18
  41. data/lib/berkshelf/init_generator.rb +1 -1
  42. data/lib/berkshelf/installer.rb +115 -104
  43. data/lib/berkshelf/location.rb +22 -121
  44. data/lib/berkshelf/locations/base.rb +75 -0
  45. data/lib/berkshelf/locations/git.rb +196 -0
  46. data/lib/berkshelf/locations/github.rb +8 -0
  47. data/lib/berkshelf/locations/path.rb +78 -0
  48. data/lib/berkshelf/lockfile.rb +452 -290
  49. data/lib/berkshelf/logger.rb +9 -3
  50. data/lib/berkshelf/mixin/logging.rb +4 -9
  51. data/lib/berkshelf/resolver.rb +12 -12
  52. data/lib/berkshelf/source.rb +13 -1
  53. data/lib/berkshelf/version.rb +1 -1
  54. data/spec/fixtures/cookbooks/example_cookbook-0.5.0/metadata.rb +3 -7
  55. data/spec/fixtures/cookbooks/example_cookbook/metadata.rb +3 -6
  56. data/spec/spec_helper.rb +5 -6
  57. data/spec/support/matchers/file_system_matchers.rb +4 -0
  58. data/spec/support/shared_examples/formatter.rb +11 -0
  59. data/spec/unit/berkshelf/berksfile_spec.rb +25 -28
  60. data/spec/unit/berkshelf/cli_spec.rb +19 -11
  61. data/spec/unit/berkshelf/dependency_spec.rb +4 -164
  62. data/spec/unit/berkshelf/formatters/base_spec.rb +35 -0
  63. data/spec/unit/berkshelf/formatters/human_spec.rb +7 -0
  64. data/spec/unit/berkshelf/formatters/json_spec.rb +7 -0
  65. data/spec/unit/berkshelf/formatters/null_spec.rb +7 -11
  66. data/spec/unit/berkshelf/location_spec.rb +16 -144
  67. data/spec/unit/berkshelf/locations/base_spec.rb +80 -0
  68. data/spec/unit/berkshelf/locations/git_spec.rb +249 -0
  69. data/spec/unit/berkshelf/locations/path_spec.rb +107 -0
  70. data/spec/unit/berkshelf/lockfile_parser_spec.rb +3 -3
  71. data/spec/unit/berkshelf/lockfile_spec.rb +55 -11
  72. data/spec/unit/berkshelf/logger_spec.rb +2 -2
  73. data/spec/unit/berkshelf/mixin/logging_spec.rb +5 -9
  74. data/spec/unit/berkshelf/source_spec.rb +32 -13
  75. data/spec/unit/berkshelf_spec.rb +6 -9
  76. metadata +33 -33
  77. data/.ruby-version +0 -1
  78. data/berkshelf-complete.sh +0 -75
  79. data/lib/berkshelf/formatters.rb +0 -110
  80. data/lib/berkshelf/formatters/human_readable.rb +0 -142
  81. data/lib/berkshelf/git.rb +0 -204
  82. data/lib/berkshelf/locations/git_location.rb +0 -135
  83. data/lib/berkshelf/locations/github_location.rb +0 -55
  84. data/lib/berkshelf/locations/mercurial_location.rb +0 -114
  85. data/lib/berkshelf/locations/path_location.rb +0 -88
  86. data/lib/berkshelf/mercurial.rb +0 -146
  87. data/lib/berkshelf/mixin.rb +0 -7
  88. data/spec/support/mercurial.rb +0 -123
  89. data/spec/unit/berkshelf/formatters_spec.rb +0 -114
  90. data/spec/unit/berkshelf/git_spec.rb +0 -312
  91. data/spec/unit/berkshelf/locations/git_location_spec.rb +0 -126
  92. data/spec/unit/berkshelf/locations/mercurial_location_spec.rb +0 -131
  93. data/spec/unit/berkshelf/locations/path_location_spec.rb +0 -25
  94. data/spec/unit/berkshelf/mercurial_spec.rb +0 -172
data/.ruby-version DELETED
@@ -1 +0,0 @@
1
- 2.0.0-p353
@@ -1,75 +0,0 @@
1
- #!/bin/bash
2
- #
3
- # Description
4
- # Add tab completion for berkshelf
5
- #
6
- # Configuration:
7
- # BERKSHELF_BERKSFILE (default is 'Berksfile')
8
- #
9
- # Notes:
10
- # Must be added to your ~/.bashrc, ~/.zshrc, etc
11
- #
12
- # Author:
13
- # Seth Vargo <sethvargo@gmail.com>
14
- #
15
- # License:
16
- # Apache 2.0
17
- #
18
-
19
- _bundler() {
20
- which bundle > /dev/null 2>&1 && [ -f "$(pwd)/Gemfile" ]
21
- }
22
-
23
- # Overwrite berks to use bundler if defined
24
- _berks() {
25
- [ _bundler ] && bundle exec berks $@ || berks $@
26
- }
27
-
28
- _berkshelf_commands() {
29
- local cachefile=~/.berkshelf/.commands
30
- [ ! -f $cachefile ] && $(_berks help | grep berks | cut -d " " -f 4 > $cachefile)
31
- cat $cachefile
32
- }
33
-
34
- _berkshelf_cookbooks() {
35
- local file=${BERKSHELF_BERKSFILE:-Berksfile}
36
- if [ -e $file ]; then
37
- # strip all quotes from cookbook name and remove trailing comma, if any
38
- grep -w '^cookbook' $file \
39
- | awk '{ print $2 }' \
40
- | sed 's/"//g' \
41
- | sed "s/'//g" \
42
- | sed 's/,$//'
43
- fi
44
- }
45
-
46
- _local_cookbooks() {
47
- [ -d cookbooks ] && ls -d cookbooks/*/ | cut -d "/" -f 2
48
- }
49
-
50
- _berkshelf() {
51
- # local curr prev commands
52
- COMPREPLY=()
53
- curr="${COMP_WORDS[COMP_CWORD]}"
54
- prev="${COMP_WORDS[COMP_CWORD-1]}"
55
-
56
- # List of commands to complete
57
- commands=`_berkshelf_commands`
58
-
59
- case "${prev}" in
60
- "open"|"outdated"|"show"|"update"|"upload")
61
- local berkshelf_cookbooks=`_berkshelf_cookbooks`
62
- local local_cookbooks=`_local_cookbooks`
63
- local cookbooks=`echo $berkshelf_cookbooks $local_cookbooks | sort -n | uniq`
64
- COMPREPLY=($(compgen -W "${cookbooks}" -- ${curr}))
65
- return 0
66
- ;;
67
- *)
68
- ;;
69
- esac
70
-
71
- COMPREPLY=($(compgen -W "${commands}" -- ${curr}))
72
- return 0
73
- }
74
-
75
- complete -F _berkshelf berks
@@ -1,110 +0,0 @@
1
- module Berkshelf
2
- module Formatters
3
- class << self
4
- @@formatters = Hash.new
5
-
6
- # Access the formatters map that links string symbols to Formatter
7
- # implementations
8
- #
9
- # @return [Hash]
10
- def formatters
11
- @@formatters
12
- end
13
-
14
- # @param [#to_sym] id
15
- # @param [Constant] klass
16
- #
17
- # @raise [Berkshelf::InternalError] if an ID that has already been registered is attempted
18
- # to be registered again
19
- #
20
- # @return [Hash]
21
- # a hash of registered formatters
22
- def register(id, klass)
23
- unless id.respond_to?(:to_sym)
24
- raise ArgumentError, "Invalid Formatter ID: must respond to #to_sym. You gave: #{id}"
25
- end
26
-
27
- id = id.to_sym
28
- if self.formatters.has_key?(id)
29
- raise Berkshelf::InternalError, "Formatter ID '#{id}' already registered"
30
- end
31
-
32
- self.formatters[id] = klass
33
- end
34
-
35
- # @param [#to_sym] id
36
- #
37
- # @return [~AbstractFormatter, nil]
38
- def get(id)
39
- unless id.respond_to?(:to_sym)
40
- raise ArgumentError, "Invalid Formatter ID: must respond to #to_sym. You gave: #{id}"
41
- end
42
-
43
- self.formatters.fetch(id.to_sym, nil)
44
- end
45
- alias_method :[], :get
46
- end
47
-
48
- # @abstract Include and override {#install} {#use} {#upload}
49
- # {#msg} {#error} to implement.
50
- #
51
- # Implement {#cleanup_hook} to run any steps required to run after the task is finished
52
- module AbstractFormatter
53
- module ClassMethods
54
- # @param [Symbol] id
55
- #
56
- # @raise [Berkshelf::InternalError] if an ID that has already been registered is attempted
57
- # to be registered again
58
- #
59
- # @return [Hash]
60
- # a hash of registered formatters
61
- def register_formatter(id)
62
- Formatters.register(id, self)
63
- end
64
- end
65
-
66
- class << self
67
- def included(base)
68
- base.send(:extend, ClassMethods)
69
- end
70
-
71
- private
72
-
73
- def formatter_methods(*args)
74
- args.each do |meth|
75
- define_method(meth.to_sym) do |*args|
76
- raise AbstractFunction, "##{meth} must be implemented on #{self.class}"
77
- end unless respond_to?(meth.to_sym)
78
- end
79
- end
80
- end
81
-
82
- formatter_methods :error,
83
- :warn,
84
- :fetch,
85
- :install,
86
- :list,
87
- :msg,
88
- :outdated,
89
- :package,
90
- :skip,
91
- :show,
92
- :upload,
93
- :use,
94
- :vendor,
95
- :version
96
-
97
- def cleanup_hook
98
- # run after the task is finished
99
- end
100
-
101
- private
102
-
103
- attr_reader :args
104
- end
105
- end
106
- end
107
-
108
- Dir["#{File.dirname(__FILE__)}/formatters/*.rb"].sort.each do |path|
109
- require_relative "formatters/#{File.basename(path, '.rb')}"
110
- end
@@ -1,142 +0,0 @@
1
- module Berkshelf
2
- module Formatters
3
- class HumanReadable
4
- include AbstractFormatter
5
-
6
- register_formatter :human
7
-
8
- # Output the version of Berkshelf
9
- def version
10
- Berkshelf.ui.info Berkshelf::VERSION
11
- end
12
-
13
- # @param [Berkshelf::Dependency] dependency
14
- def fetch(dependency)
15
- Berkshelf.ui.info "Fetching '#{dependency.name}' from #{dependency.location}"
16
- end
17
-
18
- # Output a Cookbook installation message using {Berkshelf.ui}
19
- #
20
- # @param [Source] source
21
- # the source the dependency is being downloaded from
22
- # @param [RemoteCookbook] cookbook
23
- # the cookbook to be downloaded
24
- def install(source, cookbook)
25
- message = "Installing #{cookbook.name} (#{cookbook.version})"
26
-
27
- unless source.default?
28
- message << " from #{source}"
29
- message << " ([#{cookbook.location_type}] #{cookbook.location_path})"
30
- end
31
-
32
- Berkshelf.ui.info(message)
33
- end
34
-
35
- # Output a Cookbook use message using {Berkshelf.ui}
36
- #
37
- # @param [Dependency] dependency
38
- def use(dependency)
39
- message = "Using #{dependency.name} (#{dependency.locked_version})"
40
- message << " from #{dependency.location}" if dependency.location
41
- Berkshelf.ui.info message
42
- end
43
-
44
- # Output a Cookbook upload message using {Berkshelf.ui}
45
- #
46
- # @param [Berkshelf::CachedCookbook] cookbook
47
- # @param [Ridley::Connection] conn
48
- def upload(cookbook, conn)
49
- Berkshelf.ui.info "Uploading #{cookbook.cookbook_name} (#{cookbook.version}) to: '#{conn.server_url}'"
50
- end
51
-
52
- # Output a Cookbook skip message using {Berkshelf.ui}
53
- #
54
- # @param [Berkshelf::CachedCookbook] cookbook
55
- # @param [Ridley::Connection] conn
56
- def skip(cookbook, conn)
57
- Berkshelf.ui.info "Skipping #{cookbook.cookbook_name} (#{cookbook.version}) (frozen)"
58
- end
59
-
60
- # Output a list of outdated cookbooks and the most recent version
61
- # using {Berkshelf.ui}
62
- #
63
- # @param [Hash] hash
64
- # the list of outdated cookbooks in the format
65
- # { 'cookbook' => { 'api.berkshelf.com' => #<Cookbook> } }
66
- def outdated(hash)
67
- hash.keys.each do |name|
68
- hash[name].each do |source, newest|
69
- string = " * #{newest.name} (#{newest.version})"
70
- unless source == Berksfile::DEFAULT_API_URL
71
- string << " [#{source}]"
72
- end
73
- Berkshelf.ui.info string
74
- end
75
- end
76
- end
77
-
78
- # Output a Cookbook package message using {Berkshelf.ui}
79
- #
80
- # @param [String] destination
81
- def package(destination)
82
- Berkshelf.ui.info "Cookbook(s) packaged to #{destination}"
83
- end
84
-
85
- # Output a list of cookbooks using {Berkshelf.ui}
86
- #
87
- # @param [Array<Dependency>] list
88
- def list(dependencies)
89
- Berkshelf.ui.info "Cookbooks installed by your Berksfile:"
90
- dependencies.each do |dependency|
91
- out = " * #{dependency}"
92
- out << " from #{dependency.location}" if dependency.location
93
- Berkshelf.ui.info(out)
94
- end
95
- end
96
-
97
- # Output Cookbook info message using {Berkshelf.ui}
98
- #
99
- # @param [CachedCookbook] cookbook
100
- def show(cookbook)
101
- Berkshelf.ui.info(cookbook.pretty_print)
102
- end
103
-
104
- # Output Cookbook vendor info message using {Berkshelf.ui}
105
- #
106
- # @param [CachedCookbook] cookbook
107
- # @param [String] destination
108
- def vendor(cookbook, destination)
109
- cookbook_destination = File.join(destination, cookbook.cookbook_name)
110
- Berkshelf.ui.info "Vendoring #{cookbook.cookbook_name} (#{cookbook.version}) to #{cookbook_destination}"
111
- end
112
-
113
- # Output a generic message using {Berkshelf.ui}
114
- #
115
- # @param [String] message
116
- def msg(message)
117
- Berkshelf.ui.info message
118
- end
119
-
120
- # Output an error message using {Berkshelf.ui}
121
- #
122
- # @param [String] message
123
- def error(message)
124
- Berkshelf.ui.error message
125
- end
126
-
127
- # Output a warning message using {Berkshelf.ui}
128
- #
129
- # @param [String] message
130
- def warn(message)
131
- Berkshelf.ui.warn message
132
- end
133
-
134
- # Output a deprecation warning
135
- #
136
- # @param [String] message
137
- def deprecation(message)
138
- Berkshelf.ui.info "DEPRECATED: #{message}"
139
- end
140
- end
141
- end
142
- end
data/lib/berkshelf/git.rb DELETED
@@ -1,204 +0,0 @@
1
- require 'uri'
2
- require 'buff/shell_out'
3
-
4
- module Berkshelf
5
- class Git
6
- GIT_REGEXP = URI.regexp(%w(http https ssh git+ssh git rsync))
7
- SCP_REGEXP = /^(.+@)?[\w\d\.-]+:.*$/
8
-
9
- HAS_QUOTE_RE = %r{\"}.freeze
10
- HAS_SPACE_RE = %r{\s}.freeze
11
-
12
- class << self
13
- include Buff::ShellOut
14
-
15
- # @overload git(commands)
16
- # Shellout to the Git executable on your system with the given commands.
17
- #
18
- # @param [Array<String>]
19
- #
20
- # @return [String]
21
- # the output of the execution of the Git command
22
- def git(*command)
23
- command.unshift(git_cmd)
24
- command_str = command.map { |p| quote_cmd_arg(p) }.join(' ')
25
- response = shell_out(command_str)
26
-
27
- unless response.success?
28
- raise GitError.new(response.stderr.strip)
29
- end
30
-
31
- response.stdout.strip
32
- end
33
-
34
- # Clone a remote Git repository to disk
35
- #
36
- # @param [String] uri
37
- # a Git URI to clone
38
- # @param [#to_s] destination
39
- # a local path on disk to clone to
40
- #
41
- # @return [String]
42
- # the destination the URI was cloned to
43
- def clone(uri, destination = Dir.mktmpdir)
44
- if File::ALT_SEPARATOR
45
- destination = destination.to_s.gsub(File::SEPARATOR, File::ALT_SEPARATOR)
46
- end
47
-
48
- git('clone', uri, destination.to_s)
49
-
50
- destination
51
- end
52
-
53
- # Checkout the given reference in the given repository
54
- #
55
- # @param [String] repo_path
56
- # path to a Git repo on disk
57
- # @param [String] ref
58
- # reference to checkout
59
- def checkout(repo_path, ref)
60
- Dir.chdir repo_path do
61
- git('checkout', '-qf', revision_from_ref(repo_path, ref))
62
- end
63
- end
64
-
65
- # @param [String] repo_path
66
- def rev_parse(repo_path)
67
- Dir.chdir repo_path do
68
- git('rev-parse', 'HEAD')
69
- end
70
- end
71
-
72
- # Return the sha revision for the given reference in the given repository
73
- #
74
- # @param [String] repo_path
75
- # path to a Git repo on disk
76
- # @param [String] ref
77
- # reference to show
78
- #
79
- # @return [String]
80
- # the sha revision for the given ref
81
- #
82
- # @raise [AmbiguousGitRef] if the ref could refer to more than one revision
83
- def show_ref(repo_path, ref)
84
- Dir.chdir repo_path do
85
- lines = git('show-ref', ref).lines.to_a
86
-
87
- raise AmbiguousGitRef, ref if lines.size > 1
88
-
89
- lines.first.chomp.split(/\s/).first
90
- end
91
- end
92
-
93
- # Return the sha revision for the given reference or revision in the given repository
94
- #
95
- # This method is useful when you have either a sha revision, tag, or branch and
96
- # you'd like to end up with a sha revision.
97
- #
98
- # @param [String] repo_path
99
- # path to a Git repo on disk
100
- # @param [String] ref
101
- # reference to show
102
- #
103
- # @return [String]
104
- # the sha revision for the given ref
105
- #
106
- # @raise [InvalidGitRef] if the ref could not be found
107
- def revision_from_ref(repo_path, ref)
108
- begin
109
- show_ref(repo_path, ref)
110
- rescue GitError
111
- begin
112
- git('rev-parse', ref)
113
- ref
114
- rescue GitError
115
- raise InvalidGitRef, ref
116
- end
117
- end
118
- end
119
-
120
- # Return an absolute path to the Git executable on your system
121
- #
122
- # @return [String]
123
- # absolute path to git executable
124
- #
125
- # @raise [GitNotFound] if executable is not found in system path
126
- def find_git
127
- git_path = nil
128
- ENV['PATH'].split(::File::PATH_SEPARATOR).each do |path|
129
- git_path = detect_git_path(path)
130
- break if git_path
131
- end
132
-
133
- unless git_path
134
- raise GitNotFound
135
- end
136
-
137
- return git_path
138
- end
139
-
140
- # Determines if the given URI is a valid Git URI. A valid Git URI is a string
141
- # containing the location of a Git repository by either the Git protocol,
142
- # SSH protocol, or HTTPS protocol.
143
- #
144
- # @example Valid Git protocol URI
145
- # 'git://github.com/reset/thor-foodcritic.git'
146
- # @example Valid HTTPS URI
147
- # 'https://github.com/reset/solve.git'
148
- # @example Valid SSH protocol URI
149
- # 'git@github.com:reset/solve.git'
150
- #
151
- # @param [String] uri
152
- #
153
- # @return [Boolean]
154
- def validate_uri(uri)
155
- unless uri.is_a?(String)
156
- return false
157
- end
158
-
159
- unless uri.slice(GIT_REGEXP).nil?
160
- return true
161
- end
162
-
163
- unless uri.slice(SCP_REGEXP).nil?
164
- return true
165
- end
166
-
167
- false
168
- end
169
-
170
- # @raise [InvalidGitURI] if the given object is not a String containing a valid Git URI
171
- #
172
- # @see validate_uri
173
- def validate_uri!(uri)
174
- unless validate_uri(uri)
175
- raise InvalidGitURI.new(uri)
176
- end
177
-
178
- true
179
- end
180
-
181
- private
182
-
183
- def git_cmd
184
- @git_cmd ||= find_git
185
- end
186
-
187
- def quote_cmd_arg(arg)
188
- return arg if HAS_QUOTE_RE.match(arg)
189
- return arg unless HAS_SPACE_RE.match(arg)
190
- "\"#{arg}\""
191
- end
192
-
193
- def detect_git_path(base_dir)
194
- %w(git git.exe git.cmd).each do |git_cmd|
195
- potential_path = File.join(base_dir, git_cmd)
196
- if File.executable?(potential_path)
197
- return potential_path
198
- end
199
- end
200
- nil
201
- end
202
- end
203
- end
204
- end