1 /*******************************************************************************
2  * Copyright (c) 2006, 2017 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  * IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.team.internal.core.history;
15 
16 import java.util.ArrayList;
17 
18 import org.eclipse.core.resources.IFile;
19 import org.eclipse.core.resources.IFileState;
20 import org.eclipse.core.runtime.CoreException;
21 import org.eclipse.core.runtime.IProgressMonitor;
22 import org.eclipse.team.core.TeamException;
23 import org.eclipse.team.core.history.IFileRevision;
24 import org.eclipse.team.core.history.provider.FileHistory;
25 import org.eclipse.team.internal.core.Messages;
26 
27 public class LocalFileHistory extends FileHistory {
28 
29 	protected IFile file;
30 	//used to hold all revisions (changes based on filtering)
31 	protected IFileRevision[] revisions;
32 	private final boolean includeCurrent;
33 
34 	/*
35 	 * Creates a new CVSFile history that will fetch remote revisions by default.
36 	 */
LocalFileHistory(IFile file, boolean includeCurrent)37 	public LocalFileHistory(IFile file, boolean includeCurrent) {
38 		this.file = file;
39 		this.includeCurrent = includeCurrent;
40 	}
41 
42 	@Override
getContributors(IFileRevision revision)43 	public IFileRevision[] getContributors(IFileRevision revision) {
44 
45 		IFileRevision[] revisions = getFileRevisions();
46 
47 		//the predecessor is the file with a timestamp that is the largest timestamp
48 		//from the set of all timestamps smaller than the root file's timestamp
49 		IFileRevision fileRevision = null;
50 		for (IFileRevision r : revisions) {
51 			if (((LocalFileRevision) r).isPredecessorOf(revision)) {
52 				//no revision has been set as of yet
53 				if (fileRevision == null) {
54 					fileRevision = r;
55 				}
56 				//this revision is a predecessor - now check to see if it comes
57 				//after the current predecessor, if it does make it the current predecessor
58 				if (fileRevision != null && r.getTimestamp() > fileRevision.getTimestamp()) {
59 					fileRevision = r;
60 				}
61 			}
62 		}
63 		if (fileRevision == null)
64 			return new IFileRevision[0];
65 		return new IFileRevision[] {fileRevision};
66 	}
67 
68 	@Override
getFileRevision(String id)69 	public IFileRevision getFileRevision(String id) {
70 		if (revisions != null) {
71 			for (IFileRevision revision : revisions) {
72 				if (revision.getContentIdentifier().equals(id)) {
73 					return revision;
74 				}
75 			}
76 		}
77 		return null;
78 	}
79 
80 	@Override
getFileRevisions()81 	public IFileRevision[] getFileRevisions() {
82 		if (revisions == null)
83 			return new IFileRevision[0];
84 		return revisions;
85 	}
86 
87 	@Override
getTargets(IFileRevision revision)88 	public IFileRevision[] getTargets(IFileRevision revision) {
89 		IFileRevision[] revisions = getFileRevisions();
90 		ArrayList<IFileRevision> directDescendents = new ArrayList<>();
91 
92 		for (IFileRevision r : revisions) {
93 			if (((LocalFileRevision) r).isDescendentOf(revision)) {
94 				directDescendents.add(r);
95 			}
96 		}
97 		return directDescendents.toArray(new IFileRevision[directDescendents.size()]);
98 	}
99 
100 	/**
101 	 * Refreshes the revisions for this local file.
102 	 *
103 	 * @param monitor	a progress monitor
104 	 * @throws TeamException
105 	 */
refresh(IProgressMonitor monitor)106 	public void refresh(IProgressMonitor monitor) throws TeamException {
107 		monitor.beginTask(Messages.LocalFileHistory_RefreshLocalHistory/*, file.getProjectRelativePath().toString())*/, 300);
108 		try {
109 			// Include the file's current state if and only if the file exists.
110 			LocalFileRevision currentRevision =
111 				(includeRevisionForFile() ? new LocalFileRevision(file) : null);
112 			IFileState[] fileStates = file.getHistory(monitor);
113 			int numRevisions = fileStates.length + (currentRevision != null ? 1 : 0);
114 			revisions = new LocalFileRevision[numRevisions];
115 			for (int i = 0; i < fileStates.length; i++) {
116 				revisions[i] = new LocalFileRevision(fileStates[i]);
117 			}
118 			if (currentRevision != null)
119 				revisions[fileStates.length] = currentRevision;
120 		} catch (CoreException e) {
121 			throw TeamException.asTeamException(e);
122 		} finally {
123 			monitor.done();
124 		}
125 	}
126 
includeRevisionForFile()127 	private boolean includeRevisionForFile() {
128 		return file.exists() && includeCurrent;
129 	}
130 
131 }
132