It's all about the answers!

Ask a question

Compare a change-set file to current version in stream

Atul Kumar (1872329) | asked Jun 17 '14, 1:34 a.m.
I want to compare a file contained in a change-set with the current version in the 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();
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

permanent link
Atul Kumar (1872329) | answered Jul 03 '14, 1:22 a.m.
edited Jul 03 '14, 1:23 a.m.
Here, I'm pasting the complete method to find previous version of a change-set-file for reference purposes:

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;    
Ralph Schoon selected this answer as the correct answer

Atul Kumar commented Nov 18 '14, 5:15 a.m.

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

permanent link
Tim Mok (6.6k38) | answered Jun 17 '14, 10:38 a.m.
Your terminology isn't quite right as SCM doesn't have the concept of a check-out. When you create a change and check it in, it is based on the configuration of the component at that time. When you compare the before and after states of a change in a change set, it will only show the changes added in relation to the before state.

If you want to compare that after state to the stream, you can retrieve the state of the file in the stream by getting the IConfiguration from the stream's IWorkspaceConnection. Then you can use #fetchCompleteItem on the IConfiguration to get the stream's state.

permanent link
Atul Kumar (1872329) | answered Jun 18 '14, 7:49 a.m.
By check-out, I meant the version on which the change-set was created.

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?

Tim Mok commented Jun 18 '14, 10:15 a.m.

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.

Ralph Schoon commented Jun 18 '14, 10:19 a.m. | edited Jun 18 '14, 10:19 a.m.

If you want to compare against some arbitrary file, here is some code that does this (from a change set created from zip files) .

Atul Kumar commented Jun 19 '14, 2:01 a.m.

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.:


Tim Mok commented Jun 19 '14, 8:07 a.m.

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.

Atul Kumar commented Jun 19 '14, 8:42 a.m. | edited Jun 19 '14, 8:49 a.m.

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();

Tim Mok commented Jun 20 '14, 10:53 a.m.

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.

Atul Kumar commented Jun 30 '14, 1:01 a.m.

Yes, I meant that it returns the same state UUID.

Tim Mok commented Jun 30 '14, 2:11 p.m.

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.

Atul Kumar commented Jul 01 '14, 5:11 a.m.

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) {

showing 5 of 9 show 4 more comments

permanent link
Atul Kumar (1872329) | answered Jul 03 '14, 1:15 a.m.
I used IChange#mergeStates() which returns a list of IVersionableHandle. Michael Valenta suggested this API, thanks to him.

Then I simply retrieved the last element of mergeStates, and it works fine !

Thanks Tim for your continued support.

Your answer

Register or to post your answer.

Dashboards and work items are no longer publicly available, so some links may be invalid. We now provide similar information through other means. Learn more here.