Compare a change-set file to current version in stream
If I do following:
IVersionable version = verManager.fetchCompleteState(versionHandle, monitor);
IVersionableHandle previousVersion = null;
for (Object co : changeSet.changes()) {
IChange change = (IChange) co;
if (change.afterState() != null && change.afterState().getStateId().equals(version.getStateId())) {
previousVersion = change.beforeState();
break;
}
}
I am able to compare the change-set's file to the one from which a user checked-out to create the change-set. That means, in the diff viewer it shows me all the changes (and merges) since that file was checked-out.
I need to have differences only that were made as part of that change-set (excluding others' changes).
Do I need to find the history of that file, and then find a version? How to do that ?
Accepted answer
public static IVersionableHandle findPreviousFileVersion(ITeamRepository repository, IChangeSet changeSet, IProgressMonitor monitor) throws TeamRepositoryException, FileNotFoundException {
IVersionableHandle previousVersion = null;
for (Object co : changeSet.changes()) {
IChange change = (IChange) co;
List<IVersionableHandle> merges = change.mergeStates();
for(IVersionableHandle iv:merges) {
previousVersion = iv;
}
}
return previousVersion;
}
Comments
The above code was working fine, if there were no merges since the change-set was created; but it used to show me all other changes also that I accepted as incomings into my workspace, alongwith the actual changes that were made in that change-set.
I had a conversation with Michael Valenta, and he suggested this approach to filter merges:
public static IVersionableHandle getLastMergeState(IChange change) {
if (change.mergeStates().isEmpty()) {
return change.beforeState();
}
return (IVersionableHandle) change.mergeStates().get(change.mergeStates().size() - 1);
}
This worked fine!
Thanks Michael !
3 other answers
Implemented on the lines you suggested:
IVersionableHandle versionHandle = (IVersionableHandle) IFileItem.ITEM_TYPE.createItemHandle(UUID.valueOf(fileUuid), UUID.valueOf(stateUuid));
List listOfComponents = workspaceConnection.getComponentsContainingVersionable(versionHandle, monitor);
IConfiguration config = workspaceConnection.configuration((IComponentHandle) listOfComponents.get(0));
return config.fetchCompleteItem(versionHandle, monitor);
This way I can get the latest version from the workspace, which shows no diff in the diff viewer if the workspace is loaded with the current change-set. But here, it doesn't return me a previous state, just the latest in workspace.
Is there a way to find previous state from IConfiguration?
Comments
If you want the find previous states, use IConfiguration#determineAncestorsInHistory(..). Although, you mentioned you want to compare against the current version in stream and your code is retrieving the configuration from the workspace instead of the stream unless that's how you named your stream's IWorkspaceConnection. Keep in mind that since the configuration is retrieved from the workspace, everything will be in relation to it. If you have two outgoing change sets in the workspace that modify the same file, the previous state will be in the older change set.
If you want to compare against some arbitrary file, here is some code that does this (from a change set created from zip files) https://rsjazz.wordpress.com/2013/09/30/delivering-change-sets-and-baselines-to-a-stream-using-the-plain-java-client-libraries/ .
The IConfiguration#determineAncestorsInHistory(..) returns a list of AncestorReportImpl elements, when I dig it down, it returned me data in terms of INameItemPair. This list of INameItemPair shows the hierarchy of the file and its folder hierarchy.
I could not find something on the previous state. PFA the screenshot from my debug window.:
The item in the INameItemPair is the IVersionableHandle of the file in history. Each item in the list is an ancestor to the item you queried in the #determineAncestorsInHistory(..) call. You can see in your screenshot that the field above the name is your file item.
Tried getting item on the ancestorHierarchy, but it always returns the versionable with the same UUID that I have in the workspace/changeset.
Tried next level of ancestorHierarchy as well, still the same versionable is returned:
List ancestors = config.determineAncestorsInHistory(versionableHandles, monitor);
AncestorReportImpl report = (AncestorReportImpl) ancestors.get(0);
NameItemPairImpl imp = (NameItemPairImpl) report.getNameItemPairs().get(report.getNameItemPairs().size()-1);
//rebuild the list - versionableHandles
List ancestors1 = config.determineAncestorsInHistory(versionableHandles, monitor);
AncestorReportImpl report1 = (AncestorReportImpl) ancestors1.get(0);
NameItemPairImpl imp1 = (NameItemPairImpl) report1.getNameItemPairs().get(report1.getNameItemPairs().size()-1);
IVersionable ver2 = imp1.getItem();
What do you mean by the UUID? Are you saying it returns the same state UUID or the same item UUID? The item UUID for a versionable never changes once it is assigned.
Yes, I meant that it returns the same state UUID.
Sorry, I led you down the wrong path with the ancestors call. That is the call to determine the path of the file.
If you want the previous version, you use the before state. If you're trying to filter out any merges, there's no API to give you a state without the merges. You'll have to use the merge states, retrieve the content, and filter out the merges from the after state yourself.
No issues.
I could find-out the MergeStates from a changeSet, but I couldn't find methods for retrieving/filtering-out merges in the MergeState API. Do I need to convert MergeState objects to some other APIs?
Here's how I got to MergeStates:
IChange change = (IChange) co;
List<MergeState> merges = ((ChangeImpl)change).getMerges();
if(merges != null && merges.size() > 0) {
for(MergeState ms:merges) {
//TODO
}
}