git-up-portertech 0.5.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.
- data/LICENSE +20 -0
- data/README.md +30 -0
- data/bin/git-up +6 -0
- data/lib/git-up.rb +223 -0
- data/lib/git-up/version.rb +3 -0
- metadata +97 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Aanand Prasad
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
git-up
|
2
|
+
======
|
3
|
+
|
4
|
+
So `git pull` merges by default, when it [should really rebase](http://www.gitready.com/advanced/2009/02/11/pull-with-rebase.html). You can [ask it to rebase instead](http://d.strelau.net/post/47338904/git-pull-rebase-by-default), but it still won't touch anything other than the currently checked-out branch. If you're tracking a bunch of remote branches, you'll get non-fast-forward complaints next time you push.
|
5
|
+
|
6
|
+
Solve it once and for all:
|
7
|
+
|
8
|
+

|
9
|
+
|
10
|
+
although
|
11
|
+
--------
|
12
|
+
|
13
|
+
`git-up` might mess up your branches, or set your chest hair on fire, or be racist to your cat, I don't know. It works for me.
|
14
|
+
|
15
|
+
configuration
|
16
|
+
-------------
|
17
|
+
|
18
|
+
`git-up` can check your app for any new bundled gems and suggest a `bundle install` if necessary.
|
19
|
+
|
20
|
+
It slows the process down slightly, and is therefore enabled by setting `git-up.bundler.check` to `true` in your git config, either globally or per-project. To set it globally, run this command anywhere:
|
21
|
+
|
22
|
+
git config --global git-up.bundler.check true
|
23
|
+
|
24
|
+
To set it within a project, run this command inside that project's directory:
|
25
|
+
|
26
|
+
git config git-up.bundler.check true
|
27
|
+
|
28
|
+
Replace 'true' with 'false' to disable checking.
|
29
|
+
|
30
|
+
If you're even lazier, you can tell `git-up` to run `bundle install` for you if it finds missing gems. Simply set `git-up.bundler.autoinstall` to `true`, in the same manner. As above, it works globally or per-project, but make sure `git-up.bundler.check` is also set to `true` or it won't do anything.
|
data/bin/git-up
ADDED
data/lib/git-up.rb
ADDED
@@ -0,0 +1,223 @@
|
|
1
|
+
require 'colored'
|
2
|
+
require 'grit'
|
3
|
+
|
4
|
+
class GitUp
|
5
|
+
def run
|
6
|
+
system('git', 'fetch', '--multiple', *remotes)
|
7
|
+
raise GitError, "`git fetch` failed" unless $? == 0
|
8
|
+
@remote_map = nil # flush cache after fetch
|
9
|
+
|
10
|
+
with_stash do
|
11
|
+
returning_to_current_branch do
|
12
|
+
col_width = branches.map { |b| b.name.length }.max + 1
|
13
|
+
|
14
|
+
branches.each do |branch|
|
15
|
+
remote = remote_map[branch.name]
|
16
|
+
|
17
|
+
print branch.name.ljust(col_width)
|
18
|
+
|
19
|
+
if remote.commit.sha == branch.commit.sha
|
20
|
+
puts "up to date".green
|
21
|
+
next
|
22
|
+
end
|
23
|
+
|
24
|
+
base = merge_base(branch.name, remote.name)
|
25
|
+
|
26
|
+
if base == remote.commit.sha
|
27
|
+
puts "ahead of upstream".blue
|
28
|
+
next
|
29
|
+
end
|
30
|
+
|
31
|
+
if base == branch.commit.sha
|
32
|
+
puts "fast-forwarding...".yellow
|
33
|
+
checkout(branch.name)
|
34
|
+
rebase(remote)
|
35
|
+
else
|
36
|
+
puts "diverged".red
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
check_bundler
|
44
|
+
rescue GitError => e
|
45
|
+
puts e.message
|
46
|
+
exit 1
|
47
|
+
end
|
48
|
+
|
49
|
+
def repo
|
50
|
+
@repo ||= get_repo
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_repo
|
54
|
+
git_dir = `git rev-parse --git-dir`
|
55
|
+
|
56
|
+
if $? == 0
|
57
|
+
@repo = Grit::Repo.new(File.dirname(git_dir))
|
58
|
+
else
|
59
|
+
raise GitError, "We don't seem to be in a git repository."
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def branches
|
64
|
+
@branches ||= repo.branches.select { |b| remote_map.has_key?(b.name) }
|
65
|
+
end
|
66
|
+
|
67
|
+
def remotes
|
68
|
+
@remotes ||= remote_map.values.map { |r| r.name.split('/', 2).first }.uniq
|
69
|
+
end
|
70
|
+
|
71
|
+
def remote_map
|
72
|
+
@remote_map ||= repo.branches.inject({}) { |map, branch|
|
73
|
+
if remote = remote_for_branch(branch)
|
74
|
+
map[branch.name] = remote
|
75
|
+
end
|
76
|
+
|
77
|
+
map
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
def remote_for_branch(branch)
|
82
|
+
remote_name = repo.config["branch.#{branch.name}.remote"] || "origin"
|
83
|
+
remote_branch = repo.config["branch.#{branch.name}.merge"] || branch.name
|
84
|
+
remote_branch.sub!(%r{^refs/heads/}, '')
|
85
|
+
repo.remotes.find { |r| r.name == "#{remote_name}/#{remote_branch}" }
|
86
|
+
end
|
87
|
+
|
88
|
+
def with_stash
|
89
|
+
stashed = false
|
90
|
+
|
91
|
+
status = repo.status
|
92
|
+
change_count = status.added.length + status.changed.length + status.deleted.length
|
93
|
+
|
94
|
+
if change_count > 0
|
95
|
+
puts "stashing #{change_count} changes".magenta
|
96
|
+
repo.git.stash
|
97
|
+
stashed = true
|
98
|
+
end
|
99
|
+
|
100
|
+
yield
|
101
|
+
|
102
|
+
if stashed
|
103
|
+
puts "unstashing".magenta
|
104
|
+
repo.git.stash({}, "pop")
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def returning_to_current_branch
|
109
|
+
unless repo.head.respond_to?(:name)
|
110
|
+
puts "You're not currently on a branch. I'm exiting in case you're in the middle of something.".red
|
111
|
+
return
|
112
|
+
end
|
113
|
+
|
114
|
+
branch_name = repo.head.name
|
115
|
+
|
116
|
+
yield
|
117
|
+
|
118
|
+
unless on_branch?(branch_name)
|
119
|
+
puts "returning to #{branch_name}".magenta
|
120
|
+
checkout(branch_name)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def checkout(branch_name)
|
125
|
+
output = repo.git.checkout({}, branch_name)
|
126
|
+
|
127
|
+
unless on_branch?(branch_name)
|
128
|
+
raise GitError.new("Failed to checkout #{branch_name}", output)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def rebase(target_branch)
|
133
|
+
current_branch = repo.head
|
134
|
+
|
135
|
+
output, err = repo.git.sh("#{Grit::Git.git_binary} rebase #{target_branch.name}")
|
136
|
+
|
137
|
+
unless on_branch?(current_branch.name) and is_fast_forward?(current_branch, target_branch)
|
138
|
+
raise GitError.new("Failed to rebase #{current_branch.name} onto #{target_branch.name}", output+err)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def check_bundler
|
143
|
+
return unless use_bundler?
|
144
|
+
|
145
|
+
begin
|
146
|
+
require 'bundler'
|
147
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('Gemfile')
|
148
|
+
Bundler.setup
|
149
|
+
rescue Bundler::GemNotFound, Bundler::GitError
|
150
|
+
puts
|
151
|
+
print 'Gems are missing. '.yellow
|
152
|
+
|
153
|
+
if config("bundler.autoinstall") == 'true'
|
154
|
+
puts "Running `bundle install`.".yellow
|
155
|
+
system "bundle", "install"
|
156
|
+
else
|
157
|
+
puts "You should `bundle install`.".yellow
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def is_fast_forward?(a, b)
|
163
|
+
merge_base(a.name, b.name) == b.commit.sha
|
164
|
+
end
|
165
|
+
|
166
|
+
def merge_base(a, b)
|
167
|
+
repo.git.send("merge-base", {}, a, b).strip
|
168
|
+
end
|
169
|
+
|
170
|
+
def on_branch?(branch_name=nil)
|
171
|
+
repo.head.respond_to?(:name) and repo.head.name == branch_name
|
172
|
+
end
|
173
|
+
|
174
|
+
class GitError < StandardError
|
175
|
+
def initialize(message, output=nil)
|
176
|
+
@msg = "#{message.red}"
|
177
|
+
|
178
|
+
if output
|
179
|
+
@msg << "\n"
|
180
|
+
@msg << "Here's what Git said:".red
|
181
|
+
@msg << "\n"
|
182
|
+
@msg << output
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def message
|
187
|
+
@msg
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
private
|
192
|
+
|
193
|
+
def use_bundler?
|
194
|
+
use_bundler_config? and File.exists? 'Gemfile'
|
195
|
+
end
|
196
|
+
|
197
|
+
def use_bundler_config?
|
198
|
+
if ENV.has_key?('GIT_UP_BUNDLER_CHECK')
|
199
|
+
puts <<-EOS.yellow
|
200
|
+
The GIT_UP_BUNDLER_CHECK environment variable is deprecated.
|
201
|
+
You can now tell git-up to check (or not check) for missing
|
202
|
+
gems on a per-project basis using git's config system. To
|
203
|
+
set it globally, run this command anywhere:
|
204
|
+
|
205
|
+
git config --global git-up.bundler.check true
|
206
|
+
|
207
|
+
To set it within a project, run this command inside that
|
208
|
+
project's directory:
|
209
|
+
|
210
|
+
git config git-up.bundler.check true
|
211
|
+
|
212
|
+
Replace 'true' with 'false' to disable checking.
|
213
|
+
EOS
|
214
|
+
end
|
215
|
+
|
216
|
+
config("bundler.check") == 'true' || ENV['GIT_UP_BUNDLER_CHECK'] == 'true'
|
217
|
+
end
|
218
|
+
|
219
|
+
def config(key)
|
220
|
+
repo.config["git-up.#{key}"]
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
metadata
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: git-up-portertech
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.5.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Aanand Prasad
|
9
|
+
- Elliot Crosby-McCullough
|
10
|
+
- Adrian Irving-Beer
|
11
|
+
- Joshua Wehner
|
12
|
+
autorequire:
|
13
|
+
bindir: bin
|
14
|
+
cert_chain: []
|
15
|
+
|
16
|
+
date: 2011-07-13 00:00:00 -07:00
|
17
|
+
default_executable:
|
18
|
+
dependencies:
|
19
|
+
- !ruby/object:Gem::Dependency
|
20
|
+
name: thoughtbot-shoulda
|
21
|
+
prerelease: false
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: "0"
|
28
|
+
type: :development
|
29
|
+
version_requirements: *id001
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: colored
|
32
|
+
prerelease: false
|
33
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ">="
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: "1.2"
|
39
|
+
type: :runtime
|
40
|
+
version_requirements: *id002
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: grit
|
43
|
+
prerelease: false
|
44
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: "0"
|
50
|
+
type: :runtime
|
51
|
+
version_requirements: *id003
|
52
|
+
description:
|
53
|
+
email:
|
54
|
+
- aanand.prasad@gmail.com
|
55
|
+
- elliot.cm@gmail.com
|
56
|
+
executables:
|
57
|
+
- git-up
|
58
|
+
extensions: []
|
59
|
+
|
60
|
+
extra_rdoc_files: []
|
61
|
+
|
62
|
+
files:
|
63
|
+
- bin/git-up
|
64
|
+
- lib/git-up/version.rb
|
65
|
+
- lib/git-up.rb
|
66
|
+
- LICENSE
|
67
|
+
- README.md
|
68
|
+
has_rdoc: true
|
69
|
+
homepage: http://github.com/aanand/git-up
|
70
|
+
licenses: []
|
71
|
+
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: "0"
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: "0"
|
89
|
+
requirements: []
|
90
|
+
|
91
|
+
rubyforge_project:
|
92
|
+
rubygems_version: 1.6.2
|
93
|
+
signing_key:
|
94
|
+
specification_version: 3
|
95
|
+
summary: git command to fetch and rebase all branches
|
96
|
+
test_files: []
|
97
|
+
|