acuforce 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +16 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +27 -0
- data/Rakefile +56 -0
- data/VERSION +1 -0
- data/acuforce.gemspec +70 -0
- data/lib/acuforce.rb +18 -0
- data/lib/acunote_connection.rb +113 -0
- data/lib/acunote_project.rb +25 -0
- data/lib/acunote_sprint.rb +71 -0
- data/spec/acuforce_spec.rb +13 -0
- data/spec/spec_helper.rb +12 -0
- metadata +133 -0
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
#gem 'psych'
|
7
|
+
gem 'mechanize'
|
8
|
+
|
9
|
+
# Add dependencies to develop your gem here.
|
10
|
+
# Include everything needed to run rake, tests, features, etc.
|
11
|
+
group :development do
|
12
|
+
gem "rspec", "~> 2.3.0"
|
13
|
+
gem "bundler", "~> 1.0.0"
|
14
|
+
gem "jeweler", "~> 1.6.4"
|
15
|
+
gem "rcov", ">= 0"
|
16
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Harrison Strowd
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
= AcuForce
|
2
|
+
|
3
|
+
Gem that handles integration with Acunote. Does not expose all actions at this time.
|
4
|
+
|
5
|
+
Current actions supported:
|
6
|
+
- Logging in and Logging out
|
7
|
+
- Creating a sprint
|
8
|
+
- Finding a sprint
|
9
|
+
- Uploading tasks to a sprint from a CSV file
|
10
|
+
- Exporting tasks in a sprint to a CSV file
|
11
|
+
|
12
|
+
== Contributing to AcuForce
|
13
|
+
|
14
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
15
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
16
|
+
* Fork the project
|
17
|
+
* Start a feature/bugfix branch
|
18
|
+
* Commit and push until you are happy with your contribution
|
19
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
20
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
21
|
+
|
22
|
+
== Copyright
|
23
|
+
|
24
|
+
Copyright (c) 2011 Harrison Strowd. See LICENSE.txt for
|
25
|
+
further details.
|
26
|
+
|
27
|
+
This work was forked and redesigned from work done by bfeigin in https://github.com/bfeigin/AcuPlan.
|
data/Rakefile
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "acuforce"
|
18
|
+
gem.homepage = "http://github.com/hstrowd/AcuForce"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Client API for performing actions on an Acunote site.}
|
21
|
+
gem.description = %Q{
|
22
|
+
Provides an API for the following actions:
|
23
|
+
* Logging in and Logging out
|
24
|
+
* Creating a sprint
|
25
|
+
* Finding a sprint
|
26
|
+
* Uploading tasks to a sprint from a CSV file
|
27
|
+
* Exporting tasks in a sprint to a CSV file
|
28
|
+
}
|
29
|
+
gem.email = "hstrowd@gmail.com"
|
30
|
+
gem.authors = ["Harrison Strowd"]
|
31
|
+
# dependencies defined in Gemfile
|
32
|
+
end
|
33
|
+
Jeweler::RubygemsDotOrgTasks.new
|
34
|
+
|
35
|
+
require 'rspec/core'
|
36
|
+
require 'rspec/core/rake_task'
|
37
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
38
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
39
|
+
end
|
40
|
+
|
41
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
42
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
43
|
+
spec.rcov = true
|
44
|
+
end
|
45
|
+
|
46
|
+
task :default => :spec
|
47
|
+
|
48
|
+
require 'rake/rdoctask'
|
49
|
+
Rake::RDocTask.new do |rdoc|
|
50
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
51
|
+
|
52
|
+
rdoc.rdoc_dir = 'rdoc'
|
53
|
+
rdoc.title = "acuforce #{version}"
|
54
|
+
rdoc.rdoc_files.include('README*')
|
55
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
56
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.0
|
data/acuforce.gemspec
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{acuforce}
|
8
|
+
s.version = "0.2.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Harrison Strowd"]
|
12
|
+
s.date = %q{2011-12-24}
|
13
|
+
s.description = %q{
|
14
|
+
Provides an API for the following actions:
|
15
|
+
* Logging in and Logging out
|
16
|
+
* Creating a sprint
|
17
|
+
* Finding a sprint
|
18
|
+
* Uploading tasks to a sprint from a CSV file
|
19
|
+
* Exporting tasks in a sprint to a CSV file
|
20
|
+
}
|
21
|
+
s.email = %q{hstrowd@gmail.com}
|
22
|
+
s.extra_rdoc_files = [
|
23
|
+
"LICENSE.txt",
|
24
|
+
"README.rdoc"
|
25
|
+
]
|
26
|
+
s.files = [
|
27
|
+
"Gemfile",
|
28
|
+
"LICENSE.txt",
|
29
|
+
"README.rdoc",
|
30
|
+
"Rakefile",
|
31
|
+
"VERSION",
|
32
|
+
"acuforce.gemspec",
|
33
|
+
"lib/acuforce.rb",
|
34
|
+
"lib/acunote_connection.rb",
|
35
|
+
"lib/acunote_project.rb",
|
36
|
+
"lib/acunote_sprint.rb",
|
37
|
+
"spec/acuforce_spec.rb",
|
38
|
+
"spec/spec_helper.rb"
|
39
|
+
]
|
40
|
+
s.homepage = %q{http://github.com/hstrowd/AcuForce}
|
41
|
+
s.licenses = ["MIT"]
|
42
|
+
s.require_paths = ["lib"]
|
43
|
+
s.rubygems_version = %q{1.6.2}
|
44
|
+
s.summary = %q{Client API for performing actions on an Acunote site.}
|
45
|
+
|
46
|
+
if s.respond_to? :specification_version then
|
47
|
+
s.specification_version = 3
|
48
|
+
|
49
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
50
|
+
s.add_runtime_dependency(%q<mechanize>, [">= 0"])
|
51
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
|
52
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
53
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
54
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
55
|
+
else
|
56
|
+
s.add_dependency(%q<mechanize>, [">= 0"])
|
57
|
+
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
58
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
59
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
60
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
61
|
+
end
|
62
|
+
else
|
63
|
+
s.add_dependency(%q<mechanize>, [">= 0"])
|
64
|
+
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
65
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
66
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
67
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
data/lib/acuforce.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#INITAL DEVELOPMENT
|
3
|
+
#askryl
|
4
|
+
#https://github.com/skryl/AcuForce.git
|
5
|
+
|
6
|
+
#bfeigin intense modifications
|
7
|
+
#Ripped out most of AcuForce, kept the basic Acunote logic see AcunoteBase
|
8
|
+
#https://github.com/bfeigin/AcuForce.git
|
9
|
+
|
10
|
+
#Major modifications to transition from OmniPlan to Accunote
|
11
|
+
#Notes there are a few gems required see directly below :)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'acunote_connection'
|
15
|
+
require 'acunote_project'
|
16
|
+
require 'acunote_sprint'
|
17
|
+
|
18
|
+
DEBUG = true unless defined? DEBUG
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'mechanize'
|
2
|
+
require 'yaml'
|
3
|
+
require 'singleton'
|
4
|
+
|
5
|
+
# A singleton class to contain the acunote session information.
|
6
|
+
class AcunoteConnection
|
7
|
+
include Singleton
|
8
|
+
|
9
|
+
attr_accessor :username
|
10
|
+
attr_writer :home_url
|
11
|
+
attr_reader :logged_in, :mech
|
12
|
+
|
13
|
+
def initialize()
|
14
|
+
@mech ||= Mechanize.new
|
15
|
+
end
|
16
|
+
|
17
|
+
# For lack of a better place, put sessions in tmp
|
18
|
+
SESSION_DIR = "/tmp" unless defined? SESSION_DIR
|
19
|
+
SESSION_FILE = "#{SESSION_DIR}/acunote.session" unless defined? SESSION_FILE
|
20
|
+
|
21
|
+
LOGIN_FIELDS = ['login[username]', 'login[password]'] unless defined? LOGIN_FIELDS
|
22
|
+
LOGIN_FORM_NAME = "login_form" unless defined? LOGIN_FORM_NAME
|
23
|
+
|
24
|
+
# The home_url must be set after the instance is first retrieved.
|
25
|
+
def home_url
|
26
|
+
raise "home_url not set" unless @home_url
|
27
|
+
@home_url
|
28
|
+
end
|
29
|
+
|
30
|
+
def login_url
|
31
|
+
"#{self.home_url}/login"
|
32
|
+
end
|
33
|
+
|
34
|
+
def logout_url
|
35
|
+
"#{self.home_url}/login/logout"
|
36
|
+
end
|
37
|
+
|
38
|
+
def login(username, password, force = false)
|
39
|
+
@logged_in = nil if force
|
40
|
+
return true if logged_in
|
41
|
+
|
42
|
+
#Going to assume the session is good to save time here. The session will be
|
43
|
+
#discarded and a force login will be performed if get_page fails.
|
44
|
+
if !force && File.exists?(SESSION_FILE) && ! File.zero?(SESSION_FILE) && mech.cookie_jar.load(SESSION_FILE)
|
45
|
+
STDERR.puts "Loaded session file" if DEBUG
|
46
|
+
@username = username
|
47
|
+
@logged_in = true
|
48
|
+
end
|
49
|
+
|
50
|
+
unless logged_in
|
51
|
+
|
52
|
+
#try to log in
|
53
|
+
login_page = get_page(login_url)
|
54
|
+
STDERR.puts "Navigated to '#{login_page.title}'" if DEBUG
|
55
|
+
|
56
|
+
form = login_page.forms.first
|
57
|
+
form[LOGIN_FIELDS[0]] = username
|
58
|
+
form[LOGIN_FIELDS[1]] = password
|
59
|
+
dest_page = form.submit(form.buttons.first)
|
60
|
+
|
61
|
+
STDERR.puts "Navigated to '#{dest_page.title}'" if DEBUG
|
62
|
+
if dest_page.uri == login_page.uri
|
63
|
+
STDERR.puts "Error: Bad login!"
|
64
|
+
return false
|
65
|
+
end
|
66
|
+
|
67
|
+
#serialize session and save for later reuse
|
68
|
+
mech.cookie_jar.save_as(SESSION_FILE)
|
69
|
+
@username = username
|
70
|
+
@logged_in = true
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def logout()
|
75
|
+
if File.exists?(SESSION_FILE)
|
76
|
+
File.delete(SESSION_FILE)
|
77
|
+
end
|
78
|
+
get_page(logout_url)
|
79
|
+
@username = nil
|
80
|
+
@logged_in = false
|
81
|
+
end
|
82
|
+
|
83
|
+
def set_timeout(timeout = 60)
|
84
|
+
mech.keep_alive = false
|
85
|
+
mech.open_timeout = timeout
|
86
|
+
mech.read_timeout = timeout
|
87
|
+
mech.idle_timeout = timeout
|
88
|
+
end
|
89
|
+
|
90
|
+
#Retrieves the requested page and verifies destination url to make sure there
|
91
|
+
#was no innapropriate redirect. If redirected, a force login will be performed
|
92
|
+
#(assuming credentials are passed in as arguments) and the page will be retrieved
|
93
|
+
#again.
|
94
|
+
def get_page(url, matcher = /.*/, retry_count = 1)
|
95
|
+
begin
|
96
|
+
page = mech.get(url)
|
97
|
+
if page.uri.to_s =~ matcher
|
98
|
+
page
|
99
|
+
else
|
100
|
+
#try a force login and retry once (in case the session is stale)
|
101
|
+
if retry_count > 0 && login(true)
|
102
|
+
STDERR.puts "Attn: get_page problem, overwrote stale session, retrying..."
|
103
|
+
get_page(url, matcher, retry_count - 1)
|
104
|
+
else STDERR.puts "Error: Can't retrieve valid response page for <#{url}>"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
rescue Mechanize::ResponseCodeError => e
|
108
|
+
STDERR.puts "ResponseError!"
|
109
|
+
puts url if DEBUG
|
110
|
+
puts e if DEBUG
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'acunote_connection'
|
2
|
+
|
3
|
+
# API for accessing Acunote projects.
|
4
|
+
class AcunoteProject
|
5
|
+
def self.acu_conn
|
6
|
+
AcunoteConnection.instance
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.url(id)
|
10
|
+
"#{acu_conn.home_url}/projects/#{id}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.find_id_by_name(name)
|
14
|
+
link = find_by_name(proj_id, sprint_name)
|
15
|
+
if(link.uri.to_s =~ /projects\/([0-9]*)\/sprints/)
|
16
|
+
$1
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# NAME can be a literal string or a regex.
|
21
|
+
def self.find_by_name(name)
|
22
|
+
projects = acu_conn.get_page(url(''))
|
23
|
+
projects.links_with(:href => /projects\/([0-9]*)\/sprints$/, :text => name).first if projects
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'acunote_connection'
|
2
|
+
|
3
|
+
# API for accessing Acunote projects.
|
4
|
+
class AcunoteSprint
|
5
|
+
ACUNOTE_CSV_HEADER = "Level,Number,Description,Tags,Owner,Status,Resolution,Priority,Severity,Estimate,Remaining,Due Date,QA Owner,Business Owner,Wiki,Watchers,Related,Duplicate,Predecessors,Successors,Version 1\r\n" unless defined? ACUNOTE_CSV_HEADER
|
6
|
+
|
7
|
+
def self.acu_conn
|
8
|
+
AcunoteConnection.instance
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.url(proj_id, sprint_id)
|
12
|
+
"#{acu_conn.home_url}/projects/#{proj_id}/sprints/#{sprint_id}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.create(proj_id, name, opts = {})
|
16
|
+
opts[:type] ||= 'Backlog'
|
17
|
+
opts[:start_date] ||= Date.today
|
18
|
+
opts[:end_date] ||= opts[:start_date] + 365
|
19
|
+
|
20
|
+
unless acu_conn.logged_in
|
21
|
+
STDERR.puts "Must login before creating a sprint." if DEBUG
|
22
|
+
return false
|
23
|
+
end
|
24
|
+
|
25
|
+
sprint_page = acu_conn.get_page(url(proj_id, 'new'))
|
26
|
+
|
27
|
+
# Check that the project could be found.
|
28
|
+
unless sprint_page
|
29
|
+
STDERR.puts "Spcified project could not be found." if DEBUG
|
30
|
+
return false
|
31
|
+
end
|
32
|
+
|
33
|
+
sprint_form = sprint_page.forms_with({:name => 'sprint_new_dialog'}).first
|
34
|
+
|
35
|
+
if opts[:type] == 'Backlog'
|
36
|
+
(sprint_form.radiobuttons_with(:value => /Backlog/).first &&
|
37
|
+
sprint_form.radiobuttons_with(:value => /Backlog/).first.check)
|
38
|
+
else
|
39
|
+
sprint_form.radiobuttons_with(:value => /Iteration/).first.check
|
40
|
+
sprint_form.fields_with(:id => 'sprint_start_date').first.value = opts[:start_date].to_s
|
41
|
+
end
|
42
|
+
sprint_form.fields_with(:id => 'sprint_name').first.value = name
|
43
|
+
sprint_form.fields_with(:id => 'sprint_end_date').first.value = opts[:end_date].to_s
|
44
|
+
sprint_form.submit
|
45
|
+
end
|
46
|
+
|
47
|
+
# NAME can be a literal string or a regex.
|
48
|
+
def self.find_id_by_name(proj_id, name)
|
49
|
+
link = find_by_name(proj_id, name)
|
50
|
+
if(link.uri.to_s =~ /\/sprints\/([0-9]*)/)
|
51
|
+
$1
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# NAME can be a literal string or a regex.
|
56
|
+
def self.find_by_name(proj_id, name)
|
57
|
+
sprints = acu_conn.get_page(url(proj_id, ''))
|
58
|
+
sprints.links_with(:text => name).first if sprints
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.upload_csv(raw_data, proj_id, sprint_id)
|
62
|
+
import_page = acu_conn.get_page(url(opts[:proj_id],sprint_id)+"/import")
|
63
|
+
import_form = import_page.form_with({:name => 'import_form'})
|
64
|
+
import_form.field_with(:id => 'data_to_import').value = raw_data.to_s
|
65
|
+
import_form.submit
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.export_csv(proj_id, sprint_id)
|
69
|
+
acu_conn.get_page(url(proj_id,sprint_id) + '/export').body
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Acufore Loading' do
|
4
|
+
it 'should be able to load the Connection API' do
|
5
|
+
AcunoteConnection.should === AcunoteConnection.instance
|
6
|
+
end
|
7
|
+
it 'should be able to load the Project API' do
|
8
|
+
AcunoteProject.should === AcunoteProject.new
|
9
|
+
end
|
10
|
+
it 'should be able to load the Sprint API' do
|
11
|
+
AcunoteSprint.should === AcunoteSprint.new
|
12
|
+
end
|
13
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'acuforce'
|
5
|
+
|
6
|
+
# Requires supporting files with custom matchers and macros, etc,
|
7
|
+
# in ./support/ and its subdirectories.
|
8
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: acuforce
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Harrison Strowd
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-12-24 00:00:00.000000000 -06:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: mechanize
|
17
|
+
requirement: &2156230120 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *2156230120
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rspec
|
28
|
+
requirement: &2156229640 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.3.0
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *2156229640
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: bundler
|
39
|
+
requirement: &2156229160 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 1.0.0
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *2156229160
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: jeweler
|
50
|
+
requirement: &2156228680 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ~>
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 1.6.4
|
56
|
+
type: :development
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *2156228680
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: rcov
|
61
|
+
requirement: &2156228200 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: *2156228200
|
70
|
+
description: ! '
|
71
|
+
|
72
|
+
Provides an API for the following actions:
|
73
|
+
|
74
|
+
* Logging in and Logging out
|
75
|
+
|
76
|
+
* Creating a sprint
|
77
|
+
|
78
|
+
* Finding a sprint
|
79
|
+
|
80
|
+
* Uploading tasks to a sprint from a CSV file
|
81
|
+
|
82
|
+
* Exporting tasks in a sprint to a CSV file
|
83
|
+
|
84
|
+
'
|
85
|
+
email: hstrowd@gmail.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files:
|
89
|
+
- LICENSE.txt
|
90
|
+
- README.rdoc
|
91
|
+
files:
|
92
|
+
- Gemfile
|
93
|
+
- LICENSE.txt
|
94
|
+
- README.rdoc
|
95
|
+
- Rakefile
|
96
|
+
- VERSION
|
97
|
+
- acuforce.gemspec
|
98
|
+
- lib/acuforce.rb
|
99
|
+
- lib/acunote_connection.rb
|
100
|
+
- lib/acunote_project.rb
|
101
|
+
- lib/acunote_sprint.rb
|
102
|
+
- spec/acuforce_spec.rb
|
103
|
+
- spec/spec_helper.rb
|
104
|
+
has_rdoc: true
|
105
|
+
homepage: http://github.com/hstrowd/AcuForce
|
106
|
+
licenses:
|
107
|
+
- MIT
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
segments:
|
119
|
+
- 0
|
120
|
+
hash: 102055120518766815
|
121
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
|
+
none: false
|
123
|
+
requirements:
|
124
|
+
- - ! '>='
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
requirements: []
|
128
|
+
rubyforge_project:
|
129
|
+
rubygems_version: 1.6.2
|
130
|
+
signing_key:
|
131
|
+
specification_version: 3
|
132
|
+
summary: Client API for performing actions on an Acunote site.
|
133
|
+
test_files: []
|