bard 0.3.1

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.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,6 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
6
+ tmp
@@ -0,0 +1,3 @@
1
+ [submodule "fixtures/repo"]
2
+ path = fixtures/repo
3
+ url = staging@staging.botandrose.com:fuelcafe
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Micah Geisel
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,25 @@
1
+ = BARD gem
2
+
3
+ This immaculate work of engineering genius allows mere mortals to collaborate with beings of transcendent intelligence like Micah, Michael, and Nick.
4
+
5
+ == Requirements
6
+ gem install thor
7
+ gem install systemu
8
+ gem install term-ansicolor
9
+ gem install git_remote_branch
10
+ git --version >= 1.6.0
11
+
12
+ == Note on Patches/Pull Requests
13
+
14
+ * Fork the project.
15
+ * Make your feature addition or bug fix.
16
+ * Add tests for it. This is important so I don't break it in a
17
+ future version unintentionally.
18
+ * Commit, do not mess with rakefile, version, or history.
19
+ (if you want to have your own version, that is fine but
20
+ bump version in a commit by itself I can ignore when I pull)
21
+ * Send me a pull request. Bonus points for topic branches.
22
+
23
+ == Copyright
24
+
25
+ Copyright (c) 2009 Micah Geisel. See LICENSE for details.
@@ -0,0 +1,92 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "bard"
8
+ gem.summary = %Q{Tools for collaborating with Bot and Rose Design.}
9
+ gem.description = %Q{This immaculate work of engineering genius allows mere mortals to collaborate with beings of transcendent intelligence like Micah, Michael, and Nick.}
10
+ gem.email = "info@botandrose.com"
11
+ gem.homepage = "http://github.com/botandrose/bard"
12
+ gem.authors = ["Micah Geisel", "Nick Hogle"]
13
+ gem.add_development_dependency "ruby-debug"
14
+ gem.add_development_dependency "rspec"
15
+ gem.add_development_dependency "cucumber"
16
+ gem.add_dependency(%q<rubygems-update>, [">= 1.3.2"])
17
+ gem.add_dependency(%q<thor>, [">= 0.11.7"])
18
+ gem.add_dependency(%q<grit>, [">= 1.1.1"])
19
+ gem.add_dependency(%q<git_remote_branch>, [">= 0.3.0"])
20
+ gem.add_dependency(%q<systemu>, [">= 1.2.0"])
21
+ gem.add_dependency(%q<term-ansicolor>, [">= 1.0.3"])
22
+ end
23
+ Jeweler::GemcutterTasks.new
24
+ rescue LoadError
25
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
26
+ end
27
+
28
+ require 'spec/rake/spectask'
29
+ Spec::Rake::SpecTask.new(:spec) do |spec|
30
+ spec.libs << 'lib' << 'spec'
31
+ spec.spec_files = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
35
+ spec.libs << 'lib' << 'spec'
36
+ spec.pattern = 'spec/**/*_spec.rb'
37
+ spec.rcov = true
38
+ end
39
+
40
+ task :spec => :check_dependencies
41
+
42
+ begin
43
+ require 'cucumber/rake/task'
44
+ Cucumber::Rake::Task.new(:features)
45
+
46
+ task :features => :check_dependencies
47
+ rescue LoadError
48
+ task :features do
49
+ abort "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
50
+ end
51
+ end
52
+
53
+ begin
54
+ require 'reek/rake_task'
55
+ Reek::RakeTask.new do |t|
56
+ t.fail_on_error = true
57
+ t.verbose = false
58
+ t.source_files = 'lib/**/*.rb'
59
+ end
60
+ rescue LoadError
61
+ task :reek do
62
+ abort "Reek is not available. In order to run reek, you must: sudo gem install reek"
63
+ end
64
+ end
65
+
66
+ begin
67
+ require 'roodi'
68
+ require 'roodi_task'
69
+ RoodiTask.new do |t|
70
+ t.verbose = false
71
+ end
72
+ rescue LoadError
73
+ task :roodi do
74
+ abort "Roodi is not available. In order to run roodi, you must: sudo gem install roodi"
75
+ end
76
+ end
77
+
78
+ task :default => :spec
79
+
80
+ require 'rake/rdoctask'
81
+ Rake::RDocTask.new do |rdoc|
82
+ if File.exist?('VERSION')
83
+ version = File.read('VERSION')
84
+ else
85
+ version = ""
86
+ end
87
+
88
+ rdoc.rdoc_dir = 'rdoc'
89
+ rdoc.title = "bard #{version}"
90
+ rdoc.rdoc_files.include('README*')
91
+ rdoc.rdoc_files.include('lib/**/*.rb')
92
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.3.1
@@ -0,0 +1,92 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{bard}
8
+ s.version = "0.3.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Micah Geisel", "Nick Hogle"]
12
+ s.date = %q{2009-09-30}
13
+ s.default_executable = %q{bard}
14
+ s.description = %q{This immaculate work of engineering genius allows mere mortals to collaborate with beings of transcendent intelligence like Micah, Michael, and Nick.}
15
+ s.email = %q{info@botandrose.com}
16
+ s.executables = ["bard"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.rdoc"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ ".gitignore",
24
+ ".gitmodules",
25
+ "LICENSE",
26
+ "README.rdoc",
27
+ "Rakefile",
28
+ "VERSION",
29
+ "bard.gemspec",
30
+ "bin/bard",
31
+ "features/bard_pull.feature",
32
+ "features/bard_push.feature",
33
+ "features/step_definitions/git_steps.rb",
34
+ "features/step_definitions/global_steps.rb",
35
+ "features/step_definitions/rails_steps.rb",
36
+ "features/step_definitions/submodule_steps.rb",
37
+ "features/support/env.rb",
38
+ "features/support/grit_ext.rb",
39
+ "features/support/io.rb",
40
+ "lib/bard.rb",
41
+ "lib/bard/git.rb",
42
+ "lib/bard/io.rb",
43
+ "spec/bard_spec.rb",
44
+ "spec/spec_helper.rb"
45
+ ]
46
+ s.homepage = %q{http://github.com/botandrose/bard}
47
+ s.rdoc_options = ["--charset=UTF-8"]
48
+ s.require_paths = ["lib"]
49
+ s.rubygems_version = %q{1.3.4}
50
+ s.summary = %q{Tools for collaborating with Bot and Rose Design.}
51
+ s.test_files = [
52
+ "spec/spec_helper.rb",
53
+ "spec/bard_spec.rb"
54
+ ]
55
+
56
+ if s.respond_to? :specification_version then
57
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
58
+ s.specification_version = 3
59
+
60
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
61
+ s.add_development_dependency(%q<ruby-debug>, [">= 0"])
62
+ s.add_development_dependency(%q<rspec>, [">= 0"])
63
+ s.add_development_dependency(%q<cucumber>, [">= 0"])
64
+ s.add_runtime_dependency(%q<rubygems-update>, [">= 1.3.2"])
65
+ s.add_runtime_dependency(%q<thor>, [">= 0.11.7"])
66
+ s.add_runtime_dependency(%q<grit>, [">= 1.1.1"])
67
+ s.add_runtime_dependency(%q<git_remote_branch>, [">= 0.3.0"])
68
+ s.add_runtime_dependency(%q<systemu>, [">= 1.2.0"])
69
+ s.add_runtime_dependency(%q<term-ansicolor>, [">= 1.0.3"])
70
+ else
71
+ s.add_dependency(%q<ruby-debug>, [">= 0"])
72
+ s.add_dependency(%q<rspec>, [">= 0"])
73
+ s.add_dependency(%q<cucumber>, [">= 0"])
74
+ s.add_dependency(%q<rubygems-update>, [">= 1.3.2"])
75
+ s.add_dependency(%q<thor>, [">= 0.11.7"])
76
+ s.add_dependency(%q<grit>, [">= 1.1.1"])
77
+ s.add_dependency(%q<git_remote_branch>, [">= 0.3.0"])
78
+ s.add_dependency(%q<systemu>, [">= 1.2.0"])
79
+ s.add_dependency(%q<term-ansicolor>, [">= 1.0.3"])
80
+ end
81
+ else
82
+ s.add_dependency(%q<ruby-debug>, [">= 0"])
83
+ s.add_dependency(%q<rspec>, [">= 0"])
84
+ s.add_dependency(%q<cucumber>, [">= 0"])
85
+ s.add_dependency(%q<rubygems-update>, [">= 1.3.2"])
86
+ s.add_dependency(%q<thor>, [">= 0.11.7"])
87
+ s.add_dependency(%q<grit>, [">= 1.1.1"])
88
+ s.add_dependency(%q<git_remote_branch>, [">= 0.3.0"])
89
+ s.add_dependency(%q<systemu>, [">= 1.2.0"])
90
+ s.add_dependency(%q<term-ansicolor>, [">= 1.0.3"])
91
+ end
92
+ end
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- mode: ruby -*-
3
+
4
+ require 'rubygems'
5
+ require 'thor'
6
+ require 'thor/runner'
7
+
8
+ THIS_FILE = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
9
+ require File.join(File.dirname(THIS_FILE), '..', 'lib', 'bard')
10
+
11
+ args = ARGV
12
+ if args[0] =~ /^[a-z]/i
13
+ args[0] = "bard:#{args[0]}"
14
+ else
15
+ args.unshift "bard"
16
+ end
17
+ Thor::Runner.start args
@@ -0,0 +1,82 @@
1
+ Feature: bard pull
2
+ Background:
3
+ Given a shared rails project
4
+
5
+ Scenario: Pulling down the latest changes from the remote integration branch
6
+ Given the remote integration branch has had a commit since I last pulled
7
+ When I type "bard pull"
8
+ Then the "integration" branch should match the "origin/integration" branch
9
+
10
+ Scenario: Pulling down when the latest changes include a submodule addition
11
+ Given the remote integration branch has had a commit that includes a new submodule
12
+ When I type "bard pull"
13
+ Then the "integration" branch should match the "origin/integration" branch
14
+ And there should be one new submodule
15
+ And the submodule should be checked out
16
+
17
+ Scenario: Pulling down when the latest changes include a submodule update
18
+ Given a submodule
19
+ And the remote integration branch has had a commit that includes a submodule update
20
+ When I type "bard pull"
21
+ Then the "integration" branch should match the "origin/integration" branch
22
+ And the submodule should be updated
23
+
24
+ Scenario: Pulling down when the latest changes include a submodule url change
25
+ Given a submodule
26
+ And the remote integration branch has had a commit that includes a submodule url change
27
+ When I type "bard pull"
28
+ Then the "integration" branch should match the "origin/integration" branch
29
+ And the submodule url should be changed
30
+ And the submodule should be checked out
31
+
32
+ # TODO
33
+ #Scenario: Pulling down when the latest changes include a submodule deletion
34
+ # Given a submodule
35
+ # And the remote integration branch has had a commit that includes a submodule deletion
36
+ # When I type "bard pull"
37
+ # Then the "integration" branch should match the "origin/integration" branch
38
+ # And the submodule should be deleted
39
+
40
+ Scenario: Pulling latest changes from the remote integration branch after committing locally
41
+ Given the remote integration branch has had a commit since I last pulled
42
+ And I have committed a set of changes to my local integration branch
43
+ When I type "bard pull"
44
+ Then I should see the warning "Someone has pushed some changes"
45
+ And the "integration" branch should be a fast-forward from the "origin/integration" branch
46
+
47
+ Scenario: Trying to bard pull with a dirty working directory
48
+ Given the remote integration branch has had a commit since I last pulled
49
+ And a dirty working directory
50
+ When I type "bard pull"
51
+ Then I should see the fatal error "You have uncommitted changes!"
52
+ And the "integration" branch should not match the "origin/integration" branch
53
+
54
+ Scenario: Trying to bard pull when not on the integration branch
55
+ Given the remote integration branch has had a commit since I last pulled
56
+ And I am on a non-integration branch
57
+ When I type "bard pull"
58
+ Then I should see the fatal error "not on the integration branch"
59
+ And the "integration" branch should not match the "origin/integration" branch
60
+
61
+ Scenario: Pulling in a change that includes a migration on a dev machine
62
+ Given the remote integration branch has had a commit that includes a new migration
63
+ And I have a development environment set up locally
64
+ When I type "bard pull"
65
+ Then the development database should include that migration
66
+
67
+ Scenario: Pulling in a change that includes a migration on a dev and testing machine
68
+ Given the remote integration branch has had a commit that includes a new migration
69
+ And I have development and test environments set up locally
70
+ When I type "bard pull"
71
+ Then both the development and test databases should include that migration
72
+
73
+ Scenario: Pulling in a change that includes a gem dependency change
74
+ Given I dont have the test gem installed
75
+ And the remote integration branch has had a commit that adds the test gem as a dependency
76
+ When I type "bard pull"
77
+ Then the test gem should be installed
78
+
79
+ Scenario: Pulling in a change should restart the rails server
80
+ Given the remote integration branch has had a commit since I last pulled
81
+ When I type "bard pull"
82
+ Then passenger should have been restarted
@@ -0,0 +1,89 @@
1
+ Feature: bard push
2
+ Background:
3
+ Given a shared rails project
4
+
5
+ Scenario: Uploading local changes onto the remote integration branch
6
+ Given I have committed a set of changes to my local integration branch
7
+ When I type "bard push"
8
+ Then the "integration" branch should match the "origin/integration" branch
9
+
10
+ Scenario: Pushing a change that includes a migration
11
+ Given I have committed a set of changes that includes a new migration
12
+ And the staging server has a staging and test environment set up
13
+ When I type "bard push"
14
+ Then the both the staging and test databases should include that migration
15
+
16
+ Scenario: Pushing a change that includes a gem dependency change
17
+ Given I dont have the test gem installed
18
+ And I have committed a set of changes that adds the test gem as a dependency
19
+ When I type "bard push"
20
+ Then the test gem should be installed
21
+
22
+ Scenario: Pushing a change should advance the staging HEAD and restart the staging rails server
23
+ Given I have committed a set of changes to my local integration branch
24
+ When I type "bard push"
25
+ Then the remote directory should not be dirty
26
+ And the staging passenger should have been restarted
27
+
28
+ Scenario: Pushing a change that includes a submodule addition
29
+ Given I have committed a set of changes that includes a new submodule
30
+ When I type "bard push"
31
+ Then there should be one new submodule on the remote
32
+ And the remote submodule should be checked out
33
+
34
+ Scenario: Pushing a change that includes a submodule update
35
+ Given a submodule
36
+ And I have committed a set of changes that includes a submodule update
37
+ When I type "bard push"
38
+ Then the remote submodule should be updated
39
+
40
+ Scenario: Pushing a change that includes a submodule url change
41
+ Given a submodule
42
+ Given I have committed a set of changes that includes a submodule url change
43
+ When I type "bard push"
44
+ Then the remote submodule url should be changed
45
+ And the remote submodule should be checked out
46
+
47
+ # TODO
48
+ #Scenario: Pushing a change that includes a submodule deletion
49
+ # Given a submodule
50
+ # Given I have committed a set of changes that includes a submodule deletion
51
+ # When I type "bard push"
52
+ # Then the remote submodule should be deleted
53
+
54
+ Scenario: Trying to bard push when not on the integration branch
55
+ Given I have committed a set of changes to my local integration branch
56
+ And I am on a non-integration branch
57
+ When I type "bard push"
58
+ Then I should see the fatal error "not on the integration branch"
59
+ And the "integration" branch should not match the "origin/integration" branch
60
+
61
+ Scenario: Trying to bard push with a dirty working directory
62
+ Given I have committed a set of changes to my local integration branch
63
+ And a dirty working directory
64
+ When I type "bard push"
65
+ Then I should see the fatal error "You have uncommitted changes!"
66
+ And the "integration" branch should not match the "origin/integration" branch
67
+
68
+ Scenario: Trying to bard push with a non-fast-foward changeset
69
+ Given I have committed a set of changes to my local integration branch
70
+ And the remote integration branch has had a commit since I last pulled
71
+ When I type "bard push"
72
+ Then I should see the fatal error "Someone has pushed some changes"
73
+ And the "integration" branch should not match the "origin/integration" branch
74
+
75
+ Scenario: Trying to bard push with an uncommitted change to a submodule
76
+ Given a submodule
77
+ And I have committed a set of changes to my local integration branch
78
+ And the submodule working directory is dirty
79
+ When I type "bard push"
80
+ Then I should see the fatal error "Micah"
81
+ And the "integration" branch should not match the "origin/integration" branch
82
+
83
+ Scenario: Trying to bard push with a committed but unpushed change to a submodule
84
+ Given a submodule
85
+ And I have committed a set of changes to the submodule
86
+ And I have committed a set of changes to my local integration branch
87
+ When I type "bard push"
88
+ Then I should see the fatal error "Micah"
89
+ And the "integration" branch should not match the "origin/integration" branch
@@ -0,0 +1,55 @@
1
+ Given /^I am on a non\-integration branch$/ do
2
+ type "git checkout -b bad_bad_bad"
3
+ end
4
+
5
+ Given /^a dirty working directory$/ do
6
+ File.open("dirty_file", "w") { |f| f.puts "dirty dirty" }
7
+ end
8
+
9
+ Given /^I have committed a set of changes to my local integration branch$/ do
10
+ type "echo 'fuck shit' > fuck_file"
11
+ type "git add ."
12
+ type "git commit -am'test commit to local integration branch.'"
13
+ end
14
+
15
+ Given /^the remote integration branch has had a commit since I last pulled$/ do
16
+ Dir.chdir "#{ROOT}/tmp/origin" do
17
+ type "git checkout integration"
18
+ type "echo 'zomg' > origin_change_file"
19
+ type "git add ."
20
+ type "git commit -am 'testing origin change'"
21
+ end
22
+ end
23
+
24
+ Then /^the directory should not be dirty$/ do
25
+ type("git status").should include "working directory clean"
26
+ end
27
+
28
+ Then /^the remote directory should not be dirty$/ do
29
+ Dir.chdir "#{ROOT}/tmp/origin" do
30
+ type("git status").should include "working directory clean"
31
+ end
32
+ end
33
+
34
+ Then /^I should be on the "([^\"]*)" branch$/ do |branch|
35
+ @repo.head.name.should == branch
36
+ end
37
+
38
+ Then /^there should not be a "([^\"]*)" branch$/ do |branch_name|
39
+ @repo.branches.any? { |branch| branch.name == branch_name }
40
+ end
41
+
42
+ Then /^the "([^\"]*)" branch (should|should not) match the "([^\"]*)" branch$/ do |local_branch, which, remote_branch|
43
+ type "git fetch origin"
44
+ local_sha = @repo.commits(local_branch).first.id
45
+ remote_sha = @repo.commits(remote_branch).first.id
46
+ which = which.gsub(/ /, '_').to_sym
47
+ local_sha.send(which) == remote_sha
48
+ end
49
+
50
+ Then /^the "([^\"]*)" branch should be a fast\-forward from the "([^\"]*)" branch$/ do |local_branch, remote_branch|
51
+ local_sha = @repo.commits(local_branch).first.id
52
+ remote_sha = @repo.commits(remote_branch).first.id
53
+ common_ancestor = @repo.find_common_ancestor local_sha, remote_sha
54
+ common_ancestor.should == remote_sha
55
+ end
@@ -0,0 +1,41 @@
1
+ Given /^a shared rails project$/ do
2
+ # TEARDOWN
3
+ Dir.chdir ROOT
4
+ type "rm -rf tmp"
5
+
6
+ # SETUP
7
+ Dir.chdir ROOT
8
+ Dir.mkdir 'tmp'
9
+ type "cp -R fixtures/repo tmp/origin"
10
+ Dir.chdir 'tmp/origin' do
11
+ File.open ".git/hooks/post-receive", "w" do |f|
12
+ f.puts <<-BASH
13
+ #!/bin/bash
14
+ RAILS_ENV=staging #{ROOT}/bin/bard stage
15
+ BASH
16
+ f.chmod 0775
17
+ end
18
+ type "cp config/database.yml.sample config/database.yml"
19
+ type "git checkout -b integration"
20
+ end
21
+ type "cp -R fixtures/repo tmp/submodule"
22
+ type "cp -R fixtures/repo tmp/submodule2"
23
+ type "git clone tmp/origin tmp/local"
24
+ Dir.chdir 'tmp/local'
25
+ @repo = Grit::Repo.new "."
26
+ type "grb fetch integration"
27
+ type "git checkout integration"
28
+ type "cp config/database.yml.sample config/database.yml"
29
+ end
30
+
31
+ When /^I type "([^\"]*)"$/ do |command|
32
+ type command
33
+ end
34
+
35
+ Then /^I should see the fatal error "([^\"]*)"$/ do |error_message|
36
+ @stderr.should include(error_message)
37
+ end
38
+
39
+ Then /^I should see the warning "([^\"]*)"$/ do |warning_message|
40
+ @stderr.should include(warning_message)
41
+ end
@@ -0,0 +1,104 @@
1
+ Given /^I have committed a set of changes that includes a new migration$/ do
2
+ Dir.chdir "#{ROOT}/tmp/local" do
3
+ type "script/generate migration test_migration"
4
+ type "git add ."
5
+ type "git commit -am'added test migration.'"
6
+ end
7
+ end
8
+
9
+ Given /^the remote integration branch has had a commit that includes a new migration$/ do
10
+ Dir.chdir "#{ROOT}/tmp/origin" do
11
+ type "script/generate migration test_migration"
12
+ type "git add ."
13
+ type "git commit -am'added test migration.'"
14
+ end
15
+ end
16
+
17
+ Given /^I have a development environment set up locally$/ do
18
+ Dir.chdir "#{ROOT}/tmp/local" do
19
+ type "rake db:create"
20
+ type "rake db:migrate"
21
+ end
22
+ end
23
+
24
+ Given /^the staging server has a staging and test environment set up$/ do
25
+ Dir.chdir "#{ROOT}/tmp/origin" do
26
+ type "rake db:create RAILS_ENV=staging && rake db:create RAILS_ENV=test"
27
+ type "rake db:migrate RAILS_ENV=staging && rake db:migrate RAILS_ENV=test"
28
+ end
29
+ end
30
+
31
+ Given /^I have development and test environments set up locally$/ do
32
+ Dir.chdir "#{ROOT}/tmp/local" do
33
+ type "rake db:create && rake db:create RAILS_ENV=test"
34
+ type "rake db:migrate && rake db:migrate RAILS_ENV=test"
35
+ end
36
+ end
37
+
38
+ Then /^the development database should include that migration$/ do
39
+ Dir.chdir "#{ROOT}/tmp/local" do
40
+ db_version = type("rake db:version")[/[0-9]{14}/]
41
+ test_migration_version = type("ls db/migrate/*_test_migration.rb")[/[0-9]{14}/]
42
+ db_version.should == test_migration_version
43
+ end
44
+ end
45
+
46
+ Then /^the both the staging and test databases should include that migration$/ do
47
+ Dir.chdir "#{ROOT}/tmp/origin" do
48
+ staging_db_version = type("rake db:version RAILS_ENV=staging")[/[0-9]{14}/]
49
+ test_db_version = type("rake db:version RAILS_ENV=test")[/[0-9]{14}/]
50
+ test_migration_version = type("ls db/migrate/*_test_migration.rb")[/[0-9]{14}/]
51
+ staging_db_version.should == test_migration_version
52
+ test_db_version.should == test_migration_version
53
+ end
54
+ end
55
+
56
+ Then /^both the development and test databases should include that migration$/ do
57
+ Dir.chdir "#{ROOT}/tmp/local" do
58
+ dev_db_version = type("rake db:version")[/[0-9]{14}/]
59
+ test_db_version = type("rake db:version RAILS_ENV=test")[/[0-9]{14}/]
60
+ test_migration_version = type("ls db/migrate/*_test_migration.rb")[/[0-9]{14}/]
61
+ dev_db_version.should == test_migration_version
62
+ test_db_version.should == test_migration_version
63
+ end
64
+ end
65
+
66
+ Given /^I dont have the test gem installed$/ do
67
+ type "gem uninstall rake-dotnet -v=0.0.1 -x"
68
+ end
69
+
70
+ Given /^I have committed a set of changes that adds the test gem as a dependency$/ do
71
+ Dir.chdir "#{ROOT}/tmp/local" do
72
+ file_inject "config/environment.rb", "
73
+ Rails::Initializer.run do |config|", <<-RUBY
74
+ config.gem "rake-dotnet", :version => "0.0.1"
75
+ RUBY
76
+ type "git add ."
77
+ type "git commit -am'added test gem dependency.'"
78
+ end
79
+ end
80
+
81
+ Given /^the remote integration branch has had a commit that adds the test gem as a dependency$/ do
82
+ Dir.chdir "#{ROOT}/tmp/origin" do
83
+ file_inject "config/environment.rb", "
84
+ Rails::Initializer.run do |config|", <<-RUBY
85
+ config.gem "rake-dotnet", :version => "0.0.1"
86
+ RUBY
87
+ type "git add ."
88
+ type "git commit -am'added test gem dependency.'"
89
+ end
90
+ end
91
+
92
+ Then /^the test gem should be installed$/ do
93
+ type("gem list rake-dotnet").should include "rake-dotnet (0.0.1)"
94
+ end
95
+
96
+ Then /^passenger should have been restarted$/ do
97
+ File.exist?("tmp/restart.txt").should be_true
98
+ end
99
+
100
+ Then /^the staging passenger should have been restarted$/ do
101
+ Dir.chdir "#{ROOT}/tmp/origin" do
102
+ File.exist?("tmp/restart.txt").should be_true
103
+ end
104
+ end
@@ -0,0 +1,172 @@
1
+ Given /^a submodule$/ do
2
+ Given 'the remote integration branch has had a commit that includes a new submodule'
3
+ Dir.chdir "#{ROOT}/tmp/local" do
4
+ type "git checkout integration"
5
+ type "git pull --rebase"
6
+ type "git submodule update --init"
7
+ @submodule_url = File.read(".gitmodules").match(/url = (.*)$/)[1]
8
+ @submodule_commit = type "git submodule status"
9
+ end
10
+ end
11
+
12
+ Given /^the submodule working directory is dirty$/ do
13
+ Dir.chdir "#{ROOT}/tmp/local/submodule" do
14
+ type "git checkout master"
15
+ type "echo 'submodule_update' > submodule_update"
16
+ end
17
+ end
18
+
19
+ Given /^I have committed a set of changes to the submodule$/ do
20
+ Dir.chdir "#{ROOT}/tmp/local/submodule" do
21
+ type "git checkout -b master"
22
+ type "echo 'submodule_update' > submodule_update"
23
+ type "git add ."
24
+ type "git commit -am 'update in submodule'"
25
+ end
26
+ end
27
+
28
+ Given /^the remote integration branch has had a commit that includes a new submodule$/ do
29
+ Dir.chdir "#{ROOT}/tmp/origin" do
30
+ type "git submodule add #{ROOT}/tmp/submodule submodule"
31
+ Dir.chdir "submodule" do
32
+ type "git checkout -b master"
33
+ type "grb track master"
34
+ end
35
+ type "git add ."
36
+ type "git commit -m 'added submodule'"
37
+ end
38
+ end
39
+
40
+ Given /^I have committed a set of changes that includes a new submodule$/ do
41
+ type "git submodule add #{ROOT}/tmp/submodule submodule"
42
+ Dir.chdir "submodule" do
43
+ type "git checkout -b master"
44
+ type "grb track master"
45
+ end
46
+ type "git add ."
47
+ type "git commit -m 'added submodule'"
48
+ end
49
+
50
+ Given /^I have committed a set of changes that includes a submodule update$/ do
51
+ type "git checkout integration"
52
+ Dir.chdir "submodule" do
53
+ type "git checkout master"
54
+ type "echo 'submodule_update' > submodule_update"
55
+ type "git add ."
56
+ type "git commit -m 'update in submodule'"
57
+ type "git push origin HEAD"
58
+ end
59
+ type "git add ."
60
+ type "git commit -m 'updated submodule'"
61
+ end
62
+
63
+ Given /^the remote integration branch has had a commit that includes a submodule update$/ do
64
+ Dir.chdir "#{ROOT}/tmp/origin" do
65
+ Dir.chdir "submodule" do
66
+ type "git checkout master"
67
+ type "echo 'submodule_update' > submodule_update"
68
+ type "git add ."
69
+ type "git commit -m 'update in submodule'"
70
+ type "git push origin HEAD"
71
+ end
72
+ type "git add ."
73
+ type "git commit -m 'updated submodule'"
74
+ end
75
+ end
76
+
77
+ Given /^I have committed a set of changes that includes a submodule url change$/ do
78
+ gsub_file ".gitmodules", /(url = .*submodule)$/ do |match| "#{match}2" end
79
+ type "git add ."
80
+ type "git commit -m 'updated submodule url'"
81
+ end
82
+
83
+ Given /^the remote integration branch has had a commit that includes a submodule url change$/ do
84
+ Dir.chdir "#{ROOT}/tmp/origin" do
85
+ gsub_file ".gitmodules", /(url = .*submodule)$/ do |match| "#{match}2" end
86
+ type "git add ."
87
+ type "git commit -m 'updated submodule url'"
88
+ end
89
+ end
90
+
91
+ Given /^I have committed a set of changes that includes a submodule deletion$/ do
92
+ type "rm .gitmodules"
93
+ type "rm -rf --cached submodule"
94
+ type "git add ."
95
+ type "git commit -am'removed submodule'"
96
+ end
97
+
98
+ Given /^the remote integration branch has had a commit that includes a submodule deletion$/ do
99
+ Dir.chdir "#{ROOT}/tmp/origin" do
100
+ type "rm .gitmodules"
101
+ type "rm -rf --cached submodule"
102
+ type "git add ."
103
+ type "git commit -am'removed submodule'"
104
+ end
105
+ end
106
+
107
+ Then /^there should be one new submodule$/ do
108
+ status = type "git submodule status"
109
+ status.should match /.[a-z0-9]{40} submodule/
110
+ end
111
+
112
+ Then /^there should be one new submodule on the remote$/ do
113
+ Dir.chdir "#{ROOT}/tmp/origin" do
114
+ status = type "git submodule status"
115
+ status.should match /.[a-z0-9]{40} submodule/
116
+ end
117
+ end
118
+
119
+ Then /^the submodule should be checked out$/ do
120
+ @submodule_url = File.read(".gitmodules").match(/url = (.*)$/)[1]
121
+ @submodule_commit = type "git submodule status"
122
+ @submodule_commit.should match %r( [a-z0-9]{40} submodule)
123
+ end
124
+
125
+ Then /^the remote submodule should be checked out$/ do
126
+ Dir.chdir "#{ROOT}/tmp/origin" do
127
+ @submodule_url = File.read(".gitmodules").match(/url = (.*)$/)[1]
128
+ @submodule_commit = type "git submodule status"
129
+ @submodule_commit.should match %r( [a-z0-9]{40} submodule)
130
+ end
131
+ end
132
+
133
+ Then /^the submodule should be updated$/ do
134
+ @submodule_commit[/[a-z0-9]{40}/].should_not == type("git submodule status")[/[a-z0-9]{40}/]
135
+ end
136
+
137
+ Then /^the remote submodule should be updated$/ do
138
+ Dir.chdir "#{ROOT}/tmp/origin" do
139
+ @submodule_commit[/[a-z0-9]{40}/].should_not == type("git submodule status")[/[a-z0-9]{40}/]
140
+ end
141
+ end
142
+
143
+ Then /^the submodule url should be changed$/ do
144
+ Dir.chdir "submodule" do
145
+ remote = type "git remote show origin"
146
+ remote.should_not match %r(Fetch URL: #{@submodule_url}$)
147
+ remote.should_not match %r(Push URL: #{@submodule_url}$)
148
+ end
149
+ end
150
+
151
+ Then /^the remote submodule url should be changed$/ do
152
+ Dir.chdir "#{ROOT}/tmp/origin/submodule" do
153
+ remote = type "git remote show origin"
154
+ remote.should_not match %r(Fetch URL: #{@submodule_url}$)
155
+ remote.should_not match %r(Push URL: #{@submodule_url}$)
156
+ end
157
+ end
158
+
159
+ Then /^the submodule should be deleted$/ do
160
+ Then 'the directory should not be dirty'
161
+ @submodule_commit = type "git submodule status"
162
+ @submodule_commit.should_not match /.[a-z0-9]{40} submodule/
163
+
164
+ end
165
+
166
+ Then /^the remote submodule should be deleted$/ do
167
+ Then 'the remote directory should not be dirty'
168
+ Dir.chdir "#{ROOT}/tmp/origin" do
169
+ @submodule_commit = type "git submodule status"
170
+ @submodule_commit.should_not match /.[a-z0-9]{40} submodule/
171
+ end
172
+ end
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
+ require 'ruby-debug'
3
+ require 'grit'
4
+ require 'spec/expectations'
5
+ require 'systemu'
6
+
7
+ ENV["PATH"] += ":#{File.dirname(File.expand_path(__FILE__))}/../../bin"
8
+
9
+ ROOT = File.expand_path(File.dirname(__FILE__) + '/../..')
@@ -0,0 +1,16 @@
1
+ Grit::Repo.class_eval do
2
+ def remote_branches(remote = "origin")
3
+ branches = self.remotes
4
+ branches.reject! { |r| r.name !~ %r(^#{remote}/) }
5
+ branches.collect! { |r| r.name.split('/')[1] }
6
+ branches.reject! { |b| b == "HEAD" }
7
+ end
8
+
9
+ def submodules
10
+ Grit::Submodule.config self, self.head.name
11
+ end
12
+
13
+ def find_common_ancestor(head1, head2)
14
+ `git merge-base #{head1} #{head2}`.chomp
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ def type(command)
2
+ @status, @stdout, @stderr = systemu command
3
+ if ENV['DEBUG']
4
+ puts '-' * 20
5
+ puts "Executing command: #{command}"
6
+ puts " Status: #{@status}"
7
+ puts " Stdout:\n #{@stdout}"
8
+ puts " Stderr:\n #{@stderr}"
9
+ puts '-' * 20
10
+ end
11
+ @stdout || @stderr
12
+ end
13
+
14
+ def file_inject(file_name, sentinel, string, before_after=:after)
15
+ gsub_file file_name, /(#{Regexp.escape(sentinel)})/mi do |match|
16
+ if before_after == :after
17
+ "#{match}\n#{string}"
18
+ else
19
+ "#{string}\n#{match}"
20
+ end
21
+ end
22
+ end
23
+
24
+ def gsub_file(file_name, regexp, *args, &block)
25
+ content = File.read(file_name).gsub(regexp, *args, &block)
26
+ File.open(file_name, 'wb') { |file| file.write(content) }
27
+ end
@@ -0,0 +1,108 @@
1
+ $:.unshift File.expand_path(File.dirname(__FILE__))
2
+ require 'term/ansicolor'
3
+ require 'systemu'
4
+ require 'grit'
5
+
6
+ require 'bard/git'
7
+ require 'bard/io'
8
+
9
+ class Bard < Thor
10
+ include BardGit
11
+ include BardIO
12
+
13
+ desc "pull", "pull changes to your local machine"
14
+ def pull
15
+ ensure_integration_branch!
16
+ ensure_clean_working_directory!
17
+
18
+ unless fast_forward_merge?
19
+ warn "Someone has pushed some changes since you last pulled.\n Please ensure that your changes didnt break stuff."
20
+ end
21
+
22
+ run_crucial "git pull --rebase origin integration"
23
+
24
+ changed_files = run_crucial("git diff #{@common_ancestor} origin/integration --diff-filter=ACDMR --name-only").split("\n")
25
+ puts changed_files.inspect
26
+
27
+ if changed_files.any? { |f| f =~ %r(^db/migrate/.+) }
28
+ run_crucial "rake db:migrate"
29
+ run_crucial "rake db:migrate RAILS_ENV=test"
30
+ end
31
+
32
+ if changed_files.any? { |f| f == ".gitmodules" }
33
+ run_crucial "git submodule sync"
34
+ run_crucial "git submodule init"
35
+ end
36
+ run_crucial "git submodule update"
37
+
38
+ if changed_files.any? { |f| f =~ %r(^config/environment.+) }
39
+ run_crucial "rake gems:install"
40
+ end
41
+
42
+ system "touch tmp/restart.txt"
43
+ end
44
+
45
+ desc "push", "push local changes out to the remote"
46
+ def push
47
+ ensure_integration_branch!
48
+ ensure_clean_working_directory!
49
+
50
+ if submodule_dirty?
51
+ fatal "Cannot push changes: You have uncommitted changes to a submodule!\n Please see Micah about this."
52
+ end
53
+
54
+ if submodule_unpushed?
55
+ fatal "Cannot push changes: You have unpushed changes to a submodule!\n Please see Micah about this."
56
+ end
57
+
58
+ unless fast_forward_merge?
59
+ fatal "Someone has pushed some changes since you last pulled.\n Kindly run bard pull, ensure that your your changes still work.\n Then run bard push again."
60
+ end
61
+
62
+ run_crucial "git push origin integration", true
63
+
64
+ # git post-receive hook runs stage task below
65
+ end
66
+
67
+ if ENV['RAILS_ENV'] == "staging"
68
+ desc "stage", "!!! INTERNAL USE ONLY !!! reset HEAD to integration, update submodules, run migrations, install gems, restart server"
69
+ def stage
70
+ if ENV['GIT_DIR'] == '.'
71
+ # this means the script has been called as a hook, not manually.
72
+ # get the proper GIT_DIR so we can descend into the working copy dir;
73
+ # if we don't then `git reset --hard` doesn't affect the working tree.
74
+ Dir.chdir '..'
75
+ ENV['GIT_DIR'] = '.git'
76
+ end
77
+
78
+ run_crucial "git reset --hard"
79
+
80
+ # find out the current branch
81
+ head = File.read('.git/HEAD').chomp
82
+ # abort if we're on a detached head
83
+ exit unless head.sub! 'ref: ', ''
84
+
85
+ revs = gets.split ' '
86
+ old_rev, new_rev = revs if head == revs.pop
87
+
88
+ changed_files = run_crucial("git diff #{old_rev} #{new_rev} --diff-filter=ACMRD --name-only").split("\n")
89
+
90
+ if changed_files.any? { |f| f =~ %r(^db/migrate/.+) }
91
+ run_crucial "rake db:migrate RAILS_ENV=staging"
92
+ run_crucial "rake db:migrate RAILS_ENV=test"
93
+ end
94
+
95
+ if changed_files.any? { |f| f == ".gitmodules" }
96
+ run_crucial "git submodule sync"
97
+ run_crucial "git submodule init"
98
+ end
99
+ system "git submodule update"
100
+
101
+ if changed_files.any? { |f| f =~ %r(^config/environment.+) }
102
+ run_crucial "rake gems:install"
103
+ end
104
+
105
+ system "touch tmp/restart.txt"
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,47 @@
1
+ module BardGit
2
+ private
3
+ def ensure_integration_branch!
4
+ return if `git name-rev --name-only HEAD`.chomp == "integration"
5
+ fatal "You are not on the integration branch! Type `git checkout integration` to switch to it. If you have made changes to your current branch, please see Micah for assistance."
6
+ end
7
+
8
+ def ensure_clean_working_directory!
9
+ return if`git status`.include? "working directory clean"
10
+ fatal "Cannot upload changes: You have uncommitted changes!\n Please run git commit before attempting to push or pull."
11
+ end
12
+
13
+ def fast_forward_merge?
14
+ run_crucial "git fetch origin"
15
+ head = run_crucial "git rev-parse HEAD"
16
+ remote_head = run_crucial "git rev-parse origin/integration"
17
+ @common_ancestor = find_common_ancestor head, remote_head
18
+ @common_ancestor == remote_head
19
+ end
20
+
21
+ def find_common_ancestor(head1, head2)
22
+ run_crucial "git merge-base #{head1} #{head2}"
23
+ end
24
+
25
+ def submodule_dirty?
26
+ @repo ||= Grit::Repo.new "."
27
+ submodules = Grit::Submodule.config(@repo, @repo.head.name)
28
+ submodules.any? do |name, submodule|
29
+ Dir.chdir submodule["path"] do
30
+ not `git status`.include? "working directory clean"
31
+ end
32
+ end
33
+ end
34
+
35
+ def submodule_unpushed?
36
+ @repo ||= Grit::Repo.new "."
37
+ submodules = Grit::Submodule.config(@repo, @repo.head.name)
38
+ submodules.any? do |name, submodule|
39
+ Dir.chdir submodule["path"] do
40
+ branch = `git name-rev --name-only HEAD`.chomp
41
+ `git fetch`
42
+ submodule["id"] != `git rev-parse origin/#{branch}`.chomp
43
+ end
44
+ end
45
+ end
46
+ end
47
+
@@ -0,0 +1,22 @@
1
+ module BardIO
2
+ include Term::ANSIColor
3
+ private
4
+
5
+ def warn(message)
6
+ $stderr.puts yellow("!!! ") + message
7
+ end
8
+
9
+ def fatal(message)
10
+ raise Thor::Error, red("!!! ") + message
11
+ end
12
+
13
+ def run_crucial(command, verbose = false)
14
+ status, stdout, stderr = systemu command
15
+ fatal "Running command: #{yellow(command)}: #{stderr}" if status.to_i.nonzero?
16
+ if verbose
17
+ $stdout.puts stdout
18
+ $stderr.puts stderr
19
+ end
20
+ stdout.chomp
21
+ end
22
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Bard" do
4
+ it "fails" do
5
+ fail "hey buddy, you should probably rename this file and start specing for real"
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'bard'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ end
metadata ADDED
@@ -0,0 +1,169 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bard
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.1
5
+ platform: ruby
6
+ authors:
7
+ - Micah Geisel
8
+ - Nick Hogle
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-09-30 00:00:00 -07:00
14
+ default_executable: bard
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: ruby-debug
18
+ type: :development
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ version:
26
+ - !ruby/object:Gem::Dependency
27
+ name: rspec
28
+ type: :development
29
+ version_requirement:
30
+ version_requirements: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
35
+ version:
36
+ - !ruby/object:Gem::Dependency
37
+ name: cucumber
38
+ type: :development
39
+ version_requirement:
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: "0"
45
+ version:
46
+ - !ruby/object:Gem::Dependency
47
+ name: rubygems-update
48
+ type: :runtime
49
+ version_requirement:
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 1.3.2
55
+ version:
56
+ - !ruby/object:Gem::Dependency
57
+ name: thor
58
+ type: :runtime
59
+ version_requirement:
60
+ version_requirements: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 0.11.7
65
+ version:
66
+ - !ruby/object:Gem::Dependency
67
+ name: grit
68
+ type: :runtime
69
+ version_requirement:
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 1.1.1
75
+ version:
76
+ - !ruby/object:Gem::Dependency
77
+ name: git_remote_branch
78
+ type: :runtime
79
+ version_requirement:
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 0.3.0
85
+ version:
86
+ - !ruby/object:Gem::Dependency
87
+ name: systemu
88
+ type: :runtime
89
+ version_requirement:
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: 1.2.0
95
+ version:
96
+ - !ruby/object:Gem::Dependency
97
+ name: term-ansicolor
98
+ type: :runtime
99
+ version_requirement:
100
+ version_requirements: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: 1.0.3
105
+ version:
106
+ description: This immaculate work of engineering genius allows mere mortals to collaborate with beings of transcendent intelligence like Micah, Michael, and Nick.
107
+ email: info@botandrose.com
108
+ executables:
109
+ - bard
110
+ extensions: []
111
+
112
+ extra_rdoc_files:
113
+ - LICENSE
114
+ - README.rdoc
115
+ files:
116
+ - .document
117
+ - .gitignore
118
+ - .gitmodules
119
+ - LICENSE
120
+ - README.rdoc
121
+ - Rakefile
122
+ - VERSION
123
+ - bard.gemspec
124
+ - bin/bard
125
+ - features/bard_pull.feature
126
+ - features/bard_push.feature
127
+ - features/step_definitions/git_steps.rb
128
+ - features/step_definitions/global_steps.rb
129
+ - features/step_definitions/rails_steps.rb
130
+ - features/step_definitions/submodule_steps.rb
131
+ - features/support/env.rb
132
+ - features/support/grit_ext.rb
133
+ - features/support/io.rb
134
+ - lib/bard.rb
135
+ - lib/bard/git.rb
136
+ - lib/bard/io.rb
137
+ - spec/bard_spec.rb
138
+ - spec/spec_helper.rb
139
+ has_rdoc: true
140
+ homepage: http://github.com/botandrose/bard
141
+ licenses: []
142
+
143
+ post_install_message:
144
+ rdoc_options:
145
+ - --charset=UTF-8
146
+ require_paths:
147
+ - lib
148
+ required_ruby_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: "0"
153
+ version:
154
+ required_rubygems_version: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: "0"
159
+ version:
160
+ requirements: []
161
+
162
+ rubyforge_project:
163
+ rubygems_version: 1.3.4
164
+ signing_key:
165
+ specification_version: 3
166
+ summary: Tools for collaborating with Bot and Rose Design.
167
+ test_files:
168
+ - spec/spec_helper.rb
169
+ - spec/bard_spec.rb