@@ -11,6 +11,7 @@ internal class HistoryRewriter
11
11
12
12
private readonly HashSet < Commit > targetedCommits ;
13
13
private readonly Dictionary < GitObject , GitObject > objectMap = new Dictionary < GitObject , GitObject > ( ) ;
14
+ private readonly Dictionary < Reference , Reference > refMap = new Dictionary < Reference , Reference > ( ) ;
14
15
private readonly Queue < Action > rollbackActions = new Queue < Action > ( ) ;
15
16
16
17
private readonly string backupRefsNamespace ;
@@ -76,25 +77,42 @@ public void Execute()
76
77
}
77
78
}
78
79
79
- private void RewriteReference ( Reference reference )
80
+ private Reference RewriteReference ( Reference reference )
80
81
{
82
+ // Has this target already been rewritten?
83
+ if ( refMap . ContainsKey ( reference ) )
84
+ {
85
+ return refMap [ reference ] ;
86
+ }
87
+
81
88
var sref = reference as SymbolicReference ;
82
89
if ( sref != null )
83
90
{
84
- // TODO: Handle a cornercase where a symbolic reference
85
- // points to a Tag which name has been rewritten
86
- return ;
91
+ return RewriteReference (
92
+ sref , old => old . Target , RewriteReference ,
93
+ ( refs , old , target , logMessage ) => refs . UpdateTarget ( old , target , logMessage ) ) ;
87
94
}
88
95
89
96
var dref = reference as DirectReference ;
90
97
if ( dref != null )
91
98
{
92
- RewriteReference ( dref ) ;
99
+ return RewriteReference (
100
+ dref , old => old . Target , RewriteTarget ,
101
+ ( refs , old , target , logMessage ) => refs . UpdateTarget ( old , target . Id , logMessage ) ) ;
93
102
}
103
+
104
+ return reference ;
94
105
}
95
106
96
- private void RewriteReference ( DirectReference oldRef )
107
+ private Reference RewriteReference < TRef , TTarget > (
108
+ TRef oldRef , Func < TRef , TTarget > selectTarget ,
109
+ Func < TTarget , TTarget > rewriteTarget ,
110
+ Func < ReferenceCollection , TRef , TTarget , string , Reference > updateTarget )
111
+ where TRef : Reference
112
+ where TTarget : class
97
113
{
114
+ var oldRefTarget = selectTarget ( oldRef ) ;
115
+
98
116
string newRefName = oldRef . CanonicalName ;
99
117
if ( oldRef . IsTag ( ) && options . TagNameRewriter != null )
100
118
{
@@ -103,12 +121,12 @@ private void RewriteReference(DirectReference oldRef)
103
121
false , oldRef . TargetIdentifier ) ;
104
122
}
105
123
106
- var newTarget = RewriteTarget ( oldRef . Target ) ;
124
+ var newTarget = rewriteTarget ( oldRefTarget ) ;
107
125
108
- if ( oldRef . Target == newTarget && oldRef . CanonicalName == newRefName )
126
+ if ( oldRefTarget . Equals ( newTarget ) && oldRef . CanonicalName == newRefName )
109
127
{
110
128
// The reference isn't rewritten
111
- return ;
129
+ return oldRef ;
112
130
}
113
131
114
132
string backupName = backupRefsNamespace + oldRef . CanonicalName . Substring ( "refs/" . Length ) ;
@@ -126,19 +144,20 @@ private void RewriteReference(DirectReference oldRef)
126
144
{
127
145
repo . Refs . Remove ( oldRef ) ;
128
146
rollbackActions . Enqueue ( ( ) => repo . Refs . Add ( oldRef . CanonicalName , oldRef , true , "filter-branch: abort" ) ) ;
129
- return ;
147
+ return refMap [ oldRef ] = null ;
130
148
}
131
149
132
- Reference newRef = repo . Refs . UpdateTarget ( oldRef , newTarget . Id , "filter-branch: rewrite" ) ;
133
- rollbackActions . Enqueue ( ( ) => repo . Refs . UpdateTarget ( oldRef , oldRef . Target . Id , "filter-branch: abort" ) ) ;
150
+ Reference newRef = updateTarget ( repo . Refs , oldRef , newTarget , "filter-branch: rewrite" ) ;
151
+ rollbackActions . Enqueue ( ( ) => updateTarget ( repo . Refs , oldRef , oldRefTarget , "filter-branch: abort" ) ) ;
134
152
135
153
if ( newRef . CanonicalName == newRefName )
136
154
{
137
- return ;
155
+ return refMap [ oldRef ] = newRef ;
138
156
}
139
157
140
- repo . Refs . Move ( newRef , newRefName ) ;
158
+ var movedRef = repo . Refs . Move ( newRef , newRefName ) ;
141
159
rollbackActions . Enqueue ( ( ) => repo . Refs . Move ( newRef , oldRef . CanonicalName ) ) ;
160
+ return refMap [ oldRef ] = movedRef ;
142
161
}
143
162
144
163
private void RewriteCommit ( Commit commit )
0 commit comments