codefumes 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
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