pivotal_db 0.1.0.pre
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/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.md +27 -0
- data/Rakefile +1 -0
- data/bin/pivotal-db +39 -0
- data/lib/pivotal_db/cli.rb +55 -0
- data/lib/pivotal_db/label.rb +15 -0
- data/lib/pivotal_db/labeling.rb +14 -0
- data/lib/pivotal_db/membership.rb +36 -0
- data/lib/pivotal_db/note.rb +43 -0
- data/lib/pivotal_db/person.rb +28 -0
- data/lib/pivotal_db/pivotal_source.rb +42 -0
- data/lib/pivotal_db/project.rb +61 -0
- data/lib/pivotal_db/role.rb +10 -0
- data/lib/pivotal_db/story.rb +101 -0
- data/lib/pivotal_db/story_state.rb +14 -0
- data/lib/pivotal_db/story_type.rb +14 -0
- data/lib/pivotal_db/tracker.rb +61 -0
- data/lib/pivotal_db/version.rb +3 -0
- data/lib/pivotal_db.rb +15 -0
- data/pivotal_db.gemspec +28 -0
- data/spec/pivotal_db_spec.rb +8 -0
- metadata +189 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
# Pivotal DB
|
3
|
+
|
4
|
+
Pull Pivotal Tracker stories into a local SQLite database. No changes to the local DB will be reflected in Pivotal Tracker (this is not sync).
|
5
|
+
|
6
|
+
This provides a basic CLI (pivotal-db) along with a Ruby library.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
gem install pivotal_db
|
11
|
+
|
12
|
+
## Configuration
|
13
|
+
|
14
|
+
Before starting, you'll have to add a configuration file at ~/.pivotal_db/config.yml like the following:
|
15
|
+
|
16
|
+
default:
|
17
|
+
project_id: 123
|
18
|
+
api_token: secret
|
19
|
+
db_file: ~/.pivotal_db/pivotal.db
|
20
|
+
|
21
|
+
Your API token can be found on Pivotal Tracker at https://www.pivotaltracker.com/profile.
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
To see usage, run (without any arguments)
|
26
|
+
|
27
|
+
pivotal-db
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/pivotal-db
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'pivotal_db'
|
4
|
+
require 'configliere'
|
5
|
+
|
6
|
+
pivotal_db_dir = File.expand_path("~/.pivotal_db/")
|
7
|
+
|
8
|
+
Settings.use :commandline
|
9
|
+
Settings({
|
10
|
+
:config_file => pivotal_db_dir + '/config.yml',
|
11
|
+
:project => :default,
|
12
|
+
:default => {
|
13
|
+
:project_id => nil,
|
14
|
+
:api_token => nil,
|
15
|
+
:db_file => pivotal_db_dir + '/pivotal.db'
|
16
|
+
}
|
17
|
+
})
|
18
|
+
Settings.resolve!
|
19
|
+
|
20
|
+
unless File.exist?(Settings[:config_file])
|
21
|
+
puts "The configuration file #{Settings[:config_file]} does not exist."
|
22
|
+
puts "Please create one like the following example."
|
23
|
+
puts
|
24
|
+
puts "default:"
|
25
|
+
puts " project_id: 123"
|
26
|
+
puts " api_token: secret"
|
27
|
+
puts " db_file: ~/.pivotal_db/pivotal.db"
|
28
|
+
puts
|
29
|
+
puts "The API token can be found on Pivotal Tracker at"
|
30
|
+
puts " https://www.pivotaltracker.com/profile"
|
31
|
+
Process.exit
|
32
|
+
end
|
33
|
+
|
34
|
+
Settings.use :commandline
|
35
|
+
Settings.read Settings[:config_file]
|
36
|
+
Settings.resolve!
|
37
|
+
|
38
|
+
PivotalDb::CLI.start
|
39
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
module PivotalDb
|
4
|
+
class CLI < Thor
|
5
|
+
|
6
|
+
desc "stats", "stats"
|
7
|
+
def stats
|
8
|
+
tracker = Tracker.new(Settings[Settings[:project]])
|
9
|
+
puts "Projects: #{Project.all.count}"
|
10
|
+
puts "Stories: #{Story.all.count}"
|
11
|
+
puts "Notes: #{Note.all.count}"
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "pull", "pull all stories from Pivotal Tracker (this may take a while)"
|
15
|
+
def pull
|
16
|
+
begin
|
17
|
+
Tracker.new(Settings[Settings[:project]]).pull
|
18
|
+
rescue DataMapper::SaveFailureError => e
|
19
|
+
p e.resource.errors
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
desc "random", "return a random incomplete story for review"
|
24
|
+
def random
|
25
|
+
tracker = Tracker.new(Settings[Settings[:project]])
|
26
|
+
puts
|
27
|
+
puts tracker.random
|
28
|
+
puts
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "search", "search for the given term in the stories"
|
32
|
+
def search(term)
|
33
|
+
found = Tracker.new(Settings[Settings[:project]]).search(term)
|
34
|
+
puts "#{found.count} Results"
|
35
|
+
found.each do |story|
|
36
|
+
puts
|
37
|
+
puts story.to_s(:brief)
|
38
|
+
puts
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
desc "show", "show a particular story by ID or URL"
|
43
|
+
def show(story_id)
|
44
|
+
tracker = Tracker.new(Settings[Settings[:project]])
|
45
|
+
story_id = story_id.gsub(/.*\//, "")
|
46
|
+
story = Story.get(story_id)
|
47
|
+
if story
|
48
|
+
puts story.to_s(:detailed)
|
49
|
+
else
|
50
|
+
puts "No story found"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module PivotalDb
|
2
|
+
class Label
|
3
|
+
|
4
|
+
include DataMapper::Resource
|
5
|
+
|
6
|
+
property :id, Serial
|
7
|
+
property :name, String
|
8
|
+
property :created_at, DateTime
|
9
|
+
property :updated_at, DateTime
|
10
|
+
|
11
|
+
has n, :labelings, :constraint => :destroy
|
12
|
+
has n, :stories, :through => :labelings
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module PivotalDb
|
2
|
+
class Membership
|
3
|
+
|
4
|
+
include DataMapper::Resource
|
5
|
+
include PivotalSource
|
6
|
+
|
7
|
+
property :id, Serial
|
8
|
+
property :created_at, DateTime
|
9
|
+
property :updated_at, DateTime
|
10
|
+
|
11
|
+
belongs_to :role
|
12
|
+
belongs_to :project
|
13
|
+
belongs_to :person
|
14
|
+
|
15
|
+
def find_datasource
|
16
|
+
self.project.datasource.memberships.all.find{|membership_ds| membership_ds == self.id}
|
17
|
+
end
|
18
|
+
|
19
|
+
def update_from_datasource
|
20
|
+
|
21
|
+
role = Role.first_or_create(:name => datasource.role)
|
22
|
+
|
23
|
+
person = Person.first(:email => datasource.email) || Person.new
|
24
|
+
person.datasource = datasource
|
25
|
+
person.pull
|
26
|
+
|
27
|
+
self.attributes = {
|
28
|
+
:id => datasource.id,
|
29
|
+
:role => role,
|
30
|
+
:person => person
|
31
|
+
}
|
32
|
+
self.save
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module PivotalDb
|
2
|
+
class Note
|
3
|
+
|
4
|
+
include DataMapper::Resource
|
5
|
+
include PivotalSource
|
6
|
+
|
7
|
+
property :id, Serial
|
8
|
+
property :noted_at, DateTime
|
9
|
+
property :text, Text
|
10
|
+
property :created_at, DateTime
|
11
|
+
property :updated_at, DateTime
|
12
|
+
|
13
|
+
belongs_to :story
|
14
|
+
belongs_to :author, 'Person', :required => false
|
15
|
+
|
16
|
+
def find_datasource
|
17
|
+
self.story.datasource.notes.all.find{|note_ds| note_ds.id == self.id}
|
18
|
+
end
|
19
|
+
|
20
|
+
def update_from_datasource
|
21
|
+
|
22
|
+
project = Project.first(datasource.project_id)
|
23
|
+
author = project.people.first(:name => datasource.author)
|
24
|
+
self.attributes = {
|
25
|
+
:id => datasource.id,
|
26
|
+
:story_id => datasource.story_id,
|
27
|
+
:author => author,
|
28
|
+
:noted_at => datasource.noted_at,
|
29
|
+
:text => datasource.text
|
30
|
+
}
|
31
|
+
self.save
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
str = ""
|
37
|
+
str += "#{self.author.name}, #{self.noted_at.to_s}:\n"
|
38
|
+
str += "\n#{self.text}\n"
|
39
|
+
str
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module PivotalDb
|
2
|
+
class Person
|
3
|
+
|
4
|
+
include DataMapper::Resource
|
5
|
+
include PivotalSource
|
6
|
+
|
7
|
+
property :id, Serial
|
8
|
+
property :name, String
|
9
|
+
property :email, String, :unique => true
|
10
|
+
property :initials, String
|
11
|
+
property :created_at, DateTime
|
12
|
+
property :updated_at, DateTime
|
13
|
+
|
14
|
+
has n, :notes, :child_key => [ :author_id ]
|
15
|
+
has n, :requested_stories, :model => 'Story', :child_key => [ :requested_by_id ]
|
16
|
+
has n, :owned_stories, :model => 'Story', :child_key => [ :owned_by_id ]
|
17
|
+
|
18
|
+
def update_from_datasource
|
19
|
+
self.attributes = {
|
20
|
+
:name => datasource.name,
|
21
|
+
:email => datasource.email,
|
22
|
+
:initials => datasource.initials
|
23
|
+
}
|
24
|
+
self.save
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module PivotalDb
|
2
|
+
|
3
|
+
module PivotalSource
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
|
8
|
+
base.class_eval do
|
9
|
+
property :updated_from_datasource_at, DateTime
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def find_datasource
|
14
|
+
raise NotImplementedError
|
15
|
+
end
|
16
|
+
|
17
|
+
def datasource
|
18
|
+
@datasource ||= find_datasource
|
19
|
+
end
|
20
|
+
|
21
|
+
def datasource=(ds)
|
22
|
+
@datasource = ds
|
23
|
+
end
|
24
|
+
|
25
|
+
def pull
|
26
|
+
update_from_datasource
|
27
|
+
self.updated_from_datasource_at = Time.now
|
28
|
+
self.save
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def update_from_datasource
|
34
|
+
raise NotImplementedError
|
35
|
+
end
|
36
|
+
|
37
|
+
module ClassMethods
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module PivotalDb
|
2
|
+
|
3
|
+
class Project
|
4
|
+
|
5
|
+
include DataMapper::Resource
|
6
|
+
include PivotalSource
|
7
|
+
|
8
|
+
property :id, Serial
|
9
|
+
property :name, String
|
10
|
+
property :created_at, DateTime
|
11
|
+
property :updated_at, DateTime
|
12
|
+
|
13
|
+
has n, :stories, :constraint => :destroy
|
14
|
+
has n, :notes, :through => :stories
|
15
|
+
has n, :memberships, :constraint => :destroy
|
16
|
+
has n, :people, :through => :memberships
|
17
|
+
|
18
|
+
def find_datasource
|
19
|
+
PivotalTracker::Project.find(self.id)
|
20
|
+
end
|
21
|
+
|
22
|
+
def update_from_datasource
|
23
|
+
|
24
|
+
self.attributes = {
|
25
|
+
:name => datasource.name
|
26
|
+
}
|
27
|
+
self.save
|
28
|
+
|
29
|
+
pull_memberships
|
30
|
+
pull_stories
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def pull_memberships
|
37
|
+
datasource.memberships.all.each do |membership_ds|
|
38
|
+
membership = self.memberships.first(:id => membership_ds.id, :project => self) || Membership.new(:id => membership_ds.id, :project => self)
|
39
|
+
membership.datasource = membership_ds
|
40
|
+
membership.pull
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def pull_stories
|
45
|
+
limit = 1000
|
46
|
+
offset = 0
|
47
|
+
while true
|
48
|
+
found_stories = false
|
49
|
+
datasource.stories.all(:offset => offset, :limit => limit).each do |story_ds|
|
50
|
+
found_stories = true
|
51
|
+
story = self.stories.first(:id => story_ds.id) || Story.new
|
52
|
+
story.datasource = story_ds
|
53
|
+
story.pull
|
54
|
+
end
|
55
|
+
break unless found_stories
|
56
|
+
offset += limit
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module PivotalDb
|
2
|
+
class Story
|
3
|
+
|
4
|
+
include DataMapper::Resource
|
5
|
+
include PivotalSource
|
6
|
+
|
7
|
+
property :id, Serial
|
8
|
+
property :name, Text
|
9
|
+
property :description, Text
|
10
|
+
property :estimate, Integer
|
11
|
+
property :story_created_at, DateTime
|
12
|
+
property :updated_from_pivotal_source, Boolean
|
13
|
+
property :created_at, DateTime
|
14
|
+
property :updated_at, DateTime
|
15
|
+
|
16
|
+
belongs_to :project
|
17
|
+
belongs_to :story_state
|
18
|
+
belongs_to :story_type
|
19
|
+
belongs_to :requested_by, 'Person', :required => false
|
20
|
+
belongs_to :owned_by, 'Person', :required => false
|
21
|
+
|
22
|
+
has n, :notes, :constraint => :destroy
|
23
|
+
has n, :labelings, :constraint => :destroy
|
24
|
+
has n, :labels, :through => :labelings
|
25
|
+
|
26
|
+
def find_datasource
|
27
|
+
PivotalTracker::Story.find(self.id, self.project_id)
|
28
|
+
end
|
29
|
+
|
30
|
+
def update_from_datasource
|
31
|
+
|
32
|
+
self.project ||= Project.first(:id => datasource.project_id)
|
33
|
+
|
34
|
+
requested_by = self.project.people.first(:name => datasource.requested_by)
|
35
|
+
owned_by = datasource.owned_by.nil? ? nil : self.project.people.first(:name => datasource.requested_by)
|
36
|
+
|
37
|
+
labels = (datasource.labels || "").split(",").map{|label| Label.first_or_create(:name => label.strip)}
|
38
|
+
|
39
|
+
story_state = StoryState.first_or_create(:name => datasource.current_state)
|
40
|
+
story_type = StoryType.first_or_create(:name => datasource.story_type)
|
41
|
+
|
42
|
+
self.attributes = {
|
43
|
+
:id => datasource.id,
|
44
|
+
:project_id => datasource.project_id,
|
45
|
+
:requested_by => requested_by,
|
46
|
+
:owned_by => owned_by,
|
47
|
+
:story_type => story_type,
|
48
|
+
:story_state => story_state,
|
49
|
+
:labels => labels,
|
50
|
+
:name => datasource.name,
|
51
|
+
:description => datasource.description,
|
52
|
+
:estimate => datasource.estimate,
|
53
|
+
:story_created_at => datasource.created_at
|
54
|
+
}
|
55
|
+
self.save
|
56
|
+
|
57
|
+
pull_notes
|
58
|
+
end
|
59
|
+
|
60
|
+
def pull_notes
|
61
|
+
datasource.notes.all.each do |note_ds|
|
62
|
+
note = self.notes.first(:id => note_ds.id) || self.notes.new(:id => note_ds.id)
|
63
|
+
note.datasource = note_ds
|
64
|
+
note.pull
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_s(detail_level = :summary)
|
69
|
+
detail_levels = {:brief => 1, :summary => 2, :detailed => 3}
|
70
|
+
detail = detail_levels[detail_level]
|
71
|
+
|
72
|
+
requested_by_name = self.requested_by ? self.requested_by.name : ""
|
73
|
+
owned_by_name = self.owned_by ? " => " + self.owned_by.name : ""
|
74
|
+
str = ""
|
75
|
+
str += "https://www.pivotaltracker.com/story/show/#{self.id}\n"
|
76
|
+
str += "#{self.name}\n"
|
77
|
+
str += self.story_type.name + ": " + self.labels.map{|label| label.name}.join(", ") + "\n"
|
78
|
+
str += requested_by_name + owned_by_name + ": " + self.story_created_at.to_s + "\n"
|
79
|
+
|
80
|
+
if detail_levels[:summary] <= detail
|
81
|
+
str += "\n#{self.description}\n"
|
82
|
+
end
|
83
|
+
|
84
|
+
sorted_notes = self.notes.all(:order => [:noted_at.asc])
|
85
|
+
if detail_levels[:detailed] <= detail
|
86
|
+
sorted_notes.each do |note|
|
87
|
+
str += note.to_s + "\n"
|
88
|
+
end
|
89
|
+
elsif detail_levels[:summary] <= detail
|
90
|
+
unless sorted_notes.blank?
|
91
|
+
str += "\n#{sorted_notes.count} Notes\n"
|
92
|
+
note = sorted_notes.last
|
93
|
+
str += "\nLatest Note:\n"
|
94
|
+
str += note.to_s
|
95
|
+
end
|
96
|
+
end
|
97
|
+
str
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'data_mapper'
|
2
|
+
require 'pivotal_tracker'
|
3
|
+
|
4
|
+
module PivotalDb
|
5
|
+
class Tracker
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
|
9
|
+
@api_token = options[:api_token]
|
10
|
+
@project_id = options[:project_id]
|
11
|
+
@db_file = File.expand_path(options[:db_file])
|
12
|
+
|
13
|
+
raise ArgumentError, "requires api_token, project_id, and db_file" unless @api_token && @project_id && @db_file
|
14
|
+
|
15
|
+
DataMapper::Model.raise_on_save_failure = true
|
16
|
+
|
17
|
+
DataMapper.setup(:default, 'sqlite://' + @db_file)
|
18
|
+
|
19
|
+
DataMapper.repository(:default).adapter.resource_naming_convention =
|
20
|
+
DataMapper::NamingConventions::Resource::UnderscoredAndPluralizedWithoutModule
|
21
|
+
DataMapper.finalize
|
22
|
+
DataMapper.auto_upgrade!
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
def pull
|
27
|
+
|
28
|
+
pull_start = Time.now
|
29
|
+
PivotalTracker::Client.token = @api_token
|
30
|
+
PivotalTracker::Client.use_ssl = true
|
31
|
+
project_ds = PivotalTracker::Project.find(@project_id)
|
32
|
+
project = Project.first_or_create(:id => project_ds.id)
|
33
|
+
|
34
|
+
project.datasource = project_ds
|
35
|
+
project.pull
|
36
|
+
|
37
|
+
# destroy stale records
|
38
|
+
project.stories.all(:updated_from_datasource_at.lt => pull_start).destroy
|
39
|
+
project.notes.all(:updated_from_datasource_at.lt => pull_start).destroy
|
40
|
+
end
|
41
|
+
|
42
|
+
def random
|
43
|
+
project = Project.first(:id => @project_id)
|
44
|
+
state_ids = StoryState.all(:name => ["unstarted", "unscheduled", "rejected"]).map{|state| state.id}
|
45
|
+
story_id = DataMapper.repository(:default).adapter.select('SELECT id FROM stories WHERE story_state_id IN ? ORDER BY RANDOM() LIMIT 1', state_ids).first
|
46
|
+
Story.get(story_id)
|
47
|
+
end
|
48
|
+
|
49
|
+
def search(term, states = nil)
|
50
|
+
project = Project.first(:id => @project_id)
|
51
|
+
if states.nil?
|
52
|
+
state_ids = StoryState.all.map{|state| state.id}
|
53
|
+
else
|
54
|
+
state_ids = StoryState.all(:name => states).map{|state| state.id}
|
55
|
+
end
|
56
|
+
story_ids = DataMapper.repository(:default).adapter.select('SELECT stories.id FROM stories LEFT JOIN notes ON stories.id = notes.story_id WHERE story_state_id IN ? AND (name LIKE ? OR description LIKE ? OR notes.text LIKE ?)', state_ids, "%#{term}%", "%#{term}%", "%#{term}%")
|
57
|
+
Story.all(:id => story_ids)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
data/lib/pivotal_db.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require "pivotal_db/version"
|
2
|
+
require "pivotal_db/pivotal_source"
|
3
|
+
require "pivotal_db/tracker"
|
4
|
+
require "pivotal_db/cli"
|
5
|
+
require "pivotal_db/project"
|
6
|
+
require "pivotal_db/person"
|
7
|
+
require "pivotal_db/membership"
|
8
|
+
require "pivotal_db/role"
|
9
|
+
require "pivotal_db/story"
|
10
|
+
require "pivotal_db/note"
|
11
|
+
require "pivotal_db/label"
|
12
|
+
require "pivotal_db/labeling"
|
13
|
+
require "pivotal_db/story_type"
|
14
|
+
require "pivotal_db/story_state"
|
15
|
+
|
data/pivotal_db.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "pivotal_db/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "pivotal_db"
|
7
|
+
s.version = PivotalDb::VERSION
|
8
|
+
s.authors = ["Fraser Newton"]
|
9
|
+
s.email = ["fraser@goclio.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Offline Access to Pivotal Tracker projects}
|
12
|
+
s.description = %q{Pull a Pivotal Tracker project into an sqlite DB and provides basic search functionality through a CLI}
|
13
|
+
|
14
|
+
s.rubyforge_project = "pivotal_db"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_development_dependency "rspec"
|
22
|
+
s.add_dependency "pivotal-tracker", "~>0.4"
|
23
|
+
s.add_dependency "sqlite3", "~>1.3"
|
24
|
+
s.add_dependency "data_mapper"
|
25
|
+
s.add_dependency "dm-sqlite-adapter"
|
26
|
+
s.add_dependency "thor"
|
27
|
+
s.add_dependency "configliere"
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pivotal_db
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 961915980
|
5
|
+
prerelease: 6
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
- pre
|
11
|
+
version: 0.1.0.pre
|
12
|
+
platform: ruby
|
13
|
+
authors:
|
14
|
+
- Fraser Newton
|
15
|
+
autorequire:
|
16
|
+
bindir: bin
|
17
|
+
cert_chain: []
|
18
|
+
|
19
|
+
date: 2011-09-07 00:00:00 Z
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: pivotal-tracker
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
- 4
|
47
|
+
version: "0.4"
|
48
|
+
type: :runtime
|
49
|
+
version_requirements: *id002
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: sqlite3
|
52
|
+
prerelease: false
|
53
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ~>
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
hash: 9
|
59
|
+
segments:
|
60
|
+
- 1
|
61
|
+
- 3
|
62
|
+
version: "1.3"
|
63
|
+
type: :runtime
|
64
|
+
version_requirements: *id003
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: data_mapper
|
67
|
+
prerelease: false
|
68
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
hash: 3
|
74
|
+
segments:
|
75
|
+
- 0
|
76
|
+
version: "0"
|
77
|
+
type: :runtime
|
78
|
+
version_requirements: *id004
|
79
|
+
- !ruby/object:Gem::Dependency
|
80
|
+
name: dm-sqlite-adapter
|
81
|
+
prerelease: false
|
82
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
hash: 3
|
88
|
+
segments:
|
89
|
+
- 0
|
90
|
+
version: "0"
|
91
|
+
type: :runtime
|
92
|
+
version_requirements: *id005
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: thor
|
95
|
+
prerelease: false
|
96
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
hash: 3
|
102
|
+
segments:
|
103
|
+
- 0
|
104
|
+
version: "0"
|
105
|
+
type: :runtime
|
106
|
+
version_requirements: *id006
|
107
|
+
- !ruby/object:Gem::Dependency
|
108
|
+
name: configliere
|
109
|
+
prerelease: false
|
110
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
111
|
+
none: false
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
hash: 3
|
116
|
+
segments:
|
117
|
+
- 0
|
118
|
+
version: "0"
|
119
|
+
type: :runtime
|
120
|
+
version_requirements: *id007
|
121
|
+
description: Pull a Pivotal Tracker project into an sqlite DB and provides basic search functionality through a CLI
|
122
|
+
email:
|
123
|
+
- fraser@goclio.com
|
124
|
+
executables:
|
125
|
+
- pivotal-db
|
126
|
+
extensions: []
|
127
|
+
|
128
|
+
extra_rdoc_files: []
|
129
|
+
|
130
|
+
files:
|
131
|
+
- .gitignore
|
132
|
+
- Gemfile
|
133
|
+
- README.md
|
134
|
+
- Rakefile
|
135
|
+
- bin/pivotal-db
|
136
|
+
- lib/pivotal_db.rb
|
137
|
+
- lib/pivotal_db/cli.rb
|
138
|
+
- lib/pivotal_db/label.rb
|
139
|
+
- lib/pivotal_db/labeling.rb
|
140
|
+
- lib/pivotal_db/membership.rb
|
141
|
+
- lib/pivotal_db/note.rb
|
142
|
+
- lib/pivotal_db/person.rb
|
143
|
+
- lib/pivotal_db/pivotal_source.rb
|
144
|
+
- lib/pivotal_db/project.rb
|
145
|
+
- lib/pivotal_db/role.rb
|
146
|
+
- lib/pivotal_db/story.rb
|
147
|
+
- lib/pivotal_db/story_state.rb
|
148
|
+
- lib/pivotal_db/story_type.rb
|
149
|
+
- lib/pivotal_db/tracker.rb
|
150
|
+
- lib/pivotal_db/version.rb
|
151
|
+
- pivotal_db.gemspec
|
152
|
+
- spec/pivotal_db_spec.rb
|
153
|
+
homepage: ""
|
154
|
+
licenses: []
|
155
|
+
|
156
|
+
post_install_message:
|
157
|
+
rdoc_options: []
|
158
|
+
|
159
|
+
require_paths:
|
160
|
+
- lib
|
161
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
162
|
+
none: false
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
hash: 3
|
167
|
+
segments:
|
168
|
+
- 0
|
169
|
+
version: "0"
|
170
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
171
|
+
none: false
|
172
|
+
requirements:
|
173
|
+
- - ">"
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
hash: 25
|
176
|
+
segments:
|
177
|
+
- 1
|
178
|
+
- 3
|
179
|
+
- 1
|
180
|
+
version: 1.3.1
|
181
|
+
requirements: []
|
182
|
+
|
183
|
+
rubyforge_project: pivotal_db
|
184
|
+
rubygems_version: 1.8.10
|
185
|
+
signing_key:
|
186
|
+
specification_version: 3
|
187
|
+
summary: Offline Access to Pivotal Tracker projects
|
188
|
+
test_files:
|
189
|
+
- spec/pivotal_db_spec.rb
|