rebaser 0.0.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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +27 -0
- data/Rakefile +2 -0
- data/bin/rebaser +7 -0
- data/lib/rebaser/open_branch_fetcher.rb +33 -0
- data/lib/rebaser/parser.rb +40 -0
- data/lib/rebaser/rebaser.rb +54 -0
- data/lib/rebaser/version.rb +3 -0
- data/lib/rebaser.rb +63 -0
- data/rebaser.gemspec +24 -0
- metadata +113 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5bf5a5c25788631d8326bbac9f4a5d2fbab8386d
|
4
|
+
data.tar.gz: 8b200af6e4b7596aa9f07eb61109ddf7a165aeec
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 72129e169435c4905c978d78e756abd8abe33259ad7de6bf2a9f0455523c746a60061fd99cfc5a1ebd8d6794f0c5d73c9edec0d71966d1d3bb5dba5b0b34867c
|
7
|
+
data.tar.gz: f21b73dd4c264383e12544fac1c3b3835f5b9e745e5b4e99d0acafe41db63b2eeb018d200a42bebc48052342400978303d725b56b1b8b0a69f3ccf6ded6c55ce
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Tim Minkov
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Rebaser
|
2
|
+
![Rebaser]
|
3
|
+
(http://i.imgur.com/7Sqj6v2.gif)
|
4
|
+
|
5
|
+
Rebaser rebases all open pull requests.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'rebaser'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install rebaser
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
To use Rebaser, just run `rebaser` in the directory of the target project. Rebaser will pull all open pull requests from Github, then proceed to rebase and force push up. Rebaser will abort the rebase if there are merge conflicts.
|
24
|
+
|
25
|
+
## Why?
|
26
|
+
|
27
|
+
When someone breaks master, all branches need to be rebased to include a fix. This lets a single person do it instead of waiting for a everyone to rebase their own branches.
|
data/Rakefile
ADDED
data/bin/rebaser
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'github_api'
|
2
|
+
|
3
|
+
module Rebaser
|
4
|
+
class OpenBranchFetcher
|
5
|
+
def initialize(username:, password:, token:, remote:)
|
6
|
+
@username = username
|
7
|
+
@password = password
|
8
|
+
@token = token
|
9
|
+
@remote = remote
|
10
|
+
end
|
11
|
+
|
12
|
+
def fetch
|
13
|
+
github = Github.new do |config|
|
14
|
+
config.basic_auth = "#{username}:#{password}"
|
15
|
+
if token
|
16
|
+
config.connection_options = {headers: {'X-GitHub-OTP' => token}}
|
17
|
+
end
|
18
|
+
config.auto_pagination = true
|
19
|
+
end
|
20
|
+
|
21
|
+
remote_user = remote.split('/').first
|
22
|
+
remote_repo = remote.split('/').last
|
23
|
+
|
24
|
+
pull_requests = github.pull_requests.list remote_user, remote_repo, state: 'open'
|
25
|
+
|
26
|
+
branches = pull_requests.map { |pr| pr.head.ref }
|
27
|
+
branches
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
attr_reader :username, :password, :token, :remote
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module Rebaser
|
4
|
+
class Parser
|
5
|
+
def initialize(args)
|
6
|
+
@args = args
|
7
|
+
end
|
8
|
+
|
9
|
+
def parse
|
10
|
+
options = {}
|
11
|
+
|
12
|
+
OptionParser.new do |opts|
|
13
|
+
opts.on("--username USERNAME", String, "Your github username") do |v|
|
14
|
+
options[:username] = v
|
15
|
+
end
|
16
|
+
|
17
|
+
opts.on("--password PASSWORD", String, "Your github password") do |v|
|
18
|
+
options[:password] = v
|
19
|
+
end
|
20
|
+
|
21
|
+
opts.on("--token TOKEN", String, "Your github two factor authentication code") do |v|
|
22
|
+
options[:token] = v
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on("--remote REMOTE", String, "The git remote in the form of `timminkov/rebaser`") do |v|
|
26
|
+
options[:remote] = v
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.on("--branch BRANCH", String, "Branch name to rebase onto") do |v|
|
30
|
+
options[:rebase_branch] = v
|
31
|
+
end
|
32
|
+
end.parse(args)
|
33
|
+
|
34
|
+
options
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
attr_reader :args
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'inquirer'
|
2
|
+
|
3
|
+
module Rebaser
|
4
|
+
class Rebaser
|
5
|
+
attr_reader :successful_rebases, :failed_rebases
|
6
|
+
|
7
|
+
def initialize(branches, rebase_branch, remote)
|
8
|
+
@branches = branches
|
9
|
+
@rebase_branch = rebase_branch
|
10
|
+
@successful_rebases = []
|
11
|
+
@failed_rebases = []
|
12
|
+
@remote = remote
|
13
|
+
end
|
14
|
+
|
15
|
+
def begin
|
16
|
+
checkout(rebase_branch)
|
17
|
+
|
18
|
+
branches.each do |branch|
|
19
|
+
checkout(branch)
|
20
|
+
puts "Rebasing #{branch} onto #{rebase_branch}"
|
21
|
+
output = attempt_rebase
|
22
|
+
|
23
|
+
if output =~ /Automatic merge failed/
|
24
|
+
abort_rebase
|
25
|
+
failed_rebases << branch
|
26
|
+
elsif output =~ /did not match any file/
|
27
|
+
failed_rebases << branch
|
28
|
+
else
|
29
|
+
force_push(branch)
|
30
|
+
successful_rebases << branch
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
attr_reader :branches, :rebase_branch,:remote
|
37
|
+
|
38
|
+
def checkout(branch)
|
39
|
+
system "git checkout #{branch}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def attempt_rebase
|
43
|
+
system "git rebase #{rebase_branch}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def abort_rebase
|
47
|
+
system 'git rebase --abort'
|
48
|
+
end
|
49
|
+
|
50
|
+
def force_push(branch)
|
51
|
+
system "git push -f #{remote} #{branch}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/rebaser.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'inquirer'
|
2
|
+
require 'io/console'
|
3
|
+
|
4
|
+
require 'rebaser/version'
|
5
|
+
require 'rebaser/open_branch_fetcher'
|
6
|
+
require 'rebaser/rebaser'
|
7
|
+
|
8
|
+
module Rebaser
|
9
|
+
def self.execute(options)
|
10
|
+
puts 'Rebaser'
|
11
|
+
puts 'Wanna grow up to be'
|
12
|
+
puts '♫ Be a rebaser ♫'
|
13
|
+
puts "\n"
|
14
|
+
puts 'Fetching branches...'
|
15
|
+
|
16
|
+
unless options[:username]
|
17
|
+
options[:username] = Ask.input "Github username"
|
18
|
+
end
|
19
|
+
|
20
|
+
unless options[:password]
|
21
|
+
puts "Github password:"
|
22
|
+
options[:password] = STDIN.noecho(&:gets).chomp
|
23
|
+
end
|
24
|
+
|
25
|
+
unless options[:remote]
|
26
|
+
options[:remote] = Ask.input "Where should I fetch branches from (in the form of `timminkov/rebaser`"
|
27
|
+
end
|
28
|
+
|
29
|
+
unless options[:token]
|
30
|
+
if Ask.confirm "Need to enter a 2 factor authentication code?"
|
31
|
+
options[:token] = Ask.input "2 factor code"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
branches = OpenBranchFetcher.new(
|
36
|
+
username: options[:username],
|
37
|
+
password: options[:password],
|
38
|
+
token: options[:token],
|
39
|
+
remote: options[:remote],
|
40
|
+
).fetch
|
41
|
+
|
42
|
+
puts "\n\nHere's what I'll be rebasing today:\n"
|
43
|
+
puts branches
|
44
|
+
puts "\nI'll rebase these branches onto #{options[:rebase_branch]}."
|
45
|
+
puts "If I run into merge conflicts, I'll skip that branch."
|
46
|
+
puts "This can be dangerous as I will be force pushing."
|
47
|
+
continue = Ask.confirm "Are you sure you want to continue?", default: false
|
48
|
+
|
49
|
+
return unless continue
|
50
|
+
|
51
|
+
remote = Ask.input "Please enter the remote name to push to", default: 'origin'
|
52
|
+
unless options[:rebase_branch]
|
53
|
+
options[:rebase_branch] = Ask.input "Please enter the branch to rebase onto", default: 'master'
|
54
|
+
end
|
55
|
+
|
56
|
+
rebaser = Rebaser.new(branches, options[:rebase_branch], remote)
|
57
|
+
rebaser.begin
|
58
|
+
|
59
|
+
puts "\nAll done!"
|
60
|
+
puts "#{rebaser.successful_rebases.size} branches successfully rebased and pushed."
|
61
|
+
puts "#{rebaser.failed_rebases.size} branches failed to rebase."
|
62
|
+
end
|
63
|
+
end
|
data/rebaser.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rebaser/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'rebaser'
|
8
|
+
spec.version = Rebaser::VERSION
|
9
|
+
spec.authors = ['Tim Minkov']
|
10
|
+
spec.email = ["timothyminkov@gmail.com"]
|
11
|
+
spec.summary = %q{Rebases all open pull requests on a git repo}
|
12
|
+
spec.homepage = 'https://github.com/timminkov/rebaser'
|
13
|
+
spec.license = 'MIT'
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = ['rebaser']
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ['lib']
|
19
|
+
|
20
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
21
|
+
spec.add_development_dependency 'rake'
|
22
|
+
spec.add_runtime_dependency 'github_api'
|
23
|
+
spec.add_runtime_dependency 'inquirer'
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rebaser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tim Minkov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-11-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: github_api
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: inquirer
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- timothyminkov@gmail.com
|
72
|
+
executables:
|
73
|
+
- rebaser
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- ".gitignore"
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE.txt
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- bin/rebaser
|
83
|
+
- lib/rebaser.rb
|
84
|
+
- lib/rebaser/open_branch_fetcher.rb
|
85
|
+
- lib/rebaser/parser.rb
|
86
|
+
- lib/rebaser/rebaser.rb
|
87
|
+
- lib/rebaser/version.rb
|
88
|
+
- rebaser.gemspec
|
89
|
+
homepage: https://github.com/timminkov/rebaser
|
90
|
+
licenses:
|
91
|
+
- MIT
|
92
|
+
metadata: {}
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 2.2.2
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: Rebases all open pull requests on a git repo
|
113
|
+
test_files: []
|