hone-git_pivot 0.0.0 → 0.1.0

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/README.rdoc CHANGED
@@ -2,13 +2,37 @@
2
2
 
3
3
  Tool that allows you to work with Pivotal Tracker from the command line.
4
4
 
5
+ == Installation and Usage
6
+
7
+ To install:
8
+
9
+ $ gem install hone-git_pivot -s http://gems.github.com
10
+
11
+ Now you'll need to add a <tt>git_pivot.yml</tt> to the root directory of your project:
12
+
13
+ project_id: 213992
14
+ token: 3a9390ed9309ba304903939ae948298
15
+ owner: Matt Buck
16
+ use_git: true
17
+
18
+ ... where <tt>owner</tt> is your name as it appears in the Pivotal Tracker interface. Set <tt>use_git</tt> to <tt>true</tt> if you want GitPivot to automatically create (local) topic branches when you start a story.
19
+
20
+ == Current Features
21
+ * display stories in current
22
+ * display stories under "My Work"
23
+ * start a story (optional git support to start a topic branch)
24
+ * display a story with associated "Notes"
25
+ * add a note to a story
26
+ * finish a story
27
+ * list tasks for a story
28
+ * add a task to a story
29
+ * complete tasks
30
+
5
31
  == Planned Features
6
32
 
7
33
  Planned features include:
8
- * display stories in current sprint
9
- * start working on a ticket that creates a new branch in Git, starts ticket in Pivotal Tracker
10
- * close ticket in Pivotal Tracker
11
34
  * search for stories
35
+ * backlog stories
12
36
 
13
37
  == Note on Patches/Pull Requests
14
38
 
data/Rakefile CHANGED
@@ -12,6 +12,7 @@ begin
12
12
  gem.authors = ["hone"]
13
13
  gem.add_development_dependency "hone-pivotal-tracker"
14
14
  gem.add_development_dependency "rupot"
15
+ gem.add_development_dependency "git"
15
16
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
17
  end
17
18
  rescue LoadError
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/git_pivot.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{git_pivot}
8
- s.version = "0.0.0"
8
+ s.version = "0.1.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["hone"]
12
- s.date = %q{2009-08-29}
12
+ s.date = %q{2009-09-08}
13
13
  s.default_executable = %q{git_pivot}
14
14
  s.description = %q{TODO: longer description of your gem}
15
15
  s.email = %q{hone02@gmail.com}
@@ -24,8 +24,10 @@ Gem::Specification.new do |s|
24
24
  "LICENSE",
25
25
  "README.rdoc",
26
26
  "Rakefile",
27
+ "VERSION",
27
28
  "bin/git_pivot",
28
29
  "git_pivot.gemspec",
30
+ "git_pivot.yml.example",
29
31
  "lib/git_pivot.rb",
30
32
  "lib/runner.rb"
31
33
  ]
@@ -43,12 +45,15 @@ Gem::Specification.new do |s|
43
45
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
44
46
  s.add_development_dependency(%q<hone-pivotal-tracker>, [">= 0"])
45
47
  s.add_development_dependency(%q<rupot>, [">= 0"])
48
+ s.add_development_dependency(%q<git>, [">= 0"])
46
49
  else
47
50
  s.add_dependency(%q<hone-pivotal-tracker>, [">= 0"])
48
51
  s.add_dependency(%q<rupot>, [">= 0"])
52
+ s.add_dependency(%q<git>, [">= 0"])
49
53
  end
50
54
  else
51
55
  s.add_dependency(%q<hone-pivotal-tracker>, [">= 0"])
52
56
  s.add_dependency(%q<rupot>, [">= 0"])
57
+ s.add_dependency(%q<git>, [">= 0"])
53
58
  end
54
59
  end
@@ -0,0 +1,3 @@
1
+ project_id: 213992
2
+ token: 3a9390ed9309ba304903939ae948298
3
+ owner: Matt Buck
data/lib/git_pivot.rb CHANGED
@@ -19,14 +19,16 @@
19
19
 
20
20
  require 'ruport'
21
21
  require 'pivotal-tracker'
22
+ require 'git'
22
23
 
