toolshed 1.0.2 → 1.0.3

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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rubocop.yml +11 -0
  4. data/.toolshedrc.sample +32 -0
  5. data/README.md +159 -2
  6. data/Rakefile +3 -3
  7. data/bin/toolshed +6 -1
  8. data/lib/toolshed.rb +38 -28
  9. data/lib/toolshed/base.rb +33 -11
  10. data/lib/toolshed/cli.rb +30 -38
  11. data/lib/toolshed/client.rb +87 -293
  12. data/lib/toolshed/commands/base.rb +65 -23
  13. data/lib/toolshed/commands/checkout_branch.rb +15 -2
  14. data/lib/toolshed/commands/create_branch.rb +34 -29
  15. data/lib/toolshed/commands/create_pivotal_tracker_note.rb +9 -3
  16. data/lib/toolshed/commands/create_pull_request.rb +115 -68
  17. data/lib/toolshed/commands/create_ticket_comment.rb +17 -1
  18. data/lib/toolshed/commands/delete_branch.rb +34 -3
  19. data/lib/toolshed/commands/get_daily_time_update.rb +20 -3
  20. data/lib/toolshed/commands/list_branches.rb +16 -5
  21. data/lib/toolshed/commands/push_branch.rb +28 -9
  22. data/lib/toolshed/commands/rename_branch.rb +29 -0
  23. data/lib/toolshed/commands/ssh.rb +44 -3
  24. data/lib/toolshed/commands/ticket_information.rb +30 -4
  25. data/lib/toolshed/commands/update_pivotal_tracker_story_status.rb +9 -3
  26. data/lib/toolshed/commands/update_ticket_status.rb +8 -2
  27. data/lib/toolshed/entry_point.rb +89 -0
  28. data/lib/toolshed/git.rb +59 -0
  29. data/lib/toolshed/git/branch.rb +224 -0
  30. data/lib/toolshed/git/github.rb +45 -57
  31. data/lib/toolshed/git/validator.rb +14 -0
  32. data/lib/toolshed/logger.rb +46 -0
  33. data/lib/toolshed/password.rb +11 -6
  34. data/lib/toolshed/server_administration/ssh.rb +4 -2
  35. data/lib/toolshed/ticket_tracking/jira.rb +8 -6
  36. data/lib/toolshed/ticket_tracking/pivotal_tracker.rb +8 -6
  37. data/lib/toolshed/time_tracking/harvest.rb +8 -14
  38. data/lib/toolshed/version.rb +25 -1
  39. data/test/commands/checkout_branch_test.rb +11 -7
  40. data/test/commands/create_branch_test.rb +29 -24
  41. data/test/commands/create_pull_request_test.rb +39 -31
  42. data/test/commands/delete_branch_test.rb +35 -25
  43. data/test/commands/get_daily_time_update_test.rb +8 -8
  44. data/test/commands/push_branch_test.rb +27 -15
  45. data/test/commands/rename_branch_test.rb +59 -0
  46. data/test/git/git_helper.rb +5 -5
  47. data/test/git/git_test.rb +36 -31
  48. data/test/git/github_test.rb +9 -46
  49. data/test/helper.rb +11 -11
  50. data/test/server_administration/ssh_test.rb +1 -0
  51. data/test/ticket_tracking/jira_test.rb +18 -16
  52. data/test/time_tracking/harvest_test.rb +8 -6
  53. data/toolshed.gemspec +23 -20
  54. metadata +95 -46
  55. data/bin/toolshed.rb +0 -261
  56. data/lib/toolshed/git/git.rb +0 -119
@@ -1,11 +1,28 @@
1
1
  module Toolshed
2
2
  module Commands
3
3
  class GetDailyTimeUpdate
4
+ def self.cli_options
5
+ {
6
+ banner: 'Usage: get_daily_time_update [options]',
7
+ options: {
8
+ format: {
9
+ short_on: '-f',
10
+ },
11
+ use_defaults: {
12
+ short_on: '-d'
13
+ },
14
+ project_id: {
15
+ short_on: '-p',
16
+ }
17
+ }
18
+ }
19
+ end
20
+
4
21
  def execute(args, options = {})
5
22
  begin
6
- time_tracking_class = Object.const_get("Toolshed::TimeTracking::#{Toolshed::Client.time_tracking_tool.camel_case}")
23
+ time_tracking_class = Object.const_get("Toolshed::TimeTracking::#{Toolshed::Client.instance.time_tracking_tool.camel_case}")
7
24
 
