Author: ericwa
Date: Thu Mar 27 07:18:21 2014
New Revision: 10653
URL: http://svn.gna.org/viewcvs/etoile?rev=10653&view=rev
Log:
ProjectDemo/Typewriter: quickly hack in merge context menu in the revision
history window
Modified:
trunk/Etoile/Frameworks/CoreObject/Core/COBranch.h
trunk/Etoile/Frameworks/CoreObject/Core/COBranch.m
trunk/Etoile/Frameworks/CoreObject/Diff/COLeastCommonAncestor.m
trunk/Etoile/Frameworks/CoreObject/English.lproj/Commits/org.etoile.CoreObject.json
trunk/Etoile/Frameworks/CoreObject/Samples/CommonUI/EWGraphRenderer.m
trunk/Etoile/Frameworks/CoreObject/Samples/CommonUI/EWHistoryWindowController.m
Modified: trunk/Etoile/Frameworks/CoreObject/Core/COBranch.h
URL:
http://svn.gna.org/viewcvs/etoile/trunk/Etoile/Frameworks/CoreObject/Core/COBranch.h?rev=10653&r1=10652&r2=10653&view=diff
==============================================================================
--- trunk/Etoile/Frameworks/CoreObject/Core/COBranch.h (original)
+++ trunk/Etoile/Frameworks/CoreObject/Core/COBranch.h Thu Mar 27 07:18:21 2014
@@ -107,6 +107,7 @@
ETUUID *_parentBranchUUID;
NSMutableArray *_revisions;
COBranch *_mergingBranch;
+ CORevision *_mergingRevision;
}
@@ -400,13 +401,24 @@
/**
* The branch that is currently being merged.
*
- * Always returns nil unless explicitly set.
+ * Always returns nil unless explicitly set. Only one of mergingBranch
+ * or mergingRevision can be set to non-nil.
*
* If it is set at commit time, records the <em>current revision</em> of
* the merging branch as the merge parent of the new commit.
*/
@property (nonatomic, strong) COBranch *mergingBranch;
/**
+ * The revision that is currently being merged.
+ *
+ * Always returns nil unless explicitly set. Only one of mergingBranch
+ * or mergingRevision can be set to non-nil.
+ *
+ * If it is set at commit time, records the given revision
+ * as the merge parent of the new commit.
+ */
+@property (nonatomic, strong) CORevision *mergingRevision;
+/**
* Returns a merge info object representing the changes between the receiver
and
* the given branch to be merged.
*
Modified: trunk/Etoile/Frameworks/CoreObject/Core/COBranch.m
URL:
http://svn.gna.org/viewcvs/etoile/trunk/Etoile/Frameworks/CoreObject/Core/COBranch.m?rev=10653&r1=10652&r2=10653&view=diff
==============================================================================
--- trunk/Etoile/Frameworks/CoreObject/Core/COBranch.m (original)
+++ trunk/Etoile/Frameworks/CoreObject/Core/COBranch.m Thu Mar 27 07:18:21 2014
@@ -41,6 +41,7 @@
@synthesize UUID = _UUID, persistentRoot = _persistentRoot;
@synthesize shouldMakeEmptyCommit = _shouldMakeEmptyCommit, supportsRevert =
_supportsRevert;
@synthesize mergingBranch = _mergingBranch;
+@synthesize mergingRevision = _mergingRevision;
+ (void) initialize
{
@@ -624,10 +625,17 @@
if ([[modifiedItems itemUUIDs] count] > 0 ||
self.shouldMakeEmptyCommit)
{
ETUUID *mergeParent = nil;
+ ETAssert(self.mergingBranch == nil
+ || self.mergingRevision == nil);
if (self.mergingBranch != nil)
{
mergeParent = [[self.mergingBranch
currentRevision] UUID];
self.mergingBranch = nil;
+ }
+ else if (self.mergingRevision != nil)
+ {
+ mergeParent = [self.mergingRevision UUID];
+ self.mergingRevision = nil;
}
ETUUID *revUUID = [ETUUID UUID];
Modified: trunk/Etoile/Frameworks/CoreObject/Diff/COLeastCommonAncestor.m
URL:
http://svn.gna.org/viewcvs/etoile/trunk/Etoile/Frameworks/CoreObject/Diff/COLeastCommonAncestor.m?rev=10653&r1=10652&r2=10653&view=diff
==============================================================================
--- trunk/Etoile/Frameworks/CoreObject/Diff/COLeastCommonAncestor.m
(original)
+++ trunk/Etoile/Frameworks/CoreObject/Diff/COLeastCommonAncestor.m Thu Mar
27 07:18:21 2014
@@ -13,27 +13,56 @@
@implementation COEditingContext (CommonAncestor)
-/**
- * Naiive algorithm: gather paths from commitA to the root, and commitB to the
root,
- * and return their first intersection.
- */
+- (void) addUUIDAndParents: (ETUUID *)aUUID persistentRoot: (ETUUID
*)persistentRoot toSet: (NSMutableSet *)dest
+{
+ if ([dest containsObject: aUUID])
+ return;
+
+ [dest addObject: aUUID];
+
+ CORevision *revision = [self revisionForRevisionUUID: aUUID
persistentRootUUID: persistentRoot];
+
+ if (revision.parentRevision != nil)
+ [self addUUIDAndParents: revision.parentRevision.UUID
persistentRoot: persistentRoot toSet: dest];
+
+ if (revision.mergeParentRevision != nil)
+ [self addUUIDAndParents: revision.mergeParentRevision.UUID
persistentRoot: persistentRoot toSet: dest];
+}
+
- (ETUUID *)commonAncestorForCommit: (ETUUID *)commitA
andCommit: (ETUUID *)commitB
persistentRoot: (ETUUID
*)persistentRoot
{
NSMutableSet *ancestorsOfA = [NSMutableSet set];
- for (ETUUID *temp = commitA; temp != nil; temp = [[[self
revisionForRevisionUUID: temp persistentRootUUID: persistentRoot]
parentRevision] UUID])
+ [self addUUIDAndParents: commitA persistentRoot: persistentRoot toSet:
ancestorsOfA];
+
+ // Do a BFS starting at commitB until we hit a commit in ancestorsOfA
+ // TODO: Check whether this makes sense
+
+ NSMutableArray *siblingsArray = [NSMutableArray arrayWithObject:
commitB];
+
+ while ([siblingsArray count] > 0)
{
- [ancestorsOfA addObject: temp];
- }
-
- for (ETUUID *temp = commitB; temp != nil; temp = [[[self
revisionForRevisionUUID: temp persistentRootUUID: persistentRoot]
parentRevision] UUID])
- {
- if ([ancestorsOfA containsObject: temp])
+ NSMutableArray *nextSiblingsArray = [NSMutableArray new];
+
+ for (ETUUID *sibling in siblingsArray)
{
- return temp;
+ if ([ancestorsOfA containsObject: sibling])
+ {
+ return sibling;
+ }
+
+ CORevision *revision = [self revisionForRevisionUUID:
sibling persistentRootUUID: persistentRoot];
+
+ if (revision.parentRevision != nil)
+ [nextSiblingsArray addObject:
revision.parentRevision.UUID];
+
+ if (revision.mergeParentRevision != nil)
+ [nextSiblingsArray addObject:
revision.mergeParentRevision.UUID];
}
+
+ [siblingsArray setArray: nextSiblingsArray];
}
// No common ancestor
Modified:
trunk/Etoile/Frameworks/CoreObject/English.lproj/Commits/org.etoile.CoreObject.json
URL:
http://svn.gna.org/viewcvs/etoile/trunk/Etoile/Frameworks/CoreObject/English.lproj/Commits/org.etoile.CoreObject.json?rev=10653&r1=10652&r2=10653&view=diff
==============================================================================
---
trunk/Etoile/Frameworks/CoreObject/English.lproj/Commits/org.etoile.CoreObject.json
(original)
+++
trunk/Etoile/Frameworks/CoreObject/English.lproj/Commits/org.etoile.CoreObject.json
Thu Mar 27 07:18:21 2014
@@ -52,6 +52,12 @@
{
"type": "history",
"shortDescription": "Checkpoint"
- }
+ },
+
+ "merge":
+ {
+ "type": "history",
+ "shortDescription": "Merge changes from '%@'"
+ }
}
}
Modified: trunk/Etoile/Frameworks/CoreObject/Samples/CommonUI/EWGraphRenderer.m
URL:
http://svn.gna.org/viewcvs/etoile/trunk/Etoile/Frameworks/CoreObject/Samples/CommonUI/EWGraphRenderer.m?rev=10653&r1=10652&r2=10653&view=diff
==============================================================================
--- trunk/Etoile/Frameworks/CoreObject/Samples/CommonUI/EWGraphRenderer.m
(original)
+++ trunk/Etoile/Frameworks/CoreObject/Samples/CommonUI/EWGraphRenderer.m
Thu Mar 27 07:18:21 2014
@@ -171,7 +171,19 @@
}
else
{
- ETUUID *parentUUID = [self parentUUIDsForRevisionUUID:
currentRevision][0];
+ NSArray *parentUUIDs = [self parentUUIDsForRevisionUUID:
currentRevision];
+ ETUUID *parentUUID = nil;
+
+ // Set parentUUID to the first parent for which we have already
assigned a level
+ for (ETUUID *aParent in parentUUIDs)
+ {
+ if (levelForUUID[aParent] != nil)
+ {
+ parentUUID = aParent;
+ break;
+ }
+ }
+
ETAssert(parentUUID != nil);
NSInteger value = [self maxLevelFromUUIDInclusive:
currentRevision
Modified:
trunk/Etoile/Frameworks/CoreObject/Samples/CommonUI/EWHistoryWindowController.m
URL:
http://svn.gna.org/viewcvs/etoile/trunk/Etoile/Frameworks/CoreObject/Samples/CommonUI/EWHistoryWindowController.m?rev=10653&r1=10652&r2=10653&view=diff
==============================================================================
---
trunk/Etoile/Frameworks/CoreObject/Samples/CommonUI/EWHistoryWindowController.m
(original)
+++
trunk/Etoile/Frameworks/CoreObject/Samples/CommonUI/EWHistoryWindowController.m
Thu Mar 27 07:18:21 2014
@@ -49,6 +49,17 @@
[self update];
[[self window] setTitle: [self windowTitle]];
+
+ [table setMenu: [self makeTableViewMenu]];
+}
+
+- (NSMenu *) makeTableViewMenu
+{
+ NSMenu *menu = [[NSMenu alloc] initWithTitle: @""];
+
+ [menu addItemWithTitle:@"Merge into Current Revision" action:
@selector(merge:) keyEquivalent:@""];
+
+ return menu;
}
- (NSString *)windowTitle
@@ -168,6 +179,40 @@
}
}
+- (IBAction)merge:(id)sender
+{
+ const NSInteger clickedRow = [table clickedRow];
+ if (clickedRow < 0 || clickedRow >= [graphRenderer count])
+ return;
+
+ CORevision *clickedRevision = (CORevision *)[graphRenderer
revisionAtIndex: clickedRow];
+ CORevision *currentRevision = [inspectedBranch currentRevision];
+
+ NSLog(@"Merge %@ into %@", clickedRevision, currentRevision);
+
+ COMergeInfo *mergeInfo = [inspectedBranch mergeInfoForMergingRevision:
clickedRevision];
+
+ if (nil == mergeInfo)
+ {
+ NSLog(@"No merge info generated");
+ return;
+ }
+ if ([mergeInfo.diff hasConflicts])
+ {
+ NSLog(@"Can't merge, diff has conflicts. %@", mergeInfo.diff);
+ return;
+ }
+
+ // FIXME: Inefficient, ugly
+ COObjectGraphContext *temp = [inspectedPersistentRoot
objectGraphContextForPreviewingRevision: mergeInfo.baseRevision];
+ [mergeInfo.diff applyTo: temp];
+ [[inspectedBranch objectGraphContext] insertOrUpdateItems: (NSArray
*)[[[temp loadedObjects] mappedCollection] storeItem]];
+
+ inspectedBranch.mergingRevision = clickedRevision;
+
+ [self commitWithIdentifier: @"merge" descriptionArguments:
@[[clickedRevision localizedShortDescription]]];
+}
+
/* Convenience */
- (id<COTrackNode>) selectedNode
_______________________________________________
Etoile-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/etoile-cvs