23
24
  module GitPivot
24
25
  class GitPivot
25
26
 
26
27
  # ssl should default to yes since http basic auth is insecure
27
- def initialize(project_id, token, owner, use_ssl = true)
28
+ def initialize(project_id, token, owner, git = nil, use_ssl = true)
28
29
  @owner = owner
29
30
  @tracker = PivotalTracker.new(project_id, token, {:use_ssl => use_ssl })
31
+ @g = Git.open('.') if git
30
32
  end
31
33
 
32
34
  # list stories in current sprint
@@ -61,10 +63,11 @@ module GitPivot
61
63
  end
62
64
 
63
65
  # start story
64
- def start_story(id)
66
+ def start_story(id, name = nil)
65
67
  story = @tracker.find_story(id)
66
68
  story.current_state = "started"
67
69
  @tracker.update_story(story)
70
+ create_topic_branch(topic_branch_name(story, name))
68
71
 
69
72
  display_story(id)
70
73
  end
@@ -82,6 +85,36 @@ module GitPivot
82
85
  display_story(id)
83
86
  end
84
87
 
88
+ # add a new note
89
+ def add_note(id, note_text)
90
+ note = Note.new(:text => note_text)
91
+ @tracker.create_note(id, note)
92
+
93
+ display_story(id)
94
+ end
95
+
96
+ def tasks(id)
97
+ tasks = @tracker.tasks(id)
98
+ display_tasks(id, tasks)
99
+ end
100
+
101
+ def add_task(id, task_text)
102
+ task = Task.new(:description => task_text)
103
+ @tracker.create_task(id, task)
104
+
105
+ tasks = @tracker.tasks(id)
106
+ display_tasks(id, tasks)
107
+ end
108
+
109
+ def complete_task(id, task_id)
110
+ task = @tracker.find_task(id, task_id)
111
+ task.complete = true
112
+ @tracker.update_task(id, task)
113
+
114
+ tasks = @tracker.tasks(id)
115
+ display_tasks(id, tasks)
116
+ end
117
+
85
118
  private
86
119
  def display_stories(stories)
87
120
  data = stories.collect do |story|
@@ -91,5 +124,43 @@ module GitPivot
91
124
  puts Table(:data => data, :column_names => ["ID", "Type", "Owner", "State", "Name"])
92
125
  end
93
126
 
127
+ def display_tasks(story_id, tasks)
128
+ data = tasks.collect do |task|
129
+ [task.id, task.position, task.complete, task.created_at, task.description]
130
+ end
131
+
132
+ puts "Story ID: #{story_id}"
133
+ puts Table(:data => data,
134
+ :column_names => ["ID", "Position", "Complete", "Created At", "Description"])
135
+ end
136
+
137
+ def create_topic_branch(name)
138
+ if @g
139
+ # always branch from master
140
+ unless @g.lib.branch_current == "master"
141
+ puts 'Switching to master branch'
142
+ @g.branch('master').checkout
143
+ end
144
+
145
+ puts "Switching to #{name} branch"
146
+ @g.branch(name).checkout
147
+ end
148
+ end
149
+
150
+ def topic_branch_name(story, name = nil)
151
+ name_to_use =
152
+ if name
153
+ name
154
+ else
155
+ story.name
156
+ end
157
+ # convert spaces to underscores and remove all punctation
158
+ "#{story.id}_#{transform_name(name_to_use)}"
159
+ end
160
+
161
+ def transform_name(name)
162
+ name.downcase.gsub(' ', '_').gsub(/[^\w]/, '')
163
+ end
164
+
94
165
  end
95
166
  end
data/lib/runner.rb CHANGED
@@ -17,32 +17,214 @@
17
17
  along with this program. If not, see <http://www.gnu.org/licenses/>.
18
18
  =end
19
19
 
20
- require 'optparse'
20
+ require 'trollop'
21
21
  require 'date'
22
22
 
23
23
  module GitPivot
24
24
  class Runner
25
+ SUB_COMMANDS = %w{current work display start finish note stack push tasks task complete}
26
+ STATE_FILE = "git_pivot.state"
27
+
25
28
  def initialize(args)
