codefumes 0.1.2 → 0.1.3

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/History.txt CHANGED
@@ -1,4 +1,15 @@
1
+ == 0.1.3 2009-09-22
2
+
3
+ * Added ConfigFile#save_credentials
4
+ * Added ConfigFile#credentials
5
+ * Added store_codefumes_credentials executable
6
+ * Added support for claiming projects (Project#claim, Claim#create)
7
+ * Added cf_claim_project executable
8
+ * Added :local mode for API
9
+ * Removed (almost) all "require 'rubygems'" statements
10
+
1
11
  == 0.1.2 2009-09-10
12
+
2
13
  * Documentation updated
3
14
  * Fixed dependency definitions in Rakefile
4
15
 
data/Manifest.txt CHANGED
@@ -2,23 +2,28 @@ History.txt
2
2
  Manifest.txt
3
3
  README.txt
4
4
  Rakefile
5
- config/website.yml.sample
5
+ bin/cf_claim_project
6
+ bin/store_codefumes_credentials
7
+ lib/cf_claim_project/cli.rb
6
8
  lib/codefumes.rb
7
9
  lib/codefumes/api.rb
10
+ lib/codefumes/claim.rb
8
11
  lib/codefumes/commit.rb
9
12
  lib/codefumes/config_file.rb
10
13
  lib/codefumes/payload.rb
11
14
  lib/codefumes/project.rb
15
+ lib/store_codefumes_credentials/cli.rb
16
+ spec/cf_claim_project/cli_spec.rb
12
17
  spec/codefumes/api_spec.rb
18
+ spec/codefumes/claim_spec.rb
13
19
  spec/codefumes/commit_spec.rb
14
20
  spec/codefumes/config_file_spec.rb
15
21
  spec/codefumes/payload_spec.rb
16
22
  spec/codefumes/project_spec.rb
23
+ spec/codefumes_service_stubs.rb
17
24
  spec/spec.opts
18
25
  spec/spec_helper.rb
26
+ spec/store_codefumes_credentials/cli_spec.rb
19
27
  tasks/rspec.rake
20
28
  website/index.html
21
- website/index.txt
22
- website/javascripts/rounded_corners_lite.inc.js
23
29
  website/stylesheets/screen.css
24
- website/template.html.erb
data/README.txt CHANGED
@@ -1,6 +1,10 @@
1
1
  = codefumes
2
2
 
3
- http://www.codefumes.com
3
+ * http://codefumes.rubyforge.org/codefumes
4
+ * Wiki: https://github.com/cosyn/codefumes/wikis
5
+ * Repository: https://github.com/cosyn/codefumes
6
+ * Official CodeFumes.com gems: http://codefumes.rubyforge.org/
7
+ * Website: http://www.codefumes.com
4
8
 
5
9
  == DESCRIPTION:
6
10
 
@@ -46,8 +50,8 @@ gem, you can refer to the
46
50
  # Creating & finding a CodeFumes project
47
51
  p = Project.save # optionally providing a custom public key: :public_key => 'Abc3'
48
52
  found_p = Project.find(p.public_key)
49
- p.pulic_key # => 'Abc3'
50
- p.api_uri # => 'http://codefumes.com/api/v1/xml/Abc3'
53
+ p.public_key # => 'Abc3'
54
+ p.api_uri # => 'http://codefumes.com/api/v1/xml/Abc3'
51
55
 
52
56
  # Commits
53
57
  c = Commit.find(<commit identifier>)
data/Rakefile CHANGED
@@ -1,6 +1,7 @@
1
1
  %w[hoe rake rake/clean fileutils rubigen hoe].each { |f| require f }
2
2
 
3
- require File.dirname(__FILE__) + '/lib/codefumes'
3
+ $LOAD_PATH.unshift('lib') unless $LOAD_PATH.include?('lib')
4
+ require 'lib/codefumes'
4
5
 
5
6
  begin
6
7
  require "hanna/rdoctask"
@@ -15,9 +16,14 @@ begin
15
16
  rescue LoadError
16
17
  end
17
18
 
19
+ Hoe.plugin :website
20
+
18
21
  $hoe = Hoe.spec('codefumes') do
19
22
  self.summary = "A client-side implementation of the CodeFumes.com API."
20
- self.extra_dev_deps = [['jscruggs-metric_fu', ">= 1.1.5"]]
23
+ self.extra_dev_deps = [['jscruggs-metric_fu', ">= 1.1.5"],
24
+ ['rubigen', ">= 1.5.2"],
25
+ ['fakeweb', ">= 1.2.0"]
26
+ ]
21
27
  self.extra_deps = [['httparty','>= 0.4.3']]
22
28
  developer('Tom Kersten', 'tom.kersten@cosyntech.com')
23
29
  developer('Joe Banks', 'freemarmoset@gmail.com')
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Created on 2009-9-21.
4
+ # Copyright (c) 2009. All rights reserved.
5
+
6
+ require 'lib/codefumes'
7
+ require "lib/cf_claim_project/cli"
8
+
9
+ CfClaimProject::CLI.execute(STDOUT, ARGV)
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Created on 2009-9-18.
4
+ # Copyright (c) 2009. All rights reserved.
5
+
6
+ require 'rubygems'
7
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/codefumes")
8
+ require "lib/store_codefumes_credentials/cli"
9
+
10
+ StoreCodefumesCredentials::CLI.execute(STDOUT, ARGV)
@@ -0,0 +1,81 @@
1
+ require 'optparse'
2
+ require 'codefumes/config_file'
3
+ include CodeFumes
4
+
5
+ module CfClaimProject
6
+ class CLI
7
+ @attempt_to_claim_all = false
8
+
9
+ def self.execute(stdout, arguments=[])
10
+ @stdout = stdout
11
+ parse_cli_arguments!(arguments)
12
+ retrieve_users_credentials_or_exit
13
+
14
+
15
+ @public_keys.each do |public_key|
16
+ project = Project.find(public_key)
17
+
18
+ if project.nil?
19
+ @stdout.puts "Claiming...'#{public_key}': Not found"
20
+ next
21
+ end
22
+
23
+ @stdout.print "Claiming...'#{public_key}': "
24
+ @stdout.puts Claim.create(project, @users_api_key) ? 'Success!' : 'Denied.'
25
+ end
26
+
27
+ @stdout.puts ""
28
+ @stdout.puts "Done!"
29
+ end
30
+
31
+ private
32
+ def self.parse_cli_arguments!(arguments)
33
+ OptionParser.new do |opts|
34
+ opts.banner = <<-BANNER.gsub(/^ /,'')
35
+ This application is wonderful because...
36
+
37
+ Usage: #{File.basename($0)} [options]
38
+
39
+ Options are:
40
+ BANNER
41
+ opts.separator ""
42
+ opts.on("-a", "--all", String,
43
+ "Attempt to claim all projects in your CodeFumes config file"
44
+ ) {@attempt_to_claim_all = true}
45
+ opts.on("-h", "--help",
46
+ "Show this help message.") { @stdout.puts opts; exit(1) }
47
+ opts.parse!(arguments)
48
+ end
49
+
50
+ @public_keys = claim_all_projects_flag_set? ? ConfigFile.public_keys : [ARGV[0]].compact
51
+ if @public_keys.empty?
52
+ print_missing_arguments_message
53
+ exit
54
+ end
55
+
56
+ end
57
+
58
+ def self.claim_all_projects_flag_set?
59
+ @attempt_to_claim_all == true
60
+ end
61
+
62
+ def self.print_missing_arguments_message
63
+ @stdout.puts "You must specify either a public key of a project, or -a/--all to"
64
+ @stdout.puts "claim all projects in your CodeFumes config file"
65
+ @stdout.puts ""
66
+ @stdout.puts "Exiting."
67
+ end
68
+
69
+ def self.retrieve_users_credentials_or_exit
70
+ @users_api_key = ConfigFile.credentials[:api_key]
71
+ return @users_api_key unless @users_api_key.nil?
72
+ @stdout.puts "No API key saved in your CodeFumes config file!"
73
+ @stdout.puts ""
74
+ @stdout.puts "Grab your API key from CodeFumes.com and run 'store_codefumes_credentials [api_key]."
75
+ @stdout.puts "Then try again."
76
+ @stdout.puts ""
77
+ @stdout.puts "Exiting."
78
+ exit
79
+ end
80
+ end
81
+ end
data/lib/codefumes/api.rb CHANGED
@@ -1,19 +1,20 @@
1
1
  module CodeFumes
2
2
  class API
3
3
  include HTTParty
4
-
4
+
5
5
  format :xml
6
-
6
+
7
7
  BASE_URIS = {
8
8
  :production => 'http://www.codefumes.com/api/v1/xml',
9
- :test => 'http://test.codefumes.com/api/v1/xml'
9
+ :test => 'http://test.codefumes.com/api/v1/xml',
10
+ :local => 'http://localhost:3000/api/v1/xml'
10
11
  }
11
-
12
+
12
13
  def self.mode(mode)
13
14
  base_uri(BASE_URIS[mode]) if BASE_URIS[mode]
14
15
  end
15
-
16
+
16
17
  mode(:production)
17
18
 
18
19
  end
19
- end
20
+ end
@@ -0,0 +1,24 @@
1
+ module CodeFumes
2
+ class Claim < CodeFumes::API
3
+ attr_accessor :created_at
4
+
5
+ # Attempts to claim the specified Project instance using the
6
+ # supplied API key.
7
+ #
8
+ # Similar to Project#claim, but more explicit.
9
+ #
10
+ # Returns true if the request is successful.
11
+ #
12
+ # Returns +false+ in all other cases.
13
+ def self.create(project, api_key)
14
+ auth_args = {:username => project.public_key, :password => project.private_key}
15
+
16
+ uri = "/projects/#{project.public_key}/claim"
17
+ response = post(uri, :query => {:api_key => api_key}, :basic_auth => auth_args)
18
+ case response.code
19
+ when 201 : true
20
+ else false
21
+ end
22
+ end
23
+ end
24
+ end
@@ -92,11 +92,11 @@ module CodeFumes
92
92
  def self.find(identifier)
93
93
  response = get("/commits/#{identifier}")
94
94
  case response.code
95
- when 200
96
- return nil if response["commit"].empty?
97
- new(response["commit"])
98
- else
99
- nil
95
+ when 200
96
+ return nil if response["commit"].empty?
97
+ new(response["commit"])
98
+ else
99
+ nil
100
100
  end
101
101
  end
102
102
 
@@ -105,13 +105,13 @@ module CodeFumes
105
105
  def self.all(project_public_key)
106
106
  response = get("/projects/#{project_public_key}/commits")
107
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
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
115
  end
116
116
  end
117
117
 
@@ -120,10 +120,10 @@ module CodeFumes
120
120
  def self.latest(project_public_key)
121
121
  response = get("/projects/#{project_public_key}/commits/latest")
122
122
  case response.code
123
- when 200
124
- new(response["commit"])
125
- else
126
- nil
123
+ when 200
124
+ new(response["commit"])
125
+ else
126
+ nil
127
127
  end
128
128
  end
129
129
 
@@ -34,20 +34,30 @@ module CodeFumes
34
34
 
35
35
  # Store the supplied project into the CodeFumes config file.
36
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
37
+ update_config_file do |config|
38
+ if config[:projects]
39
+ config[:projects].merge!(project.to_config)
40
+ else
41
+ config[:projects] = project.to_config
42
+ end
42
43
  end
43
- write(config)
44
44
  end
45
45
 
46
46
  # Remove the supplied project from the CodeFumes config file.
47
47
  def delete_project(project)
48
- config = serialized
49
- config[:projects] && config[:projects].delete(project.public_key.to_sym)
50
- write(config)
48
+ update_config_file do |config|
49
+ config[:projects] && config[:projects].delete(project.public_key.to_sym)
50
+ end
51
+ end
52
+
53
+ def save_credentials(api_key)
54
+ update_config_file do |config|
55
+ config.merge!(:credentials => {:api_key => api_key})
56
+ end
57
+ end
58
+
59
+ def credentials
60
+ serialized[:credentials] || {}
51
61
  end
52
62
 
53
63
  # Returns a Hash representation of the CodeFumes config file
@@ -62,6 +72,11 @@ module CodeFumes
62
72
  public_key && config[:projects] && config[:projects][public_key.to_sym] || {}
63
73
  end
64
74
 
75
+ def public_keys
76
+ serialized_projects = serialized[:projects]
77
+ serialized_projects.nil? ? [] : serialized_projects.keys
78
+ end
79
+
65
80
  private
66
81
  def write(serializable_object)
67
82
  File.open(path, 'w') do |f|
@@ -80,6 +95,12 @@ module CodeFumes
80
95
  def loaded
81
96
  YAML::load_file(path)
82
97
  end
98
+
99
+ def update_config_file(&block)
100
+ config = serialized
101
+ yield config
102
+ write(config)
103
+ end
83
104
  end
84
105
  end
85
106
  end
@@ -16,7 +16,7 @@ module CodeFumes
16
16
  #
17
17
  # {:public_key => "abC3", :private_key => "some-private-key",
18
18
  # :content => {:commits => [{:identifier => "commit_identifer",
19
- # :files_affected => 3, :any_metric_you_want => "value"}]}}
19
+ # :files_affected => 3, :custom_attributes => {:any_metric_you_want => "value"}}]}}
20
20
  def initialize(options = {})
21
21
  @project_public_key = options[:public_key]
22
22
  @project_private_key = options[:private_key]
@@ -36,11 +36,11 @@ module CodeFumes
36
36
  response = self.class.post("/projects/#{@project_public_key}/payloads", :query => {:payload => @content}, :basic_auth => {:username => @project_public_key, :password => @project_private_key})
37
37
 
38
38
  case response.code
39
- when 201
40
- @created_at = response['payload']['created_at']
41
- true
42
- else
43
- false
39
+ when 201
40
+ @created_at = response['payload']['created_at']
41
+ true
42
+ else
43
+ false
44
44
  end
45
45
  end
46
46
 
@@ -65,7 +65,7 @@ module CodeFumes
65
65
 
66
66
  public_key = raw_payload.delete(:public_key)
67
67
  raise ArgumentError, "No public key provided" if public_key.nil?
68
-
68
+
69
69
  private_key = raw_payload.delete(:private_key)
70
70
 
71
71
  if raw_payload[:content].nil? || raw_payload[:content][:commits].nil?
@@ -25,10 +25,10 @@ module CodeFumes
25
25
  def delete
26
26
  response = destroy!
27
27
  case response.code
28
- when 200
29
- return true
30
- else
31
- return false
28
+ when 200
29
+ return true
30
+ else
31
+ return false
32
32
  end
33
33
  end
34
34
 
@@ -43,11 +43,11 @@ module CodeFumes
43
43
  def save
44
44
  response = exists? ? update : create
45
45
  case response.code
46
- when 201, 200
47
- reinitialize!(response)
48
- true
49
- else
50
- false
46
+ when 201, 200
47
+ reinitialize!(response)
48
+ true
49
+ else
50
+ false
51
51
  end
52
52
  end
53
53
 
@@ -79,11 +79,11 @@ module CodeFumes
79
79
  def self.find(public_key)
80
80
  response = get("/projects/#{public_key}")
81
81
  case response.code
82
- when 200
83
- project = Project.new
84
- project.reinitialize!(response)
85
- else
86
- nil
82
+ when 200
83
+ project = Project.new
84
+ project.reinitialize!(response)
85
+ else
86
+ nil
87
87
  end
88
88
  end
89
89
 
@@ -97,6 +97,20 @@ module CodeFumes
97
97
  self
98
98
  end
99
99
 
100
+ # Attempts to claim "ownership" of the project using the API key
101
+ # defined in the "credentials" section of your CodeFumes config
102
+ # file.
103
+ #
104
+ # If you need to claim a project for a key that is not defined in
105
+ # your config file, refer to Claim#create.
106
+ #
107
+ # Returns true if the request is successful.
108
+ #
109
+ # Returns +false+ in all other cases.
110
+ def claim
111
+ Claim.create(self, ConfigFile.credentials[:api_key])
112
+ end
113
+
100
114
  private
101
115
  def update
102
116
  self.class.put("/projects/#{@public_key}", :query => {:project => {:name => @name}}, :basic_auth => {:username => @public_key, :password => @private_key})
data/lib/codefumes.rb CHANGED
@@ -1,11 +1,12 @@
1
1
  require 'httparty'
2
2
 
3
3
  require 'codefumes/api'
4
- require 'codefumes/project'
4
+ require 'codefumes/claim'
5
+ require 'codefumes/commit'
5
6
  require 'codefumes/config_file'
6
7
  require 'codefumes/payload'
7
- require 'codefumes/commit'
8
+ require 'codefumes/project'
8
9
 
9
10
  module CodeFumes
10
- VERSION = '0.1.2'
11
+ VERSION = '0.1.3'
11
12
  end
@@ -0,0 +1,49 @@
1
+ require 'optparse'
2
+
3
+ module StoreCodefumesCredentials
4
+ class CLI
5
+ def self.execute(stdout, arguments=[])
6
+ parse_command_line_options!(stdout, arguments)
7
+
8
+ api_key = ARGV[0]
9
+ if CodeFumes::ConfigFile.credentials.empty? || @force_overwrite == true
10
+ CodeFumes::ConfigFile.save_credentials(api_key)
11
+ stdout.puts "Saved credentials to codefumes config file.\n\nExiting."
12
+ else
13
+ if CodeFumes::ConfigFile.credentials == api_key
14
+ stdout.puts "Credentials already stored in config file!\n"
15
+ else
16
+ stdout.puts "You have already stored CodeFumes credentials.\n\n"
17
+ stdout.puts "The current value you have stored is: #{CodeFumes::ConfigFile.credentials[:api_key]}\n\n"
18
+ stdout.puts "If you would like to replace this value, execute:\n\n"
19
+ stdout.puts "\t#{File.basename($0)} --force #{api_key}\n\n"
20
+ end
21
+ end
22
+ end
23
+
24
+ private
25
+ def self.parse_command_line_options!(stdout, arguments = [])
26
+ @force_overwrite = false
27
+
28
+ parser = OptionParser.new do |opts|
29
+ opts.banner = <<-BANNER.gsub(/^ /,'')
30
+ Stores user's API_KEY from CodFumes.com in the CodeFumes global config file.
31
+
32
+ Usage: #{File.basename($0)} [options] api_key
33
+
34
+ Options are:
35
+ BANNER
36
+ opts.separator ""
37
+ opts.on("-h", "--help",
38
+ "Show this help message.") { stdout.puts opts; exit }
39
+ opts.on("-f", "--force",
40
+ "Force overwrite of existing API key in config file.") { @force_overwrite = true }
41
+ opts.parse!(arguments)
42
+
43
+ if ARGV[0].nil?
44
+ stdout.puts opts; exit
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec/spec_helper'
2
+ require 'lib/cf_claim_project/cli'
3
+
4
+ describe CfClaimProject::CLI, "execute" do
5
+ before(:each) do
6
+ ConfigFile.save_credentials("sample_credentials")
7
+ Project.stub!(:find).and_return(mock(Project))
8
+ @stdout_io = StringIO.new
9
+ end
10
+
11
+ it "calls Claim#create" do
12
+ Claim.should_receive(:create)
13
+ CfClaimProject::CLI.execute(@stdout_io, [])
14
+ end
15
+ end
@@ -4,30 +4,37 @@ class APIClass < CodeFumes::API
4
4
  end
5
5
 
6
6
  describe "API" do
7
-
8
7
  after(:all) do
9
8
  CodeFumes::API.mode(:production)
10
9
  end
11
-
10
+
12
11
  it "defaults the base uri to the production site" do
13
12
  APIClass.base_uri.should == 'http://www.codefumes.com/api/v1/xml'
14
13
  end
15
-
14
+
16
15
  context "switching modes" do
17
16
  before(:each) do
18
17
  CodeFumes::API.mode(:test)
19
18
  end
19
+
20
20
  it "changes the base uri to the test site when switched to test mode" do
21
21
  APIClass.base_uri.should == 'http://test.codefumes.com/api/v1/xml'
22
22
  end
23
+
23
24
  it "changes the base uri to the production site when switched to production mode" do
24
25
  CodeFumes::API.mode(:production)
25
26
  APIClass.base_uri.should == 'http://www.codefumes.com/api/v1/xml'
26
27
  end
28
+
27
29
  it "ignores unrecognized modes" do
28
30
  CodeFumes::API.mode(:incomprehensible)
29
31
  APIClass.base_uri.should == 'http://test.codefumes.com/api/v1/xml'
30
32
  end
33
+
34
+ it "changes the base uri to 'localhost:3000' when switched to local mode (for developer testing)" do
35
+ CodeFumes::API.mode(:local)
36
+ APIClass.base_uri.should == 'http://localhost:3000/api/v1/xml'
37
+ end
31
38
  end
32
39
 
33
40
  end
@@ -0,0 +1,30 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe Claim do
4
+ after(:all) do
5
+ FakeWeb.allow_net_connect = false
6
+ FakeWeb.clean_registry
7
+ end
8
+
9
+ before(:each) do
10
+ @api_key = "USERS_API_KEY"
11
+ @project = Project.new(:public_key => 'public_key_value', :private_key => 'private_key_value')
12
+ @claim_uri = "http://www.codefumes.com/api/v1/xml/projects/#{@project.public_key}/claim?api_key=#{@api_key}"
13
+ end
14
+
15
+ describe "create" do
16
+ context "with 201 Created response" do
17
+ it "returns an instance of Claim with the created_at attribute set" do
18
+ FakeWeb.register_uri( :post, @claim_uri, :status => ["201", "Created"], :string => "")
19
+ Claim.create(@project, @api_key).should be_true
20
+ end
21
+ end
22
+
23
+ context "with Unauthorized response" do
24
+ it "returns false" do
25
+ FakeWeb.register_uri( :post, @claim_uri, :status => ["401", "Unauthorized"], :string => "")
26
+ Claim.create(@project, @api_key).should be_false
27
+ end
28
+ end
29
+ end
30
+ end