geet 0.3.0 → 0.3.1

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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +6 -10
  3. data/Gemfile.lock +8 -2
  4. data/README.md +27 -2
  5. data/Rakefile +3 -1
  6. data/bin/geet +37 -17
  7. data/geet.gemspec +3 -1
  8. data/lib/geet/commandline/configuration.rb +18 -5
  9. data/lib/geet/commandline/editor.rb +14 -24
  10. data/lib/geet/git/repository.rb +30 -84
  11. data/lib/geet/github/api_interface.rb +11 -3
  12. data/lib/geet/github/gist.rb +1 -0
  13. data/lib/geet/gitlab/api_interface.rb +5 -2
  14. data/lib/geet/helpers/os_helper.rb +36 -3
  15. data/lib/geet/helpers/summary_helper.rb +20 -0
  16. data/lib/geet/resources/{edit_summary_template.md → templates/edit_summary.md} +0 -3
  17. data/lib/geet/services/create_gist.rb +18 -2
  18. data/lib/geet/services/create_issue.rb +46 -21
  19. data/lib/geet/services/create_label.rb +8 -4
  20. data/lib/geet/services/create_pr.rb +67 -18
  21. data/lib/geet/services/list_issues.rb +9 -5
  22. data/lib/geet/services/list_labels.rb +6 -2
  23. data/lib/geet/services/list_milestones.rb +11 -7
  24. data/lib/geet/services/list_prs.rb +6 -2
  25. data/lib/geet/services/merge_pr.rb +18 -11
  26. data/lib/geet/utils/git_client.rb +160 -0
  27. data/lib/geet/utils/manual_list_selection.rb +41 -23
  28. data/lib/geet/version.rb +1 -1
  29. data/spec/integration/create_gist_spec.rb +2 -5
  30. data/spec/integration/create_issue_spec.rb +10 -10
  31. data/spec/integration/create_label_spec.rb +30 -5
  32. data/spec/integration/create_pr_spec.rb +85 -10
  33. data/spec/integration/list_issues_spec.rb +12 -11
  34. data/spec/integration/list_labels_spec.rb +28 -5
  35. data/spec/integration/list_milestones_spec.rb +30 -3
  36. data/spec/integration/list_prs_spec.rb +8 -7
  37. data/spec/integration/merge_pr_spec.rb +8 -7
  38. data/spec/vcr_cassettes/create_gist_private.yml +1 -1
  39. data/spec/vcr_cassettes/create_gist_public.yml +1 -1
  40. data/spec/vcr_cassettes/create_issue.yml +9 -9
  41. data/spec/vcr_cassettes/create_issue_upstream.yml +3 -3
  42. data/spec/vcr_cassettes/create_label.yml +1 -1
  43. data/spec/vcr_cassettes/create_label_upstream.yml +80 -0
  44. data/spec/vcr_cassettes/create_label_with_random_color.yml +1 -1
  45. data/spec/vcr_cassettes/create_pr.yml +13 -13
  46. data/spec/vcr_cassettes/create_pr_in_auto_mode_create_upstream.yml +235 -0
  47. data/spec/vcr_cassettes/create_pr_in_auto_mode_with_push.yml +235 -0
  48. data/spec/vcr_cassettes/create_pr_upstream.yml +4 -4
  49. data/spec/vcr_cassettes/github_com/list_issues.yml +5 -5
  50. data/spec/vcr_cassettes/github_com/list_issues_upstream.yml +6 -6
  51. data/spec/vcr_cassettes/github_com/list_issues_with_assignee.yml +4 -4
  52. data/spec/vcr_cassettes/github_com/list_labels.yml +1 -1
  53. data/spec/vcr_cassettes/github_com/list_labels_upstream.yml +78 -0
  54. data/spec/vcr_cassettes/gitlab_com/list_issues.yml +5 -5
  55. data/spec/vcr_cassettes/gitlab_com/list_labels.yml +1 -1
  56. data/spec/vcr_cassettes/list_milestones.yml +15 -15
  57. data/spec/vcr_cassettes/list_milestones_upstream.yml +155 -0
  58. data/spec/vcr_cassettes/list_prs.yml +6 -6
  59. data/spec/vcr_cassettes/list_prs_upstream.yml +3 -3
  60. data/spec/vcr_cassettes/merge_pr.yml +2 -2
  61. data/spec/vcr_cassettes/merge_pr_with_branch_deletion.yml +2 -2
  62. metadata +24 -4
  63. data/lib/geet/utils/git.rb +0 -30
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 37b511c318e9f2cb1c18ecf1a1f247236c841040
4
- data.tar.gz: 61aeabbdbd6e3616e49247acf47ffbbbf18d8085
3
+ metadata.gz: a73b4ce8509349204e7abc8c667856acf8baa421
4
+ data.tar.gz: b94ef51efb18f859f7aa547cb718861a2ca03eeb
5
5
  SHA512:
