octo_merge 0.5.0 → 0.6.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.
- checksums.yaml +4 -4
- data/.travis.yml +4 -0
- data/README.md +46 -38
- data/TODO.md +3 -3
- data/bin/octo-merge +9 -0
- data/exe/octo-merge +3 -85
- data/lib/git.rb +21 -1
- data/lib/octo_merge.rb +2 -0
- data/lib/octo_merge/cli.rb +44 -0
- data/lib/octo_merge/cli/parser.rb +98 -0
- data/lib/octo_merge/interactive_pull_requests.rb +13 -20
- data/lib/octo_merge/options.rb +97 -0
- data/lib/octo_merge/pull_request.rb +5 -1
- data/lib/octo_merge/strategy/base.rb +15 -0
- data/lib/octo_merge/strategy/merge_with_rebase.rb +16 -7
- data/lib/octo_merge/strategy/merge_with_rebase_and_message.rb +9 -8
- data/lib/octo_merge/strategy/merge_without_rebase.rb +13 -6
- data/lib/octo_merge/strategy/rebase.rb +8 -7
- data/lib/octo_merge/version.rb +1 -1
- data/octo_merge.gemspec +1 -0
- metadata +20 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2482c938e80d647236fe97a04dbc6c1cfe37030
|
4
|
+
data.tar.gz: 3d73221e7a4333a12fb0c1c8cfb8b41654295ec2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 020c3885470f6fc1c9d75c0f37ee544213d5d723fd6fd2033eec035eb9ab66c257c383a73422fab703dd7309bb8c131ac10d1dd44b9fcf472813c2ef3c02168d
|
7
|
+
data.tar.gz: e0aeca7a705de6167661542eac69f5e803356c1ff6cb89682976c839a5a74c4cc7ade18c466770e07689cd510ded70a94315c4a3e99f8a01367a666945c6aefd
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -39,56 +39,64 @@ octo-merge \
|
|
39
39
|
--strategy=MergeWithRebase
|
40
40
|
```
|
41
41
|
|
42
|
-
* You can find
|
42
|
+
* You can find your API token [here](https://github.com/settings/tokens)
|
43
43
|
|
44
|
-
##
|
44
|
+
## Available Strategies
|
45
|
+
|
46
|
+
* NOTE: All strategies are using read-only branches for a specific pull requests.
|
47
|
+
This way we avoid adding lot of remotes.
|
48
|
+
* Read more: [Checking out pull requests locally](https://help.github.com/articles/checking-out-pull-requests-locally/)
|
45
49
|
|
46
50
|
### MergeWithoutRebase
|
47
51
|
|
48
|
-
```
|
49
|
-
|
50
|
-
git
|
51
|
-
git
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
git
|
56
|
-
git
|
57
|
-
|
52
|
+
```
|
53
|
+
# Reset master
|
54
|
+
git checkout master
|
55
|
+
git fetch upstream
|
56
|
+
git reset --hard upstream/master
|
57
|
+
|
58
|
+
# For each pull request
|
59
|
+
git fetch upstream pull/23/head:pull/23 --force"
|
60
|
+
git merge --no-ff pull/23
|
61
|
+
git branch -D pull/23
|
58
62
|
```
|
59
63
|
|
60
64
|
### MergeWithRebase
|
61
65
|
|
62
|
-
```
|
63
|
-
|
64
|
-
git
|
65
|
-
git
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
git
|
70
|
-
git
|
71
|
-
git
|
72
|
-
|
73
|
-
git
|
74
|
-
|
66
|
+
```
|
67
|
+
# Reset master
|
68
|
+
git checkout master
|
69
|
+
git fetch upstream
|
70
|
+
git reset --hard upstream/master
|
71
|
+
|
72
|
+
# For each pull request
|
73
|
+
git fetch upstream pull/23/head:pull/23 --force"
|
74
|
+
git checkout pull/23
|
75
|
+
git rebase master
|
76
|
+
|
77
|
+
git checkout master
|
78
|
+
git merge --no-ff pull/23
|
79
|
+
|
80
|
+
git branch -D pull/23
|
75
81
|
```
|
76
82
|
|
77
83
|
### Rebase
|
78
84
|
|
79
|
-
```
|
80
|
-
|
81
|
-
git
|
82
|
-
git
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
git
|
87
|
-
git
|
88
|
-
git
|
89
|
-
|
90
|
-
git
|
91
|
-
|
85
|
+
```
|
86
|
+
# Reset master
|
87
|
+
git checkout master
|
88
|
+
git fetch upstream
|
89
|
+
git reset --hard upstream/master
|
90
|
+
|
91
|
+
# For each pull request
|
92
|
+
git fetch upstream pull/23/head:pull/23 --force"
|
93
|
+
git checkout pull/23
|
94
|
+
git rebase master
|
95
|
+
|
96
|
+
git checkout master
|
97
|
+
git rebase pull/23
|
98
|
+
|
99
|
+
git branch -D pull/23
|
92
100
|
```
|
93
101
|
|
94
102
|
## Development
|
data/TODO.md
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
Before we release `v1.0.0` the following tasks needs to be done:
|
4
4
|
|
5
|
-
* [
|
6
|
-
* [
|
5
|
+
* [x] Move logic from `exe/octo-merge` into a testable class
|
6
|
+
* [x] Add specs for `InteractivePullRequests`
|
7
7
|
* [ ] Create a setup task
|
8
8
|
* [ ] Complete docs (`README.md`)
|
9
9
|
* [ ] Try to get rid of external dependencies (`octokit`, `inquirer`)
|
10
10
|
* [ ] Decide on gem name (`octo_merge` VS `octo-merge`)
|
11
|
-
* [
|
11
|
+
* [x] Use GitHubs `secret` pull requests branches instead of adding new remotes
|
data/bin/octo-merge
ADDED
data/exe/octo-merge
CHANGED
@@ -1,90 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require "optparse"
|
4
3
|
require "octo_merge"
|
5
|
-
require "yaml"
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
strategy: "MergeWithoutRebase"
|
10
|
-
}
|
5
|
+
verbose = !(ENV["VERBOSE"] == "0")
|
6
|
+
Git.verbose!(verbose)
|
11
7
|
|
12
|
-
|
13
|
-
|
14
|
-
if File.exist?(user_config_path)
|
15
|
-
body = File.read(user_config_path)
|
16
|
-
options.merge!(YAML.load(body))
|
17
|
-
end
|
18
|
-
|
19
|
-
if File.exist?(".octo-merge.yml")
|
20
|
-
body = File.read(".octo-merge.yml")
|
21
|
-
options.merge!(YAML.load(body))
|
22
|
-
end
|
23
|
-
|
24
|
-
# Symbolize keys
|
25
|
-
options = options.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
|
26
|
-
|
27
|
-
OptionParser.new do |opts|
|
28
|
-
opts.banner = "Usage: octo-merge [options]"
|
29
|
-
|
30
|
-
opts.on("--repo=REPO", "Repository (e.g.: 'rails/rails')") do |repo|
|
31
|
-
options[:repo] = repo
|
32
|
-
end
|
33
|
-
|
34
|
-
opts.on("--dir=DIR", "Working directory (e.g.: '~/Dev/Rails/rails')") do |dir|
|
35
|
-
options[:dir] = dir
|
36
|
-
end
|
37
|
-
|
38
|
-
opts.on("--pull_requests=PULL_REQUESTS", "Pull requests (e.g.: '23,42,66')") do |pull_requests|
|
39
|
-
options[:pull_requests] = pull_requests
|
40
|
-
end
|
41
|
-
|
42
|
-
opts.on("--login=login", "Login (Your GitHub username)") do |login|
|
43
|
-
options[:login] = login
|
44
|
-
end
|
45
|
-
|
46
|
-
opts.on("--password=password", "Password (Your GitHub API-Token)") do |password|
|
47
|
-
options[:password] = password
|
48
|
-
end
|
49
|
-
|
50
|
-
opts.on("--strategy=STRATEGY", "Merge strategy (e.g.: 'MergeWithoutRebase')") do |strategy|
|
51
|
-
options[:strategy] = strategy
|
52
|
-
end
|
53
|
-
|
54
|
-
opts.on("--query=QUERY", "Query to use in interactive mode (e.g.: 'label:ready-to-merge')") do |query|
|
55
|
-
options[:query] = query
|
56
|
-
end
|
57
|
-
|
58
|
-
opts.on('--interactive', 'Select PullRequests within an interactive session') do |interactive|
|
59
|
-
options[:interactive] = interactive
|
60
|
-
end
|
61
|
-
|
62
|
-
opts.on('-h', '--help', 'Display this screen') do
|
63
|
-
puts opts
|
64
|
-
exit
|
65
|
-
end
|
66
|
-
|
67
|
-
opts.on('-v', '--version', 'Display the version') do
|
68
|
-
puts OctoMerge::VERSION
|
69
|
-
exit
|
70
|
-
end
|
71
|
-
end.parse!
|
72
|
-
|
73
|
-
OctoMerge.configure do |config|
|
74
|
-
config.login = options[:login]
|
75
|
-
config.password = options[:password]
|
76
|
-
end
|
77
|
-
|
78
|
-
options[:dir] = File.expand_path(options[:dir])
|
79
|
-
|
80
|
-
options[:strategy] = Object.const_get("OctoMerge::Strategy::#{options[:strategy]}")
|
81
|
-
|
82
|
-
options[:pull_requests] = OctoMerge::InteractivePullRequests.get(options) if options[:interactive]
|
83
|
-
options[:pull_requests] = options[:pull_requests].to_s.split(",")
|
84
|
-
|
85
|
-
OctoMerge.run(
|
86
|
-
repo: options[:repo],
|
87
|
-
pull_request_numbers: options[:pull_requests],
|
88
|
-
working_directory: options[:dir],
|
89
|
-
strategy: options[:strategy]
|
90
|
-
)
|
8
|
+
OctoMerge::CLI.run(ARGV)
|
data/lib/git.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
1
3
|
# TODO: Move to another repository (e.g.: `SimpleGit`)
|
2
4
|
class Git
|
3
5
|
def self.git(method_name, cmd = nil)
|
@@ -10,6 +12,14 @@ class Git
|
|
10
12
|
end
|
11
13
|
end
|
12
14
|
|
15
|
+
def self.verbose!(is_verbose = true)
|
16
|
+
@verbose = is_verbose
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.verbose?
|
20
|
+
!!@verbose
|
21
|
+
end
|
22
|
+
|
13
23
|
attr_reader :working_directory
|
14
24
|
|
15
25
|
def initialize(working_directory)
|
@@ -18,6 +28,7 @@ class Git
|
|
18
28
|
|
19
29
|
git :checkout
|
20
30
|
git :commit
|
31
|
+
git :delete_branch, "branch -D"
|
21
32
|
git :fetch
|
22
33
|
git :merge_no_ff, "merge --no-ff"
|
23
34
|
git :rebase
|
@@ -30,12 +41,21 @@ class Git
|
|
30
41
|
run "git #{cmd}"
|
31
42
|
end
|
32
43
|
|
44
|
+
def verbose?
|
45
|
+
self.class.verbose?
|
46
|
+
end
|
47
|
+
|
33
48
|
def run(cmd)
|
49
|
+
puts "$: #{cmd}" if verbose?
|
50
|
+
|
34
51
|
cmd = <<-CMD
|
35
52
|
cd #{working_directory} &&
|
36
53
|
#{cmd}
|
37
54
|
CMD
|
38
55
|
|
39
|
-
|
56
|
+
# NOTE: Logging and debugging is writte to stderr
|
57
|
+
_stdin, stdout, stderr = Open3.popen3(cmd)
|
58
|
+
print stderr.read if verbose?
|
59
|
+
stdout.read
|
40
60
|
end
|
41
61
|
end
|
data/lib/octo_merge.rb
CHANGED
@@ -2,11 +2,13 @@ require "octo_merge/version"
|
|
2
2
|
|
3
3
|
require "git"
|
4
4
|
|
5
|
+
require "octo_merge/cli"
|
5
6
|
require "octo_merge/configuration"
|
6
7
|
require "octo_merge/context"
|
7
8
|
require "octo_merge/execute"
|
8
9
|
require "octo_merge/interactive_pull_requests"
|
9
10
|
require "octo_merge/list_pull_requests"
|
11
|
+
require "octo_merge/options"
|
10
12
|
require "octo_merge/pull_request"
|
11
13
|
require "octo_merge/strategy"
|
12
14
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "octo_merge/cli/parser"
|
2
|
+
|
3
|
+
module OctoMerge
|
4
|
+
class CLI
|
5
|
+
attr_reader :args
|
6
|
+
|
7
|
+
def self.run(*args)
|
8
|
+
new(*args).run
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(args)
|
12
|
+
@args = args
|
13
|
+
end
|
14
|
+
|
15
|
+
def run
|
16
|
+
configure
|
17
|
+
execute
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def configure
|
23
|
+
OctoMerge.configure do |config|
|
24
|
+
config.login = options.login
|
25
|
+
config.password = options.password
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def execute
|
30
|
+
OctoMerge.run(
|
31
|
+
pull_request_numbers: options.pull_requests,
|
32
|
+
repo: options.repo,
|
33
|
+
strategy: options.strategy,
|
34
|
+
working_directory: options.dir
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
def options
|
39
|
+
@options ||= Options.new.tap do |options|
|
40
|
+
options.cli_options = Parser.parse(args)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module OctoMerge
|
4
|
+
class CLI
|
5
|
+
class Parser
|
6
|
+
def self.parse(args)
|
7
|
+
new(args).parse!
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(args)
|
11
|
+
@args = args
|
12
|
+
end
|
13
|
+
|
14
|
+
def parse!
|
15
|
+
setup
|
16
|
+
opts.parse!(args)
|
17
|
+
options
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_reader :args
|
23
|
+
|
24
|
+
def setup
|
25
|
+
setup_banner
|
26
|
+
|
27
|
+
setup_application
|
28
|
+
|
29
|
+
opts.separator ""
|
30
|
+
opts.separator "Common options:"
|
31
|
+
|
32
|
+
setup_help
|
33
|
+
setup_version
|
34
|
+
end
|
35
|
+
|
36
|
+
def setup_banner
|
37
|
+
opts.banner = "Usage: octo-merge [options]"
|
38
|
+
opts.separator ""
|
39
|
+
end
|
40
|
+
|
41
|
+
def setup_application
|
42
|
+
opts.on("--repo=REPO", "Repository (e.g.: 'rails/rails')") do |repo|
|
43
|
+
options[:repo] = repo
|
44
|
+
end
|
45
|
+
|
46
|
+
opts.on("--dir=DIR", "Working directory (e.g.: '~/Dev/Rails/rails')") do |dir|
|
47
|
+
options[:dir] = dir
|
48
|
+
end
|
49
|
+
|
50
|
+
opts.on("--pull_requests=PULL_REQUESTS", "Pull requests (e.g.: '23,42,66')") do |pull_requests|
|
51
|
+
options[:pull_requests] = pull_requests
|
52
|
+
end
|
53
|
+
|
54
|
+
opts.on("--login=login", "Login (Your GitHub username)") do |login|
|
55
|
+
options[:login] = login
|
56
|
+
end
|
57
|
+
|
58
|
+
opts.on("--password=password", "Password (Your GitHub API-Token)") do |password|
|
59
|
+
options[:password] = password
|
60
|
+
end
|
61
|
+
|
62
|
+
opts.on("--strategy=STRATEGY", "Merge strategy (e.g.: 'MergeWithoutRebase')") do |strategy|
|
63
|
+
options[:strategy] = strategy
|
64
|
+
end
|
65
|
+
|
66
|
+
opts.on("--query=QUERY", "Query to use in interactive mode (e.g.: 'label:ready-to-merge')") do |query|
|
67
|
+
options[:query] = query
|
68
|
+
end
|
69
|
+
|
70
|
+
opts.on('--interactive', 'Select PullRequests within an interactive session') do |interactive|
|
71
|
+
options[:interactive] = interactive
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def setup_help
|
76
|
+
opts.on_tail('-h', '--help', 'Display this screen') do
|
77
|
+
puts opts
|
78
|
+
exit
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def setup_version
|
83
|
+
opts.on_tail('-v', '--version', 'Display the version') do
|
84
|
+
puts OctoMerge::VERSION
|
85
|
+
exit
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def opts
|
90
|
+
@opts ||= OptionParser.new
|
91
|
+
end
|
92
|
+
|
93
|
+
def options
|
94
|
+
@options ||= {}
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'inquirer'
|
2
2
|
|
3
3
|
module OctoMerge
|
4
|
-
# TODO: Write specs
|
5
4
|
class InteractivePullRequests
|
6
5
|
def initialize(repo:, query:)
|
7
6
|
@repo = repo
|
@@ -9,37 +8,32 @@ module OctoMerge
|
|
9
8
|
end
|
10
9
|
|
11
10
|
def self.get(options = {})
|
12
|
-
new(repo: options[:repo], query: options[:query]).
|
11
|
+
new(repo: options[:repo], query: options[:query]).to_s
|
13
12
|
end
|
14
13
|
|
15
|
-
def
|
16
|
-
prs = list.all
|
17
|
-
|
18
|
-
formatted_prs = prs.map do |pull_request|
|
19
|
-
format_pull_request(pull_request)
|
20
|
-
end
|
21
|
-
|
14
|
+
def to_s
|
22
15
|
system("clear")
|
23
|
-
idx = Ask.checkbox "Select the pull requests you want to merge", formatted_prs
|
24
16
|
|
25
|
-
idx
|
17
|
+
idx = Ask.checkbox(
|
18
|
+
"Select the pull requests you want to merge",
|
19
|
+
formatted_pull_requests
|
20
|
+
)
|
21
|
+
|
22
|
+
idx.zip(pull_requests).select { |e| e[0] }.map { |e| e[1].number }.join(",")
|
26
23
|
end
|
27
24
|
|
28
25
|
private
|
29
26
|
|
30
27
|
attr_reader :repo, :query
|
31
28
|
|
32
|
-
def
|
33
|
-
|
34
|
-
|
35
|
-
list.all.each do |pull_request|
|
36
|
-
puts format_pull_request(pull_request)
|
29
|
+
def formatted_pull_requests
|
30
|
+
pull_requests.map do |pull_request|
|
31
|
+
format_pull_request(pull_request)
|
37
32
|
end
|
38
33
|
end
|
39
34
|
|
40
|
-
def
|
41
|
-
|
42
|
-
print "$: "
|
35
|
+
def pull_requests
|
36
|
+
list.all
|
43
37
|
end
|
44
38
|
|
45
39
|
def format_pull_request(pull_request)
|
@@ -51,4 +45,3 @@ module OctoMerge
|
|
51
45
|
end
|
52
46
|
end
|
53
47
|
end
|
54
|
-
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require "yaml"
|
2
|
+
|
3
|
+
module OctoMerge
|
4
|
+
class Options
|
5
|
+
def self.option(key)
|
6
|
+
define_method(key) { self[key] }
|
7
|
+
end
|
8
|
+
|
9
|
+
option :login
|
10
|
+
option :password
|
11
|
+
|
12
|
+
option :dir
|
13
|
+
option :pull_requests
|
14
|
+
option :repo
|
15
|
+
option :strategy
|
16
|
+
|
17
|
+
def [](key)
|
18
|
+
data[key]
|
19
|
+
end
|
20
|
+
|
21
|
+
def cli_options=(options)
|
22
|
+
reset_cache
|
23
|
+
@cli_options = options
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
CONFIG_FILE = ".octo-merge.yml"
|
29
|
+
DEFAULT_OPTIONS = {
|
30
|
+
dir: ".",
|
31
|
+
strategy: "MergeWithoutRebase"
|
32
|
+
}
|
33
|
+
USER_CONFIG_PATH = File.expand_path("~/#{CONFIG_FILE}")
|
34
|
+
|
35
|
+
def data
|
36
|
+
@data ||= begin
|
37
|
+
options = default_options
|
38
|
+
.merge(user_options)
|
39
|
+
.merge(project_options)
|
40
|
+
.merge(cli_options)
|
41
|
+
|
42
|
+
|
43
|
+
# Sanitize input
|
44
|
+
options[:dir] = File.expand_path(options[:dir])
|
45
|
+
options[:strategy] = Object.const_get("OctoMerge::Strategy::#{options[:strategy]}")
|
46
|
+
options[:pull_requests] = get_interactive_pull_requests(options) if options[:interactive]
|
47
|
+
options[:pull_requests] = options[:pull_requests].to_s.split(",")
|
48
|
+
|
49
|
+
options
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# This hotfix will configure the API credentials before doing the API call.
|
54
|
+
def get_interactive_pull_requests(options)
|
55
|
+
OctoMerge.configure do |config|
|
56
|
+
config.login = options[:login]
|
57
|
+
config.password = options[:password]
|
58
|
+
end
|
59
|
+
|
60
|
+
OctoMerge::InteractivePullRequests.get(options)
|
61
|
+
end
|
62
|
+
|
63
|
+
def reset_cache
|
64
|
+
@data = nil
|
65
|
+
end
|
66
|
+
|
67
|
+
def default_options
|
68
|
+
DEFAULT_OPTIONS
|
69
|
+
end
|
70
|
+
|
71
|
+
def user_options
|
72
|
+
if File.exist?(USER_CONFIG_PATH)
|
73
|
+
body = File.read(USER_CONFIG_PATH)
|
74
|
+
symbolize_keys YAML.load(body)
|
75
|
+
else
|
76
|
+
{}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def project_options
|
81
|
+
if File.exist?(CONFIG_FILE)
|
82
|
+
body = File.read(CONFIG_FILE)
|
83
|
+
symbolize_keys YAML.load(body)
|
84
|
+
else
|
85
|
+
{}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def cli_options
|
90
|
+
@cli_options ||= {}
|
91
|
+
end
|
92
|
+
|
93
|
+
def symbolize_keys(hash)
|
94
|
+
hash.inject({}){ |memo, (k, v)| memo[k.to_sym] = v; memo }
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -26,6 +26,21 @@ module OctoMerge
|
|
26
26
|
@git ||= Git.new(working_directory)
|
27
27
|
end
|
28
28
|
|
29
|
+
# Fetch the read-only branch for the corresponding pull request and
|
30
|
+
# create a local branch to rebase the current master on.
|
31
|
+
#
|
32
|
+
# Read more: [Checking out pull requests locally](https://help.github.com/articles/checking-out-pull-requests-locally/)
|
33
|
+
def fetch(pull_request)
|
34
|
+
git.fetch "#{upstream} #{pull_request.number_branch}/head:#{pull_request.number_branch} --force"
|
35
|
+
end
|
36
|
+
|
37
|
+
def fetch_master
|
38
|
+
git.checkout(master)
|
39
|
+
git.fetch(upstream)
|
40
|
+
git.reset_hard("#{upstream}/#{master}")
|
41
|
+
end
|
42
|
+
|
43
|
+
|
29
44
|
def upstream
|
30
45
|
:upstream
|
31
46
|
end
|
@@ -2,19 +2,28 @@ module OctoMerge
|
|
2
2
|
module Strategy
|
3
3
|
class MergeWithRebase < Base
|
4
4
|
def run
|
5
|
-
|
6
|
-
git.fetch(upstream)
|
7
|
-
git.reset_hard("#{upstream}/#{master}")
|
5
|
+
fetch_master
|
8
6
|
|
9
7
|
pull_requests.each do |pull_request|
|
10
|
-
|
11
|
-
|
12
|
-
git.checkout(pull_request.
|
8
|
+
fetch(pull_request)
|
9
|
+
|
10
|
+
git.checkout(pull_request.number_branch)
|
13
11
|
git.rebase(master)
|
12
|
+
|
14
13
|
git.checkout(master)
|
15
|
-
|
14
|
+
merge(pull_request)
|
15
|
+
|
16
|
+
git.delete_branch(pull_request.number_branch)
|
16
17
|
end
|
17
18
|
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def merge(pull_request)
|
23
|
+
message = "Merge branch '#{pull_request.remote_branch}'"
|
24
|
+
|
25
|
+
git.merge_no_ff("-m \"#{message}\" #{pull_request.number_branch}")
|
26
|
+
end
|
18
27
|
end
|
19
28
|
end
|
20
29
|
end
|
@@ -4,19 +4,20 @@ module OctoMerge
|
|
4
4
|
module Strategy
|
5
5
|
class MergeWithRebaseAndMessage < Base
|
6
6
|
def run
|
7
|
-
|
8
|
-
git.fetch(upstream)
|
9
|
-
git.reset_hard("#{upstream}/#{master}")
|
7
|
+
fetch_master
|
10
8
|
|
11
9
|
pull_requests.each do |pull_request|
|
12
|
-
|
13
|
-
|
14
|
-
git.checkout(pull_request.
|
10
|
+
fetch(pull_request)
|
11
|
+
|
12
|
+
git.checkout(pull_request.number_branch)
|
15
13
|
git.rebase(master)
|
14
|
+
|
16
15
|
git.checkout(master)
|
17
|
-
git.merge_no_ff(pull_request.
|
16
|
+
git.merge_no_ff(pull_request.number_branch)
|
18
17
|
|
19
18
|
add_merge_message(pull_request)
|
19
|
+
|
20
|
+
git.delete_branch(pull_request.number_branch)
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
@@ -66,7 +67,7 @@ module OctoMerge
|
|
66
67
|
|
67
68
|
def body
|
68
69
|
sanitize <<-BODY
|
69
|
-
Merge branch '#{pull_request.
|
70
|
+
Merge branch '#{pull_request.remote_branch}'
|
70
71
|
|
71
72
|
Resolves and closes: #{pull_request.url}
|
72
73
|
|
@@ -2,16 +2,23 @@ module OctoMerge
|
|
2
2
|
module Strategy
|
3
3
|
class MergeWithoutRebase < Base
|
4
4
|
def run
|
5
|
-
|
6
|
-
git.fetch(upstream)
|
7
|
-
git.reset_hard("#{upstream}/#{master}")
|
5
|
+
fetch_master
|
8
6
|
|
9
7
|
pull_requests.each do |pull_request|
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
fetch(pull_request)
|
9
|
+
merge(pull_request)
|
10
|
+
|
11
|
+
git.delete_branch(pull_request.number_branch)
|
13
12
|
end
|
14
13
|
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def merge(pull_request)
|
18
|
+
message = "Merge remote branch '#{pull_request.remote}/#{pull_request.remote_branch}'"
|
19
|
+
|
20
|
+
git.merge_no_ff("-m \"#{message}\" #{pull_request.number_branch}")
|
21
|
+
end
|
15
22
|
end
|
16
23
|
end
|
17
24
|
end
|
@@ -2,17 +2,18 @@ module OctoMerge
|
|
2
2
|
module Strategy
|
3
3
|
class Rebase < Base
|
4
4
|
def run
|
5
|
-
|
6
|
-
git.fetch(upstream)
|
7
|
-
git.reset_hard("#{upstream}/#{master}")
|
5
|
+
fetch_master
|
8
6
|
|
9
7
|
pull_requests.each do |pull_request|
|
10
|
-
|
11
|
-
|
12
|
-
git.checkout(pull_request.
|
8
|
+
fetch(pull_request)
|
9
|
+
|
10
|
+
git.checkout(pull_request.number_branch)
|
13
11
|
git.rebase(master)
|
12
|
+
|
14
13
|
git.checkout(master)
|
15
|
-
git.rebase("#{pull_request.
|
14
|
+
git.rebase("#{pull_request.number_branch}")
|
15
|
+
|
16
|
+
git.delete_branch(pull_request.number_branch)
|
16
17
|
end
|
17
18
|
end
|
18
19
|
end
|
data/lib/octo_merge/version.rb
CHANGED
data/octo_merge.gemspec
CHANGED
@@ -37,5 +37,6 @@ Gem::Specification.new do |spec|
|
|
37
37
|
spec.add_development_dependency "rake", "~> 10.0"
|
38
38
|
spec.add_development_dependency "rspec", "~> 3.0"
|
39
39
|
spec.add_development_dependency "rspec-its"
|
40
|
+
spec.add_development_dependency "simplecov"
|
40
41
|
spec.add_development_dependency "webmock"
|
41
42
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: octo_merge
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Patrick Helm
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-07-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: octokit
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: simplecov
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: webmock
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -141,15 +155,19 @@ files:
|
|
141
155
|
- Rakefile
|
142
156
|
- TODO.md
|
143
157
|
- bin/console
|
158
|
+
- bin/octo-merge
|
144
159
|
- bin/setup
|
145
160
|
- exe/octo-merge
|
146
161
|
- lib/git.rb
|
147
162
|
- lib/octo_merge.rb
|
163
|
+
- lib/octo_merge/cli.rb
|
164
|
+
- lib/octo_merge/cli/parser.rb
|
148
165
|
- lib/octo_merge/configuration.rb
|
149
166
|
- lib/octo_merge/context.rb
|
150
167
|
- lib/octo_merge/execute.rb
|
151
168
|
- lib/octo_merge/interactive_pull_requests.rb
|
152
169
|
- lib/octo_merge/list_pull_requests.rb
|
170
|
+
- lib/octo_merge/options.rb
|
153
171
|
- lib/octo_merge/pull_request.rb
|
154
172
|
- lib/octo_merge/strategy.rb
|
155
173
|
- lib/octo_merge/strategy/base.rb
|