26
- @argv = args
27
- process_args
29
+ @method, @cmd, @cmd_opts = process_args(args)
30
+
28
31
  # configuration stuff
29
32
  configuration = YAML.load_file("git_pivot.yml")
33
+ if File.exist?(STATE_FILE)
34
+ File.open(STATE_FILE) do |file|
35
+ @states = Marshal.load(file)
36
+ if @states.is_a?(Array)
37
+ @states.uniq!
38
+ else
39
+ @states = nil
40
+ end
41
+ end
42
+ end
30
43
 
31
- @git_pivot = GitPivot.new(configuration["project_id"], configuration["token"], configuration["owner"])
44
+ @git_pivot = GitPivot.new(configuration["project_id"], configuration["token"], configuration["owner"], configuration["use_git"])
32
45
  end
33
46
 
34
47
  def run
35
- if @arg1
36
- @git_pivot.send(@command, @arg1)
37
- else
38
- @git_pivot.send(@command)
48
+ args = [@method]
49
+ if @method and @git_pivot.method(@method).arity.abs > 0
50
+ if @cmd_opts[:id]
51
+ args << @cmd_opts[:id]
52
+ elsif @states.any?
53
+ args << @states.first
54
+ else
55
+ Trollop::die "Need to specify a story id"
56
+ end
57
+
58
+ if @cmd_opts[:name]
59
+ args << @cmd_opts[:name].join(' ')
60
+ end
61
+ if @cmd_opts[:text]
62
+ args << @cmd_opts[:text].join(' ')
63
+ end
64
+ if @cmd_opts[:"task-id"]
65
+ args << @cmd_opts[:"task-id"]
66
+ end
67
+ end
68
+
69
+ if @method == :start_story
70
+ add_story_to_states(@cmd_opts[:id])
71
+ end
72
+
73
+ if @method
74
+ @git_pivot.send(*args)
75
+ end
76
+
77
+ # must do this after, in case finish fails, don't want to pop
78
+ if @method == :finish_story
79
+ if @states and @states.first == args[1]
80
+ @states.shift
81
+
82
+ save_state
83
+ end
84
+ end
85
+
86
+ case @cmd
87
+ when "stack"
88
+ puts @states
89
+ when "push"
90
+ add_story_to_states(@cmd_opts[:id])
91
+ puts @states
39
92
  end
40
93
  end
41
94
 
42
95
  private