6
- metadata.gz: 6692e7597431f0d0ef9d194030086112985f7f1f2e4e0b6b8caf3c6dbeea565fd3d22b7b0033cf3290bf156e6f331e4e70ea6b3cf3be962e45110aa32ffdf05c
7
- data.tar.gz: e57f240a2c9a3b0ecb65a874efa7f3c4c61e0102cd365c7a53ac6b2579367c37c95dae072014f33ac5d6077ca75df649aff0dd4e7912a92502503e5a6a0e554e
6
+ metadata.gz: f07424e685a1265e5e083889c9ee627893f63bbcb56d268b2fe5cfabd2e475f98bade4c9eca5e67da4a84e53e6652c3dbecb05fd5f4b3acbc8fe05819b9250d5
7
+ data.tar.gz: acabfcbaa84a7e3f0423706ca3a84a95ce779f8bf6771a6b1b02a7920a54b3068922ec241c61ad275af12fd7b08469ffd78fb91e575ecc0d8e335278a4aac968
data/Gemfile CHANGED
@@ -2,19 +2,15 @@
2
2
 
3
3
  source 'https://rubygems.org'
4
4
 
5
- git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
-
7
- gem 'simple_scripting', '~> 0.9.3'
8
- gem 'temp-fork-tp-filter', '= 0.0.3'
9
-
10
- group :development, :test do
11
- gem 'byebug', '~> 9.1.0'
12
- gem 'rake', '~> 12.3.0'
13
- gem 'rubocop', '~> 0.52.0'
14
- end
5
+ gemspec
15
6
 
16
7
  group :test do
17
8
  gem 'rspec', '~> 3.7.0'
18
9
  gem 'vcr', '~> 3.0.3'
19
10
  gem 'webmock', '~> 3.1.1'
20
11
  end
12
+
13
+ group :tools do
14
+ gem 'byebug', '~> 9.1.0'
15
+ gem 'rubocop', '~> 0.52.0'
16
+ end
data/Gemfile.lock CHANGED
@@ -1,3 +1,10 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ geet (0.3.0)
5
+ simple_scripting (~> 0.9.3)
6
+ temp-fork-tp-filter (= 0.0.3)
7
+
1
8
  GEM
2
9
  remote: https://rubygems.org/
3
10
  specs:
@@ -75,11 +82,10 @@ PLATFORMS
75
82
 
76
83
  DEPENDENCIES
77
84
  byebug (~> 9.1.0)
85
+ geet!
78
86
  rake (~> 12.3.0)
79
87
  rspec (~> 3.7.0)
80
88
  rubocop (~> 0.52.0)
81
- simple_scripting (~> 0.9.3)
82
- temp-fork-tp-filter (= 0.0.3)
83
89
  vcr (~> 3.0.3)
84
90
  webmock (~> 3.1.1)
85
91
 
data/README.md CHANGED
@@ -55,6 +55,31 @@ patterns are partial matches, so, for example, `johncarmack` will be matched as
55
55
 
56
56
  After creation, the issue page will be automatically opened in the default browser.
57
57
 
58
+ ### Using menus for options selection
59
+
60
+ Geet supports selecting options (labels, collaborators, etc.), using the `-` parameter:
61
+
62
+ $ geet issue create --label-patterns -
63
+
64
+ This will show a menu like the following:
65
+
66
+ Please select the label(s): (Use arrow keys, press Space to select and Enter to finish, and alphanumeric/underscore characters to filter)
67
+ ‣ ⬡ bug
68
+ ⬡ enhancement
69
+ ⬡ not_an_issue
70
+ ⬡ requires_design
71
+ ⬡ technical_debt
72
+ ⬡ top_priority
73
+ ⬡ ux
74
+
75
+ Typing alphanumeric keys and underscore will enable filtering:
76
+
77
+ Please select the label(s): (Filter: "b")
78
+ ‣ ⬡ bug
79
+ ⬡ technical_debt
80
+
81
+ When a filter is active, use `Backspace` to cancel the last character, and `Canc` to reset it.
82
+
58
83
  ### Create a PR (with label, reviewers, and assigned to self)
