git-up-decklin 0.5.1.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.
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: []