/*******************************************************************************
* Copyright (c) 2010, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Dariusz Luksza <dariusz@luksza.org>
* Daniel Megert <daniel_megert@ch.ibm.com> - remove unnecessary @SuppressWarnings
*******************************************************************************/
package org.eclipse.egit.core.synchronize;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.egit.core.Activator;
import org.eclipse.egit.core.synchronize.dto.GitSynchronizeDataSet;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.variants.IResourceVariant;
import org.eclipse.team.core.variants.IResourceVariantComparator;
class GitResourceVariantComparator implements IResourceVariantComparator {
private final GitSynchronizeDataSet gsd;
GitResourceVariantComparator(GitSynchronizeDataSet dataSet) {
gsd = dataSet;
}
@Override
public boolean compare(IResource local, IResourceVariant remote) {
if (!local.exists() || remote == null) {
return false;
}
if (local instanceof IFile) {
if (remote.isContainer()) {
return false;
}
InputStream stream = null;
InputStream remoteStream = null;
try {
remoteStream = remote.getStorage(new NullProgressMonitor())
.getContents();
stream = getLocal(local);
byte[] remoteBytes = new byte[8096];
byte[] bytes = new byte[8096];
int remoteRead = remoteStream.read(remoteBytes);
int read = stream.read(bytes);
if (remoteRead != read) {
return false;
}
while (Arrays.equals(bytes, remoteBytes)) {
remoteRead = remoteStream.read(remoteBytes);
read = stream.read(bytes);
if (remoteRead != read) {
// didn't read the same amount, it's uneven
return false;
} else if (read == -1) {
// both at EOF, check their contents
return Arrays.equals(bytes, remoteBytes);
}
}
} catch (IOException e) {
logException(e);
return false;
} catch (CoreException e) {
logException(e);
return false;
} finally {
closeStream(stream);
closeStream(remoteStream);
}
} else if (local instanceof IContainer) {
GitRemoteFolder gitVariant = (GitRemoteFolder) remote;
if (!remote.isContainer() || (local.exists() ^ gitVariant.exists()))
return false;
return local.getLocation().toString().equals(gitVariant.getCachePath());
}
return false;
}
@Override
public boolean compare(IResourceVariant base, IResourceVariant remote) {
GitRemoteResource gitBase = (GitRemoteResource) base;
GitRemoteResource gitRemote = (GitRemoteResource) remote;
boolean exists = gitBase.exists() && gitRemote.exists();
boolean equalType = !(gitBase.isContainer() ^ gitRemote.isContainer());
boolean equalSha1 = gitBase.getObjectId().getName()
.equals(gitRemote.getObjectId().getName());
return equalType && exists && equalSha1;
}
@Override
public boolean isThreeWay() {
return true;
}
private InputStream getLocal(IResource resource) throws CoreException {
if (gsd.getData(resource.getProject().getName()).shouldIncludeLocal())
return getSynchronizedFile(resource).getContents();
else
try {
if (resource.getType() == IResource.FILE)
return getSynchronizedFile(resource).getContents();
else
return new ByteArrayInputStream(new byte[0]);
} catch (TeamException e) {
throw new CoreException(e.getStatus());
}
}
private IFile getSynchronizedFile(IResource resource) throws CoreException {
IFile file = ((IFile) resource);
if (!file.isSynchronized(0))
file.refreshLocal(0, null);
return file;
}
private void logException(Exception e) {
IStatus error = new Status(IStatus.ERROR, Activator.getPluginId(),
e.getMessage(), e);
Activator.getDefault().getLog().log(error);
}
private void closeStream(InputStream stream) {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
logException(e);
}
}
}
}