blob: 0d6c0b51955fdf9c449522ddb417799f7deb3a4e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2013 SAP AG 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:
* Stefan Lay (SAP AG) - initial implementation
* Benjamin Muskalla (Tasktop Technologies) - moved into Core for reusability
*******************************************************************************/
package org.eclipse.egit.core.internal;
import java.io.IOException;
import java.util.List;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IEncodedStorage;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.egit.core.internal.util.ResourceUtil;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.diff.RenameDetector;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.treewalk.TreeWalk;
/**
* Utility class for compare-related functionality
*/
public class CompareCoreUtils {
/**
* Determine the encoding used by Eclipse for the resource which belongs to
* repoPath in the eclipse workspace or null if no resource is found
*
* @param db
* the repository
* @param repoPath
* the path in the git repository
* @return the encoding used in eclipse for the resource or null if no
* resource was found for given path
*
*/
@Nullable
public static String getResourceEncoding(Repository db, String repoPath) {
if (db.isBare()) {
return null;
}
IFile resource = ResourceUtil.getFileForLocation(db, repoPath, false);
if (resource == null) {
return null;
}
return getResourceEncoding(resource);
}
/**
* Determine the encoding used by eclipse for the resource.
*
* @param resource
* must be non null
* @return the encoding used in Eclipse for the resource if found, never
* null
*/
@NonNull
public static String getResourceEncoding(@NonNull IResource resource) {
// Get the encoding for the current version. As a matter of
// principle one might want to use the eclipse settings for the
// version we are retrieving as that may be defined by the
// project settings, but there is no historic API for this.
String charset;
if (resource instanceof IEncodedStorage) {
IEncodedStorage encodedStorage = ((IEncodedStorage) resource);
try {
charset = encodedStorage.getCharset();
if (charset == null) {
charset = resource.getParent().getDefaultCharset();
}
} catch (CoreException e) {
charset = ResourcesPlugin.getEncoding();
}
} else if (resource instanceof IContainer) {
try {
charset = ((IContainer) resource).getDefaultCharset();
} catch (CoreException e) {
charset = ResourcesPlugin.getEncoding();
}
} else {
charset = ResourcesPlugin.getEncoding();
}
return charset;
}
/**
* Get the {@link DiffEntry} corresponding to a change in file path. If the
* file was renamed, the resulting {@link DiffEntry} will contain the old
* path and blob ID. If the file was only added, null will be returned.
*
* @param repository
* @param newPath
* path of the file in new commit
* @param newCommit
* new commit
* @param oldCommit
* old commit, e.g. parent commit of newCommit
* @param objectReader
* reader for the repository
* @return the diff entry corresponding to the change for path, or null if
* none could be found
* @throws IOException
*/
public static DiffEntry getChangeDiffEntry(Repository repository, String newPath,
RevCommit newCommit, RevCommit oldCommit, ObjectReader objectReader)
throws IOException {
try (TreeWalk walk = new TreeWalk(objectReader)) {
walk.setRecursive(true);
walk.addTree(oldCommit.getTree());
walk.addTree(newCommit.getTree());
List<DiffEntry> entries = DiffEntry.scan(walk);
for (DiffEntry diff : entries) {
if (diff.getChangeType() == ChangeType.MODIFY
&& newPath.equals(diff.getNewPath()))
return diff;
}
if (entries.size() < 2)
return null;
RenameDetector detector = new RenameDetector(repository);
detector.addAll(entries);
List<DiffEntry> renames = detector.compute(walk.getObjectReader(),
NullProgressMonitor.INSTANCE);
for (DiffEntry diff : renames) {
if (diff.getChangeType() == ChangeType.RENAME
&& newPath.equals(diff.getNewPath()))
return diff;
}
return null;
}
}
}