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.
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.rb +223 -0
  5. data/lib/git-up/version.rb +3 -0
  6. 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.
@@ -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.
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'git-up'
4
+
5
+ GitUp.new.run
6
+
@@ -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
+
@@ -0,0 +1,3 @@
1
+ class GitUp
2
+ VERSION = "0.5.0"
3
+ end
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
+