@@ -17,32 +17,8 @@ namespace LibGit2Sharp
1717 [ DebuggerDisplay ( "{DebuggerDisplay,nq}" ) ]
1818 public class TreeChanges : IEnumerable < TreeEntryChanges > , IDiffResult
1919 {
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 ;
4622
4723 /// <summary>
4824 /// Needed for mocking purposes.
@@ -52,22 +28,46 @@ protected TreeChanges()
5228
5329 internal unsafe TreeChanges ( DiffHandle diff )
5430 {
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 ) ) ;
5733 }
5834
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 )
6040 {
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+ }
6350 }
6451
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 )
6657 {
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." ) ;
6860
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 ;
7171 }
7272
7373 #region IEnumerable<TreeEntryChanges> Members
@@ -78,7 +78,22 @@ private unsafe void AddFileChange(git_diff_delta* delta)
7878 /// <returns>An <see cref="IEnumerator{T}"/> object that can be used to iterate through the collection.</returns>
7979 public virtual IEnumerator < TreeEntryChanges > GetEnumerator ( )
8080 {
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 ) ) ;
8297 }
8398
8499 /// <summary>
@@ -97,63 +112,63 @@ IEnumerator IEnumerable.GetEnumerator()
97112 /// </summary>
98113 public virtual IEnumerable < TreeEntryChanges > Added
99114 {
100- get { return added ; }
115+ get { return GetChangesOfKind ( ChangeKind . Added ) ; }
101116 }
102117
103118 /// <summary>
104119 /// List of <see cref="TreeEntryChanges"/> that have been deleted.
105120 /// </summary>
106121 public virtual IEnumerable < TreeEntryChanges > Deleted
107122 {
108- get { return deleted ; }
123+ get { return GetChangesOfKind ( ChangeKind . Deleted ) ; }
109124 }
110125
111126 /// <summary>
112127 /// List of <see cref="TreeEntryChanges"/> that have been modified.
113128 /// </summary>
114129 public virtual IEnumerable < TreeEntryChanges > Modified
115130 {
116- get { return modified ; }
131+ get { return GetChangesOfKind ( ChangeKind . Modified ) ; }
117132 }
118133
119134 /// <summary>
120135 /// List of <see cref="TreeEntryChanges"/> which type have been changed.
121136 /// </summary>
122137 public virtual IEnumerable < TreeEntryChanges > TypeChanged
123138 {
124- get { return typeChanged ; }
139+ get { return GetChangesOfKind ( ChangeKind . TypeChanged ) ; }
125140 }
126141
127142 /// <summary>
128143 /// List of <see cref="TreeEntryChanges"/> which have been renamed
129144 /// </summary>
130145 public virtual IEnumerable < TreeEntryChanges > Renamed
131146 {
132- get { return renamed ; }
147+ get { return GetChangesOfKind ( ChangeKind . Renamed ) ; }
133148 }
134149
135150 /// <summary>
136151 /// List of <see cref="TreeEntryChanges"/> which have been copied
137152 /// </summary>
138153 public virtual IEnumerable < TreeEntryChanges > Copied
139154 {
140- get { return copied ; }
155+ get { return GetChangesOfKind ( ChangeKind . Copied ) ; }
141156 }
142157
143158 /// <summary>
144159 /// List of <see cref="TreeEntryChanges"/> which are unmodified
145160 /// </summary>
146161 public virtual IEnumerable < TreeEntryChanges > Unmodified
147162 {
148- get { return unmodified ; }
163+ get { return GetChangesOfKind ( ChangeKind . Unmodified ) ; }
149164 }
150165
151166 /// <summary>
152167 /// List of <see cref="TreeEntryChanges"/> which are conflicted
153168 /// </summary>
154169 public virtual IEnumerable < TreeEntryChanges > Conflicted
155170 {
156- get { return conflicted ; }
171+ get { return GetChangesOfKind ( ChangeKind . Conflicted ) ; }
157172 }
158173
159174 private string DebuggerDisplay
@@ -186,8 +201,7 @@ public void Dispose()
186201 /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
187202 protected virtual void Dispose ( bool disposing )
188203 {
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 ( ) ;
191205 }
192206 }
193207}
0 commit comments