git-race 0.0.2 → 0.0.3
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 +4 -4
- data/bin/git-race +68 -26
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e0d34c05f848d4ac765d295b1032e3f801ead60
|
4
|
+
data.tar.gz: abddd753525253dc6a77979d2f6f46f865a337d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 496dc94a50d8e698ed82bd3f2259c34958dc89a0b520c846b3bb2a14d3361ca7fc8a58b705d070b2eb91e4867b9b2eb076814bbdafa60398cba31b2265671f1b
|
7
|
+
data.tar.gz: f1a5d2aef47dd499798ce87f44e8023d064562cec9a19aaab4f005c03d6338117ea9d1258db0131ccecc25d36c023ca3be0b01f9faf17fc87fc2e343bf62f33c
|
data/bin/git-race
CHANGED
@@ -11,25 +11,73 @@ def command(cmd)
|
|
11
11
|
system("#{cmd} > /dev/null 2>&1")
|
12
12
|
end
|
13
13
|
|
14
|
-
|
14
|
+
MergeInformation = Struct.new(:branch) do
|
15
15
|
def conflict?
|
16
|
-
|
16
|
+
conflict_diff.size > 0
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
20
|
-
|
19
|
+
def description
|
20
|
+
"#{file_count} files, #{conflict_lines} line conflict with #{branch}, last authored by #{last_author}"
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
|
23
|
+
def <=>(their)
|
24
|
+
sort_fields <=> their.sort_fields
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
def sort_fields
|
30
|
+
[file_count, conflict_lines]
|
25
31
|
end
|
26
32
|
|
27
33
|
private
|
28
34
|
|
29
|
-
def
|
30
|
-
|
35
|
+
def file_count
|
36
|
+
diff_extract(/(\d+) file/).to_i
|
37
|
+
end
|
38
|
+
|
39
|
+
def conflict_lines
|
40
|
+
insertion_count + deletion_count
|
31
41
|
end
|
32
42
|
|
43
|
+
def insertion_count
|
44
|
+
diff_extract(/(\d+) insertion/).to_i
|
45
|
+
end
|
46
|
+
|
47
|
+
def deletion_count
|
48
|
+
diff_extract(/(\d+) deletion/).to_i
|
49
|
+
end
|
50
|
+
|
51
|
+
def diff_extract(regex)
|
52
|
+
if match = conflict_diff.match(regex)
|
53
|
+
match[1]
|
54
|
+
else
|
55
|
+
nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def conflict_diff
|
60
|
+
@conflict_diff ||= begin
|
61
|
+
# sadly we can't dry run a merge
|
62
|
+
command("git merge --no-ff --no-commit #{branch}")
|
63
|
+
query("git diff --shortstat").tap do
|
64
|
+
command("git merge --abort")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def last_author
|
70
|
+
query("git log -n1 --format='%an <%ae>' #{branch}")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
BranchAgeChecker = Struct.new(:branch, :stale_cutoff_date) do
|
75
|
+
def stale?
|
76
|
+
last_touched < stale_cutoff_date
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
33
81
|
def last_touched
|
34
82
|
Date.parse(log_date)
|
35
83
|
end
|
@@ -37,14 +85,6 @@ Merge = Struct.new(:branch, :days_till_stale) do
|
|
37
85
|
def log_date
|
38
86
|
query("git log -1 --date=iso --format=%cd #{branch}")
|
39
87
|
end
|
40
|
-
|
41
|
-
def diff
|
42
|
-
# you can't dry run a merge, so we have to apply and abort merges
|
43
|
-
command("git merge --no-ff --no-commit #{branch}")
|
44
|
-
query("git diff").tap do
|
45
|
-
command("git merge --abort")
|
46
|
-
end
|
47
|
-
end
|
48
88
|
end
|
49
89
|
|
50
90
|
MergeRacer = Struct.new(:branch) do
|
@@ -57,12 +97,12 @@ MergeRacer = Struct.new(:branch) do
|
|
57
97
|
puts "Cowardly refusing to run, please commit your work or update .gitignore"
|
58
98
|
puts "You can figure out what files to modify with\n"
|
59
99
|
puts " git status"
|
60
|
-
elsif
|
100
|
+
elsif merge_conflicts.none?
|
61
101
|
puts "Congratulations! Your branch doesn't conflict with anyone"
|
62
102
|
else
|
63
103
|
puts "Danger! Merge race in progress"
|
64
|
-
|
65
|
-
puts "*
|
104
|
+
merge_conflicts.each do |merge|
|
105
|
+
puts "* #{merge.description}"
|
66
106
|
end
|
67
107
|
end
|
68
108
|
|
@@ -80,23 +120,25 @@ MergeRacer = Struct.new(:branch) do
|
|
80
120
|
query("git status --porcelain").length > 0
|
81
121
|
end
|
82
122
|
|
83
|
-
def
|
84
|
-
@
|
123
|
+
def merge_conflicts
|
124
|
+
@merge_conflicts ||= recent_merges.select(&:conflict?)
|
85
125
|
end
|
86
126
|
|
87
|
-
def
|
88
|
-
branches_from_merge_base
|
127
|
+
def recent_merges
|
128
|
+
branches_from_merge_base
|
129
|
+
.reject { |branch| BranchAgeChecker.new(branch, stale_cutoff).stale? }
|
130
|
+
.map { |branch| MergeInformation.new(branch) }
|
89
131
|
end
|
90
132
|
|
91
133
|
def branches_from_merge_base
|
92
134
|
query("git branch --remotes --no-merged #{MAINLINE}").split("\n").map(&:strip)
|
93
135
|
end
|
94
136
|
|
95
|
-
def
|
96
|
-
|
137
|
+
def stale_cutoff
|
138
|
+
Date.today - STALE_THRESHOLD
|
97
139
|
end
|
98
140
|
end
|
99
141
|
|
100
142
|
service = MergeRacer.new("HEAD")
|
101
|
-
|
143
|
+
Signal.trap("INT") { service.abort and exit }
|
102
144
|
service.call
|