Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: d32cec0f179436b6ec2d64390aadd5d445b82dcc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*******************************************************************************
 * 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 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * 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.jgit.annotations.NonNull;
import org.eclipse.jgit.annotations.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;
		}
	}
}

Back to the top