package bluej.groupwork.svn;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javafx.application.Platform;
import org.tigris.subversion.javahl.ClientException;
import org.tigris.subversion.javahl.ConflictDescriptor;
import org.tigris.subversion.javahl.ConflictResult;
import org.tigris.subversion.javahl.Depth;
import org.tigris.subversion.javahl.NodeKind;
import org.tigris.subversion.javahl.Notify2;
import org.tigris.subversion.javahl.NotifyAction;
import org.tigris.subversion.javahl.NotifyInformation;
import org.tigris.subversion.javahl.NotifyStatus;
import org.tigris.subversion.javahl.PropertyData;
import org.tigris.subversion.javahl.Revision;
import org.tigris.subversion.javahl.SVNClientInterface;
import org.tigris.subversion.javahl.Status;
import org.tigris.subversion.javahl.StatusCallback;
import org.tigris.subversion.javahl.SubversionException;
import bluej.groupwork.TeamworkCommandAborted;
import bluej.groupwork.TeamworkCommandError;
import bluej.groupwork.TeamworkCommandResult;
import bluej.groupwork.UpdateListener;
import bluej.groupwork.UpdateResults;
import bluej.utility.Debug;
import threadchecker.OnThread;
import threadchecker.Tag;
| Subversion command to update to a particular revision.
|
| @author Davin McCall
|
public class SvnUpdateToCommand
extends SvnCommand implements UpdateResults{
private long version;
private Set<File> files;
private Set<File> forceFiles;
private UpdateListener listener;
private List<File> conflicts = new ArrayList<File>();
private Set<File> binaryConflicts = new HashSet<File>();
public SvnUpdateToCommand(SvnRepository repository, UpdateListener listener,
long version, Set<File> files, Set<File> forceFiles)
{
super(repository);
this.version = version;
this.files = files;
this.forceFiles = forceFiles;
this.listener = listener;
}
@OnThread(Tag.Worker)
protected TeamworkCommandResult doCommand()
{
SVNClientInterface client = getClient();
final List<File> addedList = new ArrayList<File>();
final List<File> updatedList = new ArrayList<File>();
final List<File> removedList = new ArrayList<File>();
final List<File> removedDirs = new ArrayList<File>();
try {
String [] paths = new String[forceFiles.size() + files.size()];
int j = 0;
for (Iterator<File> i = forceFiles.iterator(); i.hasNext(); ) {
File file = i.next();
paths[j++] = file.getAbsolutePath();
file.delete();
}
for (Iterator<File> i = files.iterator(); i.hasNext(); ) {
File file = i.next();
paths[j++] = file.getAbsolutePath();
}
client.notification2(new Notify2() {
public void onNotify(NotifyInformation ninfo)
{
if (ninfo.getKind() == NodeKind.file
|| ninfo.getKind() == NodeKind.none) {
int action = ninfo.getAction();
if (ninfo.getPath() != null) {
File file = new File(ninfo.getPath());
if (action == NotifyAction.update_add
|| action == NotifyAction.restore) {
addedList.add(file);
}
else if (action == NotifyAction.update_update) {
updatedList.add(file);
if (ninfo.getContentState() == NotifyStatus.conflicted) {
conflicts.add(file);
}
}
else if (action == NotifyAction.update_delete) {
removedList.add(file);
}
else if (action == NotifyAction.tree_conflict) {
binaryConflicts.add(file);
}
}
}
else if (ninfo.getKind() == NodeKind.dir) {
int action = ninfo.getAction();
if (action == NotifyAction.update_delete) {
removedDirs.add(new File(ninfo.getPath()));
}
}
}
});
client.update(paths, Revision.getInstance(version),
Depth.immediates, false, false, false);
}
catch (ClientException ce) {
if (isCancelled()) {
return new TeamworkCommandAborted();
}
else {
return new TeamworkCommandError(ce.getMessage(), ce.getLocalizedMessage());
}
}
finally {
client.notification2(null);
Platform.runLater(() ->
{
Iterator<File> i;
for (i = addedList.iterator(); i.hasNext(); )
{
listener.fileModified(i.next());
}
for (i = updatedList.iterator(); i.hasNext(); )
{
listener.fileModified(i.next());
}
for (i = removedList.iterator(); i.hasNext(); )
{
listener.fileRemoved(i.next());
}
for (i = removedDirs.iterator(); i.hasNext(); )
{
listener.dirRemoved(i.next());
}
});
if (! conflicts.isEmpty()) {
Iterator<File> i;
for (i = conflicts.iterator(); i.hasNext(); ) {
File file = (File) i.next();
try {
PropertyData pdata = client.propertyGet(
file.getAbsolutePath(), "svn:mime-type", Revision.getInstance(version));
if (pdata != null && "application/octet-stream".equals(pdata.getValue())) {
i.remove();
binaryConflicts.add(file);
}
else {
client.resolve(file.getAbsolutePath(), 0, ConflictResult.chooseMerged);
}
}
catch (SubversionException se) {
Debug.message("Subversion client exception when resolving conflicts: " + se.getLocalizedMessage());
Debug.message(" (on file: " + file + ")");
}
}
}
if (! conflicts.isEmpty() || ! binaryConflicts.isEmpty()) {
Platform.runLater(() -> listener.handleConflicts(this));
}
}
return new TeamworkCommandResult();
}
@Override
public boolean mergeCommitNeeded()
{
return false;
}
@Override
public Set getBinaryConflicts()
{
return binaryConflicts;
}
@Override
public List getConflicts()
{
return conflicts;
}
@Override
public void overrideFiles(final Set<File> files)
{
final SVNClientInterface client = getRepository().getClient();
StatusCallback scb = new StatusCallback() {
public void doStatus(Status status)
{
File file = new File(status.getPath());
try {
ConflictDescriptor cd = status.getConflictDescriptor();
if (cd != null) {
int action = cd.getAction();
int kind = cd.getKind();
int reason = cd.getReason();
if (kind != ConflictDescriptor.Kind.text) {
return;
}
if (action == ConflictDescriptor.Action.delete
&& reason == ConflictDescriptor.Reason.edited) {
client.resolve(file.getAbsolutePath(), 0, ConflictResult.chooseMerged);
boolean keepLocal = ! files.contains(file);
String [] paths = new String[] { file.getPath()
};
client.remove(paths, "", true, keepLocal, Collections.emptyMap());
if (!keepLocal)
{
Platform.runLater(() -> listener.fileRemoved(file));
}
return;
}
else if (action == ConflictDescriptor.Action.edit
&& reason == ConflictDescriptor.Reason.deleted) {
client.resolve(file.getAbsolutePath(), 0, ConflictResult.chooseTheirsFull);
}
}
String conflictOld = status.getConflictOld();
if (conflictOld != null) {
File oldRev = new File(file.getParent(), status.getConflictOld());
oldRev.delete();
}
if (files.contains(file)) {
client.resolve(file.getAbsolutePath(), 0, ConflictResult.chooseTheirsFull);
}
else {
client.resolve(file.getAbsolutePath(), 0, ConflictResult.chooseMineFull);
}
}
catch (SubversionException sve) {
Debug.message("Subversion library exception trying to resolve binary conflict: " + sve.getLocalizedMessage());
Debug.message(" (on file: " + file + ")");
}
}
};
for (Iterator<File> i = binaryConflicts.iterator(); i.hasNext(); ) {
File file = i.next();
try {
client.status(file.getAbsolutePath(), Depth.empty, false,
true, true, true, new String[0], scb);
}
catch (ClientException ce) {
Debug.message("Subversion library exception trying to resolve binary conflict: " + ce.getLocalizedMessage());
Debug.message(" (on file: " + file + ")");
}
}
}
}
top,
use,
map,
class SvnUpdateToCommand
. SvnUpdateToCommand
. doCommand
. onNotify
. mergeCommitNeeded
. getBinaryConflicts
. getConflicts
. overrideFiles
. doStatus
391 neLoCode
+ 2 LoComm