Commits

Jens Alfke committed 028cab3

Fix #18. HgRepository was mutating its 'revisions' array in place, confusing the RevisionGraph. Changed the _revisions array to be immutable, updated by setting a new array.

Comments (0)

Files changed (2)

Source/HgRepository.h

 @interface HgRepository : NSObject
 {
     NSString *_absolutePath;
-    NSMutableArray *_revisions;
+    NSArray *_revisions;
     HgRevision *_currentRevision;
     HgUncommittedRevision *_uncommittedRevision;
     HgConfigFile *_hgrc;
 @property (readonly) NSURL *URL;
 @property (readonly) NSString *webName, *webDescription;
 
-@property (readonly) NSArray* revisions;
+@property (readonly,copy) NSArray* revisions;
 @property (readonly) HgRevision *currentRevision, *tipRevision;
 @property (readonly) HgUncommittedRevision *uncommittedRevision, *modifiedRevision;
 @property (readonly) BOOL isUncommitted;

Source/HgRepository.m

 
 
 @interface HgRepository (Internal)
+@property (copy) NSArray* revisions;
 - (BOOL) _checkWorkingTreePaths: (NSSet*)paths error: (NSError**)outError;
 - (BOOL) _checkWorkingTree: (NSError**)outError;
 - (BOOL) _checkRevisions;
     BOOL hasChanges = _uncommittedRevision.root.isUncommitted;
     if( hasChanges != self.isUncommitted ) {
         // Add or remove the uncommitted revision according to the working tree's status:
-        [self willChangeValueForKey: @"revisions"];
+        NSMutableArray *nuRevisions = [_revisions mutableCopy];
         if( hasChanges )
-            [_revisions addObject: _uncommittedRevision];
+            [nuRevisions addObject: _uncommittedRevision];
         else
-            [_revisions removeObject: _uncommittedRevision];
-        [self didChangeValueForKey: @"revisions"];
+            [nuRevisions removeObject: _uncommittedRevision];
+        self.revisions = nuRevisions;
     }
     return YES;
 }
     if( tip<0 )
         return NO;
     
-    int curTip = _revisions ?self.tipRevision.localNumber :-1;
+    int curTip = _revisions.count>0 ?self.tipRevision.localNumber :-1;
     if( tip != curTip ) {
         // Revisions have changed!
         NSLog(@"Tip changed from %i to %i ... updating revisions", curTip,tip);
 
-        if( ! _revisions )
-            _revisions = [NSMutableArray array];
         // Run "hg log" to get all revisions of this repository:
+        if (!_revisions)
+            _revisions = [NSArray array];   // Because HgLogOperation will call my -revisions
         HgLogOperation *op = [[HgLogOperation alloc] initWithRepository: self 
                                                                    file: nil 
                                                                    full: YES];
-        if( _revisions )
+        if( _revisions.count > 0 )
             op.limit = tip-curTip;      // only need to ask about the new revisions
         if( ! [op run] )
             return NO;
-        NSArray *newRevisions = op.revisions;
-        NSAssert([[newRevisions objectAtIndex: 0] localNumber]==curTip+1,@"Unexpected revision numbers from log");
+        NSAssert([[op.revisions objectAtIndex: 0] localNumber]==curTip+1,@"Unexpected revision numbers from log");
         
-        [self willChangeValueForKey: @"revisions"];
-        BOOL unc = [_revisions containsObject: _uncommittedRevision];
+        // Add the new revisions, but before the uncommitted one if any:
+        NSMutableArray *nuRevisions = [_revisions mutableCopy];
+        BOOL unc = [nuRevisions containsObject: _uncommittedRevision];
         if( unc )
-            [_revisions removeObject: _uncommittedRevision];
-        [_revisions addObjectsFromArray: newRevisions];
+            [nuRevisions removeObject: _uncommittedRevision];
+        [nuRevisions addObjectsFromArray: op.revisions];
         if( unc )
-            [_revisions addObject: _uncommittedRevision];
+            [nuRevisions addObject: _uncommittedRevision];
         
-        _currentRevision = [_revisions objectAtIndex: curRevNo];
+        _currentRevision = [nuRevisions objectAtIndex: curRevNo];
         _uncommittedRevision.parent = _currentRevision;
-        _uncommittedRevision.parent2 = curParent2>=0 ?[_revisions objectAtIndex: curParent2] :nil;
+        _uncommittedRevision.parent2 = curParent2>=0 ?[nuRevisions objectAtIndex: curParent2] :nil;
                 
-        [self didChangeValueForKey: @"revisions"];
+        self.revisions = nuRevisions;
+        
         [self _checkWorkingTree: &error];
         return YES;
         
 
 - (NSArray*) revisions
 {
-    if( ! _revisions )
+    if( ! _revisions ) {
+        _revisions = [NSArray array];   // in case of re-entrant call during _checkRevisions!
         [self _checkRevisions];
+    }
     return _revisions;
 }
 
+- (void) setRevisions: (NSArray*)revisions
+{
+    _revisions = [revisions copy];
+}
+
 - (HgRevision*) currentRevision
 {
     if( ! _revisions )