codefumes 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/Manifest.txt +24 -0
- data/README.txt +102 -0
- data/Rakefile +31 -0
- data/config/website.yml.sample +2 -0
- data/lib/codefumes.rb +11 -0
- data/lib/codefumes/api.rb +19 -0
- data/lib/codefumes/commit.rb +144 -0
- data/lib/codefumes/config_file.rb +85 -0
- data/lib/codefumes/payload.rb +103 -0
- data/lib/codefumes/project.rb +113 -0
- data/spec/codefumes/api_spec.rb +33 -0
- data/spec/codefumes/commit_spec.rb +270 -0
- data/spec/codefumes/config_file_spec.rb +142 -0
- data/spec/codefumes/payload_spec.rb +161 -0
- data/spec/codefumes/project_spec.rb +274 -0
- data/spec/spec.opts +1 -1
- data/spec/spec_helper.rb +19 -0
- data/tasks/rspec.rake +21 -0
- data/website/index.html +11 -0
- data/website/index.txt +81 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +159 -0
- data/website/template.html.erb +50 -0
- metadata +110 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
README.txt
|
4
|
+
Rakefile
|
5
|
+
config/website.yml.sample
|
6
|
+
lib/codefumes.rb
|
7
|
+
lib/codefumes/api.rb
|
8
|
+
lib/codefumes/commit.rb
|
9
|
+
lib/codefumes/config_file.rb
|
10
|
+
lib/codefumes/payload.rb
|
11
|
+
lib/codefumes/project.rb
|
12
|
+
spec/codefumes/api_spec.rb
|
13
|
+
spec/codefumes/commit_spec.rb
|
14
|
+
spec/codefumes/config_file_spec.rb
|
15
|
+
spec/codefumes/payload_spec.rb
|
16
|
+
spec/codefumes/project_spec.rb
|
17
|
+
spec/spec.opts
|
18
|
+
spec/spec_helper.rb
|
19
|
+
tasks/rspec.rake
|
20
|
+
website/index.html
|
21
|
+
website/index.txt
|
22
|
+
website/javascripts/rounded_corners_lite.inc.js
|
23
|
+
website/stylesheets/screen.css
|
24
|
+
website/template.html.erb
|
data/README.txt
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
= codefumes
|
2
|
+
|
3
|
+
http://www.codefumes.com
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
CodeFumes.com[http://codefumes.com] is a service intended to help people
|
8
|
+
involved with software projects who are interested in tracking, sharing,
|
9
|
+
and reviewing metrics/information about a project in relation to the
|
10
|
+
commits of said project's repository. The site supports a small set of
|
11
|
+
'standard' metrics, but also provides a simple method of supplying
|
12
|
+
and retrieving custom metrics, allowing users to gather any metric they
|
13
|
+
are interested in tracking.
|
14
|
+
|
15
|
+
The 'codefumes' gem is an implementation of the
|
16
|
+
CodeFumes.com[http://codefumes.com] API. The intention of the
|
17
|
+
gem is to simplify integration with CodeFumes.com for developers of
|
18
|
+
other libraries & and applications.
|
19
|
+
|
20
|
+
For an example of another library using the current features of this
|
21
|
+
gem, you can refer to the
|
22
|
+
'codefumes_harvester[http://codefumes.rubyforge.org/codefumes_harvester]' gem.
|
23
|
+
|
24
|
+
== FEATURES/PROBLEMS:
|
25
|
+
|
26
|
+
=== Features
|
27
|
+
* Saving, finding, marshalling, and destroying CodeFumes
|
28
|
+
projects
|
29
|
+
* Associating and retrieving a repository's history of commits for a
|
30
|
+
CodeFumes 'project'
|
31
|
+
* Simple interface for accessing both CodeFumes's 'standard' commit
|
32
|
+
metrics, as well as custom commit attributes; simplifying
|
33
|
+
integration with other tools & libraries users may be interested in
|
34
|
+
using.
|
35
|
+
* Interfaces with the CodeFumes config file (used to track projects a
|
36
|
+
user has created on the site)
|
37
|
+
|
38
|
+
=== Problems / Things to Note
|
39
|
+
|
40
|
+
* CodeFumes 'projects' are repository-specific, not branch-specific.
|
41
|
+
|
42
|
+
== SYNOPSIS:
|
43
|
+
|
44
|
+
require 'codefumes'
|
45
|
+
|
46
|
+
# Creating & finding a CodeFumes project
|
47
|
+
p = Project.save # optionally providing a custom public key: :public_key => 'Abc3'
|
48
|
+
found_p = Project.find(p.public_key)
|
49
|
+
p.pulic_key # => 'Abc3'
|
50
|
+
p.api_uri # => 'http://codefumes.com/api/v1/xml/Abc3'
|
51
|
+
|
52
|
+
# Commits
|
53
|
+
c = Commit.find(<commit identifier>)
|
54
|
+
c.identifier # => git commit SHA (svn support coming soon)
|
55
|
+
c.short_message # => commit message
|
56
|
+
|
57
|
+
# Custom attributes associated with a commit
|
58
|
+
c.custom_attributes[:coverage] # => "80"
|
59
|
+
|
60
|
+
|
61
|
+
# Payloads, used to break up large HTTP requests
|
62
|
+
content = Payload.prepare(payload_content)
|
63
|
+
content.each {|chunk| chunk.save}
|
64
|
+
|
65
|
+
== REQUIREMENTS:
|
66
|
+
|
67
|
+
* httparty (0.4.3)
|
68
|
+
|
69
|
+
== INSTALL:
|
70
|
+
|
71
|
+
From RubyForge:
|
72
|
+
|
73
|
+
sudo gem install codefumes
|
74
|
+
|
75
|
+
Or, from Github:
|
76
|
+
|
77
|
+
sudo gem install cosyn-codefumes
|
78
|
+
|
79
|
+
== LICENSE:
|
80
|
+
|
81
|
+
(The MIT License)
|
82
|
+
|
83
|
+
Copyright (c) 2009 Cosyn Technologies, Inc.
|
84
|
+
|
85
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
86
|
+
a copy of this software and associated documentation files (the
|
87
|
+
'Software'), to deal in the Software without restriction, including
|
88
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
89
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
90
|
+
permit persons to whom the Software is furnished to do so, subject to
|
91
|
+
the following conditions:
|
92
|
+
|
93
|
+
The above copyright notice and this permission notice shall be
|
94
|
+
included in all copies or substantial portions of the Software.
|
95
|
+
|
96
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
97
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
98
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
99
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
100
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
101
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
102
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
%w[hoe rake rake/clean fileutils rubigen hoe].each { |f| require f }
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/lib/codefumes'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require "hanna/rdoctask"
|
7
|
+
rescue LoadError
|
8
|
+
require 'rake/rdoctask'
|
9
|
+
end
|
10
|
+
|
11
|
+
# Load in the harvester ane metric_fu gems if available so we can collect metrics
|
12
|
+
begin
|
13
|
+
require "metric_fu"
|
14
|
+
require "codefumes_harvester"
|
15
|
+
rescue LoadError
|
16
|
+
end
|
17
|
+
|
18
|
+
$hoe = Hoe.spec('codefumes') do |p|
|
19
|
+
p.developer('Cosyn Technologies', 'devs@codefumes.com')
|
20
|
+
p.summary = "API gem for the CodeFumes website"
|
21
|
+
p.extra_deps = [
|
22
|
+
['httparty','>= 0.4.3']
|
23
|
+
]
|
24
|
+
p.extra_dev_deps = [
|
25
|
+
['jscruggs-metric_fu', ">= 1.1.5"],
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
Dir['tasks/**/*.rake'].each { |t| load t}
|
30
|
+
|
31
|
+
task :default => [:spec]
|
data/lib/codefumes.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module CodeFumes
|
2
|
+
class API
|
3
|
+
include HTTParty
|
4
|
+
|
5
|
+
format :xml
|
6
|
+
|
7
|
+
BASE_URIS = {
|
8
|
+
:production => 'http://www.codefumes.com/api/v1/xml',
|
9
|
+
:test => 'http://test.codefumes.com/api/v1/xml'
|
10
|
+
}
|
11
|
+
|
12
|
+
def self.mode(mode)
|
13
|
+
base_uri(BASE_URIS[mode]) if BASE_URIS[mode]
|
14
|
+
end
|
15
|
+
|
16
|
+
mode(:production)
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
module CodeFumes
|
2
|
+
# Similar to a revision control system, a Commit encompasses a set of
|
3
|
+
# changes to a codebase, who made them, when said changes were applied
|
4
|
+
# to the previous revision of codebase, et cetera.
|
5
|
+
#
|
6
|
+
# A Commit has a concept of 'standard attributes' which will always be
|
7
|
+
# present in a response from CodeFumes.com[http://codefumes.com], such
|
8
|
+
# as the +identifier+, +author+, and +commit_message+ (see the list of
|
9
|
+
# attributes for a comprehensive listing). In addition to this, users
|
10
|
+
# are able to associate 'custom attributes' to a Commit, allowing
|
11
|
+
# users to link any number of attributes with a commit identifier and
|
12
|
+
# easily retrieve them later.
|
13
|
+
#
|
14
|
+
# One thing to note about Commit objects is that they are read-only.
|
15
|
+
# To associate metrics with a Commit object, a Payload object should
|
16
|
+
# be created and saved. Refer to the Payload documentation for more
|
17
|
+
# information.
|
18
|
+
class Commit < CodeFumes::API
|
19
|
+
attr_reader :identifier, :author_name, :author_email, :committer_name,
|
20
|
+
:committer_email, :short_message, :message,:committed_at,
|
21
|
+
:authored_at, :uploaded_at, :api_uri, :parent_identifiers,
|
22
|
+
:line_additions, :line_deletions, :line_total,
|
23
|
+
:affected_file_count, :custom_attributes
|
24
|
+
|
25
|
+
# Instantiates a new Commit object
|
26
|
+
#
|
27
|
+
# Accepts a Hash of options, including:
|
28
|
+
# * identifier
|
29
|
+
# * author_email
|
30
|
+
# * author_name
|
31
|
+
# * committer_email
|
32
|
+
# * committer_name
|
33
|
+
# * short_message
|
34
|
+
# * message
|
35
|
+
# * committed_at
|
36
|
+
# * authored_at
|
37
|
+
# * uploaded_at
|
38
|
+
# * api_uri
|
39
|
+
# * parent_identifiers
|
40
|
+
# * line_additions
|
41
|
+
# * line_deletions
|
42
|
+
# * line_total
|
43
|
+
# * affected_file_count
|
44
|
+
# * custom_attributes
|
45
|
+
#
|
46
|
+
# +custom_attributes+ should be a Hash of attribute_name/value
|
47
|
+
# pairs associated with the commit. All other attributes are
|
48
|
+
# expected to be String values, other than +committed_at+ and
|
49
|
+
# +authored_at+, which are expected to be DateTime objects.
|
50
|
+
# Technically speaking, you could pass anything you wanted into
|
51
|
+
# the fields, but when using with the CodeFumes API, the attribute
|
52
|
+
# values will be of the type String, DateTime, or Hash.
|
53
|
+
def initialize(options)
|
54
|
+
@identifier = options["identifier"]
|
55
|
+
@author_email = options["author_email"]
|
56
|
+
@author_name = options["author_name"]
|
57
|
+
@committer_email = options["committer_email"]
|
58
|
+
@committer_name = options["committer_name"]
|
59
|
+
@short_message = options["short_message"]
|
60
|
+
@message = options["message"]
|
61
|
+
@committed_at = options["committed_at"]
|
62
|
+
@authored_at = options["authored_at"]
|
63
|
+
@uploaded_at = options["uploaded_at"]
|
64
|
+
@api_uri = options["api_uri"]
|
65
|
+
@parent_identifiers = options["parent_identifiers"]
|
66
|
+
@line_additions = options["line_additions"]
|
67
|
+
@line_deletions = options["line_deletions"]
|
68
|
+
@line_total = options["line_total"]
|
69
|
+
@affected_file_count = options["affected_file_count"]
|
70
|
+
@custom_attributes = options["custom_attributes"] || {}
|
71
|
+
convert_custom_attributes_keys_to_symbols
|
72
|
+
end
|
73
|
+
|
74
|
+
# Returns the name of the author and the email associated
|
75
|
+
# with the commit in a string formatted as:
|
76
|
+
# "Name [email_address]"
|
77
|
+
# (ie: "John Doe [jdoe@example.com]")
|
78
|
+
def author
|
79
|
+
"#{author_name} [#{author_email}]"
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns the name of the committer and the email associated
|
83
|
+
# with the commit in a string formatted as:
|
84
|
+
# "Name [email_address]"
|
85
|
+
# (ie: "John Doe [jdoe@example.com]")
|
86
|
+
def committer
|
87
|
+
"#{committer_name} [#{committer_email}]"
|
88
|
+
end
|
89
|
+
|
90
|
+
# Returns the Commit object associated with the supplied identifier.
|
91
|
+
# Returns nil if the identifier is not found.
|
92
|
+
def self.find(identifier)
|
93
|
+
response = get("/commits/#{identifier}")
|
94
|
+
case response.code
|
95
|
+
when 200
|
96
|
+
return nil if response["commit"].empty?
|
97
|
+
new(response["commit"])
|
98
|
+
else
|
99
|
+
nil
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Returns a collection of commits associated with the specified
|
104
|
+
# Project public key.
|
105
|
+
def self.all(project_public_key)
|
106
|
+
response = get("/projects/#{project_public_key}/commits")
|
107
|
+
case response.code
|
108
|
+
when 200
|
109
|
+
return [] if response["commits"].empty? || response["commits"]["commit"].nil?
|
110
|
+
response["commits"]["commit"].map do |commit_data|
|
111
|
+
new(commit_data)
|
112
|
+
end
|
113
|
+
else
|
114
|
+
nil
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Returns the most recent commit associated with the specified
|
119
|
+
# Project public key.
|
120
|
+
def self.latest(project_public_key)
|
121
|
+
response = get("/projects/#{project_public_key}/commits/latest")
|
122
|
+
case response.code
|
123
|
+
when 200
|
124
|
+
new(response["commit"])
|
125
|
+
else
|
126
|
+
nil
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Returns the commit identifier of the most recent commit of with
|
131
|
+
# the specified Project public key.
|
132
|
+
def self.latest_identifier(project_public_key)
|
133
|
+
latest_commit = latest(project_public_key)
|
134
|
+
latest_commit.nil? ? nil : latest_commit.identifier
|
135
|
+
end
|
136
|
+
|
137
|
+
private
|
138
|
+
def convert_custom_attributes_keys_to_symbols
|
139
|
+
@custom_attributes = @custom_attributes.inject({}) do |results, key_and_value|
|
140
|
+
results.merge! key_and_value.first.to_sym => key_and_value.last
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module CodeFumes
|
2
|
+
# CodeFumes uses a global (per-user) config file to store relevant
|
3
|
+
# information around a user's use of the service. Doing so addresses
|
4
|
+
# the following goals:
|
5
|
+
# * A defined location for all tools to utilize which contains URI's
|
6
|
+
# and and keys for all projects a user has set up on
|
7
|
+
# CodeFumes.com[http://codefumes.com], simplifying integration.
|
8
|
+
# * Associating (or disassociating) a project to (or from) a CodeFumes
|
9
|
+
# project does not require any modifications to said project's
|
10
|
+
# repository.
|
11
|
+
# * Simplified the implementation of 'user-less' projects on the
|
12
|
+
# website.
|
13
|
+
#
|
14
|
+
# This class wraps up reading and writing this config file so other
|
15
|
+
# developers should not have to concern themselves with how to
|
16
|
+
# serialize & write the data of a project into the appropriate format,
|
17
|
+
# output file, et cetera.
|
18
|
+
class ConfigFile
|
19
|
+
DEFAULT_FILE_STRUCTURE = {}
|
20
|
+
DEFAULT_PATH = File.expand_path('~/.codefumes_config')
|
21
|
+
|
22
|
+
class << self
|
23
|
+
# Returns the path to the CodeFumes global (per-user) config file.
|
24
|
+
# The default path is '~/.codefumes_config'.
|
25
|
+
def path
|
26
|
+
@path || ENV['CODEFUMES_CONFIG_FILE'] || DEFAULT_PATH.dup
|
27
|
+
end
|
28
|
+
|
29
|
+
# Sets the path which should be used for storing the configuration
|
30
|
+
# CodeFumes.com data.
|
31
|
+
def path=(custom_path)
|
32
|
+
@path = custom_path.nil? ? path : File.expand_path(custom_path)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Store the supplied project into the CodeFumes config file.
|
36
|
+
def save_project(project)
|
37
|
+
config = serialized
|
38
|
+
if config[:projects]
|
39
|
+
config[:projects].merge!(project.to_config)
|
40
|
+
else
|
41
|
+
config[:projects] = project.to_config
|
42
|
+
end
|
43
|
+
write(config)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Remove the supplied project from the CodeFumes config file.
|
47
|
+
def delete_project(project)
|
48
|
+
config = serialized
|
49
|
+
config[:projects] && config[:projects].delete(project.public_key.to_sym)
|
50
|
+
write(config)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns a Hash representation of the CodeFumes config file
|
54
|
+
def serialized
|
55
|
+
empty? ? DEFAULT_FILE_STRUCTURE.dup : loaded
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns a Hash representation of a specific project contained in
|
59
|
+
# the CodeFumes config file.
|
60
|
+
def options_for_project(public_key)
|
61
|
+
config = serialized
|
62
|
+
public_key && config[:projects] && config[:projects][public_key.to_sym] || {}
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
def write(serializable_object)
|
67
|
+
File.open(path, 'w') do |f|
|
68
|
+
f.puts YAML::dump(serializable_object)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def exists?
|
73
|
+
File.exists?(path)
|
74
|
+
end
|
75
|
+
|
76
|
+
def empty?
|
77
|
+
!(exists? && loaded)
|
78
|
+
end
|
79
|
+
|
80
|
+
def loaded
|
81
|
+
YAML::load_file(path)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module CodeFumes
|
2
|
+
# Payloads are intended to simplify sending up large amounts of
|
3
|
+
# content at one time. For example, when sending up the entire
|
4
|
+
# history of a repository, making a POST request for each commit would
|
5
|
+
# require a very large number of requests. Using a Payload object
|
6
|
+
# allows larger amounts of content to be saved at one time,
|
7
|
+
# significantly reducing the number of requests made.
|
8
|
+
class Payload < CodeFumes::API
|
9
|
+
PAYLOAD_CHARACTER_LIMIT = 4000 #:nodoc:
|
10
|
+
|
11
|
+
attr_reader :project_public_key, :project_private_key, :created_at
|
12
|
+
|
13
|
+
# Accepts +:public_key+, +:private_key+, and :content keys.
|
14
|
+
# +:content+ should also contain a key named +:commits+, with a list
|
15
|
+
# of commits and associated data. An example would be:
|
16
|
+
#
|
17
|
+
# {:public_key => "abC3", :private_key => "some-private-key",
|
18
|
+
# :content => {:commits => [{:identifier => "commit_identifer",
|
19
|
+
# :files_affected => 3, :any_metric_you_want => "value"}]}}
|
20
|
+
def initialize(options = {})
|
21
|
+
@project_public_key = options[:public_key]
|
22
|
+
@project_private_key = options[:private_key]
|
23
|
+
@content = options[:content]
|
24
|
+
end
|
25
|
+
|
26
|
+
# Saves instance to CodeFumes.com. After a successful save, the
|
27
|
+
# +created_at+ attribute will be populated with the timestamp the
|
28
|
+
# Payload was created.
|
29
|
+
#
|
30
|
+
# Returns +true+ if the Payload does not contain any content to be
|
31
|
+
# saved or the request was successful.
|
32
|
+
#
|
33
|
+
# Returns +false+ if the request failed.
|
34
|
+
def save
|
35
|
+
return true if empty_payload?
|
36
|
+
response = self.class.post("/projects/#{@project_public_key}/payloads", :query => {:payload => @content}, :basic_auth => {:username => @project_public_key, :password => @project_private_key})
|
37
|
+
|
38
|
+
case response.code
|
39
|
+
when 201
|
40
|
+
@created_at = response['payload']['created_at']
|
41
|
+
true
|
42
|
+
else
|
43
|
+
false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# +save+ requests are made with a standard POST request (not a
|
48
|
+
# multi-part POST), so the request size is limited by the
|
49
|
+
# application server. The current configuration on CodeFumes.com
|
50
|
+
# limits requests to approximately 8,000 bytes (a little over). In
|
51
|
+
# order to simplify dealing with these constraints, without
|
52
|
+
# requiring a multi-part POST request, +prepare+ can be used to
|
53
|
+
# "chunk" up the data into Payloads which do not exceed this limit.
|
54
|
+
#
|
55
|
+
# Returns collection of payload objects which fall into the
|
56
|
+
# constraints of a individual payload (ie: length of raw request,
|
57
|
+
# et cetera).
|
58
|
+
#--
|
59
|
+
# TODO: Clean up how the size of the request is constrained, this
|
60
|
+
# is pretty hackish right now (basically guesses how many
|
61
|
+
# characters would be added when HTTParty wraps the content in XML.
|
62
|
+
def self.prepare(data = {})
|
63
|
+
return [] if data.nil? || data.empty?
|
64
|
+
raw_payload = data.dup
|
65
|
+
|
66
|
+
public_key = raw_payload.delete(:public_key)
|
67
|
+
raise ArgumentError, "No public key provided" if public_key.nil?
|
68
|
+
|
69
|
+
private_key = raw_payload.delete(:private_key)
|
70
|
+
|
71
|
+
if raw_payload[:content].nil? || raw_payload[:content][:commits].nil?
|
72
|
+
raise ArgumentError, "No commits key provided"
|
73
|
+
end
|
74
|
+
|
75
|
+
content = raw_payload[:content][:commits]
|
76
|
+
initial_chunks = {:on_deck => [], :prepared => []}
|
77
|
+
|
78
|
+
# TODO: Clean this up
|
79
|
+
chunked = content.inject(initial_chunks) do |chunks, new_commit|
|
80
|
+
if chunks[:on_deck].to_s.length + new_commit.to_s.length >= PAYLOAD_CHARACTER_LIMIT
|
81
|
+
chunks[:prepared] << chunks[:on_deck]
|
82
|
+
chunks[:on_deck] = [new_commit]
|
83
|
+
elsif new_commit == content.last
|
84
|
+
chunks[:on_deck] << new_commit
|
85
|
+
chunks[:prepared] << chunks[:on_deck]
|
86
|
+
chunks[:on_deck] = []
|
87
|
+
else
|
88
|
+
chunks[:on_deck] << new_commit
|
89
|
+
end
|
90
|
+
chunks
|
91
|
+
end
|
92
|
+
|
93
|
+
chunked[:prepared].map do |raw_content|
|
94
|
+
Payload.new(:public_key => public_key, :private_key => private_key, :content => {:commits => raw_content})
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
def empty_payload?
|
100
|
+
@content.empty? || @content[:commits].nil? || @content[:commits].blank?
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|