geet 0.3.12 → 0.3.17
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +8 -0
- data/README.md +2 -0
- data/bin/geet +23 -6
- data/extra/anonymize_vcr_data +58 -0
- data/geet.gemspec +1 -1
- data/lib/geet/commandline/commands.rb +4 -0
- data/lib/geet/commandline/configuration.rb +23 -0
- data/lib/geet/git/repository.rb +13 -1
- data/lib/geet/github/abstract_issue.rb +9 -0
- data/lib/geet/github/branch.rb +1 -1
- data/lib/geet/github/issue.rb +1 -1
- data/lib/geet/github/label.rb +2 -2
- data/lib/geet/github/milestone.rb +29 -2
- data/lib/geet/github/user.rb +2 -2
- data/lib/geet/gitlab/label.rb +2 -2
- data/lib/geet/gitlab/milestone.rb +1 -1
- data/lib/geet/gitlab/user.rb +1 -1
- data/lib/geet/helpers/services_workflow_helper.rb +33 -0
- data/lib/geet/services/close_milestones.rb +46 -0
- data/lib/geet/services/comment_pr.rb +31 -0
- data/lib/geet/services/create_issue.rb +5 -3
- data/lib/geet/services/create_milestone.rb +24 -0
- data/lib/geet/services/create_pr.rb +5 -3
- data/lib/geet/services/list_issues.rb +4 -1
- data/lib/geet/services/merge_pr.rb +55 -15
- data/lib/geet/services/open_pr.rb +30 -0
- data/lib/geet/shared/branches.rb +9 -0
- data/lib/geet/shared/selection.rb +3 -0
- data/lib/geet/utils/attributes_selection_manager.rb +5 -3
- data/lib/geet/utils/git_client.rb +61 -11
- data/lib/geet/version.rb +1 -1
- data/spec/integration/comment_pr_spec.rb +44 -0
- data/spec/integration/create_issue_spec.rb +1 -1
- data/spec/integration/create_milestone_spec.rb +34 -0
- data/spec/integration/merge_pr_spec.rb +26 -1
- data/spec/integration/open_pr_spec.rb +44 -0
- data/spec/vcr_cassettes/create_gist_private.yml +1 -1
- data/spec/vcr_cassettes/create_gist_public.yml +1 -1
- data/spec/vcr_cassettes/create_issue.yml +13 -13
- data/spec/vcr_cassettes/create_issue_upstream.yml +2 -2
- data/spec/vcr_cassettes/github_com/comment_pr.yml +161 -0
- data/spec/vcr_cassettes/github_com/create_label.yml +1 -1
- data/spec/vcr_cassettes/github_com/create_label_upstream.yml +1 -1
- data/spec/vcr_cassettes/github_com/create_label_with_random_color.yml +1 -1
- data/spec/vcr_cassettes/github_com/create_milestone.yml +82 -0
- data/spec/vcr_cassettes/github_com/create_pr.yml +16 -16
- data/spec/vcr_cassettes/github_com/create_pr_in_auto_mode_create_upstream.yml +7 -7
- data/spec/vcr_cassettes/github_com/create_pr_in_auto_mode_with_push.yml +7 -7
- data/spec/vcr_cassettes/github_com/create_pr_upstream.yml +8 -8
- data/spec/vcr_cassettes/github_com/create_pr_upstream_without_write_permissions.yml +3 -3
- data/spec/vcr_cassettes/github_com/list_issues.yml +5 -5
- data/spec/vcr_cassettes/github_com/list_issues_upstream.yml +6 -6
- data/spec/vcr_cassettes/github_com/list_issues_with_assignee.yml +4 -4
- data/spec/vcr_cassettes/github_com/list_labels.yml +1 -1
- data/spec/vcr_cassettes/github_com/list_labels_upstream.yml +1 -1
- data/spec/vcr_cassettes/github_com/list_milestones.yml +50 -50
- data/spec/vcr_cassettes/github_com/merge_pr.yml +2 -2
- data/spec/vcr_cassettes/github_com/merge_pr_with_branch_deletion.yml +2 -2
- data/spec/vcr_cassettes/github_com/open_pr.yml +81 -0
- data/spec/vcr_cassettes/gitlab_com/create_label.yml +1 -1
- data/spec/vcr_cassettes/gitlab_com/list_issues.yml +4 -4
- data/spec/vcr_cassettes/gitlab_com/list_issues_with_assignee.yml +8 -8
- data/spec/vcr_cassettes/gitlab_com/list_labels.yml +1 -1
- data/spec/vcr_cassettes/gitlab_com/list_milestones.yml +9 -9
- data/spec/vcr_cassettes/gitlab_com/merge_pr.yml +5 -5
- data/spec/vcr_cassettes/list_milestones_upstream.yml +21 -21
- data/spec/vcr_cassettes/list_prs.yml +10 -10
- data/spec/vcr_cassettes/list_prs_upstream.yml +10 -10
- metadata +16 -4
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'English'
|
4
|
+
require 'open3'
|
5
|
+
require 'shellwords'
|
6
|
+
|
7
|
+
module Geet
|
8
|
+
module Helpers
|
9
|
+
# Helper for services common workflow, for example, find the merge head.
|
10
|
+
#
|
11
|
+
module ServicesWorkflowHelper
|
12
|
+
# Requires: @git_client
|
13
|
+
#
|
14
|
+
def find_merge_head
|
15
|
+
[@git_client.owner, @git_client.current_branch]
|
16
|
+
end
|
17
|
+
|
18
|
+
# Expect to find only one.
|
19
|
+
#
|
20
|
+
# Requires: @out, @repository.
|
21
|
+
#
|
22
|
+
def checked_find_branch_pr(owner, head)
|
23
|
+
@out.puts "Finding PR with head (#{owner}:#{head})..."
|
24
|
+
|
25
|
+
prs = @repository.prs(owner: owner, head: head)
|
26
|
+
|
27
|
+
raise "Expected to find only one PR for the current branch; found: #{prs.size}" if prs.size != 1
|
28
|
+
|
29
|
+
prs[0]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../shared/selection'
|
4
|
+
|
5
|
+
module Geet
|
6
|
+
module Services
|
7
|
+
class CloseMilestones
|
8
|
+
include Geet::Shared::Selection
|
9
|
+
|
10
|
+
def initialize(repository, out: $stdout)
|
11
|
+
@repository = repository
|
12
|
+
@out = out
|
13
|
+
end
|
14
|
+
|
15
|
+
def execute(numbers: nil)
|
16
|
+
numbers = find_and_select_milestone_numbers(numbers)
|
17
|
+
|
18
|
+
close_milestone_threads = close_milestones(numbers)
|
19
|
+
|
20
|
+
close_milestone_threads.each(&:join)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def find_and_select_milestone_numbers(numbers)
|
26
|
+
selection_manager = Geet::Utils::AttributesSelectionManager.new(@repository, out: @out)
|
27
|
+
|
28
|
+
selection_manager.add_attribute(:milestones, 'milestone', numbers, SELECTION_MULTIPLE, name_method: :title)
|
29
|
+
|
30
|
+
milestones = selection_manager.select_attributes[0]
|
31
|
+
|
32
|
+
milestones.map(&:number)
|
33
|
+
end
|
34
|
+
|
35
|
+
def close_milestones(numbers)
|
36
|
+
@out.puts "Closing milestones #{numbers.join(', ')}..."
|
37
|
+
|
38
|
+
numbers.map do |number|
|
39
|
+
Thread.new do
|
40
|
+
@repository.close_milestone(number)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end # CloseMilestones
|
45
|
+
end # Services
|
46
|
+
end # Geet
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../helpers/os_helper'
|
4
|
+
require_relative '../helpers/services_workflow_helper'
|
5
|
+
|
6
|
+
module Geet
|
7
|
+
module Services
|
8
|
+
# Add a comment to the PR for the current branch.
|
9
|
+
#
|
10
|
+
class CommentPr
|
11
|
+
include Geet::Helpers::OsHelper
|
12
|
+
include Geet::Helpers::ServicesWorkflowHelper
|
13
|
+
|
14
|
+
DEFAULT_GIT_CLIENT = Geet::Utils::GitClient.new
|
15
|
+
|
16
|
+
def initialize(repository, out: $stdout, git_client: DEFAULT_GIT_CLIENT)
|
17
|
+
@repository = repository
|
18
|
+
@out = out
|
19
|
+
@git_client = git_client
|
20
|
+
end
|
21
|
+
|
22
|
+
def execute(comment, no_open_pr: nil)
|
23
|
+
merge_owner, merge_head = find_merge_head
|
24
|
+
pr = checked_find_branch_pr(merge_owner, merge_head)
|
25
|
+
pr.comment(comment)
|
26
|
+
open_file_with_default_application(pr.link) unless no_open_pr
|
27
|
+
pr
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -2,11 +2,13 @@
|
|
2
2
|
|
3
3
|
require_relative 'abstract_create_issue'
|
4
4
|
require_relative '../shared/repo_permissions'
|
5
|
+
require_relative '../shared/selection'
|
5
6
|
|
6
7
|
module Geet
|
7
8
|
module Services
|
8
9
|
class CreateIssue < AbstractCreateIssue
|
9
10
|
include Geet::Shared::RepoPermissions
|
11
|
+
include Geet::Shared::Selection
|
10
12
|
|
11
13
|
# options:
|
12
14
|
# :labels
|
@@ -56,9 +58,9 @@ module Geet
|
|
56
58
|
def find_and_select_attributes(labels, milestone, assignees)
|
57
59
|
selection_manager = Geet::Utils::AttributesSelectionManager.new(@repository, out: @out)
|
58
60
|
|
59
|
-
selection_manager.add_attribute(:labels, 'label', labels,
|
60
|
-
selection_manager.add_attribute(:milestones, 'milestone', milestone,
|
61
|
-
selection_manager.add_attribute(:collaborators, 'assignee', assignees,
|
61
|
+
selection_manager.add_attribute(:labels, 'label', labels, SELECTION_MULTIPLE, name_method: :name) if labels
|
62
|
+
selection_manager.add_attribute(:milestones, 'milestone', milestone, SELECTION_SINGLE, name_method: :title) if milestone
|
63
|
+
selection_manager.add_attribute(:collaborators, 'assignee', assignees, SELECTION_MULTIPLE, name_method: :username) if assignees
|
62
64
|
|
63
65
|
selection_manager.select_attributes
|
64
66
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Geet
|
4
|
+
module Services
|
5
|
+
class CreateMilestone
|
6
|
+
def initialize(repository, out: $stdout)
|
7
|
+
@repository = repository
|
8
|
+
@out = out
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute(title)
|
12
|
+
create_milestone(title)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def create_milestone(title)
|
18
|
+
@out.puts 'Creating milestone...'
|
19
|
+
|
20
|
+
@repository.create_milestone(title)
|
21
|
+
end
|
22
|
+
end # class CreateMilestone
|
23
|
+
end # module Services
|
24
|
+
end # module Geet
|
@@ -2,11 +2,13 @@
|
|
2
2
|
|
3
3
|
require_relative 'abstract_create_issue'
|
4
4
|
require_relative '../shared/repo_permissions'
|
5
|
+
require_relative '../shared/selection'
|
5
6
|
|
6
7
|
module Geet
|
7
8
|
module Services
|
8
9
|
class CreatePr < AbstractCreateIssue
|
9
10
|
include Geet::Shared::RepoPermissions
|
11
|
+
include Geet::Shared::Selection
|
10
12
|
|
11
13
|
DEFAULT_GIT_CLIENT = Geet::Utils::GitClient.new
|
12
14
|
|
@@ -66,11 +68,11 @@ module Geet
|
|
66
68
|
def find_and_select_attributes(labels, milestone, reviewers)
|
67
69
|
selection_manager = Geet::Utils::AttributesSelectionManager.new(@repository, out: @out)
|
68
70
|
|
69
|
-
selection_manager.add_attribute(:labels, 'label', labels,
|
70
|
-
selection_manager.add_attribute(:milestones, 'milestone', milestone,
|
71
|
+
selection_manager.add_attribute(:labels, 'label', labels, SELECTION_MULTIPLE, name_method: :name) if labels
|
72
|
+
selection_manager.add_attribute(:milestones, 'milestone', milestone, SELECTION_SINGLE, name_method: :title) if milestone
|
71
73
|
|
72
74
|
if reviewers
|
73
|
-
selection_manager.add_attribute(:collaborators, 'reviewer', reviewers,
|
75
|
+
selection_manager.add_attribute(:collaborators, 'reviewer', reviewers, SELECTION_MULTIPLE, name_method: :username) do |all_reviewers|
|
74
76
|
authenticated_user = @repository.authenticated_user
|
75
77
|
all_reviewers.delete_if { |reviewer| reviewer.username == authenticated_user.username }
|
76
78
|
end
|
@@ -1,10 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../utils/attributes_selection_manager'
|
4
|
+
require_relative '../shared/selection'
|
4
5
|
|
5
6
|
module Geet
|
6
7
|
module Services
|
7
8
|
class ListIssues
|
9
|
+
include Geet::Shared::Selection
|
10
|
+
|
8
11
|
def initialize(repository, out: $stdout)
|
9
12
|
@repository = repository
|
10
13
|
@out = out
|
@@ -25,7 +28,7 @@ module Geet
|
|
25
28
|
def find_and_select_attributes(assignee)
|
26
29
|
selection_manager = Geet::Utils::AttributesSelectionManager.new(@repository, out: @out)
|
27
30
|
|
28
|
-
selection_manager.add_attribute(:collaborators, 'assignee', assignee,
|
31
|
+
selection_manager.add_attribute(:collaborators, 'assignee', assignee, SELECTION_SINGLE, name_method: :username)
|
29
32
|
|
30
33
|
selection_manager.select_attributes[0]
|
31
34
|
end
|
@@ -1,5 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative '../helpers/services_workflow_helper'
|
4
|
+
require_relative '../shared/branches'
|
5
|
+
|
3
6
|
module Geet
|
4
7
|
module Services
|
5
8
|
# Merges the PR for the current branch.
|
@@ -9,6 +12,9 @@ module Geet
|
|
9
12
|
# constraints, but speeds up the workflow.
|
10
13
|
#
|
11
14
|
class MergePr
|
15
|
+
include Geet::Helpers::ServicesWorkflowHelper
|
16
|
+
include Geet::Shared::Branches
|
17
|
+
|
12
18
|
DEFAULT_GIT_CLIENT = Geet::Utils::GitClient.new
|
13
19
|
|
14
20
|
def initialize(repository, out: $stdout, git_client: DEFAULT_GIT_CLIENT)
|
@@ -20,38 +26,72 @@ module Geet
|
|
20
26
|
def execute(delete_branch: false)
|
21
27
|
merge_owner, merge_head = find_merge_head
|
22
28
|
pr = checked_find_branch_pr(merge_owner, merge_head)
|
29
|
+
|
23
30
|
merge_pr(pr)
|
24
|
-
|
31
|
+
|
32
|
+
if delete_branch
|
33
|
+
branch = @git_client.current_branch
|
34
|
+
|
35
|
+
delete_remote_branch(branch)
|
36
|
+
end
|
37
|
+
|
38
|
+
fetch_repository
|
39
|
+
|
40
|
+
if upstream_branch_gone?
|
41
|
+
pr_branch = @git_client.current_branch
|
42
|
+
|
43
|
+
# The rebase could also be placed after the branch deletion. There are pros/cons;
|
44
|
+
# currently, it's not important.
|
45
|
+
#
|
46
|
+
checkout_branch(MAIN_BRANCH)
|
47
|
+
rebase
|
48
|
+
|
49
|
+
delete_local_branch(pr_branch)
|
50
|
+
end
|
51
|
+
|
25
52
|
pr
|
26
53
|
end
|
27
54
|
|
28
55
|
private
|
29
56
|
|
30
|
-
def
|
31
|
-
|
57
|
+
def merge_pr(pr)
|
58
|
+
@out.puts "Merging PR ##{pr.number}..."
|
59
|
+
|
60
|
+
pr.merge
|
32
61
|
end
|
33
62
|
|
34
|
-
|
35
|
-
|
36
|
-
@out.puts "Finding PR with head (#{owner}:#{head})..."
|
63
|
+
def delete_remote_branch(branch)
|
64
|
+
@out.puts "Deleting remote branch #{branch}..."
|
37
65
|
|
38
|
-
|
66
|
+
@repository.delete_branch(branch)
|
67
|
+
end
|
39
68
|
|
40
|
-
|
69
|
+
def fetch_repository
|
70
|
+
@out.puts "Fetching repository..."
|
41
71
|
|
42
|
-
|
72
|
+
@git_client.fetch
|
43
73
|
end
|
44
74
|
|
45
|
-
def
|
46
|
-
@
|
75
|
+
def upstream_branch_gone?
|
76
|
+
@git_client.upstream_branch_gone?
|
77
|
+
end
|
47
78
|
|
48
|
-
|
79
|
+
def checkout_branch(branch)
|
80
|
+
@out.puts "Checking out #{branch}..."
|
81
|
+
|
82
|
+
@git_client.checkout(branch)
|
83
|
+
end
|
84
|
+
|
85
|
+
def rebase
|
86
|
+
@out.puts "Rebasing..."
|
87
|
+
|
88
|
+
@git_client.rebase
|
49
89
|
end
|
50
90
|
|
51
|
-
def
|
52
|
-
@out.puts "Deleting branch #{
|
91
|
+
def delete_local_branch(branch)
|
92
|
+
@out.puts "Deleting local branch #{branch}..."
|
53
93
|
|
54
|
-
@
|
94
|
+
@git_client.delete_branch(branch)
|
55
95
|
end
|
56
96
|
end
|
57
97
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../helpers/os_helper'
|
4
|
+
require_relative '../helpers/services_workflow_helper'
|
5
|
+
|
6
|
+
module Geet
|
7
|
+
module Services
|
8
|
+
# Open in the browser the PR for the current branch.
|
9
|
+
#
|
10
|
+
class OpenPr
|
11
|
+
include Geet::Helpers::OsHelper
|
12
|
+
include Geet::Helpers::ServicesWorkflowHelper
|
13
|
+
|
14
|
+
DEFAULT_GIT_CLIENT = Geet::Utils::GitClient.new
|
15
|
+
|
16
|
+
def initialize(repository, out: $stdout, git_client: DEFAULT_GIT_CLIENT)
|
17
|
+
@repository = repository
|
18
|
+
@out = out
|
19
|
+
@git_client = git_client
|
20
|
+
end
|
21
|
+
|
22
|
+
def execute(delete_branch: false)
|
23
|
+
merge_owner, merge_head = find_merge_head
|
24
|
+
pr = checked_find_branch_pr(merge_owner, merge_head)
|
25
|
+
open_file_with_default_application(pr.link)
|
26
|
+
pr
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -30,8 +30,10 @@ module Geet
|
|
30
30
|
@selections_data = []
|
31
31
|
end
|
32
32
|
|
33
|
+
# selection_type: SELECTION_SINGLE or SELECTION_MULTIPLE
|
34
|
+
#
|
33
35
|
def add_attribute(repository_call, description, pattern, selection_type, name_method: nil, &pre_selection_hook)
|
34
|
-
raise "Unrecognized selection type #{selection_type.inspect}" if ![
|
36
|
+
raise "Unrecognized selection type #{selection_type.inspect}" if ![SELECTION_SINGLE, SELECTION_MULTIPLE].include?(selection_type)
|
35
37
|
|
36
38
|
finder_thread = find_attribute_entries(repository_call)
|
37
39
|
|
@@ -47,9 +49,9 @@ module Geet
|
|
47
49
|
entries = pre_selection_hook.(entries) if pre_selection_hook
|
48
50
|
|
49
51
|
case selection_type
|
50
|
-
when
|
52
|
+
when SELECTION_SINGLE
|
51
53
|
select_entry(description, entries, pattern, name_method)
|
52
|
-
when
|
54
|
+
when SELECTION_MULTIPLE
|
53
55
|
select_entries(description, entries, pattern, name_method)
|
54
56
|
end
|
55
57
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'English'
|
3
4
|
require 'shellwords'
|
4
5
|
require_relative '../helpers/os_helper'
|
5
6
|
|
@@ -38,13 +39,13 @@ module Geet
|
|
38
39
|
# (which start with `-`)
|
39
40
|
#
|
40
41
|
def cherry(limit)
|
41
|
-
raw_commits =
|
42
|
+
raw_commits = execute_git_command("cherry #{limit.shellescape}")
|
42
43
|
|
43
44
|
raw_commits.split("\n").grep(/^\+/).map { |line| line[3..-1] }
|
44
45
|
end
|
45
46
|
|
46
47
|
def current_branch
|
47
|
-
branch =
|
48
|
+
branch = execute_git_command("rev-parse --abbrev-ref HEAD")
|
48
49
|
|
49
50
|
raise "Couldn't find current branch" if branch == 'HEAD'
|
50
51
|
|
@@ -53,12 +54,14 @@ module Geet
|
|
53
54
|
|
54
55
|
# Not to be confused with `upstream` repository!
|
55
56
|
#
|
57
|
+
# This API doesn't reveal if the remote branch is gone.
|
58
|
+
#
|
56
59
|
# return: nil, if the upstream branch is not configured.
|
57
60
|
#
|
58
61
|
def upstream_branch
|
59
|
-
head_symbolic_ref =
|
62
|
+
head_symbolic_ref = execute_git_command("symbolic-ref -q HEAD")
|
60
63
|
|
61
|
-
raw_upstream_branch =
|
64
|
+
raw_upstream_branch = execute_git_command("for-each-ref --format='%(upstream:short)' #{head_symbolic_ref.shellescape}").strip
|
62
65
|
|
63
66
|
if raw_upstream_branch != ''
|
64
67
|
raw_upstream_branch[UPSTREAM_BRANCH_REGEX, 1] || raise("Unexpected upstream format: #{raw_upstream_branch}")
|
@@ -67,8 +70,30 @@ module Geet
|
|
67
70
|
end
|
68
71
|
end
|
69
72
|
|
73
|
+
# TODO: May be merged with :upstream_branch, although it would require designing how a gone
|
74
|
+
# remote branch is expressed.
|
75
|
+
#
|
76
|
+
# Sample command output:
|
77
|
+
#
|
78
|
+
# ## add_milestone_closing...origin/add_milestone_closing [gone]
|
79
|
+
# M spec/integration/merge_pr_spec.rb
|
80
|
+
#
|
81
|
+
def upstream_branch_gone?
|
82
|
+
git_command = "status -b --porcelain"
|
83
|
+
status_output = execute_git_command(git_command)
|
84
|
+
|
85
|
+
# Simplified branch naming pattern. The exact one (see https://stackoverflow.com/a/3651867)
|
86
|
+
# is not worth implementing.
|
87
|
+
#
|
88
|
+
if status_output =~ %r(^## .+\.\.\..+?( \[gone\])?$)
|
89
|
+
!!$LAST_MATCH_INFO[1]
|
90
|
+
else
|
91
|
+
raise "Unexpected git command #{git_command.inspect} output: #{status_output}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
70
95
|
def working_tree_clean?
|
71
|
-
git_message =
|
96
|
+
git_message = execute_git_command("status")
|
72
97
|
|
73
98
|
!!(git_message =~ CLEAN_TREE_MESSAGE_REGEX)
|
74
99
|
end
|
@@ -80,7 +105,7 @@ module Geet
|
|
80
105
|
# Show the description ("<subject>\n\n<body>") for the given git object.
|
81
106
|
#
|
82
107
|
def show_description(object)
|
83
|
-
|
108
|
+
execute_git_command("show --quiet --format='%s\n\n%b' #{object.shellescape}")
|
84
109
|
end
|
85
110
|
|
86
111
|
##########################################################################
|
@@ -117,7 +142,7 @@ module Geet
|
|
117
142
|
# The result is in the format `git@github.com:donaldduck/geet.git`
|
118
143
|
#
|
119
144
|
def remote(name)
|
120
|
-
remote_url =
|
145
|
+
remote_url = execute_git_command("ls-remote --get-url #{name}")
|
121
146
|
|
122
147
|
if remote_url == name
|
123
148
|
raise "Remote #{name.inspect} not found!"
|
@@ -132,7 +157,7 @@ module Geet
|
|
132
157
|
# purposes, any any action that needs to work with the remote, uses #remote.
|
133
158
|
#
|
134
159
|
def remote_defined?(name)
|
135
|
-
remote_url =
|
160
|
+
remote_url = execute_git_command("ls-remote --get-url #{name}")
|
136
161
|
|
137
162
|
# If the remote is not define, `git ls-remote` will return the passed value.
|
138
163
|
remote_url != name
|
@@ -142,12 +167,32 @@ module Geet
|
|
142
167
|
# OPERATION APIS
|
143
168
|
##########################################################################
|
144
169
|
|
170
|
+
def checkout(branch)
|
171
|
+
execute_git_command("checkout #{branch.shellescape}")
|
172
|
+
end
|
173
|
+
|
174
|
+
# Unforced deletion.
|
175
|
+
#
|
176
|
+
def delete_branch(branch)
|
177
|
+
execute_git_command("branch --delete #{branch.shellescape}")
|
178
|
+
end
|
179
|
+
|
180
|
+
def rebase
|
181
|
+
execute_git_command("rebase")
|
182
|
+
end
|
183
|
+
|
145
184
|
# upstream_branch: create an upstream branch.
|
146
185
|
#
|
147
186
|
def push(upstream_branch: nil)
|
148
187
|
upstream_branch_option = "-u origin #{upstream_branch.shellescape}" if upstream_branch
|
149
188
|
|
150
|
-
|
189
|
+
execute_git_command("push #{upstream_branch_option}")
|
190
|
+
end
|
191
|
+
|
192
|
+
# Performs pruning.
|
193
|
+
#
|
194
|
+
def fetch
|
195
|
+
execute_git_command("fetch --prune")
|
151
196
|
end
|
152
197
|
|
153
198
|
##########################################################################
|
@@ -156,8 +201,13 @@ module Geet
|
|
156
201
|
|
157
202
|
private
|
158
203
|
|
159
|
-
|
160
|
-
|
204
|
+
# If executing a git command without calling this API, don't forget to split `gitdir_option`
|
205
|
+
# and use it!
|
206
|
+
#
|
207
|
+
def execute_git_command(command)
|
208
|
+
gitdir_option = "-C #{@location.shellescape}" if @location
|
209
|
+
|
210
|
+
execute_command("git #{gitdir_option} #{command}")
|
161
211
|
end
|
162
212
|
end
|
163
213
|
end
|