8
- time_tracking_project_id = read_user_input_project_id("Project ID (Default: #{Toolshed::Client.time_tracking_default_project_id}):", options.merge!({ default: Toolshed::Client.time_tracking_default_project_id }))
25
+ time_tracking_project_id = read_user_input_project_id("Project ID (Default: #{Toolshed::Client.instance.time_tracking_default_project_id}):", options.merge!({ default: Toolshed::Client.instance.time_tracking_default_project_id }))
9
26
  options.merge!({ project_id: time_tracking_project_id })
10
27
  time_tracker = time_tracking_class.create_instance(options)
11
28
 
@@ -19,7 +36,7 @@ module Toolshed
19
36
 
20
37
  def read_user_input_project_id(message, options)
21
38
  return options[:project_id] if (options.has_key?(:project_id))
22
- return options[:default] if (Toolshed::Client.use_defaults)
39
+ return options[:default] if (Toolshed::Client.instance.use_defaults)
23
40
 
24
41
  puts message
25
42
  value = $stdin.gets.chomp
@@ -1,12 +1,23 @@
1
+ require 'toolshed/git'
2
+
1
3
  module Toolshed
2
4
  module Commands
3
5
  class ListBranches
6
+ def self.cli_options
7
+ {
8
+ banner: 'Usage: list_branches [options]',
9
+ options: {
10
+ repository_name: {
11
+ short_on: '-r',
12
+ },
13
+ }
14
+ }
15
+ end
16
+
4
17
  def execute(args, options = {})
5
- git = Toolshed::Git::Github.new
6
- branches = git.list_branches
7
- branches.each do |branch|
8
- puts branch['name']
9
- end
18
+ branch = Toolshed::Git::Branch.new
19
+ branch.list
20
+ Toolshed.die
10
21
  end
11
22
  end
12
23
  end
@@ -1,11 +1,30 @@
1
- module Toolshed
2
- module Commands
3
- class PushBranch
4
- def execute(args, options = {})
5
- branch_name = Toolshed::Git::Base.push(options)
6
- puts "#{branch_name} has been pushed"
7
- return
8
- end
9
- end
1
+ require 'toolshed/commands/base'
2
+ require 'toolshed/git'
3
+
4
+ class Toolshed::Commands::PushBranch < Toolshed::Commands::Base
5
+ def initialize(options = {})
6
+ super(options)
7
+ end
8
+
9
+ def self.cli_options
10
+ {
11
+ banner: 'Usage: push_branch [options]',
12
+ options: {
13
+ force_command: {
14
+ short_on: '-f',
15
+ default: true
16
+ },
17
+ branch_name: {
18
+ short_on: '-b'
19
+ }
20
+ }
21
+ }
22
+ end
23
+
24
+ def execute(args, options = {})
25
+ Toolshed.logger.info "Running toolshed push_branch with #{options.inspect}"
26
+ branch = Toolshed::Git::Branch.new(options)
27
+ branch.push
28
+ Toolshed.die
10
29
  end
11
30
  end
@@ -0,0 +1,29 @@
1
+ require 'toolshed/commands/base'
2
+ require 'toolshed/git/branch'
3
+
4
+ class Toolshed::Commands::RenameBranch < Toolshed::Commands::Base
5
+ def self.cli_options
6
+ {
7
+ banner: 'Usage: rename_branch [options]',
8
+ options: {
9
+ branch_name: {
10
+ short_on: '-b'
11
+ },
12
+ new_branch_name: {
13
+ short_on: '-n'
14
+ }
15
+ }
16
+ }
17
+ end
18
+
19
+ def execute(args, options = {})
20
+ Toolshed.logger.info "Running toolshed rename_branch with #{options.inspect}"
21
+
22
+ options[:branch_name] = options[:branch_name] || read_user_input('Branch name?', required: true)
23
+ new_branch_name = options[:new_branch_name] || read_user_input('New Branch name?', required: true)
24
+
25
+ branch = Toolshed::Git::Branch.new(options)
26
+ branch.rename(new_branch_name)
27
+ Toolshed.die
28
+ end
29
+ end
@@ -1,14 +1,55 @@
1
+ require 'toolshed/server_administration/ssh'
2
+
1
3
  module Toolshed
2
4
  module Commands
3
5
  class SSH
