Resolving path of IVersionable in selected state
All I could achieve so far is this:
IFileItemHandle fileItemHandle = (IFileItemHandle) IFileItem.ITEM_TYPE.createItemHandle(change.afterState().getItemId(), change.afterState().getStateId());
file = versionableManager.fetchCompleteState(fileItemHandle, monitor);
if (file instanceof IFolder) {
IFolder folder = (IFolder) file;
relativePath = getFilePath(file, workspaceConnection.configuration(changeSet.getComponent()), monitor);
fileName = folder.getName();
} else {
relativePath = getFilePath(file, workspaceConnection.configuration(changeSet.getComponent()), monitor);
fileName = ((FileItem) file).getName();
}
Where getFilePath is:
private String getFilePath(IVersionableHandle folder, IConfiguration config, IProgressMonitor monitor, Boolean searchInHistory) throws TeamRepositoryException {
List lst = new ArrayList<IVersionableHandle>(), ancestors;
lst.add(folder);
if (searchInHistory) {
ancestors = config.determineAncestorsInHistory(lst, monitor);
} else {
ancestors = config.locateAncestors(lst, monitor);
}
return getFullPath(ancestors);
}
private String getFullPath(List ancestor) throws TeamRepositoryException {
String directoryPath = "";
for (Object ancestorObj : ancestor) {
IAncestorReport ancestorImpl = (IAncestorReport) ancestorObj;
for (Object nameItemPairObj : ancestorImpl.getNameItemPairs()) {
INameItemPair nameItemPair = (INameItemPair) nameItemPairObj;
String pathName = nameItemPair.getName();
if (pathName != null && !pathName.equals("")) {
directoryPath = directoryPath + "\\" + pathName;
}
}
}
return directoryPath;
}
Unfortunately it doesn't work perfectly. If filename is changed in following changelists like on this example:
Changelist 1:
add file: src/newFile.java
Changelist 2:
modify file: src/newFile.java
Changelist 3:
rename file: src/newFile.java -> src/newFile_rename.java
The relative path resolved in first changelist would be:
src/newFile_rename.java
instead of
src/newFile.java
How to make it works good?
2 answers
IFileItemHandle fileItemHandle = (IFileItemHandle) IFileItem.ITEM_TYPE.createItemHandle(change.afterState().getItemId(), change.afterState().getStateId());
You're asking for the after state. It seems you're getting the state of the file from changelist 3(maybe you mean change set) after the rename.
Check that you are fetching the correct state.
Comments
For each specified item, retrieves the sequence of name-item pairs that leads to that item in the configuration starting at a root folder.
The javadoc for #determineAncestorsInHistory() retrieves the path segments as defined in the configuration. Since you're using the configuration that includes the file rename, that's the path that you get.
I recommend after you fetch the after state to use #getParent() and resolve the paths that way to get the path as it was when the change was made.
file = versionableManager.fetchCompleteState(fileItemHandle, monitor); file.getName() // the filename before the rename file.getParent() // parent folder handle, go up the tree to retrieve the other path segments
I've tried to use Mark Byrd's code which I've found here (method getParent3): https://jazz.net/forum/questions/94927/how-do-i-find-moved-from-location-for-a-movedreparented-item-using-rtc-4-java-api
This code is going through all parents of item and collecting their names. Unfortunately it doesn't work either.
Can you explain what does not work with it? It appears to have worked for him and the code looks reasonable (aside from path segments would be from the configuration used to fetch the parents). The filename would be correct as far as I can tell.
Maybe this example I posted in my question is not as good as I thought before. Let me show you a better one:
While trying to resolve path of file from first changeset I'm getting path: src/test_new/directory_new/filename.java insead of src/test/directory/filename.java.Changeset 1: add src/test/directory/filename.java
Changeset 2: modify src/test/directory/filename.java
Changeset 3: reparent src/test/directory -> src/test/directory_new
Changeset 4: reparent src/test -> src/test_new
You're getting the path as it is in the configuration you used to fetch the item's parent folder.
I don't understand what do you mean by this. IConfiguration object is based on component which contains all of those files. If I'm doing it wrong could you please give me some hint how to do it right? Mark's solution doesn't work for me at all.
The IConfiguration describes the state of the component. The one you're using includes the all of the change sets. This means the path for that file in the configuration is src/test_new/directory_new/filename.java. Mark's solution doesn't handle this as it seems to take the file's true name but the path comes from the most recent configuration.
You would need the configuration that represents the state of component for your file state (ie. get a configuration without change sets 2-4 if you're looking at change set 1). The Java plain client API doesn't expose the ability to manipulate a configuration to show the path that you want. I think your best shot is taking your workspace and discarding change sets 2-4 before asking the configuration for the path segments.
I don't know what you're trying to illustrate with your screenshot. Are you highlighting that the file paths are inconsistent? I only see two files in your screenshots and the files aren't the same so I don't know what to look at.
I'm sorry you're right this screenshots tells nothing at all. Let me make another examples. This one should be ok.
I see what's happening now. The folder names are resolved using whatever configuration you have picked. By default, it uses one of your repository workspaces that you have in Pending Changes. If the configuration of that workspace has the folder renamed, then that's what the name is resolved as. Change Summary (new in 4.0.1) view allows you to select a different stream or repository workspace to use for resolving paths.
I think I know where we can find answer for this problem, but not sure if it can be used in this particular situation. I've found that RTC UI is able to show repository files in specific stateId (file situation in selected changeSet). Right click on specific changeSet and selecting "repository files" give us ability to look at file situation after this changeSet. Maybe this is a good place to look for answer for this problem?
The Repository Files view constructs a configuration that has the changes up to the point of that change set. You can do the same with the plain Java API but there isn't direct API to help you construct that configuration. I don't know how practical it would be to implement it yourself with the limited API available.
But is it possible to construct that kind of configuration object?
If you're trying to update content on your disk, why are you not using the accept APIs in IWorkspaceConnection? You say the command line's 'scm accept' doesn't work. What happens when you try to use it?
If your file is in a specific baseline or snapshot, you could use 'scm list remotefiles' to get that path.
I'm not interested in updating sources for applying changesets. I'm only interested in displaying what was changed during every changeset applied to repository.
I see. In the work item you opened (265025), you had said "I'm working with RTC Java Plain API to checkout and update sources stored in my local machine." and "update sources stored in my local machine" sounded to me like you wanted to update the content on your disk. It seems that isn't what is actually desired here. My mistake.
The accept command is for changing the content of your sandbox to reflect the change sets you have accepted. Yes, it knows the paths on the disk so that it can update the right files and folders. I am not sure what this has to do with what you want since you seem to want to know the path of a versionable when a change set happened when this information is not stored in the change set.
Updating sources is irrelevant for me now. Now I'm only focused on obtaining right file path.
Updating sources is irrelevant for me now. Now I'm only focused on obtaining right file path.
Updating sources is irrelevant for me now. Now I'm only focused on obtaining right file path.
Sorry I didn't see this earlier, I just answered this same question on stack overflow.
The specific file state can only tell you the name of the file, not the containing folders.
You need to find the configuration that represents your workspace at the time of the changeset. This might not actually exist, so you will have to settle for the closest one and then need to consider the other changes that happened after your change.
You do this starting at IFlowNodeConnection.changeHistory() and calling IChangeHistory.previousHistory until you find the change history that contains your changeset in IChangeHistory.recent. Once you find it, the IChangeHistory.configuration is the first configuration after your change and it includes all the changes in recent().
1 vote