@@ -17,32 +17,8 @@ namespace LibGit2Sharp
17
17
[ DebuggerDisplay ( "{DebuggerDisplay,nq}" ) ]
18
18
public class TreeChanges : IEnumerable < TreeEntryChanges > , IDiffResult
19
19
{
20
- private readonly List < TreeEntryChanges > changes = new List < TreeEntryChanges > ( ) ;
21
- private readonly List < TreeEntryChanges > added = new List < TreeEntryChanges > ( ) ;
22
- private readonly List < TreeEntryChanges > deleted = new List < TreeEntryChanges > ( ) ;
23
- private readonly List < TreeEntryChanges > modified = new List < TreeEntryChanges > ( ) ;
24
- private readonly List < TreeEntryChanges > typeChanged = new List < TreeEntryChanges > ( ) ;
25
- private readonly List < TreeEntryChanges > unmodified = new List < TreeEntryChanges > ( ) ;
26
- private readonly List < TreeEntryChanges > renamed = new List < TreeEntryChanges > ( ) ;
27
- private readonly List < TreeEntryChanges > copied = new List < TreeEntryChanges > ( ) ;
28
- private readonly List < TreeEntryChanges > conflicted = new List < TreeEntryChanges > ( ) ;
29
-
30
- private readonly IDictionary < ChangeKind , Action < TreeChanges , TreeEntryChanges > > fileDispatcher = Build ( ) ;
31
-
32
- private static IDictionary < ChangeKind , Action < TreeChanges , TreeEntryChanges > > Build ( )
33
- {
34
- return new Dictionary < ChangeKind , Action < TreeChanges , TreeEntryChanges > >
35
- {
36
- { ChangeKind . Modified , ( de , d ) => de . modified . Add ( d ) } ,
37
- { ChangeKind . Deleted , ( de , d ) => de . deleted . Add ( d ) } ,
38
- { ChangeKind . Added , ( de , d ) => de . added . Add ( d ) } ,
39
- { ChangeKind . TypeChanged , ( de , d ) => de . typeChanged . Add ( d ) } ,
40
- { ChangeKind . Unmodified , ( de , d ) => de . unmodified . Add ( d ) } ,
41
- { ChangeKind . Renamed , ( de , d ) => de . renamed . Add ( d ) } ,
42
- { ChangeKind . Copied , ( de , d ) => de . copied . Add ( d ) } ,
43
- { ChangeKind . Conflicted , ( de , d ) => de . conflicted . Add ( d ) } ,
44
- } ;
45
- }
20
+ private readonly DiffHandle diff ;
21
+ private readonly Lazy < int > count ;
46
22
47
23
/// <summary>
48
24
/// Needed for mocking purposes.
@@ -52,22 +28,46 @@ protected TreeChanges()
52
28
53
29
internal unsafe TreeChanges ( DiffHandle diff )
54
30
{
55
- using ( diff )
56
- Proxy . git_diff_foreach ( diff , FileCallback , null , null ) ;
31
+ this . diff = diff ;
32
+ this . count = new Lazy < int > ( ( ) => Proxy . git_diff_num_deltas ( diff ) ) ;
57
33
}
58
34
59
- private unsafe int FileCallback ( git_diff_delta * delta , float progress , IntPtr payload )
35
+ /// <summary>
36
+ /// Enumerates the diff and yields deltas with the specified change kind.
37
+ /// </summary>
38
+ /// <param name="changeKind">Change type to filter on.</param>
39
+ private IEnumerable < TreeEntryChanges > GetChangesOfKind ( ChangeKind changeKind )
60
40
{
61
- AddFileChange ( delta ) ;
62
- return 0 ;
41
+ TreeEntryChanges entry ;
42
+
43
+ for ( int i = 0 ; i < count . Value ; i ++ )
44
+ {
45
+ if ( TryGetEntryWithChangeTypeAt ( i , changeKind , out entry ) )
46
+ {
47
+ yield return entry ;
48
+ }
49
+ }
63
50
}
64
51
65
- private unsafe void AddFileChange ( git_diff_delta * delta )
52
+ /// <summary>
53
+ /// This is method exists to work around .net not allowing unsafe code
54
+ /// in iterators.
55
+ /// </summary>
56
+ private unsafe bool TryGetEntryWithChangeTypeAt ( int index , ChangeKind changeKind , out TreeEntryChanges entry )
66
57
{
67
- var treeEntryChanges = new TreeEntryChanges ( delta ) ;
58
+ if ( index < 0 || index > count . Value )
59
+ throw new ArgumentOutOfRangeException ( "index" , "Index was out of range. Must be non-negative and less than the size of the collection." ) ;
68
60
69
- fileDispatcher [ treeEntryChanges . Status ] ( this , treeEntryChanges ) ;
70
- changes . Add ( treeEntryChanges ) ;
61
+ var delta = Proxy . git_diff_get_delta ( diff , index ) ;
62
+
63
+ if ( TreeEntryChanges . GetStatusFromChangeKind ( delta ->status ) == changeKind )
64
+ {
65
+ entry = new TreeEntryChanges ( delta ) ;
66
+ return true ;
67
+ }
68
+
69
+ entry = null ;
70
+ return false ;
71
71
}
72
72
73
73
#region IEnumerable<TreeEntryChanges> Members
@@ -78,7 +78,22 @@ private unsafe void AddFileChange(git_diff_delta* delta)
78
78
/// <returns>An <see cref="IEnumerator{T}"/> object that can be used to iterate through the collection.</returns>
79
79
public virtual IEnumerator < TreeEntryChanges > GetEnumerator ( )
80
80
{
81
- return changes . GetEnumerator ( ) ;
81
+ for ( int i = 0 ; i < count . Value ; i ++ )
82
+ {
83
+ yield return GetEntryAt ( i ) ;
84
+ }
85
+ }
86
+
87
+ /// <summary>
88
+ /// This is method exists to work around .net not allowing unsafe code
89
+ /// in iterators.
90
+ /// </summary>
91
+ private unsafe TreeEntryChanges GetEntryAt ( int index )
92
+ {
93
+ if ( index < 0 || index > count . Value )
94
+ throw new ArgumentOutOfRangeException ( "index" , "Index was out of range. Must be non-negative and less than the size of the collection." ) ;
95
+
96
+ return new TreeEntryChanges ( Proxy . git_diff_get_delta ( diff , index ) ) ;
82
97
}
83
98
84
99
/// <summary>
@@ -97,63 +112,63 @@ IEnumerator IEnumerable.GetEnumerator()
97
112
/// </summary>
98
113
public virtual IEnumerable < TreeEntryChanges > Added
99
114
{
100
- get { return added ; }
115
+ get { return GetChangesOfKind ( ChangeKind . Added ) ; }
101
116
}
102
117
103
118
/// <summary>
104
119
/// List of <see cref="TreeEntryChanges"/> that have been deleted.
105
120
/// </summary>
106
121
public virtual IEnumerable < TreeEntryChanges > Deleted
107
122
{
108
- get { return deleted ; }
123
+ get { return GetChangesOfKind ( ChangeKind . Deleted ) ; }
109
124
}
110
125
111
126
/// <summary>
112
127
/// List of <see cref="TreeEntryChanges"/> that have been modified.
113
128
/// </summary>
114
129
public virtual IEnumerable < TreeEntryChanges > Modified
115
130
{
116
- get { return modified ; }
131
+ get { return GetChangesOfKind ( ChangeKind . Modified ) ; }
117
132
}
118
133
119
134
/// <summary>
120
135
/// List of <see cref="TreeEntryChanges"/> which type have been changed.
121
136
/// </summary>
122
137
public virtual IEnumerable < TreeEntryChanges > TypeChanged
123
138
{
124
- get { return typeChanged ; }
139
+ get { return GetChangesOfKind ( ChangeKind . TypeChanged ) ; }
125
140
}
126
141
127
142
/// <summary>
128
143
/// List of <see cref="TreeEntryChanges"/> which have been renamed
129
144
/// </summary>
130
145
public virtual IEnumerable < TreeEntryChanges > Renamed
131
146
{
132
- get { return renamed ; }
147
+ get { return GetChangesOfKind ( ChangeKind . Renamed ) ; }
133
148
}
134
149
135
150
/// <summary>
136
151
/// List of <see cref="TreeEntryChanges"/> which have been copied
137
152
/// </summary>
138
153
public virtual IEnumerable < TreeEntryChanges > Copied
139
154
{
140
- get { return copied ; }
155
+ get { return GetChangesOfKind ( ChangeKind . Copied ) ; }
141
156
}
142
157
143
158
/// <summary>
144
159
/// List of <see cref="TreeEntryChanges"/> which are unmodified
145
160
/// </summary>
146
161
public virtual IEnumerable < TreeEntryChanges > Unmodified
147
162
{
148
- get { return unmodified ; }
163
+ get { return GetChangesOfKind ( ChangeKind . Unmodified ) ; }
149
164
}
150
165
151
166
/// <summary>
152
167
/// List of <see cref="TreeEntryChanges"/> which are conflicted
153
168
/// </summary>
154
169
public virtual IEnumerable < TreeEntryChanges > Conflicted
155
170
{
156
- get { return conflicted ; }
171
+ get { return GetChangesOfKind ( ChangeKind . Conflicted ) ; }
157
172
}
158
173
159
174
private string DebuggerDisplay
@@ -186,8 +201,7 @@ public void Dispose()
186
201
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
187
202
protected virtual void Dispose ( bool disposing )
188
203
{
189
- // This doesn't do anything yet because it loads everything
190
- // eagerly and disposes of the diff handle in the constructor.
204
+ diff . SafeDispose ( ) ;
191
205
}
192
206
}
193
207
}
0 commit comments