bob 0.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.
- data/.gitignore +5 -0
- data/LICENSE +22 -0
- data/README.rdoc +58 -0
- data/Rakefile +43 -0
- data/bob.gemspec +46 -0
- data/lib/bob.rb +41 -0
- data/lib/bob/background_engines.rb +9 -0
- data/lib/bob/background_engines/foreground.rb +6 -0
- data/lib/bob/builder.rb +53 -0
- data/lib/bob/scm.rb +23 -0
- data/lib/bob/scm/abstract.rb +49 -0
- data/lib/bob/scm/git.rb +57 -0
- data/lib/core_ext/object.rb +7 -0
- data/test/bob_test.rb +22 -0
- data/test/helper.rb +32 -0
- data/test/helper/buildable_stub.rb +55 -0
- data/test/helper/git_helper.rb +48 -0
- metadata +119 -0
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
(The MIT License)
|
2
|
+
|
3
|
+
Copyright (c) 2008-2009 Nicolas Sanguinetti, entp.com
|
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 NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
20
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
21
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
22
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
= Bob the Builder
|
2
|
+
|
3
|
+
Given a Buildable object with the following public API:
|
4
|
+
|
5
|
+
* <tt>buildable.kind</tt>
|
6
|
+
|
7
|
+
Should return a Symbol with whatever kind of repository the buildable's code is
|
8
|
+
in (:git, :svn, etc).
|
9
|
+
|
10
|
+
* <tt>buildable.uri</tt>
|
11
|
+
|
12
|
+
Returns a string like "git://github.com/integrity/bob.git", pointing to the code
|
13
|
+
repository.
|
14
|
+
|
15
|
+
* <tt>buildable.branch</tt>
|
16
|
+
|
17
|
+
What branch of the repository should we build?
|
18
|
+
|
19
|
+
* <tt>buildable.build_script</tt>
|
20
|
+
|
21
|
+
Returns a string containing the build script to be run when "building".
|
22
|
+
|
23
|
+
* <tt>buildable.start_building(commit_id)</tt>
|
24
|
+
|
25
|
+
`commit_id` is a String that contains whatever is appropriate for the repo type,
|
26
|
+
so it would be a SHA1 hash for git repos, or a numeric id for svn, etc. This is a
|
27
|
+
callback so the buildable can determine how long it takes to build. It doesn't
|
28
|
+
need to return anything.
|
29
|
+
|
30
|
+
* <tt>buildable.finish_building(commit_id, build_status, build_output)</tt>
|
31
|
+
|
32
|
+
Callback for when the build finishes. It doesn't need to return anything. It will
|
33
|
+
receive a string with the commit identifier, a boolean for the build exit status
|
34
|
+
(true for successful builds, false fore failed ones) and a string with the build
|
35
|
+
output (both STDOUT and STDERR).
|
36
|
+
|
37
|
+
A successful build is one where the build script returns a zero status code.
|
38
|
+
|
39
|
+
Bob will, when called like:
|
40
|
+
|
41
|
+
Bob.build(buildable, commit_id)
|
42
|
+
|
43
|
+
1. Checkout the buildable on the specified commit
|
44
|
+
2. Call <tt>buildable.start_building</tt>
|
45
|
+
3. Run the script provided in <tt>build_script</tt> in the buildable.
|
46
|
+
4. When the build process finishes, it will call <tt>finish_building</tt> with
|
47
|
+
the commit_id, the build status (true if the script returns a status code
|
48
|
+
of 0, false otherwise), and a string with the build output (both STDOUT and STDERR).
|
49
|
+
|
50
|
+
== Do I need this?
|
51
|
+
|
52
|
+
Probably not. Check out integrity[http://integrityapp.com] for a full fledged
|
53
|
+
automated CI server, which is what most people need.
|
54
|
+
|
55
|
+
== Credits
|
56
|
+
|
57
|
+
Authors:: Nicolas Sanguinetti (foca[http://github.com/foca]) and Simon Rozet (sr[http://github.com/sr])
|
58
|
+
License:: MIT (Check LICENSE for details)
|
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require "rake/testtask"
|
2
|
+
|
3
|
+
begin
|
4
|
+
require "hanna/rdoctask"
|
5
|
+
rescue LoadError
|
6
|
+
require "rake/rdoctask"
|
7
|
+
end
|
8
|
+
|
9
|
+
begin
|
10
|
+
require "metric_fu"
|
11
|
+
rescue LoadError
|
12
|
+
end
|
13
|
+
|
14
|
+
begin
|
15
|
+
require "mg"
|
16
|
+
MG.new("bob.gemspec")
|
17
|
+
rescue LoadError
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "Default: run all tests"
|
21
|
+
task :default => :test
|
22
|
+
|
23
|
+
SCMs = %w[git svn]
|
24
|
+
|
25
|
+
desc "Run unit tests"
|
26
|
+
task :test => SCMs.map { |scm| "test:#{scm}" } do
|
27
|
+
ruby "test/bob_test.rb"
|
28
|
+
ruby "test/background_engine/threaded_test.rb"
|
29
|
+
end
|
30
|
+
|
31
|
+
SCMs.each { |scm|
|
32
|
+
desc "Run unit tests with #{scm}"
|
33
|
+
task "test:#{scm}" do
|
34
|
+
ruby "test/scm/#{scm}_test.rb"
|
35
|
+
end
|
36
|
+
}
|
37
|
+
|
38
|
+
Rake::RDocTask.new do |rd|
|
39
|
+
rd.main = "README"
|
40
|
+
rd.title = "Documentation for Bob the Builder"
|
41
|
+
rd.rdoc_files.include("README.rdoc", "LICENSE", "lib/**/*.rb")
|
42
|
+
rd.rdoc_dir = "doc"
|
43
|
+
end
|
data/bob.gemspec
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "bob"
|
3
|
+
s.version = "0.1"
|
4
|
+
s.date = "2009-04-12"
|
5
|
+
|
6
|
+
s.description = "Bob the Builder will build your code. Simple."
|
7
|
+
s.summary = "Bob builds!"
|
8
|
+
s.homepage = "http://integrityapp.com"
|
9
|
+
|
10
|
+
s.authors = ["Nicolás Sanguinetti", "Simon Rozet"]
|
11
|
+
s.email = "info@integrityapp.com"
|
12
|
+
|
13
|
+
s.require_paths = ["lib"]
|
14
|
+
s.rubyforge_project = "integrity"
|
15
|
+
s.has_rdoc = true
|
16
|
+
s.rubygems_version = "1.3.1"
|
17
|
+
|
18
|
+
s.add_dependency "addressable"
|
19
|
+
|
20
|
+
if s.respond_to?(:add_development_dependency)
|
21
|
+
s.add_development_dependency "sr-mg"
|
22
|
+
s.add_development_dependency "contest"
|
23
|
+
s.add_development_dependency "redgreen"
|
24
|
+
s.add_development_dependency "ruby-debug"
|
25
|
+
end
|
26
|
+
|
27
|
+
s.files = %w[
|
28
|
+
.gitignore
|
29
|
+
LICENSE
|
30
|
+
README.rdoc
|
31
|
+
Rakefile
|
32
|
+
bob.gemspec
|
33
|
+
lib/bob.rb
|
34
|
+
lib/bob/background_engines.rb
|
35
|
+
lib/bob/background_engines/foreground.rb
|
36
|
+
lib/bob/builder.rb
|
37
|
+
lib/bob/scm.rb
|
38
|
+
lib/bob/scm/abstract.rb
|
39
|
+
lib/bob/scm/git.rb
|
40
|
+
lib/core_ext/object.rb
|
41
|
+
test/bob_test.rb
|
42
|
+
test/helper.rb
|
43
|
+
test/helper/git_helper.rb
|
44
|
+
test/helper/buildable_stub.rb
|
45
|
+
]
|
46
|
+
end
|
data/lib/bob.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require "yaml"
|
3
|
+
require "logger"
|
4
|
+
require "time"
|
5
|
+
require "addressable/uri"
|
6
|
+
|
7
|
+
require "bob/builder"
|
8
|
+
require "bob/scm"
|
9
|
+
require "bob/background_engines"
|
10
|
+
|
11
|
+
module Bob
|
12
|
+
# Builds the specified <tt>buildable</tt>. This object must understand
|
13
|
+
# the API described in the README.
|
14
|
+
def self.build(buildable, commit_ids)
|
15
|
+
Array(commit_ids).each do |commit_id|
|
16
|
+
Builder.new(buildable, commit_id).build
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Directory where the code for the different buildables will be checked out. Make sure
|
21
|
+
# the user running Bob is allowed to write to this directory.
|
22
|
+
def self.directory
|
23
|
+
@directory || "/tmp"
|
24
|
+
end
|
25
|
+
|
26
|
+
# What will you use to build in background. Must respond to <tt>call</tt> and take a block
|
27
|
+
# which will be run "in background". The default is to run in foreground.
|
28
|
+
def self.engine
|
29
|
+
@engine || BackgroundEngines::Foreground
|
30
|
+
end
|
31
|
+
|
32
|
+
# What to log with (must implement ruby's Logger interface). Logs to STDOUT by
|
33
|
+
# default.
|
34
|
+
def self.logger
|
35
|
+
@logger || Logger.new(STDOUT)
|
36
|
+
end
|
37
|
+
|
38
|
+
class << self
|
39
|
+
attr_writer :directory, :engine, :logger
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Bob
|
2
|
+
# Different engines to run code in background. An engine is any object
|
3
|
+
# that responds to #call and takes a Proc object, which should be executed
|
4
|
+
# "in the background". The different engines are:
|
5
|
+
module BackgroundEngines
|
6
|
+
autoload :Foreground, "bob/background_engines/foreground"
|
7
|
+
autoload :Threaded, "bob/background_engines/threaded"
|
8
|
+
end
|
9
|
+
end
|
data/lib/bob/builder.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
module Bob
|
2
|
+
# A Builder will take care of building a buildable (wow, you didn't see that coming,
|
3
|
+
# right?).
|
4
|
+
class Builder
|
5
|
+
attr_reader :buildable, :commit_id
|
6
|
+
|
7
|
+
def initialize(buildable, commit_id)
|
8
|
+
@buildable = buildable
|
9
|
+
@commit_id = commit_id
|
10
|
+
end
|
11
|
+
|
12
|
+
# This is where the magic happens:
|
13
|
+
#
|
14
|
+
# 1. Check out the repo to the appropriate commit.
|
15
|
+
# 2. Notify the buildable that the build is starting.
|
16
|
+
# 3. Run the build script on it in the background.
|
17
|
+
# 4. Reports the build back to the buildable.
|
18
|
+
def build
|
19
|
+
Bob.logger.info "Building #{commit_id} of the #{buildable.kind} repo at #{buildable.uri}"
|
20
|
+
in_background do
|
21
|
+
scm.with_commit(commit_id) do
|
22
|
+
buildable.start_building(commit_id, scm.info(commit_id))
|
23
|
+
build_status, build_output = run_build_script
|
24
|
+
buildable.finish_building(commit_id, build_status, build_output)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def run_build_script
|
32
|
+
build_output = nil
|
33
|
+
|
34
|
+
Bob.logger.debug "Running the build script for #{buildable.uri}"
|
35
|
+
IO.popen(build_script, "r") { |output| build_output = output.read }
|
36
|
+
Bob.logger.debug("Ran build script `#{build_script}` and got:\n#{build_output}")
|
37
|
+
|
38
|
+
[$?.success?, build_output]
|
39
|
+
end
|
40
|
+
|
41
|
+
def build_script
|
42
|
+
"(cd #{scm.working_dir} && #{buildable.build_script} 2>&1)"
|
43
|
+
end
|
44
|
+
|
45
|
+
def scm
|
46
|
+
@scm ||= SCM.new(buildable.kind, buildable.uri, buildable.branch)
|
47
|
+
end
|
48
|
+
|
49
|
+
def in_background(&block)
|
50
|
+
Bob.engine.call(block)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/bob/scm.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require "bob/scm/abstract"
|
2
|
+
|
3
|
+
module Bob
|
4
|
+
module SCM
|
5
|
+
autoload :Git, "bob/scm/git"
|
6
|
+
autoload :Svn, "bob/scm/svn"
|
7
|
+
|
8
|
+
class CantRunCommand < RuntimeError; end
|
9
|
+
|
10
|
+
# Factory to return appropriate SCM instances (according to repository kind)
|
11
|
+
def self.new(kind, uri, branch)
|
12
|
+
class_for(kind).new(uri, branch)
|
13
|
+
end
|
14
|
+
|
15
|
+
# A copy of Inflector.camelize, from ActiveSupport. It will convert
|
16
|
+
# string to UpperCamelCase.
|
17
|
+
def self.class_for(kind)
|
18
|
+
class_name = kind.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
|
19
|
+
const_get(class_name)
|
20
|
+
end
|
21
|
+
private_class_method :class_for
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Bob
|
2
|
+
module SCM
|
3
|
+
class Abstract
|
4
|
+
attr_reader :uri, :branch
|
5
|
+
|
6
|
+
def initialize(uri, branch)
|
7
|
+
@uri = Addressable::URI.parse(uri)
|
8
|
+
@branch = branch
|
9
|
+
end
|
10
|
+
|
11
|
+
# Checkout the code into <tt>working_dir</tt> at the specified revision and
|
12
|
+
# call the passed block
|
13
|
+
def with_commit(commit_id)
|
14
|
+
update_code
|
15
|
+
checkout(commit_id)
|
16
|
+
yield
|
17
|
+
end
|
18
|
+
|
19
|
+
# Directory where the code will be checked out. Make sure the user running Bob is
|
20
|
+
# allowed to write to this directory (or you'll get a <tt>Errno::EACCESS</tt>)
|
21
|
+
def working_dir
|
22
|
+
@working_dir ||= "#{Bob.directory}/#{path_from_uri}".tap do |path|
|
23
|
+
FileUtils.mkdir_p path
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Get some information about the specified commit. Returns a hash with:
|
28
|
+
#
|
29
|
+
# [<tt>:author</tt>] Commit author's name and email
|
30
|
+
# [<tt>:message</tt>] Commit message
|
31
|
+
# [<tt>:committed_at</tt>] Commit date (as a <tt>Time</tt> object)
|
32
|
+
def info(commit_id)
|
33
|
+
raise NotImplementedError
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
def run(command)
|
39
|
+
command = "(cd #{working_dir} && #{command} &>/dev/null)"
|
40
|
+
Bob.logger.debug command
|
41
|
+
system(command) || raise(CantRunCommand, "Couldn't run SCM command `#{command}`")
|
42
|
+
end
|
43
|
+
|
44
|
+
def path_from_uri
|
45
|
+
raise NotImplementedError
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/bob/scm/git.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
module Bob
|
2
|
+
module SCM
|
3
|
+
class Git < Abstract
|
4
|
+
def info(commit_id)
|
5
|
+
format = %Q(---%n:author: %an <%ae>%n:message: >-%n %s%n:committed_at: %ci%n)
|
6
|
+
YAML.load(`cd #{working_dir} && git show -s --pretty=format:"#{format}" #{commit_id}`).tap do |info|
|
7
|
+
info[:committed_at] = Time.parse(info[:committed_at])
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def path_from_uri
|
14
|
+
path = uri.path.
|
15
|
+
gsub(/\~[a-z0-9]*\//i, ""). # remove ~foobar/
|
16
|
+
gsub(/\s+|\.|\//, "-"). # periods, spaces, slashes -> hyphens
|
17
|
+
gsub(/^-+|-+$/, "") # remove trailing hyphens
|
18
|
+
path += "-#{branch}"
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def update_code
|
24
|
+
cloned? ? fetch : clone
|
25
|
+
end
|
26
|
+
|
27
|
+
def cloned?
|
28
|
+
File.directory?("#{working_dir}/.git")
|
29
|
+
end
|
30
|
+
|
31
|
+
def clone
|
32
|
+
git "clone #{uri} #{working_dir}"
|
33
|
+
rescue CantRunCommand
|
34
|
+
FileUtils.rm_r working_dir
|
35
|
+
retry
|
36
|
+
end
|
37
|
+
|
38
|
+
def fetch
|
39
|
+
git "fetch origin"
|
40
|
+
end
|
41
|
+
|
42
|
+
def checkout(commit_id)
|
43
|
+
# First checkout the branch just in case the commit_id turns out to be HEAD or other non-sha identifier
|
44
|
+
git "checkout origin/#{branch}"
|
45
|
+
git "reset --hard #{commit_id}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def reset(commit_id)
|
49
|
+
git "reset --hard #{commit_id}"
|
50
|
+
end
|
51
|
+
|
52
|
+
def git(command)
|
53
|
+
run "git #{command}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/test/bob_test.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/helper"
|
2
|
+
|
3
|
+
class BobTest < Test::Unit::TestCase
|
4
|
+
test "directory" do
|
5
|
+
Bob.directory = "/foo/bar"
|
6
|
+
assert_equal "/foo/bar", Bob.directory
|
7
|
+
end
|
8
|
+
|
9
|
+
test "logger" do
|
10
|
+
logger = Logger.new("/tmp/bob.log")
|
11
|
+
Bob.logger = logger
|
12
|
+
|
13
|
+
assert_same logger, Bob.logger
|
14
|
+
end
|
15
|
+
|
16
|
+
test "engine" do
|
17
|
+
engine = Object.new
|
18
|
+
Bob.engine = engine
|
19
|
+
|
20
|
+
assert_same engine, Bob.engine
|
21
|
+
end
|
22
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "contest"
|
3
|
+
require "hpricot"
|
4
|
+
|
5
|
+
begin
|
6
|
+
require "redgreen"
|
7
|
+
require "ruby-debug"
|
8
|
+
rescue LoadError
|
9
|
+
end
|
10
|
+
|
11
|
+
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"),
|
12
|
+
File.expand_path(File.dirname(__FILE__) + "/../test/helper"))
|
13
|
+
|
14
|
+
require "bob"
|
15
|
+
require "git_helper"
|
16
|
+
require "svn_helper"
|
17
|
+
require "buildable_stub"
|
18
|
+
|
19
|
+
Bob.logger = Logger.new("/dev/null")
|
20
|
+
Bob.engine = Bob::BackgroundEngines::Foreground
|
21
|
+
Bob.directory = File.expand_path(File.dirname(__FILE__) + "/../tmp")
|
22
|
+
|
23
|
+
class Test::Unit::TestCase
|
24
|
+
include Bob
|
25
|
+
include TestHelper
|
26
|
+
|
27
|
+
attr_reader :repo, :buildable
|
28
|
+
|
29
|
+
def setup
|
30
|
+
FileUtils.rm_rf(Bob.directory)
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module TestHelper
|
2
|
+
module BuildableStub
|
3
|
+
attr_reader :repo, :builds, :metadata
|
4
|
+
|
5
|
+
def initialize(repo)
|
6
|
+
@repo = repo
|
7
|
+
@builds = {}
|
8
|
+
@metadata = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def build_script
|
12
|
+
"./test"
|
13
|
+
end
|
14
|
+
|
15
|
+
def start_building(commit_id, commit_info)
|
16
|
+
@metadata[commit_id] = commit_info
|
17
|
+
end
|
18
|
+
|
19
|
+
def finish_building(commit_id, status, output)
|
20
|
+
@builds[commit_id] = [status ? :successful : :failed, output]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class GitBuildableStub
|
25
|
+
include BuildableStub
|
26
|
+
|
27
|
+
def kind
|
28
|
+
:git
|
29
|
+
end
|
30
|
+
|
31
|
+
def uri
|
32
|
+
repo.path
|
33
|
+
end
|
34
|
+
|
35
|
+
def branch
|
36
|
+
"master"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class SvnBuildableStub
|
41
|
+
include BuildableStub
|
42
|
+
|
43
|
+
def kind
|
44
|
+
:svn
|
45
|
+
end
|
46
|
+
|
47
|
+
def uri
|
48
|
+
"file://#{SvnRepo.server_root}/#{repo.name}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def branch
|
52
|
+
""
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/abstract_scm_helper"
|
2
|
+
|
3
|
+
module TestHelper
|
4
|
+
class GitRepo < AbstractSCMRepo
|
5
|
+
def create
|
6
|
+
FileUtils.mkdir_p @path
|
7
|
+
|
8
|
+
Dir.chdir(@path) do
|
9
|
+
system 'git init &>/dev/null'
|
10
|
+
system 'git config user.name "John Doe"'
|
11
|
+
system 'git config user.email "johndoe@example.org"'
|
12
|
+
system 'echo "just a test repo" >> README'
|
13
|
+
add 'README &>/dev/null'
|
14
|
+
commit "First commit"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def commits
|
19
|
+
Dir.chdir(@path) do
|
20
|
+
commits = `git log --pretty=oneline`.collect { |l| l.split(" ").first }
|
21
|
+
commits.inject([]) do |commits, sha1|
|
22
|
+
format = "---%n:message: >-%n %s%n:timestamp: %ci%n" +
|
23
|
+
":identifier: %H%n:author: %n :name: %an%n :email: %ae%n"
|
24
|
+
commits << YAML.load(`git show -s --pretty=format:"#{format}" #{sha1}`)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def head
|
30
|
+
Dir.chdir(@path) do
|
31
|
+
`git log --pretty=format:%H | head -1`.chomp
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def short_head
|
36
|
+
head[0..6]
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
def add(file)
|
41
|
+
system "git add #{file}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def commit(message)
|
45
|
+
system %Q{git commit -m "#{message}" &>/dev/null}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
metadata
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bob
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.1"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- "Nicol\xC3\xA1s Sanguinetti"
|
8
|
+
- Simon Rozet
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2009-04-12 00:00:00 -03:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: addressable
|
18
|
+
type: :runtime
|
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: sr-mg
|
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: contest
|
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: redgreen
|
48
|
+
type: :development
|
49
|
+
version_requirement:
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: ruby-debug
|
58
|
+
type: :development
|
59
|
+
version_requirement:
|
60
|
+
version_requirements: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: "0"
|
65
|
+
version:
|
66
|
+
description: Bob the Builder will build your code. Simple.
|
67
|
+
email: info@integrityapp.com
|
68
|
+
executables: []
|
69
|
+
|
70
|
+
extensions: []
|
71
|
+
|
72
|
+
extra_rdoc_files: []
|
73
|
+
|
74
|
+
files:
|
75
|
+
- .gitignore
|
76
|
+
- LICENSE
|
77
|
+
- README.rdoc
|
78
|
+
- Rakefile
|
79
|
+
- bob.gemspec
|
80
|
+
- lib/bob.rb
|
81
|
+
- lib/bob/background_engines.rb
|
82
|
+
- lib/bob/background_engines/foreground.rb
|
83
|
+
- lib/bob/builder.rb
|
84
|
+
- lib/bob/scm.rb
|
85
|
+
- lib/bob/scm/abstract.rb
|
86
|
+
- lib/bob/scm/git.rb
|
87
|
+
- lib/core_ext/object.rb
|
88
|
+
- test/bob_test.rb
|
89
|
+
- test/helper.rb
|
90
|
+
- test/helper/git_helper.rb
|
91
|
+
- test/helper/buildable_stub.rb
|
92
|
+
has_rdoc: true
|
93
|
+
homepage: http://integrityapp.com
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options: []
|
96
|
+
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: "0"
|
104
|
+
version:
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: "0"
|
110
|
+
version:
|
111
|
+
requirements: []
|
112
|
+
|
113
|
+
rubyforge_project: integrity
|
114
|
+
rubygems_version: 1.3.1
|
115
|
+
signing_key:
|
116
|
+
specification_version: 2
|
117
|
+
summary: Bob builds!
|
118
|
+
test_files: []
|
119
|
+
|