6
+ def self.cli_options
7
+ {
8
+ banner: 'Usage: ssh [options]',
9
+ options: {
10
+ use_sudo: {
11
+ short_on: '-e'
12
+ },
13
+ host: {
14
+ short_on: '-o'
15
+ },
16
+ connection_string_options: {
17
+ short_on: '-n'
18
+ },
19
+ commands: {
20
+ short_on: '-c'
21
+ },
22
+ password: {
23
+ short_on: '-p'
24
+ },
25
+ prompt_for_password: {
26
+ short_on: '-r'
27
+ },
28
+ user: {
29
+ short_on: '-u'
30
+ },
31
+ keys: {
32
+ short_on: '-k'
33
+ },
34
+ sudo_password: {
35
+ short_on: '-s'
36
+ },
37
+ verbose_output: {
38
+ short_on: '-v'
39
+ }
40
+ }
41
+ }
42
+ end
43
+
4
44
  def execute(args, options = {})
5
- puts "running ssh command with options #{options.inspect}" unless options[:verbose_output].blank?
45
+ Toolshed.logger.info "Running ssh command with options #{options.inspect}" unless options[:verbose_output].nil? || options[:verbose_output].empty? # rubocop:disable Metrics/LineLength
6
46
  begin
7
47
  ssh = Toolshed::ServerAdministration::SSH.new(options)
8
48
  ssh.execute
9
49
  rescue => e
10
- puts e.inspect
11
- puts "Unable to connect to #{options[:host]}"
50
+ Toolshed.logger.fatal e.message
51
+ Toolshed.logger.fatal "Unable to connect to #{options[:host]}"
52
+ Toolshed.die
12
53
  end
13
54
  end
14
55
  end
@@ -1,23 +1,49 @@
1
+ require 'toolshed/git'
2
+
1
3
  module Toolshed
2
4
  module Commands
3
5
  class TicketInformation
6
+ def self.cli_options
7
+ {
8
+ banner: 'Usage: ticket_information [options]',
9
+ options: {
10
+ use_defaults: {
11
+ short_on: '-d'
12
+ },
13
+ clipboard: {
14
+ short_on: '-c'
15
+ },
16
+ field: {
17
+ short_on: '-f'
18
+ },
19
+ formatted_string: {
20
+ short_on: '-fs'
21
+ }
22
+ }
23
+ }
24
+ end
25
+
26
+ def branch
27
+ @branch ||= Toolshed::Git::Branch.new
28
+ end
29
+
4
30
  def execute(args, options = {})
5
31
  begin
6
- ticket_tracker_class = Object.const_get("Toolshed::TicketTracking::#{Toolshed::Client.ticket_tracking_tool.camel_case}")
32
+ ticket_tracker_class = Object.const_get("Toolshed::TicketTracking::#{Toolshed::Client.instance.ticket_tracking_tool.camel_case}")
7
33
 
8
34
  use_project_id = Object.const_get("#{ticket_tracker_class}::USE_PROJECT_ID") rescue false
9
35
  if use_project_id
10
- ticket_tracker_project_id = read_user_input_project("Project ID (Default: #{Toolshed::Client.default_pivotal_tracker_project_id}):", options.merge!({ default: Toolshed::Client.default_pivotal_tracker_project_id }))
36
+ ticket_tracker_project_id = read_user_input_project("Project ID (Default: #{Toolshed::Client.instance.default_pivotal_tracker_project_id}):", options.merge!({ default: Toolshed::Client.instance.default_pivotal_tracker_project_id }))
11
37
  options.merge!({ project_id: ticket_tracker_project_id })
12
38
  end
13
39
 
14
40
  use_project_name = Object.const_get("#{ticket_tracker_class}::USE_PROJECT_NAME") rescue false
15
41
  if use_project_name
16
- ticket_tracker_project_name = read_user_input_project("Project Name (Default: #{Toolshed::Client.default_ticket_tracker_project}):", options.merge!({ default: Toolshed::Client.default_ticket_tracker_project }))
42
+ ticket_tracker_project_name = read_user_input_project("Project Name (Default: #{Toolshed::Client.instance.default_ticket_tracker_project}):", options.merge!({ default: Toolshed::Client.instance.default_ticket_tracker_project }))
17
43
  options.merge!({ project: ticket_tracker_project_name })
18
44
  end
19
45
 
20
- default_ticket_id = Toolshed::TicketTracking::story_id_from_branch_name(Toolshed::Git::Base.branch_name)
46
+ default_ticket_id = Toolshed::TicketTracking::story_id_from_branch_name(branch.name)
21
47
  ticket_id = read_user_input_ticket_id("Story ID (Default: #{default_ticket_id}):", options.merge!({ default: default_ticket_id }))