59
84
 
60
85
  Basic creation of a PR:
@@ -132,8 +157,8 @@ Examples:
132
157
 
133
158
  ## Development status
134
159
 
135
- Geet is in alpha status. Although I use it daily, new features are frequently added, and internal/external APIs/workflows may change.
160
+ Geet is in beta status. Although I use it daily, new features are frequently added, and internal/external APIs/workflows may change.
136
161
 
137
- The public release will be 1.0, and is expected to be released in February 2018 or earlier.
162
+ The public release will be 1.0.
138
163
 
139
164
  [BS img]: https://travis-ci.org/saveriomiroddi/geet.svg?branch=master
data/Rakefile CHANGED
@@ -1,5 +1,7 @@
1
1
  require 'rspec/core/rake_task'
2
2
 
3
- RSpec::Core::RakeTask.new(:spec)
3
+ RSpec::Core::RakeTask.new(:spec) do |task|
4
+ task.rspec_opts = ['--order rand']
5
+ end
4
6
 
5
7
  task default: :spec
data/bin/geet CHANGED
@@ -5,17 +5,20 @@ require_relative '../lib/geet/commandline/configuration.rb'
5
5
  require_relative '../lib/geet/commandline/commands.rb'
6
6
  require_relative '../lib/geet/commandline/editor.rb'
7
7
  require_relative '../lib/geet/git/repository.rb'
8
- require_relative '../lib/geet/utils/git.rb'
8
+ require_relative '../lib/geet/helpers/summary_helper.rb'
9
+ require_relative '../lib/geet/utils/git_client.rb'
9
10
  Dir[File.join(__dir__, '../lib/geet/services/*.rb')].each { |filename| require filename }
10
11
 
11
12
  class GeetLauncher
12
13
  include Geet
13
14
  include Geet::Commandline::Commands
15
+ include Geet::Helpers::SummaryHelper
16
+
17
+ SUMMARY_TEMPLATE = IO.read(File.expand_path('../lib/geet/resources/templates/edit_summary.md', __dir__))
14
18
 
15
19
  def launch
16
20
  command, options = Commandline::Configuration.new.decode_argv || exit
17
21
 
18
- # `:upstream` is always false in the gist command case.
19
22
  repository = Git::Repository.new(upstream: !!options[:upstream])
20
23
 
21
24
  case command
@@ -23,40 +26,57 @@ class GeetLauncher
23
26
  filename = options.delete(:filename)
24
27
  options[:publik] = options.delete(:public) if options.key?(:public)
25
28
 
26
- Services::CreateGist.new.execute(repository, filename, options)
29
+ Services::CreateGist.new.execute(filename, options)
27
30
  when ISSUE_CREATE_COMMAND
28
- title, description = Commandline::Editor.new.edit_summary
31
+ summary = options[:summary] || Commandline::Editor.new.edit_content(help: SUMMARY_TEMPLATE)
32
+ title, description = split_summary(summary)
33
+
29
34
  options[:milestone_pattern] = options.delete(:milestone) if options.key?(:milestone)
30
35
 
31
- Services::CreateIssue.new.execute(repository, title, description, options)
36
+ Services::CreateIssue.new(repository).execute(title, description, options)
32
37
  when LABEL_CREATE_COMMAND
33
38
  name = options.delete(:name)
34
39
 
35
- Services::CreateLabel.new.execute(repository, name, options)
40
+ Services::CreateLabel.new(repository).execute(name, options)
36
41
  when ISSUE_LIST_COMMAND
37
- Services::ListIssues.new.execute(repository, options)
42
+ Services::ListIssues.new(repository).execute(options)
38
43
  when LABEL_LIST_COMMAND
39
- Services::ListLabels.new.execute(repository)
44
+ Services::ListLabels.new(repository).execute
40
45
  when MILESTONE_LIST_COMMAND
