codefumes 0.1.10 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +19 -0
- data/Gemfile.lock +135 -0
- data/History.txt +12 -0
- data/LICENSE +20 -0
- data/Manifest.txt +40 -19
- data/README.txt +11 -29
- data/Rakefile +15 -10
- data/bin/fumes +214 -0
- data/config/website.yml +2 -0
- data/cucumber.yml +2 -0
- data/features/claiming_a_project.feature +46 -0
- data/features/deleting_a_project.feature +32 -0
- data/features/releasing_a_project.feature +50 -0
- data/features/step_definitions/cli_steps.rb +98 -0
- data/features/step_definitions/common_steps.rb +168 -0
- data/features/step_definitions/filesystem_steps.rb +19 -0
- data/features/storing_user_api_key.feature +41 -0
- data/features/support/common.rb +29 -0
- data/features/support/env.rb +24 -0
- data/features/support/matchers.rb +11 -0
- data/features/synchronizing_repository_with_project.feature +33 -0
- data/lib/codefumes.rb +10 -8
- data/lib/codefumes/api.rb +20 -11
- data/lib/codefumes/api/build.rb +139 -0
- data/lib/codefumes/api/claim.rb +74 -0
- data/lib/codefumes/api/commit.rb +150 -0
- data/lib/codefumes/api/payload.rb +93 -0
- data/lib/codefumes/api/project.rb +158 -0
- data/lib/codefumes/cli_helpers.rb +54 -0
- data/lib/codefumes/config_file.rb +3 -2
- data/lib/codefumes/errors.rb +21 -0
- data/lib/codefumes/exit_codes.rb +10 -0
- data/lib/codefumes/harvester.rb +113 -0
- data/lib/codefumes/quick_build.rb +43 -0
- data/lib/codefumes/quick_metric.rb +20 -0
- data/lib/codefumes/source_control.rb +137 -0
- data/lib/integrity_notifier/codefumes.haml +11 -0
- data/lib/integrity_notifier/codefumes.rb +62 -0
- data/spec/codefumes/{build_spec.rb → api/build_spec.rb} +14 -24
- data/spec/codefumes/{claim_spec.rb → api/claim_spec.rb} +42 -3
- data/spec/codefumes/{commit_spec.rb → api/commit_spec.rb} +34 -24
- data/spec/codefumes/api/payload_spec.rb +148 -0
- data/spec/codefumes/api/project_spec.rb +286 -0
- data/spec/codefumes/api_spec.rb +38 -15
- data/spec/codefumes/config_file_spec.rb +69 -13
- data/spec/codefumes/harvester_spec.rb +118 -0
- data/spec/codefumes/source_control_spec.rb +199 -0
- data/spec/codefumes_service_helpers.rb +23 -19
- data/spec/fixtures/sample_project_dirs/no_scm/description +4 -0
- data/spec/spec_helper.rb +1 -0
- data/tasks/cucumber.rake +11 -0
- metadata +145 -60
- data/bin/cf_claim_project +0 -9
- data/bin/cf_release_project +0 -10
- data/bin/cf_store_credentials +0 -10
- data/lib/cf_claim_project/cli.rb +0 -95
- data/lib/cf_release_project/cli.rb +0 -76
- data/lib/cf_store_credentials/cli.rb +0 -50
- data/lib/codefumes/build.rb +0 -131
- data/lib/codefumes/claim.rb +0 -57
- data/lib/codefumes/commit.rb +0 -144
- data/lib/codefumes/payload.rb +0 -103
- data/lib/codefumes/project.rb +0 -129
- data/spec/cf_claim_project/cli_spec.rb +0 -17
- data/spec/cf_release_project/cli_spec.rb +0 -41
- data/spec/cf_store_credentials/cli_spec.rb +0 -28
- data/spec/codefumes/payload_spec.rb +0 -155
- data/spec/codefumes/project_spec.rb +0 -274
@@ -0,0 +1,43 @@
|
|
1
|
+
module CodeFumes
|
2
|
+
class QuickBuild
|
3
|
+
# Creates a new build for the CodeFumes project linked
|
4
|
+
# at the specified repository path and associates
|
5
|
+
# it with the current local commit identifier
|
6
|
+
#
|
7
|
+
# Returns +true+ if the request succeeded.
|
8
|
+
#
|
9
|
+
# Returns +false+ if the request failed.
|
10
|
+
def self.start(build_name, options = {})
|
11
|
+
repo = SourceControl.new(options[:repository_path] || './')
|
12
|
+
|
13
|
+
commit_identifier = options[:commit_identifier] || repo.local_commit_identifier
|
14
|
+
public_key = options[:public_key] || repo.public_key
|
15
|
+
private_key = options[:private_key] || repo.private_key
|
16
|
+
started_at = options[:started_at] || Time.now
|
17
|
+
|
18
|
+
project = Project.new(public_key, :private_key => private_key)
|
19
|
+
commit = Commit.new(project, commit_identifier)
|
20
|
+
timestamps = {:started_at => started_at, :ended_at => ""}
|
21
|
+
build = Build.new(commit, build_name, :running, timestamps)
|
22
|
+
build.save
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.finish(build_name, success_or_failure, options = {})
|
26
|
+
repo = SourceControl.new(options[:repository_path] || './')
|
27
|
+
|
28
|
+
commit_identifier = options[:commit_identifier] || repo.local_commit_identifier
|
29
|
+
public_key = options[:public_key] || repo.public_key
|
30
|
+
private_key = options[:private_key] || repo.private_key
|
31
|
+
ended_at = options[:ended_at] || Time.now
|
32
|
+
|
33
|
+
project = Project.new(public_key, :private_key => private_key)
|
34
|
+
commit = Commit.new(project, commit_identifier)
|
35
|
+
|
36
|
+
build = Build.find(commit, build_name)
|
37
|
+
return false if build.nil?
|
38
|
+
build.state = success_or_failure.to_s
|
39
|
+
build.ended_at = ended_at
|
40
|
+
build.save
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module CodeFumes
|
2
|
+
class QuickMetric
|
3
|
+
# Associates a Hash of +custom_attributes+ with the current commit
|
4
|
+
# identifier of the repository located at +repository_path+.
|
5
|
+
#
|
6
|
+
# Returns +true+ if the request succeeded.
|
7
|
+
#
|
8
|
+
# Returns +false+ if the request failed.
|
9
|
+
def self.save(custom_attributes, repository_path = './')
|
10
|
+
repo = SourceControl.new(repository_path)
|
11
|
+
commit = {:identifier => repo.local_commit_identifier,
|
12
|
+
:custom_attributes => custom_attributes
|
13
|
+
}
|
14
|
+
content = {:content => {:commits => [commit]}}
|
15
|
+
project = Project.new(repo.public_key, :private_key => repo.private_key)
|
16
|
+
payload_set = Payload.prepare(project, content)
|
17
|
+
payload_set.reject {|payload| payload.save}.empty?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
module CodeFumes
|
2
|
+
# Defines the contract between CodeFumes and any local source control
|
3
|
+
# management system (SCM).
|
4
|
+
#
|
5
|
+
# *NOTE:* Git is currently the only supported SCM. We look
|
6
|
+
# forward to changing this soon.
|
7
|
+
class SourceControl
|
8
|
+
SUPPORTED_SCMS_AND_DETECTORS = {:git => '.git'} #:nodoc:
|
9
|
+
|
10
|
+
# Sets up a SourceControl object to read content from the repository
|
11
|
+
# located at +path+.
|
12
|
+
def initialize(path)
|
13
|
+
begin
|
14
|
+
@repository = Grit::Repo.new(path)
|
15
|
+
rescue Grit::InvalidGitRepositoryError
|
16
|
+
raise Errors::UnsupportedScmToolError
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns a serialized Hash containing a single +:commits+ key
|
21
|
+
# associated with an Array of serialized commit information, ready
|
22
|
+
# to be sent to the CodeFumes service.
|
23
|
+
def payload_between(from = initial_commit_identifier, to = "HEAD")
|
24
|
+
start_commit = from || initial_commit_identifier
|
25
|
+
end_commit = to || "HEAD"
|
26
|
+
new_commits = commits_between(start_commit, end_commit)
|
27
|
+
new_commits.empty? ? {} : {:commits => new_commits}
|
28
|
+
end
|
29
|
+
alias :payload :payload_between
|
30
|
+
|
31
|
+
# Returns the first commit identifier of a repository's history.
|
32
|
+
def initial_commit_identifier
|
33
|
+
initial_commit.sha
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns an array of 'symbolized' executable names for all
|
37
|
+
# supported SCMs.
|
38
|
+
#
|
39
|
+
# The names are returned as symbols.
|
40
|
+
def self.supported_systems
|
41
|
+
SUPPORTED_SCMS_AND_DETECTORS.keys
|
42
|
+
end
|
43
|
+
|
44
|
+
# Accepts command-line executable name of SCM and returns whether it
|
45
|
+
# is a supported SCM or not. +tool_cli_name+ should be the
|
46
|
+
# name of the executable, not the 'full name' of the application
|
47
|
+
# (ex: 'svn' not 'subversion').
|
48
|
+
#
|
49
|
+
# Returns +true+ if the SCM is supported
|
50
|
+
#
|
51
|
+
# Returns +false+ if the SCM is not supported.
|
52
|
+
def self.supported_system?(tool_cli_name)
|
53
|
+
SUPPORTED_SCMS_AND_DETECTORS.keys.include?(tool_cli_name.to_sym)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Stores the public_key of the project associated with the
|
57
|
+
# underlying local repository. This will not be necessary
|
58
|
+
# with all SCMs.
|
59
|
+
#
|
60
|
+
# For example, in a git repository, this method will store a
|
61
|
+
# +codefumes+ key in the +.git/config+ file. This value can be used
|
62
|
+
# as a lookup key for other tools to use in conjunction with the
|
63
|
+
# CodeFumes config file (see +ConfigFile+) to interact with a
|
64
|
+
# CodeFumes project.
|
65
|
+
def store_public_key(public_key)
|
66
|
+
@repository.config["codefumes.public-key"] = public_key
|
67
|
+
end
|
68
|
+
|
69
|
+
# Removes any association to the CodeFumes service which would have
|
70
|
+
# been added using the +store_public_key+ method.
|
71
|
+
#
|
72
|
+
# This method does not remove anything from the user's global
|
73
|
+
# CodeFumes config file.
|
74
|
+
def unlink_from_codefumes!
|
75
|
+
@repository.git.config({}, "--remove-section", "codefumes")
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns the public key of the project associated with this
|
79
|
+
# repository.
|
80
|
+
def public_key
|
81
|
+
@repository.config["codefumes.public-key"]
|
82
|
+
end
|
83
|
+
|
84
|
+
# Returns the private key of the project assciated with this
|
85
|
+
# repository.
|
86
|
+
def private_key
|
87
|
+
ConfigFile.options_for_project(public_key)[:private_key]
|
88
|
+
end
|
89
|
+
|
90
|
+
# Returns the current commit identifier of the underlying
|
91
|
+
# repository ('HEAD' of the supplied branch in git parlance).
|
92
|
+
def local_commit_identifier(branch_name = "master")
|
93
|
+
raise ArgumentError, "nil branch name supplied" if branch_name.nil?
|
94
|
+
@repository.get_head(branch_name).commit.sha
|
95
|
+
end
|
96
|
+
|
97
|
+
# Returns the full path of the underlying repository.
|
98
|
+
def path
|
99
|
+
@repository.path
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
def initial_commit
|
104
|
+
@repository.log.last
|
105
|
+
end
|
106
|
+
|
107
|
+
# Returns Array of serialized commit data. Each item in the Array
|
108
|
+
# contains attributes of a single commit.
|
109
|
+
def commits_between(from, to, including_from_commit = false)
|
110
|
+
commit_list = @repository.commits_between(from,to)
|
111
|
+
|
112
|
+
if including_from_commit == true || from == initial_commit_identifier
|
113
|
+
commit_list = [initial_commit] + commit_list
|
114
|
+
end
|
115
|
+
|
116
|
+
commit_list.map do |commit|
|
117
|
+
commit_stats = commit.stats
|
118
|
+
{
|
119
|
+
:identifier => commit.sha,
|
120
|
+
:author_name => commit.author.name,
|
121
|
+
:author_email => commit.author.email,
|
122
|
+
:committer_name => commit.committer.name,
|
123
|
+
:committer_email => commit.committer.email,
|
124
|
+
:authored_at => commit.authored_date,
|
125
|
+
:committed_at => commit.committed_date,
|
126
|
+
:message => commit.message,
|
127
|
+
:short_message => commit.short_message,
|
128
|
+
:parent_identifiers => commit.parents.map(&:sha).join(','),
|
129
|
+
:line_additions => commit_stats.additions,
|
130
|
+
:line_deletions => commit_stats.deletions,
|
131
|
+
:line_total => commit_stats.deletions,
|
132
|
+
:affected_file_count => commit_stats.files.count
|
133
|
+
}
|
134
|
+
end.reverse
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
%p.normal
|
2
|
+
%label{ :for => "cf_build_name" } Build name
|
3
|
+
%input.text#cf_build_name{ :name => "notifiers[CodeFumes][build_name]", :type => "text", :value => config["build_name"] }
|
4
|
+
|
5
|
+
%p.normal
|
6
|
+
%label{ :for => "cf_public_key" } Public key
|
7
|
+
%input.text#cf_public_key{ :name => "notifiers[CodeFumes][public_key]", :type => "text", :value => config["public_key"] }
|
8
|
+
|
9
|
+
%p.normal
|
10
|
+
%label{ :for => "cf_private_key" } Private key
|
11
|
+
%input.text#cf_private_key{ :name => "notifiers[CodeFumes][private_key]", :type => "text", :value => config["private_key"] }
|
@@ -0,0 +1,62 @@
|
|
1
|
+
begin
|
2
|
+
require 'codefumes_harvester'
|
3
|
+
rescue LoadError
|
4
|
+
abort "Install codefumes_harvester to use the CodeFumes notifier"
|
5
|
+
end
|
6
|
+
|
7
|
+
module CodeFumesHarvester
|
8
|
+
class IntegrityNotifier
|
9
|
+
class CodeFumes < ::Integrity::Notifier::Base
|
10
|
+
attr_reader :private_key, :public_key
|
11
|
+
|
12
|
+
def self.to_haml
|
13
|
+
@haml ||= File.read(File.dirname(__FILE__) + "/codefumes.haml")
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(build, config={})
|
17
|
+
@public_key = config["public_key"]
|
18
|
+
@private_key = config["private_key"]
|
19
|
+
@build_name = config["build_name"]
|
20
|
+
@repo_path = Integrity::Repository.new(
|
21
|
+
build.id, build.project.uri, build.project.branch, build.commit.identifier
|
22
|
+
).directory
|
23
|
+
super(build, config)
|
24
|
+
end
|
25
|
+
|
26
|
+
def deliver!
|
27
|
+
Integrity.log "Updating build '#{@build_name}' for '#{@public_key}' (state: #{build_state})"
|
28
|
+
qb_options = {:public_key => @public_key,
|
29
|
+
:private_key => @private_key,
|
30
|
+
:ended_at => @build.completed_at,
|
31
|
+
:repository_path => @repo_path}
|
32
|
+
|
33
|
+
CodeFumesHarvester::QuickBuild.finish(@build_name, build_state, qb_options)
|
34
|
+
end
|
35
|
+
|
36
|
+
def deliver_started_notification!
|
37
|
+
Integrity.log "Adding build '#{@build_name}' for '#{@public_key}' (state: #{build_state})"
|
38
|
+
qb_options = {:public_key => @public_key,
|
39
|
+
:private_key => @private_key,
|
40
|
+
:started_at => @build.started_at,
|
41
|
+
:repository_path => @repo_path}
|
42
|
+
|
43
|
+
CodeFumesHarvester::QuickBuild.start(@build_name, qb_options)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
def build_state
|
48
|
+
case @build.status
|
49
|
+
when :success then :successful
|
50
|
+
when :failed then :failed
|
51
|
+
when :building then :running
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
module Integrity
|
59
|
+
class Notifier
|
60
|
+
register CodeFumesHarvester::IntegrityNotifier::CodeFumes
|
61
|
+
end
|
62
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
|
-
require File.dirname(__FILE__) + '
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
2
|
|
3
|
-
describe "Build" do
|
4
|
-
include CodeFumesServiceHelpers::
|
3
|
+
describe "API::Build" do
|
4
|
+
include CodeFumesServiceHelpers::BuildHelpers
|
5
5
|
|
6
6
|
after(:all) do
|
7
7
|
FakeWeb.allow_net_connect = false
|
@@ -11,11 +11,7 @@ describe "Build" do
|
|
11
11
|
before(:each) do
|
12
12
|
setup_fixture_base
|
13
13
|
setup_build_fixtures
|
14
|
-
@
|
15
|
-
:name => @build_name, :commit_identifier => @commit_identifier,
|
16
|
-
:started_at => @started_at, :state => @state}
|
17
|
-
|
18
|
-
@build = Build.new(@build_params)
|
14
|
+
@build = Build.new(@commit, @build_name, @state, {:started_at => @started_at})
|
19
15
|
end
|
20
16
|
|
21
17
|
describe "save" do
|
@@ -23,10 +19,10 @@ describe "Build" do
|
|
23
19
|
@build.stub!(:exists?).and_return(false)
|
24
20
|
register_create_uri(["401", "Unauthorized"], "")
|
25
21
|
|
26
|
-
basic_auth_params = {:username => @
|
22
|
+
basic_auth_params = {:username => @project.public_key, :password => @project.private_key}
|
27
23
|
|
28
24
|
build_query = {:build => {:name => @build_name, :ended_at => nil, :started_at => @started_at, :state => @state}}
|
29
|
-
|
25
|
+
API.should_receive(:post).with("/projects/#{@project.public_key}/commits/#{@commit_identifier}/builds", :query => build_query, :basic_auth => basic_auth_params).and_return(mock("response", :code => 401))
|
30
26
|
@build.save
|
31
27
|
end
|
32
28
|
|
@@ -63,16 +59,13 @@ describe "Build" do
|
|
63
59
|
end
|
64
60
|
|
65
61
|
context "when the build already exists on the server" do
|
66
|
-
before(:each) do
|
67
|
-
register_update_uri(["200", "OK"])
|
68
|
-
@build = Build.new(@build_params.merge(:identifier => @build_identifier))
|
69
|
-
Build.stub!(:find).and_return(@build)
|
70
|
-
end
|
71
|
-
|
72
62
|
it "updates the existing build" do
|
63
|
+
register_update_uri(["200", "OK"])
|
64
|
+
build = Build.new(@commit, @build_name, @state, {:identifier => @build_identifier})
|
65
|
+
Build.stub!(:find).and_return(build)
|
73
66
|
mock_response = mock("Response", :code => 200).as_null_object
|
74
|
-
|
75
|
-
|
67
|
+
build.should_receive(:update).and_return(mock_response)
|
68
|
+
build.save
|
76
69
|
end
|
77
70
|
end
|
78
71
|
end
|
@@ -81,21 +74,18 @@ describe "Build" do
|
|
81
74
|
before(:each) do
|
82
75
|
setup_fixture_base
|
83
76
|
setup_build_fixtures
|
84
|
-
@find_params = {:public_key => @pub_key,
|
85
|
-
:commit_identifier => @commit_identifier,
|
86
|
-
:identifier => @build_identifier}
|
87
77
|
end
|
88
78
|
|
89
79
|
it "returns an instance of Build when found" do
|
90
80
|
register_show_uri(["200", "OK"])
|
91
|
-
returned_object = Build.find(@
|
81
|
+
returned_object = Build.find(@commit, @build_name)
|
92
82
|
returned_object.should be_instance_of(Build)
|
93
83
|
returned_object.state.should_not be_nil
|
94
84
|
end
|
95
85
|
|
96
86
|
it "returns nil when not found" do
|
97
87
|
register_show_uri(["404", "Not found"])
|
98
|
-
Build.find(@
|
88
|
+
Build.find(@commit, @build_name).should be_nil
|
99
89
|
end
|
100
90
|
end
|
101
91
|
|
@@ -103,7 +93,7 @@ describe "Build" do
|
|
103
93
|
before(:each) do
|
104
94
|
setup_fixture_base
|
105
95
|
setup_build_fixtures
|
106
|
-
@build = Build.new(@
|
96
|
+
@build = Build.new(@commit, @build_name, @state)
|
107
97
|
end
|
108
98
|
|
109
99
|
it "returns true when the request returns a status of '200 Ok'" do
|
@@ -1,7 +1,7 @@
|
|
1
|
-
require File.dirname(__FILE__) + '
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
2
|
|
3
|
-
describe Claim do
|
4
|
-
include CodeFumesServiceHelpers::
|
3
|
+
describe "API::Claim" do
|
4
|
+
include CodeFumesServiceHelpers::ClaimHelpers
|
5
5
|
|
6
6
|
after(:all) do
|
7
7
|
FakeWeb.allow_net_connect = false
|
@@ -47,6 +47,32 @@ describe Claim do
|
|
47
47
|
}.should raise_error(ArgumentError)
|
48
48
|
end
|
49
49
|
end
|
50
|
+
|
51
|
+
context "a nil value is passed in for the api_key" do
|
52
|
+
it "should not hit the CodeFumes API" do
|
53
|
+
API.should_not_receive(:put)
|
54
|
+
lambda {Claim.create(@project, nil)}
|
55
|
+
end
|
56
|
+
|
57
|
+
it "raises a NoUserApiKeyError" do
|
58
|
+
lambda {
|
59
|
+
Claim.create(@project, nil)
|
60
|
+
}.should raise_error(Errors::NoUserApiKeyError)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "an empty string is passed in for the api_key" do
|
65
|
+
it "should not hit the CodeFumes API" do
|
66
|
+
API.should_not_receive(:put)
|
67
|
+
lambda {Claim.create(@project, '')}
|
68
|
+
end
|
69
|
+
|
70
|
+
it "raises a NoUserApiKeyError" do
|
71
|
+
lambda {
|
72
|
+
Claim.create(@project, '')
|
73
|
+
}.should raise_error(Errors::NoUserApiKeyError)
|
74
|
+
end
|
75
|
+
end
|
50
76
|
end
|
51
77
|
|
52
78
|
describe "destroy" do
|
@@ -63,5 +89,18 @@ describe Claim do
|
|
63
89
|
Claim.destroy(@project, @api_key).should be_false
|
64
90
|
end
|
65
91
|
end
|
92
|
+
|
93
|
+
context "a nil value is passed in for the api_key" do
|
94
|
+
it "should not hit the CodeFumes API" do
|
95
|
+
API.should_not_receive(:delete)
|
96
|
+
lambda {Claim.destroy(@project, nil)}
|
97
|
+
end
|
98
|
+
|
99
|
+
it "raises a NoUserApiKeyError" do
|
100
|
+
lambda {
|
101
|
+
Claim.destroy(@project, nil)
|
102
|
+
}.should raise_error(Errors::NoUserApiKeyError)
|
103
|
+
end
|
104
|
+
end
|
66
105
|
end
|
67
106
|
end
|
@@ -1,7 +1,7 @@
|
|
1
|
-
require File.dirname(__FILE__) + '
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
2
|
|
3
|
-
describe "Commit" do
|
4
|
-
include CodeFumesServiceHelpers::
|
3
|
+
describe "API::Commit" do
|
4
|
+
include CodeFumesServiceHelpers::CommitHelpers
|
5
5
|
|
6
6
|
before(:all) do
|
7
7
|
FakeWeb.allow_net_connect = false
|
@@ -11,9 +11,7 @@ describe "Commit" do
|
|
11
11
|
@priv_key = 'private_key_value'
|
12
12
|
@anonymous_base_uri = "http://codefumes.com/api/v1/xml"
|
13
13
|
@authenticated_base_uri = "http://#{@pub_key}:#{@priv_key}@codefumes.com/api/v1/xml/projects"
|
14
|
-
@project = Project.new(:
|
15
|
-
:private_key => @priv_key,
|
16
|
-
:name => @project_name)
|
14
|
+
@project = Project.new(@pub_key, :private_key => @priv_key, :name => @project_name)
|
17
15
|
@authd_project_api_uri = "#{@authenticated_base_uri}/projects/#{@pub_key}"
|
18
16
|
@anon_project_api_uri = "#{@anonymous_base_uri}/projects/#{@pub_key}"
|
19
17
|
@basic_auth_params = {:username => @pub_key, :password => @priv_key}
|
@@ -24,11 +22,23 @@ describe "Commit" do
|
|
24
22
|
FakeWeb.clean_registry
|
25
23
|
end
|
26
24
|
|
27
|
-
describe "
|
25
|
+
describe "#id" do
|
26
|
+
it "returns the value of #identifier" do
|
27
|
+
Commit.new(@project, @identifier).id.should == @identifier
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#sha" do
|
32
|
+
it "returns the value of #identifier" do
|
33
|
+
Commit.new(@project, @identifier).sha.should == @identifier
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#find" do
|
28
38
|
context "with a valid commit identifier" do
|
29
39
|
before(:each) do
|
30
40
|
register_find_uri
|
31
|
-
@commit = Commit.find(@identifier)
|
41
|
+
@commit = Commit.find(@project, @identifier)
|
32
42
|
end
|
33
43
|
|
34
44
|
[:identifier,
|
@@ -60,40 +70,40 @@ describe "Commit" do
|
|
60
70
|
end
|
61
71
|
|
62
72
|
it "returns nil" do
|
63
|
-
Commit.find(@identifier).should == nil
|
73
|
+
Commit.find(@project, @identifier).should == nil
|
64
74
|
end
|
65
75
|
end
|
66
76
|
end
|
67
77
|
|
68
|
-
describe "
|
78
|
+
describe "#latest" do
|
69
79
|
context "with valid parameters" do
|
70
80
|
it "returns a commit object for the latest commit" do
|
71
81
|
register_latest_uri
|
72
|
-
Commit.latest(@
|
82
|
+
Commit.latest(@project).identifier.should == @identifier
|
73
83
|
end
|
74
84
|
end
|
75
85
|
|
76
86
|
context "with invalid parameters" do
|
77
87
|
it "returns nil" do
|
78
88
|
register_latest_uri(["404", "Not Found"], "")
|
79
|
-
Commit.latest(@
|
89
|
+
Commit.latest(@project).should == nil
|
80
90
|
end
|
81
91
|
end
|
82
92
|
end
|
83
93
|
|
84
|
-
describe "
|
94
|
+
describe "#latest_identifier" do
|
85
95
|
context "with valid parameters" do
|
86
96
|
context "when the specified project has commits stored" do
|
87
97
|
it "returns the commit identifier of the latest commit" do
|
88
98
|
register_latest_uri
|
89
|
-
Commit.latest_identifier(@
|
99
|
+
Commit.latest_identifier(@project).should == @identifier
|
90
100
|
end
|
91
101
|
end
|
92
102
|
|
93
103
|
context "when the specified project does not have any commits stored" do
|
94
104
|
it "returns nil" do
|
95
105
|
register_latest_uri(["404", "Not Found"], "")
|
96
|
-
Commit.latest_identifier(@
|
106
|
+
Commit.latest_identifier(@project).should == nil
|
97
107
|
end
|
98
108
|
end
|
99
109
|
end
|
@@ -101,23 +111,23 @@ describe "Commit" do
|
|
101
111
|
context "with invalid parameters" do
|
102
112
|
it "returns nil" do
|
103
113
|
register_latest_uri(["404", "Not Found"], "")
|
104
|
-
Commit.latest(@
|
114
|
+
Commit.latest(@project).should == nil
|
105
115
|
end
|
106
116
|
end
|
107
117
|
end
|
108
118
|
|
109
|
-
describe "
|
119
|
+
describe "#all" do
|
110
120
|
context "with valid parameters" do
|
111
121
|
it "returns an array of commits" do
|
112
122
|
register_index_uri
|
113
|
-
Commit.all(@
|
123
|
+
Commit.all(@project).should have(3).items
|
114
124
|
end
|
115
125
|
end
|
116
126
|
|
117
127
|
context "with invalid parameters" do
|
118
128
|
it "returns nil" do
|
119
129
|
register_index_uri(["404", "Not Found"], "")
|
120
|
-
Commit.all(@
|
130
|
+
Commit.all(@project).should == nil
|
121
131
|
end
|
122
132
|
end
|
123
133
|
end
|
@@ -127,17 +137,17 @@ describe "Commit" do
|
|
127
137
|
register_find_uri
|
128
138
|
@email = "jdoe@example.com"
|
129
139
|
@name = "John Doe"
|
130
|
-
@commit = Commit.find(@identifier)
|
140
|
+
@commit = Commit.find(@project, @identifier)
|
131
141
|
end
|
132
142
|
|
133
|
-
describe "author" do
|
143
|
+
describe "#author" do
|
134
144
|
it "returns a concatenated string containing the author's name & email" do
|
135
145
|
@commit.author.should =~ /#{@name}/
|
136
146
|
@commit.author.should =~ /#{@email}/
|
137
147
|
end
|
138
148
|
end
|
139
149
|
|
140
|
-
describe "committer" do
|
150
|
+
describe "#committer" do
|
141
151
|
it "returns a concatenated string containing the author's name & email" do
|
142
152
|
@commit.committer.should =~ /#{@name}/
|
143
153
|
@commit.committer.should =~ /#{@email}/
|
@@ -152,14 +162,14 @@ describe "Commit" do
|
|
152
162
|
end
|
153
163
|
|
154
164
|
it "returns an empty Hash" do
|
155
|
-
Commit.latest(@
|
165
|
+
Commit.latest(@project).custom_attributes.should == {}
|
156
166
|
end
|
157
167
|
end
|
158
168
|
|
159
169
|
context "when the commit has defined custom attributes" do
|
160
170
|
before(:each) do
|
161
171
|
register_latest_uri(["200", "Ok"], fixtures[:commit_with_custom_attrs])
|
162
|
-
@commit = Commit.latest(@
|
172
|
+
@commit = Commit.latest(@project)
|
163
173
|
end
|
164
174
|
|
165
175
|
it "returns a Hash of key-value pairs (attribute_name -> attribute_value)" do
|