22
48
  options.merge!({ ticket_id: ticket_id })
23
49
 
@@ -1,13 +1,19 @@
1
+ require 'toolshed/git'
2
+
1
3
  module Toolshed
2
4
  module Commands
3
5
  class UpdatePivotalTrackerStoryStatus
4
6
  STORY_STATUS_DEFAULT = 'finished'
5
7
 
8
+ def branch
9
+ @branch ||= Toolshed::Git::Branch.new
10
+ end
11
+
6
12
  def execute(args, options = {})
7
- print "Project ID (Default: #{Toolshed::Client.default_pivotal_tracker_project_id})? "
13
+ print "Project ID (Default: #{Toolshed::Client.instance.default_pivotal_tracker_project_id})? "
8
14
  project_id = $stdin.gets.chomp.strip
9
15
  if (project_id == '')
10
- project_id = Toolshed::Client.default_pivotal_tracker_project_id
16
+ project_id = Toolshed::Client.instance.default_pivotal_tracker_project_id
11
17
  end
12
18
 
13
19
  pivotal_tracker = Toolshed::TicketTracking::PivotalTracker.new({
@@ -16,7 +22,7 @@ module Toolshed
16
22
  password: Toolshed::TicketTracking::PivotalTracker.password,
17
23
  })
18
24
 
19
- default_story_id = Toolshed::TicketTracking::PivotalTracker::story_id_from_branch_name(Toolshed::Git::Base.branch_name)
25
+ default_story_id = Toolshed::TicketTracking::PivotalTracker::story_id_from_branch_name(branch.name)
20
26
  print "Story ID (Default: #{default_story_id})? "
21
27
  story_id = $stdin.gets.chomp.strip
22
28
  if (story_id == '')
@@ -1,6 +1,12 @@
1
+ require 'toolshed/git'
2
+
1
3
  module Toolshed
2
4
  module Commands
3
5
  class UpdateTicketStatus
6
+ def branch
7
+ @branch ||= Toolshed::Git::Branch.new
8
+ end
9
+
4
10
  def execute(args, options = {})
5
11
  ticket_tracker_class = Object.const_get("Toolshed::TicketTracking::#{Toolshed::Client.ticket_tracking_tool.camel_case}")
6
12
 
@@ -16,7 +22,7 @@ module Toolshed
16
22
  options.merge!({ project: ticket_tracker_project_name })
17
23
  end
18
24
 
19
- default_ticket_id = Toolshed::TicketTracking::story_id_from_branch_name(Toolshed::Git::Base.branch_name)
25
+ default_ticket_id = Toolshed::TicketTracking::story_id_from_branch_name(branch.name)
20
26
  ticket_id = read_user_input_ticket_id("Ticket ID (Default: #{default_ticket_id}):", options.merge!({ default: default_ticket_id }))
21
27
  options.merge!({ ticket_id: ticket_id })
22
28
 
@@ -63,7 +69,7 @@ module Toolshed
63
69
  puts message
64
70
  value = $stdin.gets.chomp
65
71
 
66
- until (!value.blank?)
72
+ until !value.nil? && !value.empty?
67
73
  puts "Status must be passed in"
68
74
  puts message
69
75
  value = $stdin.gets.chomp