41
- Services::ListMilestones.new.execute(repository)
46
+ Services::ListMilestones.new(repository).execute
42
47
  when PR_CREATE_COMMAND
43
- # Tricky. It would be best to have Git logic exlusively inside the services,
44
- # but at the same time, the summary editing should be out.
45
- git = Utils::Git.new(repository)
46
- summary = git.cherry('master').size == 1 ? git.show_description('HEAD') : ''
48
+ summary = options[:summary] || edit_pr_summary
49
+ title, description = split_summary(summary)
47
50
 
48
- title, description = Commandline::Editor.new.edit_summary(summary: summary)
49
51
  options[:milestone_pattern] = options.delete(:milestone) if options.key?(:milestone)
50
52
 
51
- Services::CreatePr.new.execute(repository, title, description, options)
53
+ Services::CreatePr.new(repository).execute(title, description, options)
52
54
  when PR_LIST_COMMAND
53
- Services::ListPrs.new.execute(repository)
55
+ Services::ListPrs.new(repository).execute
54
56
  when PR_MERGE_COMMAND
55
- Services::MergePr.new.execute(repository, options)
57
+ Services::MergePr.new(repository).execute(options)
56
58
  else
57
59
  raise "Internal error - Unrecognized command #{command.inspect}"
58
60
  end
59
61
  end
62
+
63
+ private
64
+
65
+ def edit_pr_summary
66
+ # Tricky. It would be best to have Git logic exlusively inside the services,
67
+ # but at the same time, the summary editing should be out.
68
+ git = Utils::GitClient.new
69
+ pr_commits = git.cherry('master')
70
+
71
+ if pr_commits.size == 1
72
+ prepopulated_summary = git.show_description('HEAD')
73
+ cancel_pr_help = "In order to cancel the PR creation, delete the description above.\n"
74
+
75
+ Commandline::Editor.new.edit_content(content: prepopulated_summary, help: SUMMARY_TEMPLATE + cancel_pr_help)
76
+ else
77
+ Commandline::Editor.new.edit_content(help: SUMMARY_TEMPLATE)
78
+ end
79
+ end
60
80
  end
61
81
 
62
82
  GeetLauncher.new.launch if $PROGRAM_NAME == __FILE__
data/geet.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
10
10
  s.platform = Gem::Platform::RUBY
11
11
  s.required_ruby_version = '>= 2.3.0'
12
12
  s.authors = ['Saverio Miroddi']
13
- s.date = '2018-01-19'
13
+ s.date = '2018-01-25'
14
14
  s.email = ['saverio.pub2@gmail.com']
15
15
  s.homepage = 'https://github.com/saveriomiroddi/geet'
16
16
  s.summary = 'Commandline interface for performing SCM (eg. GitHub) operations (eg. PR creation).'
@@ -20,6 +20,8 @@ Gem::Specification.new do |s|
20
20
  s.add_runtime_dependency 'simple_scripting', '~> 0.9.3'
21
21
  s.add_runtime_dependency 'temp-fork-tp-filter', '= 0.0.3'
22
22
 
23
+ s.add_development_dependency 'rake', '~> 12.3.0'
24
+
23
25
  s.files = `git ls-files`.split("\n")
24
26
  s.executables << 'geet'
25
27
  s.require_paths = ['lib']
@@ -24,13 +24,15 @@ module Geet
24
24
  ['-n', '--no-open-issue', "Don't open the issue link in the browser after creation"],
25
25
  ['-l', '--label-patterns "bug,help wanted"', 'Label patterns'],
26
26
  ['-m', '--milestone 1.5.0', 'Milestone title pattern'],
27
- ['-a', '--assignee-patterns john,tom,adrian,kevin', 'Assignee login patterns. Defaults to authenticated user'],
27
+ ['-a', '--assignee-patterns john,tom,adrian,kevin', 'Assignee login patterns'],
28
+ ['-s', '--summary title_and_description', 'Set the summary (title and optionally description'],
28
29
  ['-u', '--upstream', 'Create on the upstream repository'],
29
30
  long_help: 'The default editor will be opened for editing title and description.'
30
31
  ]
31
32
 
