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 ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in pivotal_db.gemspec
4
+ gemspec
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,14 @@
1
+ module PivotalDb
2
+ class Labeling
3
+
4
+ include DataMapper::Resource
5
+
6
+ property :id, Serial
7
+ property :created_at, DateTime
8
+ property :updated_at, DateTime
9
+
10
+ belongs_to :story
11
+ belongs_to :label
12
+
13
+ end
14
+ 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,10 @@
1
+ module PivotalDb
2
+ class Role
3
+
4
+ include DataMapper::Resource
5
+
6
+ property :id, Serial
7
+ property :name, String
8
+
9
+ end
10
+ 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,14 @@
1
+ module PivotalDb
2
+ class StoryState
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, :stories
12
+
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module PivotalDb
2
+ class StoryType
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, :stories
12
+
13
+ end
14
+ 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
@@ -0,0 +1,3 @@
1
+ module PivotalDb
2
+ VERSION = "0.1.0.pre"
3
+ 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
+
@@ -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
@@ -0,0 +1,8 @@
1
+ require 'pivotal_db/tracker'
2
+
3
+ describe PivotalDb::Tracker do
4
+ it "example test" do
5
+ PivotalDb::Tracker.example.should eql("example")
6
+ end
7
+
8
+ 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