git-up-decklin 0.5.1.1

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