32
33
  LABEL_CREATE_OPTIONS = [
33
34
  ['-c', '--color color', '6-digits hex color; if not specified, a random one is created'],
35
+ ['-u', '--upstream', 'Create on the upstream repository'],
34
36
  'name',
35
37
  ].freeze
36
38
 
@@ -39,18 +41,29 @@ module Geet
39
41
  ['-u', '--upstream', 'List on the upstream repository'],
40
42
  ].freeze
41
43
 
42
- LABEL_LIST_OPTIONS = [].freeze
44
+ LABEL_LIST_OPTIONS = [
45
+ ['-u', '--upstream', 'List on the upstream repository'],
46
+ ].freeze
43
47
 
44
- MILESTONE_LIST_OPTIONS = [].freeze
48
+ MILESTONE_LIST_OPTIONS = [
49
+ ['-u', '--upstream', 'List on the upstream repository'],
50
+ ].freeze
45
51
 
46
52
  PR_CREATE_OPTIONS = [
53
+ ['-A', '--automated-mode', "Automate the branch operations (see long help)"],
47
54
  ['-n', '--no-open-pr', "Don't open the PR link in the browser after creation"],
48
55
  ['-l', '--label-patterns "legacy,code review"', 'Label patterns'],
49
56
  ['-m', '--milestone 1.5.0', 'Milestone title pattern'],
50
57
  ['-r', '--reviewer-patterns john,tom,adrian,kevin', 'Reviewer login patterns'],
58
+ ['-s', '--summary title_and_description', 'Set the summary (title and optionally description'],
51
59
  ['-u', '--upstream', 'Create on the upstream repository'],
52
- long_help: 'The default editor will be opened for editing title and description; if the PR adds one commit only, '\
53
- 'the content will be prepopulated with the commit description.'
60
+ long_help: <<~STR
61
+ The default editor will be opened for editing title and description; if the PR adds one commit only, the content will be prepopulated with the commit description.
62
+
63
+ The "automated mode" will automate branch operations:
64
+ - raise an error if the current tree is dirty;
65
+ - if the upstream branch is not present, it will create it, otherwise, it will perform a push.
66
+ STR
54
67
  ]
55
68
 
