1
1
import sys
2
2
3
3
import git
4
- import manim as m
5
4
import numpy
5
+ import random
6
+
7
+ import manim as m
6
8
7
- from git_sim .git_sim_base_command import GitSimBaseCommand
8
9
from git_sim .settings import settings
10
+ from git_sim .git_sim_base_command import GitSimBaseCommand , DottedLine
9
11
10
12
11
13
class Rebase (GitSimBaseCommand ):
@@ -33,6 +35,16 @@ def __init__(self, branch: str):
33
35
34
36
self .cmd += f"{ type (self ).__name__ .lower ()} { self .branch } "
35
37
38
+ self .alt_colors = {
39
+ 0 : [m .BLUE_B , m .BLUE_E ],
40
+ 1 : [m .PURPLE_B , m .PURPLE_E ],
41
+ 2 : [m .RED_B , m .RED_E ],
42
+ 3 : [m .GREEN_B , m .GREEN_E ],
43
+ 4 : [m .MAROON_B , m .MAROON_E ],
44
+ 5 : [m .GOLD_B , m .GOLD_E ],
45
+ 6 : [m .TEAL_B , m .TEAL_E ],
46
+ }
47
+
36
48
def construct (self ):
37
49
if not settings .stdout and not settings .output_only_path and not settings .quiet :
38
50
print (f"{ settings .INFO_STRING } { self .cmd } " )
@@ -65,9 +77,12 @@ def construct(self):
65
77
branch_commit = self .get_commit (self .branch )
66
78
self .parse_commits (branch_commit )
67
79
head_commit = self .get_commit ()
80
+ default_commits = {}
81
+ self .get_default_commits (self .get_commit (), default_commits )
82
+ default_commits = self .sort_and_flatten (default_commits )
68
83
69
84
reached_base = False
70
- for commit in self . get_default_commits () :
85
+ for commit in default_commits :
71
86
if commit != "dark" and self .branch in self .repo .git .branch (
72
87
"--contains" , commit
73
88
):
@@ -78,27 +93,45 @@ def construct(self):
78
93
self .center_frame_on_commit (branch_commit )
79
94
80
95
to_rebase = []
81
- i = 0
82
- current = head_commit
83
- while self .branch not in self .repo .git .branch ("--contains" , current ):
84
- to_rebase .append (current )
85
- i += 1
86
- if i >= self .n :
87
- break
88
- current = self .get_default_commits ()[i ]
96
+ for c in default_commits :
97
+ if self .branch not in self .repo .git .branch ("--contains" , c ):
98
+ to_rebase .append (c )
89
99
90
100
parent = branch_commit .hexsha
91
-
101
+ branch_counts = {}
102
+ rebased_shas = []
92
103
for j , tr in enumerate (reversed (to_rebase )):
104
+ if len (tr .parents ) > 1 :
105
+ continue
93
106
if not reached_base and j == 0 :
94
107
message = "..."
95
108
else :
96
109
message = tr .message
97
- parent = self .setup_and_draw_parent (parent , message )
98
- self .draw_arrow_between_commits (tr .hexsha , parent )
110
+ color_index = int (self .drawnCommits [tr .hexsha ].get_center ()[1 ] / - 4 ) - 1
111
+ if color_index not in branch_counts :
112
+ branch_counts [color_index ] = 0
113
+ branch_counts [color_index ] += 1
114
+ commit_color = self .alt_colors [color_index % len (self .alt_colors )][1 ]
115
+ parent = self .setup_and_draw_parent (parent , message , color = commit_color )
116
+ rebased_shas .append (parent )
99
117
100
118
self .recenter_frame ()
101
119
self .scale_frame ()
120
+
121
+ branch_counts = {}
122
+ k = 0
123
+ for j , tr in enumerate (reversed (to_rebase )):
124
+ if len (tr .parents ) > 1 :
125
+ k += 1
126
+ continue
127
+ color_index = int (self .drawnCommits [tr .hexsha ].get_center ()[1 ] / - 4 ) - 1
128
+ if color_index not in branch_counts :
129
+ branch_counts [color_index ] = 0
130
+ branch_counts [color_index ] += 1
131
+ commit_color = self .alt_colors [color_index % len (self .alt_colors )][1 ]
132
+ arrow_color = self .alt_colors [color_index % len (self .alt_colors )][1 if branch_counts [color_index ] % 2 == 0 else 1 ]
133
+ self .draw_arrow_between_commits (tr .hexsha , rebased_shas [j - k ], color = arrow_color )
134
+
102
135
self .reset_head_branch (parent )
103
136
self .color_by (offset = 2 * len (to_rebase ))
104
137
self .show_command_as_title ()
@@ -111,11 +144,12 @@ def setup_and_draw_parent(
111
144
commitMessage = "New commit" ,
112
145
shift = numpy .array ([0.0 , 0.0 , 0.0 ]),
113
146
draw_arrow = True ,
147
+ color = m .RED ,
114
148
):
115
149
circle = m .Circle (
116
- stroke_color = m . RED ,
150
+ stroke_color = color ,
117
151
stroke_width = self .commit_stroke_width ,
118
- fill_color = m . RED ,
152
+ fill_color = color ,
119
153
fill_opacity = 0.25 ,
120
154
)
121
155
circle .height = 1
@@ -139,15 +173,9 @@ def setup_and_draw_parent(
139
173
length = numpy .linalg .norm (start - end ) - (1.5 if start [1 ] == end [1 ] else 3 )
140
174
arrow .set_length (length )
141
175
142
- sha = "" .join (
143
- chr (ord (letter ) + 1 )
144
- if (
145
- (chr (ord (letter ) + 1 ).isalpha () and letter < "f" )
146
- or chr (ord (letter ) + 1 ).isdigit ()
147
- )
148
- else letter
149
- for letter in child [:6 ]
150
- )
176
+ sha = None
177
+ while not sha or sha in self .drawnCommits :
178
+ sha = self .generate_random_sha ()
151
179
commitId = m .Text (
152
180
sha if commitMessage != "..." else "..." ,
153
181
font = self .font ,
@@ -190,3 +218,28 @@ def setup_and_draw_parent(
190
218
self .toFadeOut .add (arrow )
191
219
192
220
return sha
221
+
222
+ def get_default_commits (self , commit , default_commits , branch_index = 0 ):
223
+ if branch_index not in default_commits :
224
+ default_commits [branch_index ] = []
225
+ if len (default_commits [branch_index ]) < self .n :
226
+ if commit not in self .sort_and_flatten (default_commits ):
227
+ default_commits [branch_index ].append (commit )
228
+ for i , parent in enumerate (commit .parents ):
229
+ self .get_default_commits (parent , default_commits , branch_index + i )
230
+ return default_commits
231
+
232
+ def draw_arrow_between_commits (self , startsha , endsha , color ):
233
+ start = self .drawnCommits [startsha ].get_center ()
234
+ end = self .drawnCommits [endsha ].get_center ()
235
+
236
+ arrow = DottedLine (
237
+ start , end , color = color , dot_kwargs = {"color" : color }
238
+ ).add_tip ()
239
+ length = numpy .linalg .norm (start - end ) - 1.65
240
+ arrow .set_length (length )
241
+ self .draw_arrow (True , arrow )
242
+
243
+ def sort_and_flatten (self , d ):
244
+ sorted_values = [d [key ] for key in sorted (d .keys (), reverse = True )]
245
+ return sum (sorted_values , [])
0 commit comments