git-extras 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f5ba92b639627411f03a70fb68d6224f2a3b1b78
4
+ data.tar.gz: 9a35848a79d382eb4b558561baadba3050731b02
5
+ SHA512:
6
+ metadata.gz: ec9c52981ed131cb97169f2a807a32f3e4b7cd9e1397ed634102a86d3915057a03a85643219eb0a33edfe54f52234fc7befc585f9f43befe85a87686ed0cc65c
7
+ data.tar.gz: 74d2dda77f0a1e0b386c4f356e343cfb91f77ee234bce9fd67364e75a07bb54db11c3f2e681ce40ee1ac5316e54d507aaf376fa800b25083dc1dc3f40fe0aa69
@@ -0,0 +1 @@
1
+ pkg/
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,25 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ git-extras (0.1.0)
5
+ faker
6
+ thor
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ faker (1.6.6)
12
+ i18n (~> 0.5)
13
+ i18n (0.7.0)
14
+ rake (11.2.2)
15
+ thor (0.19.1)
16
+
17
+ PLATFORMS
18
+ ruby
19
+
20
+ DEPENDENCIES
21
+ git-extras!
22
+ rake
23
+
24
+ BUNDLED WITH
25
+ 1.12.5
@@ -0,0 +1,5 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ task default: [
4
+ :release,
5
+ ]
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ p ARGV
4
+ # version=ARGV[1]
5
+ bump = "!f(){ git bump $(git ltag);};f"
6
+
@@ -0,0 +1,295 @@
1
+ #!/usr/bin/env ruby
2
+ line = DATA.readlines.sample
3
+ name = ['Nick', 'Andy', 'Steve', 'Sarah', 'Jason', 'Todd'].sample
4
+ puts line.sub('{{Name}}', name).sub('{{UPPER}}', name.upcase)
5
+
6
+ __END__
7
+ {{UPPER}}, WE WENT OVER THIS. EXPANDTAB.
8
+ {{UPPER}}, WE WENT OVER THIS. C++ IO SUCKS.
9
+ This is the last time we let {{Name}} commit ascii porn in the comments.
10
+ de-misunderestimating
11
+ Some shit.
12
+ add actual words
13
+ I CAN HAZ COMMENTZ.
14
+ giggle.
15
+ Whatever.
16
+ Finished fondling.
17
+ FONDLED THE CODE
18
+ this is how we generate our shit.
19
+ unh
20
+ It works!
21
+ unionfind is no longer being molested.
22
+ Well, it's doing something.
23
+ I'M PUSHING.
24
+ Whee.
25
+ Whee, good night.
26
+ It'd be nice if type errors caused the compiler to issue a type error
27
+ Fucking templates.
28
+ I hate this fucking language.
29
+ marks
30
+ that coulda been bad
31
+ hoo boy
32
+ It was the best of times, it was the worst of times
33
+ Fucking egotistical bastard. adds expandtab to vimrc
34
+ if you're not using et, fuck off
35
+ WHO THE FUCK CAME UP WITH MAKE?
36
+ This is a basic implementation that works.
37
+ By works, I meant 'doesnt work'. Works now..
38
+ Last time I said it works? I was kidding. Try this.
39
+ Just stop reading these for a while, ok..
40
+ Give me a break, it's 2am. But it works now.
41
+ Make that it works in 90% of the cases. 3:30.
42
+ Ok, 5am, it works. For real.
43
+ FOR REAL.
44
+ I don't know what these changes are supposed to accomplish but somebody told me to make them.
45
+ I don't get paid enough for this shit.
46
+ fix some fucking errors
47
+ first blush
48
+ So my boss wanted this button ...
49
+ uhhhhhh
50
+ forgot we're not using a smart language
51
+ include shit
52
+ To those I leave behind, good luck!
53
+ things occurred
54
+ i dunno, maybe this works
55
+ 8==========D
56
+ No changes made
57
+ whooooooooooooooooooooooooooo
58
+ clarify further the brokenness of C++. why the fuck are we using C++?
59
+ (\ /)\n(O.o)\n(> <) Bunny approves these changes.
60
+ .
61
+ Friday 5pm
62
+ changes
63
+ A fix I believe, not like I tested or anything
64
+ Useful text
65
+ pgsql is being a pain
66
+ pgsql is more strict, increase the hackiness up to 11
67
+ c&p fail
68
+ syntax
69
+ {{Name}} sucks
70
+ {{UPPER}} SUCKS
71
+ fix
72
+ just shoot me
73
+ arrrggghhhhh fixed!
74
+ someone fails and it isn't me
75
+ Gross hack because {{Name}} doesn't know how to code
76
+ totally more readable
77
+ better grepping
78
+ fix
79
+ fix bug, for realz
80
+ fix /sigh
81
+ Does this work
82
+ MOAR BIFURCATION
83
+ bifurcation
84
+ REALLY FUCKING FIXED
85
+ FIX
86
+ better ignores
87
+ More ignore
88
+ more ignores
89
+ more ignored words
90
+ more fixes
91
+ really ignore ignored worsd
92
+ fixes
93
+ /sigh
94
+ fix
95
+ fail
96
+ pointless limitation
97
+ eppic fail {{Name}}
98
+ omg what have I done?
99
+ added super-widget 2.0.
100
+ tagging release w.t.f.
101
+ I can't believe it took so long to fix this.
102
+ I must have been drunk.
103
+ This is why the cat shouldn't sit on my keyboard.
104
+ This is why git rebase is a horrible horrible thing.
105
+ ajax-loader hotness, oh yeah
106
+ {{Name}} broke the regex, lame
107
+ small is a real HTML tag, who knew.
108
+ WTF is this.
109
+ Do things better, faster, stronger
110
+ Fixed a bug cause {{Name}} said to
111
+ Use a real JS construct, WTF knows why this works in chromium.
112
+ Added a banner to the default admin page. Please have mercy on me =(
113
+ needs more cow bell
114
+ Switched off unit test X because the build had to go out now and there was no time to fix it properly.
115
+ Updated
116
+ I must sleep... it's working... in just three hours...
117
+ I was wrong...
118
+ Completed with no bugs...
119
+ Fixed a little bug...
120
+ Fixed a bug in NoteLineCount... not seriously...
121
+ woa!! this one was really HARD!
122
+ Made it to compile...
123
+ changed things...
124
+ touched...
125
+ i think i fixed a bug...
126
+ perfect...
127
+ Moved something to somewhere... goodnight...
128
+ oops, forgot to add the file
129
+ Corrected mistakes
130
+ oops
131
+ oops!
132
+ put code that worked where the code that didn't used to be
133
+ Nothing to see here, move along
134
+ I am even stupider than I thought
135
+ I don't know what the hell I was thinking.
136
+ fixed errors in the previous commit
137
+ Committed some changes
138
+ Some bugs fixed
139
+ Minor updates
140
+ Added missing file in previous commit
141
+ bug fix
142
+ typo
143
+ bara bra grejjor
144
+ Continued development...
145
+ Does anyone read this? I'll be at the coffee shop accross the street.
146
+ That's just how I roll
147
+ work in progress
148
+ minor changes
149
+ some brief changes
150
+ assorted changes
151
+ lots and lots of changes
152
+ another big bag of changes
153
+ lots of changes after a lot of time
154
+ LOTS of changes. period
155
+ {{Name}} made me do it
156
+ Test commit. Please ignore
157
+ I'm just a grunt. Don't blame me for this awful PoS.
158
+ I did it for the lulz!
159
+ I'll explain this when I'm sober .. or revert it
160
+ Obligatory placeholder commit message
161
+ A long time ago, in a galaxy far far away...
162
+ Fixed the build.
163
+ Fixing {{Name}}'s bug.
164
+ Fixing {{Name}}'s bugs.
165
+ various changes
166
+ One more time, but with feeling.
167
+ Handled a particular error.
168
+ Fixed unnecessary bug.
169
+ Removed code.
170
+ Added translation.
171
+ Updated build targets.
172
+ Refactored configuration.
173
+ Locating the required gigapixels to render...
174
+ Spinning up the hamster...
175
+ Shovelling coal into the server...
176
+ Programming the flux capacitor
177
+ The last time I tried this the monkey didn't survive. Let's hope it works better this time.
178
+ I should have had a V8 this morning.
179
+ 640K ought to be enough for anybody
180
+ pay no attention to the man behind the curtain
181
+ a few bits tried to escape, but we caught them
182
+ Who has two thumbs and remembers the rudiments of his linear algebra courses? Apparently, this guy.
183
+ workaround for ant being a pile of fail
184
+ Don't push this commit
185
+ rats
186
+ squash me
187
+ fixed mistaken bug
188
+ Final commit, ready for tagging
189
+ -m \'So I hear you like commits ...\'
190
+ epic
191
+ need another beer
192
+ Well the book was obviously wrong.
193
+ lolwhat?
194
+ Another commit to keep my CAN streak going.
195
+ I cannot believe that it took this long to write a test for this.
196
+ TDD: 1, Me: 0
197
+ Yep, {{Name}} was right on this one.
198
+ Yes, I was being sarcastic.
199
+ Apparently works-for-me is a crappy excuse.
200
+ tl;dr
201
+ I would rather be playing SC2.
202
+ Crap. Tonight is raid night and I am already late.
203
+ I know what I am doing. Trust me.
204
+ You should have trusted me.
205
+ Is there an award for this?
206
+ Is there an achievement for this?
207
+ I'm totally adding this to epic win. +300
208
+ This really should not take 19 minutes to build.
209
+ fixed the israeli-palestinian conflict
210
+ SHIT ===> GOLD
211
+ Committing in accordance with the prophecy.
212
+ It compiles! Ship it!
213
+ LOL!
214
+ Reticulating splines...
215
+ SEXY RUSSIAN CODES WAITING FOR YOU TO CALL
216
+ s/import/include/
217
+ extra debug for stuff module
218
+ debug line test
219
+ debugo
220
+ remove debug<br/>all good
221
+ debug suff
222
+ more debug... who overwrote!
223
+ FUCKING {{UPPER}}
224
+ these confounded tests drive me nuts
225
+ For great justice.
226
+ QuickFix.
227
+ oops - thought I got that one.
228
+ removed echo and die statements, lolz.
229
+ somebody keeps erasing my changes.
230
+ doh.
231
+ pam anderson is going to love me.
232
+ added security.
233
+ arrgghh... damn this thing for not working.
234
+ jobs... steve jobs
235
+ and a comma
236
+ this is my quickfix branch and i will use to do my quickfixes
237
+ Fix my stupidness
238
+ and so the crazy refactoring process sees the sunlight after some months in the dark!
239
+ gave up and used tables.
240
+ [Insert your commit message here. Be sure to make it descriptive.]
241
+ Removed test case since code didn't pass QA
242
+ removed tests since i can't make them green
243
+ stuff
244
+ more stuff
245
+ Become a programmer, they said. It'll be fun, they said.
246
+ Same as last commit with changes
247
+ foo
248
+ just checking if git is working properly...
249
+ fixed some minor stuff, might need some additional work.
250
+ just trolling the repo
251
+ All your codebase are belong to us.
252
+ Somebody set up us the bomb.
253
+ should work I guess...
254
+ To be honest, I do not quite remember everything I changed here today. But it is all good, I tell ya.
255
+ well crap.
256
+ herpderp (redux)
257
+ herpderp
258
+ Derp
259
+ derpherp
260
+ Herping the derp
261
+ sometimes you just herp the derp so hard it herpderps
262
+ Derp. Fix missing constant post rename
263
+ Herping the fucking derp right here and now.
264
+ Derp, asset redirection in dev mode
265
+ mergederp
266
+ Derp search/replace fuckup
267
+ Herpy dooves.
268
+ Derpy hooves
269
+ derp, helper method rename
270
+ Herping the derp derp (silly scoping error)
271
+ Herp derp I left the debug in there and forgot to reset errors.
272
+ Reset error count between rows. herpderp
273
+ hey, what's that over there?!
274
+ hey, look over there!
275
+ It worked for me...
276
+ Does not work.
277
+ Either Hot Shit or Total Bollocks
278
+ Arrrrgggg
279
+ Don’t mess with Voodoo
280
+ I expected something different.
281
+ Todo!!!
282
+ This is supposed to crash
283
+ No changes after this point.
284
+ I know, I know, this is not how I’m supposed to do it, but I can't think of something better.
285
+ Don’t even try to refactor it.
286
+ (c) Microsoft 1988
287
+ Please no changes this time.
288
+ Why The Fuck?
289
+ We should delete this crap before shipping.
290
+ Shit code!
291
+ ALL SORTS OF THINGS
292
+ Herpderp, shoulda check if it does really compile.
293
+ I CAN HAZ PYTHON, I CAN HAZ INDENTS
294
+ {{Name}} rebase plx?
295
+ Major fixup.
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ require "faker"
3
+
4
+ types = {
5
+ "hacker" => "Faker::Hacker.say_something_smart",
6
+ "hipster" => "Faker::Hipster.sentences(1)[0]",
7
+ "book" => "Faker::Book.title",
8
+ "doing" => "Faker::Hacker.ingverb + '' '' + Faker::Hacker.adjective",
9
+ "biz" => "Faker::Company.catch_phrase",
10
+ "buzz" => "Faker::Company.buzzword",
11
+ "bs" => "Faker::Company.bs",
12
+ "team" => "Faker::Team.name",
13
+ }
14
+
15
+ puts eval(ARGV[1] ? types[ARGV[1]] : types[types.keys.sample]).capitalize
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ## git-rank-contributors: a simple script to trace through the logs and
4
+ ## rank contributors by the total size of the diffs they're responsible for.
5
+ ## A change counts twice as much as a plain addition or deletion.
6
+ ##
7
+ ## Output may or may not be suitable for inclusion in a CREDITS file.
8
+ ## Probably not without some editing, because people often commit from more
9
+ ## than one address.
10
+ ##
11
+ ## git-rank-contributors Copyright 2008 William Morgan <wmorgan-git-wt-add@masanjin.net>.
12
+ ## This program is free software: you can redistribute it and/or modify
13
+ ## it under the terms of the GNU General Public License as published by
14
+ ## the Free Software Foundation, either version 3 of the License, or (at
15
+ ## your option) any later version.
16
+ ##
17
+ ## This program is distributed in the hope that it will be useful,
18
+ ## but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
+ ## GNU General Public License for more details.
21
+ ##
22
+ ## You can find the GNU General Public License at:
23
+ ## http://www.gnu.org/licenses/
24
+
25
+ class String
26
+ def obfuscate; gsub(/@/, " at the ").gsub(/\.(\w+)(>|$)/, ' dot \1s\2') end
27
+ def htmlize; gsub("&", "&amp;").gsub("<", "&lt;").gsub(">", "&gt;") end
28
+ end
29
+
30
+ lines = {}
31
+ verbose = ARGV.delete("-v")
32
+ obfuscate = ARGV.delete("-o")
33
+ htmlize = ARGV.delete("-h")
34
+
35
+ author = nil
36
+ state = :pre_author
37
+ `git log -M -C -C -p --no-color`
38
+ .encode('UTF-8', 'binary', :invalid => :replace, :undef => :replace)
39
+ .split("\n")
40
+ .each do |l|
41
+ case
42
+ when (state == :pre_author || state == :post_author) && l =~ /Author: (.*)$/
43
+ author = $1
44
+ state = :post_author
45
+ lines[author] ||= 0
46
+ when state == :post_author && l =~ /^\+\+\+/
47
+ state = :in_diff
48
+ when state == :in_diff && l =~ /^[\+\-]/
49
+ lines[author] += 1
50
+ when state == :in_diff && l =~ /^commit /
51
+ state = :pre_author
52
+ end
53
+ end
54
+
55
+ lines.sort_by { |a, c| -c }.each do |a, c|
56
+ a = a.obfuscate if obfuscate
57
+ a = a.htmlize if htmlize
58
+ if verbose
59
+ puts "#{a}: #{c} lines of diff"
60
+ else
61
+ puts a
62
+ end
63
+ end
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ release = "!f(){ git tag -a v$(git nn) -m \"$(git last)\" && git push origin master --tags;};f"
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+
3
+ root="$(git rev-parse --show-toplevel)"
4
+ file="$(dirname ${root})/$(basename $PWD).tar.gz"
5
+ git archive --format=tar.gz -o ${file} HEAD
6
+ echo "File ${file} created."
@@ -0,0 +1,186 @@
1
+ #!/usr/bin/env ruby
2
+ require "thor"
3
+ require "yaml"
4
+
5
+ DIR = "#{ENV['HOME']}/.git-users"
6
+
7
+ module Git
8
+ module Account
9
+ class CancelledException < Exception
10
+ end
11
+
12
+ class Cli < Thor
13
+
14
+ desc "ls", "List accounts"
15
+ def ls
16
+ getLs do |name|
17
+ puts name
18
+ end
19
+ end
20
+
21
+ desc "all", "Show all settings"
22
+ def all
23
+ rows = []
24
+ rows << ["ACCOUNT", "KEY", "VALUE"]
25
+ Dir["#{DIR}/*.yaml"].each do |file|
26
+ first = false
27
+ name = file.sub("#{DIR}/", "").sub(".yaml", "")
28
+ data = YAML.load_file(file)
29
+ data.each do |k,v|
30
+ if first
31
+ name = ""
32
+ end
33
+
34
+ rows << [name, k, v]
35
+ first = true
36
+ end
37
+ end
38
+ table rows
39
+ end
40
+
41
+ desc "new", "Adds a a new account"
42
+ def new name = nil
43
+ print "Enter the new account name: "
44
+ account = $stdin.readline().chomp
45
+
46
+ print "Enter your name: "
47
+ name = $stdin.readline().chomp
48
+
49
+ print "Enter your email address: "
50
+ email = $stdin.readline().chomp
51
+
52
+ data = {}
53
+ data["user.name"] = name
54
+ data["user.email"] = email
55
+
56
+ puts
57
+ puts "Now you can set more key values."
58
+ begin
59
+ loop do
60
+ print "Enter a key (leave empty to skip): "
61
+ key = $stdin.readline().chomp
62
+ raise CancelledException if key.empty?
63
+
64
+ print "Enter the value for key \033[1m#{key}\033[0m: "
65
+ value = $stdin.readline().chomp
66
+ raise CancelledException if value.empty?
67
+
68
+ data[key] = value
69
+ end
70
+
71
+ rescue CancelledException
72
+ puts "Skipping"
73
+ end
74
+
75
+ file = "#{DIR}/#{account}.yaml"
76
+ File.write(file, data.to_yaml)
77
+ puts `cat #{file}`
78
+ end
79
+
80
+ desc "set NAME KEY VALUE", "Apply a user config"
81
+ def set name, key, value
82
+ file = "#{DIR}/#{name}.yaml"
83
+ data = YAML.load_file(file)
84
+ data[key] = value
85
+ File.write(file, data.to_yaml)
86
+ end
87
+
88
+ desc "rm NAME", "Removes a user account"
89
+ def rm name
90
+ file = "#{DIR}/#{name}.yaml"
91
+ system "rm #{file}"
92
+ end
93
+
94
+ desc "del NAME KEY", "Removes a user config"
95
+ def del name, key
96
+ file = "#{DIR}/#{name}.yaml"
97
+ data = YAML.load_file(file)
98
+ data.delete key
99
+ File.write(file, data.to_yaml)
100
+ end
101
+
102
+ desc "show", "Show current account configuration"
103
+ def show
104
+ rows = []
105
+ rows << ["KEY", "VALUE"]
106
+ name = file.sub("#{DIR}/", "").sub(".yaml", "")
107
+ data = YAML.load_file(file)
108
+ data.each do |k,v|
109
+ rows << [k, v]
110
+ end
111
+ table rows
112
+ end
113
+
114
+ desc "use NAME", "Apply the account setting"
115
+ def use(name)
116
+ file = "#{DIR}/#{name}.yaml"
117
+ data = YAML.load_file(file)
118
+ data.each do |k, v|
119
+ system "git config #{k} #{v}"
120
+ puts "#{k}: " + `git config #{k}`
121
+ end
122
+ end
123
+
124
+ desc "fix", "Fixes the author in the last commit"
125
+ def fix
126
+ user = `git config user.name`.chomp
127
+ email = `git config user.email`.chomp
128
+ system "git commit --amend --author '#{user} <#{email}>'"
129
+ end
130
+
131
+ private
132
+ def getLs
133
+ Dir["#{DIR}/*.yaml"].each do |file|
134
+ name = file.sub("#{DIR}/", "").sub(".yaml", "")
135
+ yield name
136
+ end
137
+ end
138
+
139
+ def table data
140
+ widths = []
141
+ data.each do |line|
142
+ c = 0
143
+ line.each do |col|
144
+ str = col.to_s
145
+ len = str.length
146
+ widths[c] = len if widths[c].nil? || len > widths[c]
147
+ c += 1
148
+ end
149
+ end
150
+
151
+ format = widths.collect{|n| "%-#{n}s"}.join(" ").chomp + "\n"
152
+ data.each do |row|
153
+ printf format, *row
154
+ end
155
+ end
156
+
157
+ def getAll
158
+ rows = []
159
+ rows << ["ACCOUNT", "KEY", "VALUE"]
160
+ Dir["#{DIR}/*.yaml"].each do |file|
161
+ first = false
162
+ name = file.sub("#{DIR}/", "").sub(".yaml", "")
163
+ data = YAML.load_file(file)
164
+ data.each do |k,v|
165
+ if first
166
+ name = ""
167
+ end
168
+
169
+ rows << [name, k, v]
170
+ first = true
171
+ end
172
+ end
173
+ table rows
174
+ end
175
+ end
176
+ end
177
+ end
178
+
179
+
180
+ begin
181
+ Git::Account::Cli.start ARGV
182
+
183
+ rescue SystemExit, Interrupt
184
+ print "Bye"
185
+
186
+ end
@@ -0,0 +1,364 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ HELP = <<EOS
4
+ git-wtf displays the state of your repository in a readable, easy-to-scan
5
+ format. It's useful for getting a summary of how a branch relates to a remote
6
+ server, and for wrangling many topic branches.
7
+
8
+ git-wtf can show you:
9
+ - How a branch relates to the remote repo, if it's a tracking branch.
10
+ - How a branch relates to integration branches, if it's a feature branch.
11
+ - How a branch relates to the feature branches, if it's an integration
12
+ branch.
13
+
14
+ git-wtf is best used before a git push, or between a git fetch and a git
15
+ merge. Be sure to set color.ui to auto or yes for maximum viewing pleasure.
16
+ EOS
17
+
18
+ KEY = <<EOS
19
+ KEY:
20
+ () branch only exists locally
21
+ {} branch only exists on a remote repo
22
+ [] branch exists locally and remotely
23
+
24
+ x merge occurs both locally and remotely
25
+ ~ merge occurs only locally
26
+ (space) branch isn't merged in
27
+
28
+ (It's possible for merges to occur remotely and not locally, of course, but
29
+ that's a less common case and git-wtf currently doesn't display anything
30
+ special for it.)
31
+ EOS
32
+
33
+ USAGE = <<EOS
34
+ Usage: git wtf [branch+] [options]
35
+
36
+ If [branch] is not specified, git-wtf will use the current branch. The possible
37
+ [options] are:
38
+
39
+ -l, --long include author info and date for each commit
40
+ -a, --all show all branches across all remote repos, not just
41
+ those from origin
42
+ -A, --all-commits show all commits, not just the first 5
43
+ -s, --short don't show commits
44
+ -k, --key show key
45
+ -r, --relations show relation to features / integration branches
46
+ --dump-config print out current configuration and exit
47
+
48
+ git-wtf uses some heuristics to determine which branches are integration
49
+ branches, and which are feature branches. (Specifically, it assumes the
50
+ integration branches are named "master", "next" and "edge".) If it guesses
51
+ incorrectly, you will have to create a .git-wtfrc file.
52
+
53
+ To start building a configuration file, run "git-wtf --dump-config >
54
+ .git-wtfrc" and edit it. The config file is a YAML file that specifies the
55
+ integration branches, any branches to ignore, and the max number of commits to
56
+ display when --all-commits isn't used. git-wtf will look for a .git-wtfrc file
57
+ starting in the current directory, and recursively up to the root.
58
+
59
+ IMPORTANT NOTE: all local branches referenced in .git-wtfrc must be prefixed
60
+ with heads/, e.g. "heads/master". Remote branches must be of the form
61
+ remotes/<remote>/<branch>.
62
+ EOS
63
+
64
+ COPYRIGHT = <<EOS
65
+ git-wtf Copyright 2008--2009 William Morgan <wmorgan at the masanjin dot nets>.
66
+ This program is free software: you can redistribute it and/or modify it
67
+ under the terms of the GNU General Public License as published by the Free
68
+ Software Foundation, either version 3 of the License, or (at your option)
69
+ any later version.
70
+
71
+ This program is distributed in the hope that it will be useful, but WITHOUT
72
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
73
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
74
+ more details.
75
+
76
+ You can find the GNU General Public License at: http://www.gnu.org/licenses/
77
+ EOS
78
+
79
+ require 'yaml'
80
+ CONFIG_FN = ".git-wtfrc"
81
+
82
+ class Numeric; def pluralize s; "#{to_s} #{s}" + (self != 1 ? "s" : "") end end
83
+
84
+ if ARGV.delete("--help") || ARGV.delete("-h")
85
+ puts USAGE
86
+ exit
87
+ end
88
+
89
+ ## poor man's trollop
90
+ $long = ARGV.delete("--long") || ARGV.delete("-l")
91
+ $short = ARGV.delete("--short") || ARGV.delete("-s")
92
+ $all = ARGV.delete("--all") || ARGV.delete("-a")
93
+ $all_commits = ARGV.delete("--all-commits") || ARGV.delete("-A")
94
+ $dump_config = ARGV.delete("--dump-config")
95
+ $key = ARGV.delete("--key") || ARGV.delete("-k")
96
+ $show_relations = ARGV.delete("--relations") || ARGV.delete("-r")
97
+ ARGV.each { |a| abort "Error: unknown argument #{a}." if a =~ /^--/ }
98
+
99
+ ## search up the path for a file
100
+ def find_file fn
101
+ while true
102
+ return fn if File.exist? fn
103
+ fn2 = File.join("..", fn)
104
+ return nil if File.expand_path(fn2) == File.expand_path(fn)
105
+ fn = fn2
106
+ end
107
+ end
108
+
109
+ want_color = `git config color.wtf`
110
+ want_color = `git config color.ui` if want_color.empty?
111
+ $color = case want_color.chomp
112
+ when "true"; true
113
+ when "auto"; $stdout.tty?
114
+ end
115
+
116
+ def red s; $color ? "\033[31m#{s}\033[0m" : s end
117
+ def green s; $color ? "\033[32m#{s}\033[0m" : s end
118
+ def yellow s; $color ? "\033[33m#{s}\033[0m" : s end
119
+ def cyan s; $color ? "\033[36m#{s}\033[0m" : s end
120
+ def grey s; $color ? "\033[1;30m#{s}\033[0m" : s end
121
+ def purple s; $color ? "\033[35m#{s}\033[0m" : s end
122
+
123
+ ## the set of commits in 'to' that aren't in 'from'.
124
+ ## if empty, 'to' has been merged into 'from'.
125
+ def commits_between from, to
126
+ if $long
127
+ `git log --pretty=format:"- %s [#{yellow "%h"}] (#{purple "%ae"}; %ar)" #{from}..#{to}`
128
+ else
129
+ `git log --pretty=format:"- %s [#{yellow "%h"}]" #{from}..#{to}`
130
+ end.split(/[\r\n]+/)
131
+ end
132
+
133
+ def show_commits commits, prefix=" "
134
+ if commits.empty?
135
+ puts "#{prefix} none"
136
+ else
137
+ max = $all_commits ? commits.size : $config["max_commits"]
138
+ max -= 1 if max == commits.size - 1 # never show "and 1 more"
139
+ commits[0 ... max].each { |c| puts "#{prefix}#{c}" }
140
+ puts grey("#{prefix}... and #{commits.size - max} more (use -A to see all).") if commits.size > max
141
+ end
142
+ end
143
+
144
+ def ahead_behind_string ahead, behind
145
+ [ahead.empty? ? nil : "#{ahead.size.pluralize 'commit'} ahead",
146
+ behind.empty? ? nil : "#{behind.size.pluralize 'commit'} behind"].
147
+ compact.join("; ")
148
+ end
149
+
150
+ def widget merged_in, remote_only=false, local_only=false, local_only_merge=false
151
+ left, right = case
152
+ when remote_only; %w({ })
153
+ when local_only; %w{( )}
154
+ else %w([ ])
155
+ end
156
+ middle = case
157
+ when merged_in && local_only_merge; green("~")
158
+ when merged_in; green("x")
159
+ else " "
160
+ end
161
+ print left, middle, right
162
+ end
163
+
164
+ def show b
165
+ have_both = b[:local_branch] && b[:remote_branch]
166
+
167
+ pushc, pullc, oosync = if have_both
168
+ [x = commits_between(b[:remote_branch], b[:local_branch]),
169
+ y = commits_between(b[:local_branch], b[:remote_branch]),
170
+ !x.empty? && !y.empty?]
171
+ end
172
+
173
+ if b[:local_branch]
174
+ puts "Local branch: " + green(b[:local_branch].sub(/^heads\//, ""))
175
+
176
+ if have_both
177
+ if pushc.empty?
178
+ puts "#{widget true} in sync with remote"
179
+ else
180
+ action = oosync ? "push after rebase / merge" : "push"
181
+ puts "#{widget false} NOT in sync with remote (you should #{action})"
182
+ show_commits pushc unless $short
183
+ end
184
+ end
185
+ end
186
+
187
+ if b[:remote_branch]
188
+ puts "Remote branch: #{cyan b[:remote_branch]} (#{b[:remote_url]})"
189
+
190
+ if have_both
191
+ if pullc.empty?
192
+ puts "#{widget true} in sync with local"
193
+ else
194
+ action = pushc.empty? ? "merge" : "rebase / merge"
195
+ puts "#{widget false} NOT in sync with local (you should #{action})"
196
+ show_commits pullc unless $short
197
+ end
198
+ end
199
+ end
200
+
201
+ puts "\n#{red "WARNING"}: local and remote branches have diverged. A merge will occur unless you rebase." if oosync
202
+ end
203
+
204
+ def show_relations b, all_branches
205
+ ibs, fbs = all_branches.partition { |name, br| $config["integration-branches"].include?(br[:local_branch]) || $config["integration-branches"].include?(br[:remote_branch]) }
206
+ if $config["integration-branches"].include? b[:local_branch]
207
+ puts "\nFeature branches:" unless fbs.empty?
208
+ fbs.each do |name, br|
209
+ next if $config["ignore"].member?(br[:local_branch]) || $config["ignore"].member?(br[:remote_branch])
210
+ next if br[:ignore]
211
+ local_only = br[:remote_branch].nil?
212
+ remote_only = br[:local_branch].nil?
213
+ name = if local_only
214
+ purple br[:name]
215
+ elsif remote_only
216
+ cyan br[:name]
217
+ else
218
+ green br[:name]
219
+ end
220
+
221
+ ## for remote_only branches, we'll compute wrt the remote branch head. otherwise, we'll
222
+ ## use the local branch head.
223
+ head = remote_only ? br[:remote_branch] : br[:local_branch]
224
+
225
+ remote_ahead = b[:remote_branch] ? commits_between(b[:remote_branch], head) : []
226
+ local_ahead = b[:local_branch] ? commits_between(b[:local_branch], head) : []
227
+
228
+ if local_ahead.empty? && remote_ahead.empty?
229
+ puts "#{widget true, remote_only, local_only} #{name} #{local_only ? "(local-only) " : ""}is merged in"
230
+ elsif local_ahead.empty?
231
+ puts "#{widget true, remote_only, local_only, true} #{name} merged in (only locally)"
232
+ else
233
+ behind = commits_between head, (br[:local_branch] || br[:remote_branch])
234
+ ahead = remote_only ? remote_ahead : local_ahead
235
+ puts "#{widget false, remote_only, local_only} #{name} #{local_only ? "(local-only) " : ""}is NOT merged in (#{ahead_behind_string ahead, behind})"
236
+ show_commits ahead unless $short
237
+ end
238
+ end
239
+ else
240
+ puts "\nIntegration branches:" unless ibs.empty? # unlikely
241
+ ibs.sort_by { |v, br| v }.each do |v, br|
242
+ next if $config["ignore"].member?(br[:local_branch]) || $config["ignore"].member?(br[:remote_branch])
243
+ next if br[:ignore]
244
+ local_only = br[:remote_branch].nil?
245
+ remote_only = br[:local_branch].nil?
246
+ name = remote_only ? cyan(br[:name]) : green(br[:name])
247
+
248
+ ahead = commits_between v, (b[:local_branch] || b[:remote_branch])
249
+ if ahead.empty?
250
+ puts "#{widget true, local_only} merged into #{name}"
251
+ else
252
+ #behind = commits_between b[:local_branch], v
253
+ puts "#{widget false, local_only} NOT merged into #{name} (#{ahead.size.pluralize 'commit'} ahead)"
254
+ show_commits ahead unless $short
255
+ end
256
+ end
257
+ end
258
+ end
259
+
260
+ #### EXECUTION STARTS HERE ####
261
+
262
+ ## find config file and load it
263
+ $config = { "integration-branches" => %w(heads/master heads/next heads/edge), "ignore" => [], "max_commits" => 5 }.merge begin
264
+ fn = find_file CONFIG_FN
265
+ if fn && (h = YAML::load_file(fn)) # yaml turns empty files into false
266
+ h["integration-branches"] ||= h["versions"] # support old nomenclature
267
+ h
268
+ else
269
+ {}
270
+ end
271
+ end
272
+
273
+ if $dump_config
274
+ puts $config.to_yaml
275
+ exit
276
+ end
277
+
278
+ ## first, index registered remotes
279
+ remotes = `git config --get-regexp ^remote\.\*\.url`.split(/[\r\n]+/).inject({}) do |hash, l|
280
+ l =~ /^remote\.(.+?)\.url (.+)$/ or next hash
281
+ hash[$1] ||= $2
282
+ hash
283
+ end
284
+
285
+ ## next, index followed branches
286
+ branches = `git config --get-regexp ^branch\.`.split(/[\r\n]+/).inject({}) do |hash, l|
287
+ case l
288
+ when /branch\.(.*?)\.remote (.+)/
289
+ name, remote = $1, $2
290
+
291
+ hash[name] ||= {}
292
+ hash[name].merge! :remote => remote, :remote_url => remotes[remote]
293
+ when /branch\.(.*?)\.merge ((refs\/)?heads\/)?(.+)/
294
+ name, remote_branch = $1, $4
295
+ hash[name] ||= {}
296
+ hash[name].merge! :remote_mergepoint => remote_branch
297
+ end
298
+ hash
299
+ end
300
+
301
+ ## finally, index all branches
302
+ remote_branches = {}
303
+ `git show-ref`.split(/[\r\n]+/).each do |l|
304
+ sha1, ref = l.chomp.split " refs/"
305
+
306
+ if ref =~ /^heads\/(.+)$/ # local branch
307
+ name = $1
308
+ next if name == "HEAD"
309
+ branches[name] ||= {}
310
+ branches[name].merge! :name => name, :local_branch => ref
311
+ elsif ref =~ /^remotes\/(.+?)\/(.+)$/ # remote branch
312
+ remote, name = $1, $2
313
+ remote_branches["#{remote}/#{name}"] = true
314
+ next if name == "HEAD"
315
+ ignore = !($all || remote == "origin")
316
+
317
+ branch = name
318
+ if branches[name] && branches[name][:remote] == remote
319
+ # nothing
320
+ else
321
+ name = "#{remote}/#{branch}"
322
+ end
323
+
324
+ branches[name] ||= {}
325
+ branches[name].merge! :name => name, :remote => remote, :remote_branch => "#{remote}/#{branch}", :remote_url => remotes[remote], :ignore => ignore
326
+ end
327
+ end
328
+
329
+ ## assemble remotes
330
+ branches.each do |k, b|
331
+ next unless b[:remote] && b[:remote_mergepoint]
332
+ b[:remote_branch] = if b[:remote] == "."
333
+ b[:remote_mergepoint]
334
+ else
335
+ t = "#{b[:remote]}/#{b[:remote_mergepoint]}"
336
+ remote_branches[t] && t # only if it's still alive
337
+ end
338
+ end
339
+
340
+ show_dirty = ARGV.empty?
341
+ targets = if ARGV.empty?
342
+ [`git symbolic-ref HEAD`.chomp.sub(/^refs\/heads\//, "")]
343
+ else
344
+ ARGV.map { |x| x.sub(/^heads\//, "") }
345
+ end.map { |t| branches[t] or abort "Error: can't find branch #{t.inspect}." }
346
+
347
+ targets.each do |t|
348
+ show t
349
+ show_relations t, branches if $show_relations || t[:remote_branch].nil?
350
+ end
351
+
352
+ modified = show_dirty && `git ls-files -m` != ""
353
+ uncommitted = show_dirty && `git diff-index --cached HEAD` != ""
354
+
355
+ if $key
356
+ puts
357
+ puts KEY
358
+ end
359
+
360
+ puts if modified || uncommitted
361
+ puts "#{red "NOTE"}: working directory contains modified files." if modified
362
+ puts "#{red "NOTE"}: staging area contains staged but uncommitted files." if uncommitted
363
+
364
+ # the end!
@@ -0,0 +1,24 @@
1
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
2
+
3
+ require "date"
4
+ require "git_extras"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "git-extras"
8
+ spec.version = GitExtras::VERSION
9
+ spec.date = (Date.today << 1).to_s
10
+ spec.summary = "A bunch of git utility scripts"
11
+ spec.description = "A bunch of git utility scripts."
12
+ spec.authors = ["ptdorf"]
13
+ spec.email = ["ptdorf@gmail.com"]
14
+ spec.homepage = "https://github.com/ptdorf/git-extras"
15
+ spec.license = "MIT"
16
+ spec.require_paths = ["lib"]
17
+
18
+ spec.files = `git ls-files`.split $/
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename f }
20
+
21
+ spec.add_dependency "thor"
22
+ spec.add_dependency "faker"
23
+ spec.add_development_dependency "rake"
24
+ end
@@ -0,0 +1 @@
1
+ require "git_extras/version"
@@ -0,0 +1,5 @@
1
+ module GitExtras
2
+
3
+ VERSION = "0.1.0"
4
+
5
+ end
@@ -0,0 +1,3 @@
1
+ # git-extras
2
+
3
+ A bunch of git utility scripts.
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: git-extras
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - ptdorf
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-07-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: faker
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
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: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: A bunch of git utility scripts.
56
+ email:
57
+ - ptdorf@gmail.com
58
+ executables:
59
+ - git-bump
60
+ - git-commitment
61
+ - git-faker
62
+ - git-names
63
+ - git-release
64
+ - git-tar
65
+ - git-user
66
+ - git-wtf
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - ".gitignore"
71
+ - Gemfile
72
+ - Gemfile.lock
73
+ - Rakefile
74
+ - bin/git-bump
75
+ - bin/git-commitment
76
+ - bin/git-faker
77
+ - bin/git-names
78
+ - bin/git-release
79
+ - bin/git-tar
80
+ - bin/git-user
81
+ - bin/git-wtf
82
+ - git_extras.gemspec
83
+ - lib/git_extras.rb
84
+ - lib/git_extras/version.rb
85
+ - readme.md
86
+ homepage: https://github.com/ptdorf/git-extras
87
+ licenses:
88
+ - MIT
89
+ metadata: {}
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 2.6.6
107
+ signing_key:
108
+ specification_version: 4
109
+ summary: A bunch of git utility scripts
110
+ test_files: []