56
69
  PR_LIST_OPTIONS = [
@@ -7,23 +7,24 @@ require_relative '../helpers/os_helper.rb'
7
7
  module Geet
8
8
  module Commandline
9
9
  class Editor
10
- # Liberally ripp..., ahem, inspired from git.
11
- SUMMARY_TEMPLATE = File.expand_path('../resources/edit_summary_template.md', __dir__)
12
- SUMMARY_TEMPLATE_SEPARATOR = '------------------------ >8 ------------------------'
13
-
14
10
  include Geet::Helpers::OsHelper
15
11
 
16
- # Edits a summary in the default editor, providing the SUMMARY_TEMPLATE.
12
+ # Git style!
13
+ HELP_SEPARATOR = '------------------------ >8 ------------------------'
14
+
15
+ # Edits a content in the default editor, optionally providing help.
17
16
  #
18
- # A summary is a composition with a title and an optional description;
19
- # if the description is not found, a blank string is returned.
17
+ # When the help is provided, it's appended to the bottom, separated by HELP_SEPARATOR.
18
+ # The help is stripped after the content if edited.
20
19
  #
21
- def edit_summary(summary: '')
22
- full_summary = summary + IO.read(SUMMARY_TEMPLATE)
20
+ def edit_content(content: '', help: nil)
21
+ content += "\n\n" + HELP_SEPARATOR + "\n" + help if help
23
22
 
24
- raw_summary = edit_content_in_default_editor(full_summary)
23
+ edited_content = edit_content_in_default_editor(content)
25
24
 
26
- split_raw_summary(raw_summary)
25
+ edited_content = edited_content.split(HELP_SEPARATOR, 2).first if help
26
+
27
+ edited_content.strip
27
28
  end
28
29
 
29
30
  private
@@ -36,8 +37,9 @@ module Geet
36
37
  #
37
38
  def edit_content_in_default_editor(content)
38
39
  tempfile = Tempfile.open(['geet_editor', '.md']) { |file| file << content }.path
40
+ command = "#{system_editor} #{tempfile.shellescape}"
39
41
 
40
- execute_command('editing', system_editor, tempfile)
42
+ execute_command(command, description: 'editing', interactive: true)
41
43
 
42
44
  content = IO.read(tempfile)
43
45
 
@@ -46,18 +48,6 @@ module Geet
46
48
  content
47
49
  end
48
50
 
49
- def split_raw_summary(raw_summary)
50
- raw_summary, _ = raw_summary.strip.split(SUMMARY_TEMPLATE_SEPARATOR, 2)
51
-
52
- raise "Missing title!" if raw_summary.empty?
53
-
54
- title, description = raw_summary.split(/\r|\n/, 2)
55
-
56
- # The title may have a residual newline char; the description may not be present,
57
- # or have multiple blank lines.
58
- [title.strip, description.to_s.strip]
59
- end
60
-
61
51
  # HELPERS ##########################################################################
62
52
 
63
53
  def system_editor
@@ -1,28 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'shellwords'
4
+ require_relative '../utils/git_client'
4
5
 
5
6
  module Geet
6
7
  module Git
7
8
  # This class represents, for convenience, both the local and the remote repository, but the
8
9
  # remote code is separated in each provider module.
9
10
  class Repository
10
- # For simplicity, we match any character except the ones the separators.
11
- REMOTE_ORIGIN_REGEX = %r{
12
- \A
13
- (?:https://(.+?)/|git@(.+?):)
14
- ([^/]+/.*?)
15
- (?:\.git)?
16
- \Z
17
- }x
18
-
19
- ORIGIN_NAME = 'origin'
20
- UPSTREAM_NAME = 'upstream'
21
-
22
- def initialize(upstream: false, location: nil)
11
+ CONFIRM_ACTION_TEXT = <<~STR
12
+ WARNING! The action will be performed on a fork, but an upstream repository has been found!
13
+ Press Enter to continue, or Ctrl+C to exit now.
14
+ STR
15
+
16
+ DEFAULT_GIT_CLIENT = Geet::Utils::GitClient.new
17
+
18
+ def initialize(upstream: false, git_client: DEFAULT_GIT_CLIENT, warnings: true)
23
19
  @upstream = upstream
24
- @location = location
20
+ @git_client = git_client
25
21
  @api_token = extract_env_api_token
22
+ @warnings = warnings
26
23
  end
27
24
 
28
25
  # REMOTE FUNCTIONALITIES (REPOSITORY)
@@ -35,12 +32,8 @@ module Geet
35
32
  attempt_provider_call(:Label, :list, api_interface)
36
33
  end
37
34
 
38
- def create_gist(filename, content, description: nil, publik: false)
39
- attempt_provider_call(:Gist, :create, filename, content, api_interface, description: description, publik: publik)
40
- end
41
-
42
35
  def create_issue(title, description)
43
- ask_confirm_action if location_action_with_upstream_repository?
36
+ ask_confirm_action if local_action_with_upstream_repository? && @warnings
44
37
  attempt_provider_call(:Issue, :create, title, description, api_interface)
45
38
  end
46
39
 
@@ -69,7 +62,7 @@ module Geet
69
62
  end
70
63
 
71
64
  def create_pr(title, description, head)
72
- ask_confirm_action if location_action_with_upstream_repository?
65
+ ask_confirm_action if local_action_with_upstream_repository? && @warnings
73
66
  attempt_provider_call(:PR, :create, title, description, head, api_interface)
74
67
  end
75
68
 
@@ -85,69 +78,25 @@ module Geet
85
78
 
86
79
  # OTHER/CONVENIENCE FUNCTIONALITIES
87
80
 
88
- def current_branch
89
- gitdir_option = "--git-dir #{@location.shellescape}/.git" if @location
90
- branch = `git #{gitdir_option} rev-parse --abbrev-ref HEAD`.strip
91
-
92
- raise "Couldn't find current branch" if branch == 'HEAD'
93
-
94
- branch
81
+ def upstream?
82
+ @upstream
95
83
  end
96
84
 
97
85
  private
98
86
 
99
- # REPOSITORY METADATA
100
-
101
- # The result is in the format `git@github.com:donaldduck/geet.git`
102
- #
103
- def remote(name)
104
- gitdir_option = "--git-dir #{@location.shellescape}/.git" if @location
105
- remote_url = `git #{gitdir_option} ls-remote --get-url #{name}`.strip
106
-
107
- if remote_url == name
108
- raise "Remote #{name.inspect} not found!"
109
- elsif remote_url !~ REMOTE_ORIGIN_REGEX
110
- raise "Unexpected remote reference format: #{remote_url.inspect}"
111
- end
112
-
113
- remote_url
114
- end
115
-
116
- # "Lightweight" version of #remote.
117
- # Doesn't sanity check for the remote url format; this action is for querying
118
- # purposes, any any action that needs to work with the remote, uses #remote.
119
- #
120
- def has_remote?(name)
121
- gitdir_option = "--git-dir #{@location.shellescape}/.git" if @location
122
- remote_url = `git #{gitdir_option} ls-remote --get-url #{name}`.strip
123
-
124
- remote_url != name
125
- end
126
-
127
87
  # PROVIDER
128
88
 
129
89
  def extract_env_api_token
130
- env_variable_name = "#{provider_domain[/(.*)\.\w+/, 1].upcase}_API_TOKEN"
90
+ provider_name = @git_client.provider_domain[/(.*)\.\w+/, 1]
91
+ env_variable_name = "#{provider_name.upcase}_API_TOKEN"
131
92
 
132
93
  ENV[env_variable_name] || raise("#{env_variable_name} not set!")
133
94
  end
134
95
 
135
- def provider_domain
136
- # We assume that it's not possible to have origin and upstream on different providers.
137
- #
138
- remote_url = remote(ORIGIN_NAME)
139
-
140
- domain = remote_url[REMOTE_ORIGIN_REGEX, 1] || remote_url[REMOTE_ORIGIN_REGEX, 2]
141
-
142
- raise "Can't identify domain in the provider domain string: #{provider_domain}" if domain !~ /(.*)\.\w+/
143
-
144
- domain
145
- end
146
-
147
96
  # Attempt to find the provider class and send the specified method, returning a friendly
148
97
  # error (functionality X [Y] is missing) when a class/method is missing.
149
98
  def attempt_provider_call(class_name, meth, *args)
150
- module_name = provider_domain[/(.*)\.\w+/, 1].capitalize
99
+ module_name = provider_name.capitalize
151
100
 
152
101
  require_provider_modules
153
102
 
@@ -167,8 +116,7 @@ module Geet
167
116
  end
168
117
 
169
118
  def require_provider_modules
170
- provider_dirname = provider_domain[/(.*)\.\w+/, 1]
171
- files_pattern = "#{__dir__}/../#{provider_dirname}/*.rb"
119
+ files_pattern = "#{__dir__}/../#{provider_name}/*.rb"
172
120
 
173
121
  Dir[files_pattern].each { |filename| require filename }
174
122
  end
@@ -176,25 +124,23 @@ module Geet
176
124
  # OTHER HELPERS
177
125
 
178
126
  def api_interface
179
- attempt_provider_call(:ApiInterface, :new, @api_token, path(upstream: @upstream), @upstream)
180
- end
181
-
182
- # Example: `donaldduck/geet`
183
- #
184
- def path(upstream: false)
185
- remote_name = upstream ? UPSTREAM_NAME : ORIGIN_NAME
186
-
187
- remote(remote_name)[REMOTE_ORIGIN_REGEX, 3]
127
+ path = @git_client.path(upstream: @upstream)
128
+ attempt_provider_call(:ApiInterface, :new, @api_token, repo_path: path, upstream: @upstream)
188
129
  end
189
130
 
190
131
  def ask_confirm_action
191
- puts "WARNING! The action will be performed on a fork, but an upstream repository has been found!"
192
- print "Press Enter to continue, or Ctrl+C to exit now."
132
+ print CONFIRM_ACTION_TEXT.rstrip
193
133
  gets
194
134
  end
195
135
 
196
- def location_action_with_upstream_repository?
197
- has_remote?('upstream') && !@upstream
136
+ def local_action_with_upstream_repository?
137
+ @git_client.remote_defined?('upstream') && !@upstream
138
+ end
139
+
140
+ # Bare downcase provider name, eg. `github`
141
+ #
142
+ def provider_name
143
+ @git_client.provider_domain[/(.*)\.\w+/, 1]
198
144
  end
199
145
  end
200
146
  end