43
- def process_args
44
- @command = @argv.shift
45
- @arg1 = @argv.shift
96
+ def save_state
97
+ File.open(STATE_FILE, 'w') {|file| Marshal.dump(@states, file) }
98
+ end
99
+
100
+ def add_story_to_states(story_id)
101
+ if @states.nil?
102
+ @states = [story_id]
103
+ else
104
+ @states.delete(story_id)
105
+ @states.unshift(story_id)
106
+ end
107
+
108
+ save_state
109
+ end
110
+
111
+ def process_args(args)
112
+ global_opts = Trollop::options do
113
+ banner <<-BANNER
114
+ A command-line interface for Pivotal Tracker.
115
+
116
+ Subcommands:
117
+ current - Lists the stories that are part of the current iteration.
118
+ work - Lists the stories that you own.
119
+ display - Displays information about a specific story.
120
+ start - Marks a story as started.
121
+ finish - Marks a story as finished.
122
+ note - Add a new note to an existing story
123
+ stack - Current Stack of Story ids
124
+ push - Push a story to the top of the Story Stack
125
+ tasks - Display tasks associated to a story
126
+ task - Add a task to the given story
127
+ complete - Mark a task as completed
128
+
129
+ BANNER
130
+ stop_on SUB_COMMANDS
131
+ end
132
+
133
+ command = nil
134
+ cmd = args.shift
135
+ cmd_opts = case cmd
136
+ when "current"
137
+ command = :current_sprint
138
+
139
+ Trollop::options(args) do
140
+ banner "Lists the stories that are part of the current iteration."
141
+ end
142
+ when "work"
143
+ command = :my_work
144
+
145
+ # FIXME: This help message doesn't appear with a 'git_pivot work -h', but the 'git_pivot current -h' message does.
146
+ Trollop::options(args) do
147
+ banner "Lists the stories that you own."
148
+ end
149
+ when "display"
150
+ command = :display_story
151
+
152
+ Trollop::options(args) do
153
+ banner "Display information about a specific story."
154
+
155
+ opt :id, "The id of the story to display.", :type => Integer
156
+ end
157
+ when "start"
158
+ command = :start_story
159
+
160
+ Trollop::options(args) do
161
+ banner "Marks a specific story as started."
162
+
163
+ opt :id, "The id of the story to start.", :required => true, :type => Integer
164
+ opt :name, "Topic branch name", :type => :strings
165
+ end
166
+ when "finish"
167
+ command = :finish_story
168
+
169
+ Trollop::options(args) do
170
+ banner "Marks a specific story as finished."
171
+
172
+ opt :id, "The id of the story to finish.", :type => Integer
173
+ end
174
+ when "note"
175
+ command = :add_note
176
+
177
+ Trollop::options(args) do
178
+ banner "Adds a note to the story."
179
+
180
+ opt :id, "The id of the story to finish.", :type => Integer
181
+ opt :text, "The text of the note.", :required => true, :type => :strings
182
+ end
183
+ when "stack"
184
+ command = nil
185
+
186
+ Trollop::options(args) do
187
+ banner "Displays the stack of story ids."
188
+ end
189
+ when "push"
190
+ command = nil
191
+
192
+ Trollop::options(args) do
193
+ banner "Push story to the top of the story stack."
194
+
195
+ opt :id, "The id of the story.", :type => Integer
196
+ end
197
+ when "tasks"
198
+ command = :tasks
199
+
200
+ Trollop::options(args) do
201
+ banner "Tasks for a given story."
202
+
203
+ opt :id, "The id of the story.", :type => Integer
204
+ end
205
+ when "task"
206
+ command = :add_task
207
+
208
+ Trollop::options(args) do
209
+ banner "Add a task to the story."
210
+
211
+ opt :id, "The id of the story.", :type => Integer
212
+ opt :text, "The text of the task.", :required => true, :type => :strings
213
+ end
214
+ when "complete"
215
+ command = :complete_task
216
+
217
+ Trollop::options(args) do
218
+ banner "Complete a task"
219
+
220
+ opt :id, "The id of the story.", :type => Integer
221
+ opt :"task-id", "The id of the task.", :required => true, :type => Integer
222
+ end
223
+ else
224
+ Trollop::die "unknown subcommand #{cmd.inspect}"
225
+ end
226
+
227
+ [command, cmd, cmd_opts]
46
228
  end
47
229
  end
48
230
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hone-git_pivot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - hone
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-29 00:00:00 -07:00
12
+ date: 2009-09-08 00:00:00 -07:00
13
13
  default_executable: git_pivot
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -32,6 +32,16 @@ dependencies:
32
32
  - !ruby/object:Gem::Version
33
33
  version: "0"
34
34
  version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: git
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
35
45
  description: "TODO: longer description of your gem"
36
46
  email: hone02@gmail.com
37
47
  executables:
@@ -47,13 +57,14 @@ files:
47
57
  - LICENSE
48
58
  - README.rdoc
49
59
  - Rakefile
60
+ - VERSION
50
61
  - bin/git_pivot
51
62
  - git_pivot.gemspec
63
+ - git_pivot.yml.example
52
64
  - lib/git_pivot.rb
53
65
  - lib/runner.rb
54
66
  has_rdoc: true
55
67
  homepage: http://github.com/hone/git_pivot
56
- licenses:
57
68
  post_install_message:
58
69
  rdoc_options:
59
70
  - --charset=UTF-8
@@ -74,7 +85,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
74
85
  requirements: []
75
86
 
76
87
  rubyforge_project:
77
- rubygems_version: 1.3.5
88
+ rubygems_version: 1.2.0
78
89
  signing_key:
79
90
  specification_version: 2
80
91
  summary: "TODO: one-line summary of your gem"