git-extras 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +25 -0
- data/Rakefile +5 -0
- data/bin/git-bump +6 -0
- data/bin/git-commitment +295 -0
- data/bin/git-faker +15 -0
- data/bin/git-names +63 -0
- data/bin/git-release +3 -0
- data/bin/git-tar +6 -0
- data/bin/git-user +186 -0
- data/bin/git-wtf +364 -0
- data/git_extras.gemspec +24 -0
- data/lib/git_extras.rb +1 -0
- data/lib/git_extras/version.rb +5 -0
- data/readme.md +3 -0
- metadata +110 -0
checksums.yaml
ADDED
|
@@ -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
|
data/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pkg/
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -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
|
data/Rakefile
ADDED
data/bin/git-bump
ADDED
data/bin/git-commitment
ADDED
|
@@ -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.
|
data/bin/git-faker
ADDED
|
@@ -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
|
data/bin/git-names
ADDED
|
@@ -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("&", "&").gsub("<", "<").gsub(">", ">") 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
|
data/bin/git-release
ADDED
data/bin/git-tar
ADDED
data/bin/git-user
ADDED
|
@@ -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
|
data/bin/git-wtf
ADDED
|
@@ -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!
|
data/git_extras.gemspec
ADDED
|
@@ -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
|
data/lib/git_extras.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require "git_extras/version"
|
data/readme.md
ADDED
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: []
|