berks-monolith 0.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6e00e4691862cc03e4cca97a0722ad297e535391
4
+ data.tar.gz: 4183cdf8be169fc1b52c22f83e9f0fb4c8d49115
5
+ SHA512:
6
+ metadata.gz: caf6a7a55dd3b38d1e6fde05e7df7efddd6f6c8aa247af5b835aad685d455db71015cda82e1d2d9046cf84ae24d3b8340941be58973afff3a1f095dd9eb79496
7
+ data.tar.gz: 82ff7940b2e02d68125bc479c40a2c27f06af2d712bc00b4d367d6a49588e8f8be28da8d40e7eaca5b9429901785a067baeffe174535adc0af8d05cd6f968fce
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ # Bundler stuff
2
+ Gemfile.lock
3
+ .bundle
4
+ vendor/
5
+ tmp
6
+ *.gem
7
+
8
+
9
+ # In case these are used for testing
10
+ Berksfile
11
+ Berksfile.lock
12
+ cookbooks/
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ - "2.1.0"
5
+ - "2.1.1"
6
+ sudo: false
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Mark Harrison
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,63 @@
1
+ [![Stories in Ready](https://badge.waffle.io/mivok/berks-monolith.png?label=ready&title=Ready)](https://waffle.io/mivok/berks-monolith)
2
+ [![Build Status](https://travis-ci.org/mivok/berks-monolith.svg?branch=master)](https://travis-ci.org/mivok/berks-monolith)
3
+
4
+ # berks-monolith
5
+
6
+ Berks-monolith is a companion command to berkshelf that takes all cookbooks
7
+ mentioned in a Berksfile and places development friendly versions of them
8
+ under a single directory. Usually, this means you will end up with git clones
9
+ for all cookbooks with git repositories in the Berksfile, and static copies of
10
+ cookbooks that don't have identifiable VCS repositories.
11
+
12
+ ## Use cases
13
+
14
+ * You have a Berksfile with many git based sources, and want a quick way to
15
+ clone them all under a single directory.
16
+ * You have a mostly monolithic repository, but make use of berkshelf to manage
17
+ dependencies and use external cookbook sources, and you'd like to have
18
+ everything in one place to be able to search.
19
+ * You are transitioning between a monolithic repository workflow and a
20
+ independent software artefacts workflow, and have a mix of artefacts in a
21
+ Berksfile as well as cookbooks in a monolithic repository, and you want all
22
+ cookbooks in one place.
23
+
24
+ ## Why not just use X?
25
+
26
+ The `berks vendor` command comes close to what monolith does, grabbing all
27
+ cookbooks mentioned in a Berksfile and putting copies of them under a single
28
+ directory. However, berks vendor is intended for production rather than
29
+ development use, and explicitly strips any VCS directories, chef ignored
30
+ files, and metadata.rb files.
31
+
32
+ The `berks install` command collects all cookbooks into
33
+ `~/.berkshelf/cookbooks`, but again VCS information is stripped out, and this
34
+ contains all cookbooks, not just those associated with a specific Berksfile.
35
+
36
+ ## Usage
37
+
38
+ ### berks-monolith install
39
+
40
+ Clones/copies all cookbooks mentioned in the berksfile. By default they go
41
+ into the 'cookbooks' directory. You can specify an alternate path if you wish
42
+ by specifying it on the command line: `berks-monolith install vendor`.
43
+
44
+ Exactly what you get depends on what the source of the cookbook is in the
45
+ berksfile:
46
+
47
+ * Normal community cookbooks (e.g. if you just specify `cookbook 'foo'` with
48
+ no other options) are just copied in place from the berkshelf directory.
49
+ * Git cookbooks will result in a clone of the repository pointing to the
50
+ original source repository.
51
+ * Path cookbooks will be skipped completely. This means you don't have to
52
+ worry if you have existing local cookbooks in a monolithic repository in
53
+ your Berksfile. They won't be copied again.
54
+
55
+ ### berks-monolith update
56
+
57
+ Updates the cloned copies of cookbooks if possible. In practice this means
58
+ 'run git pull' for all git clones.
59
+
60
+ ### berks-monolith clean
61
+
62
+ Removes all cookbooks that were installed with `berks-monolith install`.
63
+ Anything else in the cookbooks directory is left alone.
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ task :default => :test
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.pattern = "test/test_*.rb"
8
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'monolith/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "berks-monolith"
8
+ spec.version = Monolith::VERSION
9
+ spec.authors = ["Mark Harrison"]
10
+ spec.email = ["mark@mivok.net"]
11
+ spec.summary = %q{Berkshelf monolithic repository tools}
12
+ spec.description = %q{Tools for working with cookbooks as if they were inside a monolithic repository}
13
+ spec.homepage = "http://github.com/mivok/berks-monolith"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.required_ruby_version = '>= 1.9.2'
22
+
23
+ spec.add_dependency 'berkshelf', '~> 3.0', '>= 3.0.0'
24
+
25
+ spec.add_development_dependency 'bundler', '~> 1.5'
26
+ spec.add_development_dependency 'rake', '~> 10.0'
27
+ spec.add_development_dependency 'minitest', '~> 5.0'
28
+ spec.add_development_dependency 'pry', '~> 0.10'
29
+ end
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This is a horrible hack right now until I can work out how to load
3
+ # extensions for additional commands into berks.
4
+ $:.push File.expand_path('../../lib', __FILE__)
5
+ require 'monolith'
6
+ Monolith::Command.start
data/lib/monolith.rb ADDED
@@ -0,0 +1,12 @@
1
+ require_relative 'monolith/commands'
2
+
3
+ require_relative 'monolith/locations/git'
4
+ require_relative 'monolith/locations/github'
5
+ require_relative 'monolith/locations/path'
6
+ require_relative 'monolith/locations/default'
7
+
8
+ module Monolith
9
+ def self.formatter
10
+ @formatter ||= Monolith::Formatter.new
11
+ end
12
+ end
@@ -0,0 +1,69 @@
1
+ require 'berkshelf'
2
+ require 'fileutils'
3
+
4
+ module Monolith
5
+ class Berksfile
6
+ attr_reader :berksfile
7
+
8
+ def initialize(options)
9
+ Berkshelf.ui.mute! if Monolith.formatter.quiet
10
+ begin
11
+ @berksfile = Berkshelf::Berksfile.from_options(options)
12
+ rescue Berkshelf::BerksfileNotFound => e
13
+ Monolith.formatter.error(e)
14
+ exit(e.status_code)
15
+ end
16
+ end
17
+
18
+ # Runs berks install. This is needed before we install cookbooks ourselves
19
+ # to make sure berkshelf has a local copy of them for us to clone from or
20
+ # copy. However, it's not needed for other commands, so it separated out
21
+ # here.
22
+ def install
23
+ @berksfile.install
24
+ end
25
+
26
+ # Retrieve all cookbooks listed in the berksfile.
27
+ #
28
+ # Can take a block to do something with each cookbook.
29
+ def cookbooks(path)
30
+ FileUtils.mkdir_p(path)
31
+ cached_cookbooks = @berksfile.cookbooks
32
+ if block_given?
33
+ cached_cookbooks.each do |cookbook|
34
+ destination = File.join(File.expand_path(path),
35
+ cookbook.cookbook_name)
36
+ dep = berksfile.get_dependency(cookbook.cookbook_name)
37
+ if dep
38
+ yield cookbook, dep, destination
39
+ end
40
+ end
41
+ end
42
+ cached_cookbooks
43
+ end
44
+
45
+ def monolith_action(action, cookbook, dep, destination)
46
+ obj = monolith_obj(cookbook, dep, destination)
47
+ if obj.nil?
48
+ Monolith.formatter.unsupported_location(cookbook, dep)
49
+ else
50
+ obj.send(action)
51
+ end
52
+ end
53
+
54
+ # Feteches the appropriate monolith location object for a given cookbook
55
+ # dependency. I.e. Monolith::FooLocation.
56
+ def monolith_obj(cookbook, dep, destination)
57
+ if dep.location.nil?
58
+ Monolith::DefaultLocation.new(cookbook, dep, destination)
59
+ else
60
+ klass = dep.location.class.name.split('::')[-1]
61
+ Monolith.formatter.debug("Location class for " \
62
+ "#{cookbook.cookbook_name} is #{klass}")
63
+ if Monolith.const_defined?(klass)
64
+ Monolith.const_get(klass).new(cookbook, dep, destination)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,71 @@
1
+ require 'thor'
2
+ require 'monolith/berksfile'
3
+ require 'monolith/formatter'
4
+ require 'monolith/gitexclude'
5
+
6
+ module Monolith
7
+ class Command < Thor
8
+ namespace ''
9
+
10
+ class_option :quiet,
11
+ :type => :boolean,
12
+ :desc => "Don't print out any informational messages",
13
+ :aliases => '-q',
14
+ :default => false
15
+
16
+ class_option :debug,
17
+ :type => :boolean,
18
+ :desc => 'Print additional debug messages',
19
+ :aliases => '-d',
20
+ :default => false
21
+
22
+ class_option :berksfile,
23
+ :desc => 'Location of the Berksfile to use',
24
+ :aliases => '-b'
25
+
26
+ class_option :git_exclude,
27
+ :type => :boolean,
28
+ :desc => 'Add installed cookbooks to git exclude file',
29
+ :default => true
30
+
31
+ def initialize(*args)
32
+ super(*args)
33
+
34
+ Monolith.formatter.quiet = @options[:quiet]
35
+ Monolith.formatter.debug = @options[:debug]
36
+ end
37
+
38
+ desc 'install [PATH]', 'Clone all cookbooks into the cookbooks directory'
39
+ def install(path = File.join(Dir.pwd, "cookbooks"))
40
+ berksfile = Monolith::Berksfile.new(options.dup)
41
+ berksfile.install # We need to run berks install first
42
+ gitpath = File.expand_path('../.git', berksfile.berksfile.filepath)
43
+ gitexclude = GitExclude.new(gitpath, options)
44
+ berksfile.cookbooks(path) do |cookbook, dep, destination|
45
+ berksfile.monolith_action(:install, cookbook, dep, destination)
46
+ gitexclude.add(destination)
47
+ end
48
+ gitexclude.update
49
+ end
50
+
51
+ desc 'update [PATH]', 'Update all cloned cookbooks'
52
+ def update(path = File.join(Dir.pwd, "cookbooks"))
53
+ berksfile = Monolith::Berksfile.new(options.dup)
54
+ berksfile.cookbooks(path) do |cookbook, dep, destination|
55
+ berksfile.monolith_action(:update, cookbook, dep, destination)
56
+ end
57
+ end
58
+
59
+ desc 'clean [PATH]', 'Delete all cloned cookbooks'
60
+ def clean(path = File.join(Dir.pwd, "cookbooks"))
61
+ berksfile = Monolith::Berksfile.new(options.dup)
62
+ gitpath = File.expand_path('../.git', berksfile.berksfile.filepath)
63
+ gitexclude = GitExclude.new(gitpath, options)
64
+ berksfile.cookbooks(path) do |cookbook, dep, destination|
65
+ berksfile.monolith_action(:clean, cookbook, dep, destination)
66
+ gitexclude.remove(destination)
67
+ end
68
+ gitexclude.update
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,50 @@
1
+ module Monolith
2
+ class Formatter
3
+ attr_accessor :quiet
4
+ attr_accessor :debug
5
+
6
+ def initialize
7
+ @quiet = false
8
+ @debug = false
9
+ @base_path = Pathname.new(Dir.pwd)
10
+ end
11
+
12
+ def install(cookbook, destination)
13
+ msg "Installing #{cookbook.cookbook_name} to #{rel_dir(destination)}"
14
+ end
15
+
16
+ def update(cookbook, destination)
17
+ msg "Updating #{cookbook.cookbook_name} at #{rel_dir(destination)}"
18
+ end
19
+
20
+ def clean(cookbook, destination)
21
+ msg "Removing #{cookbook.cookbook_name} from #{rel_dir(destination)}"
22
+ end
23
+
24
+ def skip(cookbook, reason)
25
+ msg "Skipping #{cookbook.cookbook_name} (#{reason})"
26
+ end
27
+
28
+ def unsupported_location(cookbook, dep)
29
+ loctype = dep.location.class.name.split('::')[-1]
30
+ msg "Unsupported location type #{loctype} for cookbook " \
31
+ "#{cookbook.cookbook_name}. Skipping."
32
+ end
33
+
34
+ def debug(msg)
35
+ puts "DEBUG: #{msg}" if @debug
36
+ end
37
+
38
+ def msg(msg)
39
+ puts msg unless @quiet
40
+ end
41
+
42
+ def error(msg)
43
+ STDERR.puts msg
44
+ end
45
+
46
+ def rel_dir(dir)
47
+ return Pathname.new(dir).relative_path_from(@base_path)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,54 @@
1
+ module Monolith
2
+ class GitExclude
3
+ def initialize(git_dir, options)
4
+ @lines_to_add = []
5
+ @lines_to_remove = []
6
+ @git_dir = Pathname.new(git_dir)
7
+ @filename = @git_dir.join('info', 'exclude')
8
+ @enabled = options[:git_exclude]
9
+ end
10
+
11
+ def relative_path(path)
12
+ Pathname.new(path).relative_path_from(@git_dir.parent).to_s
13
+ end
14
+
15
+ def add(line)
16
+ @lines_to_add << relative_path(line)
17
+ end
18
+
19
+ def remove(line)
20
+ @lines_to_remove << relative_path(line)
21
+ end
22
+
23
+ def update
24
+ return unless @enabled
25
+
26
+ # We don't want to do anything if we're not actually in a git repo
27
+ return unless File.directory?(@git_dir)
28
+
29
+ if File.exist?(@filename)
30
+ data = File.read(@filename).split("\n")
31
+ else
32
+ data = []
33
+ end
34
+ # Don't go creating a file if there's nothing to add and we're already
35
+ # empty
36
+ return if data.empty? and @lines_to_add.empty?
37
+
38
+ # Now add/remove lines - additions first
39
+ data.concat(@lines_to_add.reject { |l| data.include?(l) })
40
+ data.reject! { |l| @lines_to_remove.include?(l) }
41
+
42
+ # And write out the new file
43
+ File.open(@filename, "w") do |file|
44
+ data.each do |l|
45
+ file.puts(l)
46
+ end
47
+ end
48
+
49
+ # Reset the list of lines to add/remove
50
+ @lines_to_add = []
51
+ @lines_to_remove = []
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,37 @@
1
+ module Monolith
2
+ class BaseLocation
3
+ def initialize(cookbook, dep, destination)
4
+ @dep = dep
5
+ @location = dep.location
6
+ @cookbook = cookbook
7
+ @destination = destination
8
+ end
9
+
10
+ # Install the cookbook in the development environment. If possible, the
11
+ # installed cookbook should look exactly as it would when used for
12
+ # development (e.g. a git checkout with all git metadata, no compiled
13
+ # artefacts).
14
+ def install
15
+ nil
16
+ end
17
+
18
+ # Update the cookbook in the development environment to the latest
19
+ # version. E.g. if git is used, run git pull.
20
+ def update
21
+ nil
22
+ end
23
+
24
+ # Remove a previously installed cookbook. If a cookbook was never
25
+ # installed in the first place (either because install wasn't run, or
26
+ # because of the location type), then this should do nothing.
27
+ def clean
28
+ if File.exist?(@destination)
29
+ Monolith.formatter.clean(@cookbook, @destination)
30
+ FileUtils.rm_rf(@destination)
31
+ else
32
+ rel_dest = Monolith.formatter.rel_dir(@destination)
33
+ Monolith.formatter.skip(@cookbook, "#{rel_dest} doesn't exist")
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,24 @@
1
+ # Default location aka community/supermarket cookbook
2
+ module Monolith
3
+ class DefaultLocation < BaseLocation
4
+ def install
5
+ # For now we just copy any community cookbooks. It would be nice to be
6
+ # able to grab them from the source URL, but that isn't readily
7
+ # accessible, and then you have to guess how to check it out.
8
+ if File.directory?(@destination)
9
+ rel_dest = Monolith.formatter.rel_dir(@destination)
10
+ Monolith.formatter.skip(@cookbook, "#{rel_dest} already exists")
11
+ else
12
+ Monolith.formatter.install(@cookbook, @destination)
13
+ FileUtils.cp_r(@cookbook.path, @destination)
14
+ end
15
+ end
16
+
17
+ def update
18
+ # There isn't anything to do for updating a community cookbook except
19
+ # blowing it away and recreating it. For the moment I'm opting not to do
20
+ # that (it may be able ot be an option later)
21
+ Monolith.formatter.skip(@cookbook, "Not updating community cookbook")
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,60 @@
1
+ require 'berkshelf/mixin/git'
2
+ require_relative 'base'
3
+
4
+ module Monolith
5
+ class GitLocation < BaseLocation
6
+ include Berkshelf::Mixin::Git
7
+
8
+ def install
9
+ unless File.directory?(@destination)
10
+ Monolith.formatter.install(@cookbook, @destination)
11
+ # Clone from the cache. We've already done an install by this point, so
12
+ # berkshelf already made sure the cache exists and is up to date.
13
+ git %|clone "#{cache_path}" "#{@destination}"|
14
+
15
+ # Make sure the origin is correct and doesn't point to the cached
16
+ # version.
17
+ cached_origin_url = origin_url(cache_path)
18
+ set_origin_url(@destination, cached_origin_url)
19
+
20
+ # Not sure if I want to do this - should probably be an option
21
+ #git %|reset --hard #{@revision}|
22
+ else
23
+ rel_dest = Monolith.formatter.rel_dir(@destination)
24
+ Monolith.formatter.skip(@cookbook, "#{rel_dest} already exists")
25
+ end
26
+ end
27
+
28
+ def update
29
+ if File.directory?(@destination)
30
+ Monolith.formatter.update(@cookbook, @destination)
31
+ Dir.chdir(@destination) do
32
+ git %|pull|
33
+ end
34
+ else
35
+ rel_dest = Monolith.formatter.rel_dir(@destination)
36
+ Monolith.formatter.skip(@cookbook, "#{rel_dest} doesn't exist")
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ # Taken from Berkshelf::GitLocation
43
+ def cache_path
44
+ Pathname.new(Berkshelf.berkshelf_path)
45
+ .join('.cache', 'git', Digest::SHA1.hexdigest(@location.uri))
46
+ end
47
+
48
+ def origin_url(repo_dir)
49
+ Dir.chdir(repo_dir) do
50
+ git %|config --local --get remote.origin.url|
51
+ end
52
+ end
53
+
54
+ def set_origin_url(repo_dir, url)
55
+ Dir.chdir(repo_dir) do
56
+ git %|remote set-url origin "#{url}"|
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,6 @@
1
+ require_relative 'git'
2
+
3
+ module Monolith
4
+ class GithubLocation < GitLocation
5
+ end
6
+ end
@@ -0,0 +1,23 @@
1
+ # If a Berksfile mentions a cookbook with a path location, then we can
2
+ # assume it's already available locally in a form suitable for
3
+ # development. An example of this is if you have a (mostly) monolithic
4
+ # chef repository and want to refer to cookbooks in this repository in
5
+ # your Berksfile.
6
+ module Monolith
7
+ class PathLocation < BaseLocation
8
+ def install
9
+ Monolith.formatter.debug("Skipping cookbook #{@cookbook.cookbook_name}" \
10
+ "with path location")
11
+ end
12
+
13
+ def update
14
+ Monolith.formatter.debug("Skipping cookbook #{@cookbook.cookbook_name}" \
15
+ "with path location")
16
+ end
17
+
18
+ def clean
19
+ Monolith.formatter.debug("Skipping cookbook #{@cookbook.cookbook_name}" \
20
+ "with path location")
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,3 @@
1
+ module Monolith
2
+ VERSION = '0.1.0'
3
+ end
data/test/.gitignore ADDED
@@ -0,0 +1 @@
1
+ tmp
data/test/helpers.rb ADDED
@@ -0,0 +1,62 @@
1
+ require 'fileutils'
2
+ require 'pathname'
3
+
4
+ module Monolith
5
+ module TestHelpers
6
+ def tmp_path
7
+ Pathname.new(File.expand_path("../tmp", __FILE__))
8
+ end
9
+
10
+ def clean_tmp_path
11
+ FileUtils.rm_rf(tmp_path)
12
+ FileUtils.mkdir_p(tmp_path)
13
+ end
14
+
15
+ def make_git_repo(name)
16
+ # Makes an example git repo with a single file in and one commit
17
+ repo_path = tmp_path.join("git", name)
18
+ FileUtils.mkdir_p(repo_path)
19
+ Dir.chdir(repo_path) do
20
+ %x|git init|
21
+ File.open('metadata.rb', 'w') do |f|
22
+ f.puts "name '#{name}'"
23
+ end
24
+ %x|git add metadata.rb|
25
+ %x|git config --local user.name Me|
26
+ %x|git config --local user.email me@example.com|
27
+ %x|git commit -m "Test commit"|
28
+ %x|git remote add origin "git@git.example.com:#{name}"|
29
+ end
30
+ repo_path
31
+ end
32
+
33
+ def make_change_git(name)
34
+ repo_path = tmp_path.join("git", name)
35
+ Dir.chdir(repo_path) do
36
+ File.open('test.txt', 'w') do |f|
37
+ f.puts 'Testing'
38
+ end
39
+ %x|git add test.txt|
40
+ %x|git commit --author "Me <me@example.com>" -m "Update"|
41
+ end
42
+ end
43
+
44
+ def make_berksfile(types)
45
+ File.open(tmp_path.join('Berksfile'), 'w') do |berksfile|
46
+ berksfile.puts "source 'https://supermarket.chef.io/'"
47
+ types.each do |type|
48
+ if type == :git
49
+ repo_path = make_git_repo('test_git')
50
+ berksfile.puts("cookbook 'test_git', :git => '#{repo_path}'")
51
+ end
52
+ end
53
+ end
54
+
55
+ if block_given?
56
+ Dir.chdir(tmp_path) do
57
+ yield
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,30 @@
1
+ require 'minitest/autorun'
2
+ require_relative 'helpers'
3
+
4
+ # Fix 'Celluloid::Error Thread pool is not running' error.
5
+ # See https://github.com/celluloid/celluloid/pull/162
6
+ require 'celluloid/test'
7
+ Celluloid.init
8
+
9
+ require 'monolith'
10
+
11
+ class TestCommandInstall < MiniTest::Test
12
+ include Monolith::TestHelpers
13
+
14
+ def setup
15
+ clean_tmp_path
16
+ end
17
+
18
+ def test_clean_command
19
+ make_berksfile([:git]) do
20
+ # We need to install it first
21
+ Monolith::Command.start(['install', '-q'])
22
+ make_change_git('test_git')
23
+ # Verify the 'before' state
24
+ assert File.exist?("cookbooks/test_git")
25
+ # Perform the clean
26
+ Monolith::Command.start(['clean', '-q'])
27
+ refute File.exist?("cookbooks/test_git")
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,25 @@
1
+ require 'minitest/autorun'
2
+ require_relative 'helpers'
3
+
4
+ # Fix 'Celluloid::Error Thread pool is not running' error.
5
+ # See https://github.com/celluloid/celluloid/pull/162
6
+ require 'celluloid/test'
7
+ Celluloid.init
8
+
9
+ require 'monolith'
10
+
11
+ class TestCommandInstall < MiniTest::Test
12
+ include Monolith::TestHelpers
13
+
14
+ def setup
15
+ clean_tmp_path
16
+ end
17
+
18
+ def test_install_command
19
+ make_berksfile([:git]) do
20
+ Monolith::Command.start(['install', '-q'])
21
+ assert File.exist?("cookbooks/test_git")
22
+ assert File.exist?("cookbooks/test_git/.git")
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,32 @@
1
+ require 'minitest/autorun'
2
+ require_relative 'helpers'
3
+
4
+ # Fix 'Celluloid::Error Thread pool is not running' error.
5
+ # See https://github.com/celluloid/celluloid/pull/162
6
+ require 'celluloid/test'
7
+ Celluloid.init
8
+
9
+ require 'monolith'
10
+
11
+ class TestCommandInstall < MiniTest::Test
12
+ include Monolith::TestHelpers
13
+
14
+ def setup
15
+ clean_tmp_path
16
+ end
17
+
18
+ def test_update_command
19
+ make_berksfile([:git]) do
20
+ # We need to install it first
21
+ Monolith::Command.start(['install', '-q'])
22
+ make_change_git('test_git')
23
+ # Verify the 'before' state
24
+ refute File.exist?("cookbooks/test_git/test.txt")
25
+ # Perform the update
26
+ Monolith::Command.start(['update', '-q'])
27
+ assert File.exist?("cookbooks/test_git")
28
+ assert File.exist?("cookbooks/test_git/.git")
29
+ assert File.exist?("cookbooks/test_git/test.txt")
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,48 @@
1
+ require 'minitest/autorun'
2
+ require 'fileutils'
3
+
4
+ require 'berkshelf'
5
+ require 'monolith/locations/git'
6
+
7
+ class TestGitLocation < MiniTest::Test
8
+
9
+ def setup
10
+ # Path variables
11
+ @test_cookbook = "test_cookbook"
12
+ @test_base = File.expand_path('../tmp', __FILE__)
13
+ @mock_cache = File.join(@test_base, 'cache', @test_cookbook)
14
+ @mock_destination = File.join(@test_base, 'cloned', @test_cookbook)
15
+ @mock_origin = 'user@example.com:some/repo'
16
+ # Set up a repo to clone from rather than using the real berkshelf cache
17
+ # dir.
18
+ FileUtils.rm_rf(@test_base)
19
+ FileUtils.mkdir_p(@mock_cache)
20
+ Dir.chdir(@mock_cache) do
21
+ %x|git init|
22
+ %x|git remote add origin #{@mock_origin}|
23
+ end
24
+ # Don't print informational messages while testing
25
+ Monolith.formatter.quiet = true
26
+ end
27
+
28
+ def teardown
29
+ FileUtils.rm_rf(@test_base)
30
+ end
31
+
32
+ def test_install
33
+ # Actually do the install
34
+ @mock_cookbook = Minitest::Mock.new
35
+ @mock_cookbook.expect :cookbook_name, @test_cookbook
36
+ @mock_dep = Minitest::Mock.new
37
+ @mock_dep.expect :location, nil
38
+ location = Monolith::GitLocation.new(@mock_cookbook, @mock_dep,
39
+ @mock_destination)
40
+ location.stub(:cache_path, @mock_cache) do
41
+ location.install
42
+ end
43
+
44
+ assert File.directory?(@mock_destination)
45
+ assert File.directory?(File.join(@mock_destination, '.git'))
46
+ assert_equal @mock_origin, location.send(:origin_url, @mock_destination)
47
+ end
48
+ end
metadata ADDED
@@ -0,0 +1,154 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: berks-monolith
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Mark Harrison
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-02 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
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 3.0.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '3.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 3.0.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.5'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.5'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '10.0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '10.0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: minitest
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '5.0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '5.0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: pry
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '0.10'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '0.10'
89
+ description: Tools for working with cookbooks as if they were inside a monolithic
90
+ repository
91
+ email:
92
+ - mark@mivok.net
93
+ executables:
94
+ - berks-monolith
95
+ extensions: []
96
+ extra_rdoc_files: []
97
+ files:
98
+ - ".gitignore"
99
+ - ".travis.yml"
100
+ - Gemfile
101
+ - LICENSE.txt
102
+ - README.md
103
+ - Rakefile
104
+ - berks-monolith.gemspec
105
+ - bin/berks-monolith
106
+ - lib/monolith.rb
107
+ - lib/monolith/berksfile.rb
108
+ - lib/monolith/commands.rb
109
+ - lib/monolith/formatter.rb
110
+ - lib/monolith/gitexclude.rb
111
+ - lib/monolith/locations/base.rb
112
+ - lib/monolith/locations/default.rb
113
+ - lib/monolith/locations/git.rb
114
+ - lib/monolith/locations/github.rb
115
+ - lib/monolith/locations/path.rb
116
+ - lib/monolith/version.rb
117
+ - test/.gitignore
118
+ - test/helpers.rb
119
+ - test/test_command_clean.rb
120
+ - test/test_command_install.rb
121
+ - test/test_command_update.rb
122
+ - test/test_gitlocation.rb
123
+ homepage: http://github.com/mivok/berks-monolith
124
+ licenses:
125
+ - MIT
126
+ metadata: {}
127
+ post_install_message:
128
+ rdoc_options: []
129
+ require_paths:
130
+ - lib
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: 1.9.2
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ requirements: []
142
+ rubyforge_project:
143
+ rubygems_version: 2.4.1
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: Berkshelf monolithic repository tools
147
+ test_files:
148
+ - test/.gitignore
149
+ - test/helpers.rb
150
+ - test/test_command_clean.rb
151
+ - test/test_command_install.rb
152
+ - test/test_command_update.rb
153
+ - test/test_gitlocation.rb
154
+ has_rdoc: