in source/com.microsoft.tfs.core/src/com/microsoft/tfs/core/clients/versioncontrol/ResolveConflictHandler.java [72:255]
public void conflictResolved(
final Conflict conflict,
final GetOperation[] getOps,
final GetOperation[] undoOps,
final Conflict[] otherResolvedConflicts,
final ChangePendedFlags changePendedFlags) {
Check.notNull(conflict, "conflict"); //$NON-NLS-1$
final String updatedSourceLocalItem = updatedSourceLocalItems.get(conflict.getConflictID());
if (updatedSourceLocalItem != null) {
workspace.getWorkspaceWatcher().removeSkippedItem(updatedSourceLocalItem);
conflict.setSourceLocalItem(updatedSourceLocalItem);
}
// If we are deleting a conflict, we should get any operations.
Check.isTrue(
!Resolution.DELETE_CONFLICT.equals(conflict.getResolution()) || getOps.length == 0 && undoOps.length == 0,
MessageFormat.format(
"Didn't expect any get ops (got {0}) or undo ops (got {1})", //$NON-NLS-1$
getOps.length,
undoOps.length));
conflict.setResolved(true);
client.getEventEngine().fireConflictResolved(
new ConflictResolvedEvent(EventSource.newFromHere(), workspace, conflict, changePendedFlags));
/*
* Sort the child conflicts before firing the events so the application
* receives them in a sorted order.
*/
Arrays.sort(otherResolvedConflicts, new ConflictComparator());
/* If there were any other resolved conflicts. */
for (final Conflict c : otherResolvedConflicts) {
c.setResolved(true);
c.setResolution(conflict.getResolution());
client.getEventEngine().fireConflictResolved(
new ConflictResolvedEvent(EventSource.newFromHere(), workspace, c, changePendedFlags));
}
/*
* If you are resolving a conflict on an add / branch as acceptTheirs we
* need to set the file to readonly so we don't cause a writable file
* conflict
*/
if (Resolution.ACCEPT_THEIRS.equals(conflict.getResolution()) && !conflict.isNamespaceConflict()) {
for (final GetOperation getOp : undoOps) {
if (getOp.getTargetServerItem() != null
&& ServerPath.equals(getOp.getTargetServerItem(), conflict.getYourServerItem())
&& getOp.getVersionLocal() == 0
&& getOp.getSourceLocalItem() != null
&& ItemType.FILE.equals(getOp.getItemType())) {
getOp.setOkayToOverwriteExistingLocal(true);
}
}
}
/*
* If the user specified AcceptTheirs as the resolution to a conflict
* generated by merge or rollback and the user had a pending edit prior
* to the merge, we need to mark the target file read-only here so that
* the get code will be able to replace the file (for non-merge
* conflicts, AcceptTheirs is the same as undo). Otherwise, get will
* think it is a local conflict because it lacks the necessary context
* to know that it's not a local conflict and that it really should
* replace the writable file.
*
* If the user resolved a three-way merge conflict as AcceptMerge and
* created the output file, the client already has the content that it
* needs. In that case, set VersionLocal = VersionServer so we don't try
* to download it and get the writable file conflict incorrectly.
*/
if (Resolution.ACCEPT_THEIRS.equals(conflict.getResolution())
&& conflict.getYourLocalChangeType().contains(ChangeType.EDIT)) {
for (final GetOperation getOp : getOps) {
final String getOpItem =
getOp.getSourceServerItem() != null ? getOp.getSourceServerItem() : getOp.getTargetServerItem();
final String conflictItem = conflict.getYourServerItemSource() != null
? conflict.getYourServerItemSource() : conflict.getYourServerItem();
// server says replace it
if (ServerPath.equals(getOpItem, conflictItem)
&& getOp.getVersionLocal() == -1
&& getOp.getSourceLocalItem() != null
&& (getOp.getChangeType().contains(ChangeType.MERGE)
|| getOp.getChangeType().contains(ChangeType.ROLLBACK)
|| conflict.isShelvesetConflict())
&& getOp.getChangeType().contains(ChangeType.EDIT)) {
getOp.setOkayToOverwriteExistingLocal(true);
}
}
} else if ((Resolution.ACCEPT_MERGE.equals(conflict.getResolution())
|| Resolution.ACCEPT_YOURS.equals(conflict.getResolution()))) {
for (final GetOperation getOp : getOps) {
if ((Resolution.ACCEPT_MERGE.equals(conflict.getResolution())
&& conflict.getMergedFileName() != null
&& conflict.getMergedFileName().length() > 0
&& ServerPath.equals(getOp.getTargetServerItem(), conflict.getYourServerItem())
&& getOp.getItemID() == conflict.getYourItemID()
/* Server says replace it, or we didn't have it. */
&& (getOp.getVersionLocal() == -1 || getOp.getVersionLocal() == 0)
&& getOp.getChangeType().contains(ChangeType.MERGE)
&& getOp.getChangeType().contains(ChangeType.EDIT)) ||
/*
* if it's a version conflict and we have an edit, we need to
* ensure we don't lose our changes.
*/
((ConflictType.CHECKIN.equals(conflict.getType()) || ConflictType.GET.equals(conflict.getType()))
&& ItemType.FILE.equals(getOp.getItemType())
&& getOp.getChangeType().contains(ChangeType.EDIT)
&& LocalPath.equals(conflict.getSourceLocalItem(), getOp.getSourceLocalItem()))) {
final UpdateLocalVersionSpec ulvs = new UpdateLocalVersionSpec();
ulvs.setSourceServerItem(getOp.getSourceServerItem());
ulvs.setItemID(getOp.getItemID());
ulvs.setSourceLocalItem(conflict.getSourceLocalItem());
ulvs.setVersionServer(getOp.getVersionServer());
ulvs.setPropertyValues(getOp.getPropertyValues());
updateLocalVersionSpecs.add(ulvs);
/*
* In order for the get engine to process the get op, we
* have to tell it where the item is now, which the server
* also knows due to the ULV call, so that if the target is
* different, get can move it with all of its normal error
* checking, local conflict handling, etc.
*/
getOp.setVersionLocal(getOp.getVersionServer());
getOp.setSourceLocalItem(conflict.getSourceLocalItem());
}
}
}
flags = flags.combine(changePendedFlags);
/*
* Figure out if we can add get ops to the current group or we need to
* create a new one. We need to create a new one if one doesn't exist
* yet or if we are adding a get op for a path that is already in that
* get op group.
*/
GetOperationGroup currentGroup = null;
boolean needNewGroup = true;
if (getOpGroups.size() > 0) {
needNewGroup = false;
currentGroup = getOpGroups.get(getOpGroups.size() - 1);
for (final GetOperation getOp : getOps) {
if (getOp.getTargetLocalItem() != null
&& currentGroup.hasGetOpForLocalPath(getOp.getTargetLocalItem())) {
needNewGroup = true;
break;
}
}
if (needNewGroup == false) {
for (final GetOperation getOp : undoOps) {
if (getOp.getTargetLocalItem() != null
&& currentGroup.hasGetOpForLocalPath(getOp.getTargetLocalItem())) {
needNewGroup = true;
break;
}
}
}
}
if (needNewGroup) {
currentGroup = new GetOperationGroup();
getOpGroups.add(currentGroup);
}
currentGroup.addOperations(ProcessType.GET, getOps);
currentGroup.addOperations(ProcessType.UNDO, undoOps);
for (final Conflict otherResolvedConflict : otherResolvedConflicts) {
resolvedConflicts.add(otherResolvedConflict);
}
}