@@ -0,0 +1,89 @@
1
+ require 'toolshed'
2
+ require 'toolshed/cli'
3
+ require 'toolshed/base'
4
+ require 'toolshed/commands/base'
5
+ require 'optparse'
6
+ require 'singleton'
7
+
8
+ class EntryPoint
9
+ include Singleton
10
+
11
+ attr_accessor :cli
12
+
13
+ def initialize
14
+ self.cli = Toolshed::CLI.new
15
+ end
16
+
17
+ def execute
18
+ if $0.split("/").last == 'toolshed'
19
+ options = {}
20
+
21
+ # @TODO - clean this up as it should really be part of the command it's being used in not globally.
22
+ global = OptionParser.new do |opts|
23
+ opts.on("-u", "--github-username [ARG]") do |username|
24
+ Toolshed::Client.github_username = username
25
+ end
26
+ opts.on("-p", "--github-password [ARG]") do |password|
27
+ Toolshed::Client.github_password = password
28
+ end
29
+ opts.on("-t", "--github-token [ARG]") do |token|
30
+ Toolshed::Client.github_token = token
31
+ end
32
+ opts.on("-u", "--pivotal-tracker-username [ARG]") do |username|
33
+ Toolshed::Client.pivotal_tracker_username = username
34
+ end
35
+ opts.on("-p", "--pivotal-tracker-password [ARG]") do |password|
36
+ Toolshed::Client.pivotal_tracker_password = password
37
+ end
38
+ opts.on("-d", "--debug [ARG]") do
39
+ Toolshed::Client.debug = true
40
+ end
41
+ opts.on('-v', '--version', 'Version') do
42
+ Toolshed::Version.banner
43
+ end
44
+ end
45
+
46
+ global.order!
47
+ command = ARGV.shift
48
+ if command.nil?
49
+ usage
50
+ elsif command == 'version'
51
+ Toolshed::Version.banner
52
+ Toolshed.die
53
+ else
54
+ command_class = nil
55
+ command_class_name = command.camel_case
56
+ begin
57
+ require "toolshed/commands/#{command.to_s}"
58
+ command_class = "Toolshed::Commands::#{command_class_name}".split('::').inject(Object) { |o,c| o.const_get c }
59
+ rescue NameError
60
+ command_class = "Toolshed::Commands::#{command_class_name.upcase}".split('::').inject(Object) { |o,c| o.const_get c }
61
+ end
62
+ Toolshed::Commands::Base.parse(command, command_class.cli_options)
63
+ end
64
+ end
65
+ end
66
+
67
+ def usage
68
+ $stdout.puts <<EOF
69
+ Please see toolshedrc.sample to create your toolshedrc settings file.
70
+
71
+ Available Commands:
72
+
73
+ checkout_branch
74
+ create_branch
75
+ create_pivotal_tracker_note
76
+ create_pull_request
77
+ create_ticket_comment
78
+ delete_branch
79
+ get_daily_time_update
80
+ list_branches
81
+ push_branch
82
+ rename_branch
83
+ ssh
84
+ ticket_information
85
+ update_pivotal_tracker_story_status
86
+ update_ticket_status
87
+ EOF
88
+ end
89
+ end
@@ -0,0 +1,59 @@
1
+ require 'toolshed/base'
2
+ require 'toolshed/git/validator'
3
+ require 'highline/import'
4
+
5
+ module Toolshed
6
+ class Git
7
+ require 'toolshed/git/branch'
8
+
9
+ DEFAULT_GIT_TOOL = 'github'
10
+ DEFAULT_BRANCH_FROM = 'master'
11
+
12
+ attr_accessor :from_remote_name, :from_remote_branch_name, :to_remote_name, :to_remote_branch_name, :validator, :passed_branch_name, :force
13
+
14
+ def initialize(options = {})
15
+ # options with defaults
16
+ self.from_remote_name = Toolshed::Client.instance.pull_from_remote_name
17
+ unless (options[:from_remote_name].nil?)
18
+ self.from_remote_name = options[:from_remote_name]
19
+ end
20
+
21
+ self.to_remote_name = Toolshed::Client.instance.push_to_remote_name
22
+ unless (options[:to_remote_name].nil?)
23
+ self.to_remote_name = options[:to_remote_name]
24
+ end
25
+
26
+ # options that do not have a default
27
+ unless (options[:from_remote_branch_name].nil?)
28
+ self.from_remote_branch_name = options[:from_remote_branch_name]
29
+ end
30
+
31
+ unless (options[:to_remote_branch_name].nil?)
32
+ self.to_remote_branch_name = options[:to_remote_branch_name]
33
+ end
34
+
35
+ self.validator = ::Toolshed::Git::Validator.new
36
+ self.passed_branch_name = options[:branch_name] || ''
37
+ self.force = (options.key?(:force_command)) ? '--force' : ''
38
+ end
39
+
40
+ class << self
41
+ def git_submodule_command
42
+ git_submodule_command = ''
43
+ git_submodule_command = "git submodule update #{Toolshed::Client.instance.git_quiet}" if Toolshed::Client.instance.use_git_submodules
44
+ git_submodule_command
45
+ end
46
+
47
+ def clean_branch_name(branch_name)
48
+ branch_name.strip.downcase.tr(' ', '_').gsub('&', '').gsub('.', '_').gsub("'", '').gsub(':', '').gsub(',', '').gsub('>', '').gsub('__', '_')
49
+ end
50
+ end
51
+
52
+ def remote_update
53
+ results = Toolshed::Base.wait_for_command("git remote update #{Toolshed::Client.instance.git_quiet}")
54
+ results[:all].each do |out|
55
+ Toolshed.logger.info out
56
+ end
57
+ end
58
+ end
59
+ end