/*******************************************************************************
* Copyright (C) 2010, 2013 Dariusz Luksza <dariusz@luksza.org> 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
*******************************************************************************/
package org.eclipse.egit.ui.internal.synchronize.model;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.compare.structuremergeviewer.Differencer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.egit.core.synchronize.GitCommitsModelCache;
import org.eclipse.egit.core.synchronize.GitCommitsModelCache.Change;
import org.eclipse.egit.core.synchronize.GitCommitsModelCache.Commit;
import org.eclipse.egit.core.synchronize.StagedChangeCache;
import org.eclipse.egit.core.synchronize.WorkingTreeChangeCache;
import org.eclipse.egit.core.synchronize.dto.GitSynchronizeData;
import org.eclipse.egit.ui.Activator;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.treewalk.filter.TreeFilter;
/**
* Representation of Git repository in Git ChangeSet model.
*/
public class GitModelRepository extends GitModelObjectContainer implements HasProjects {
private IPath location;
private final GitSynchronizeData gsd;
private GitModelObject[] children;
/**
* @param gsd
* synchronization data
* @throws IOException
*/
public GitModelRepository(GitSynchronizeData gsd) throws IOException {
super(null);
this.gsd = gsd;
}
@Override
public GitModelObject[] getChildren() {
List<GitModelObjectContainer> result = new ArrayList<>();
Repository repo = gsd.getRepository();
RevCommit srcRevCommit = gsd.getSrcRevCommit();
RevCommit dstRevCommit = gsd.getDstRevCommit();
TreeFilter pathFilter = gsd.getPathFilter();
List<Commit> commitCache;
if (srcRevCommit != null && dstRevCommit != null)
try {
commitCache = GitCommitsModelCache.build(repo, srcRevCommit,
dstRevCommit, pathFilter);
} catch (IOException e) {
Activator.logError(e.getMessage(), e);
commitCache = null;
}
else
commitCache = null;
if (commitCache != null && !commitCache.isEmpty())
result.addAll(getListOfCommit(commitCache));
result.addAll(getWorkingChanges());
disposeOldChildren();
children = result.toArray(new GitModelObjectContainer[result.size()]);
return children;
}
@Override
public String getName() {
return gsd.getRepository().getWorkTree().toString();
}
@Override
public IProject[] getProjects() {
return gsd.getProjects().toArray(new IProject[gsd.getProjects().size()]);
}
@Override
public int repositoryHashCode() {
return hashCode();
}
/**
* @return source {@link RevObject}
*/
public ObjectId getSrcRev() {
return gsd.getSrcRevCommit();
}
@Override
public IPath getLocation() {
if (location == null)
location = new Path(gsd.getRepository().getWorkTree().toString());
return location;
}
@Override
public int getKind() {
return Differencer.CHANGE;
}
@Override
public void dispose() {
disposeOldChildren();
}
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (obj instanceof GitModelRepository) {
File objWorkTree = ((GitModelRepository) obj).gsd.getRepository()
.getWorkTree();
return objWorkTree.equals(gsd.getRepository().getWorkTree());
}
return false;
}
@Override
public int hashCode() {
return gsd.getRepository().getWorkTree().hashCode();
}
@Override
public String toString() {
return "ModelRepository[" + gsd.getRepository().getWorkTree() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
}
private List<GitModelObjectContainer> getListOfCommit(List<Commit> commitCache) {
Repository repo = gsd.getRepository();
Set<IProject> projectsSet = gsd.getProjects();
IProject[] projects = projectsSet.toArray(new IProject[projectsSet.size()]);
List<GitModelObjectContainer> result = new ArrayList<>();
for (Commit commit : commitCache)
result.add(new GitModelCommit(this, repo, commit, projects));
return result;
}
private List<GitModelObjectContainer> getWorkingChanges() {
List<GitModelObjectContainer> result = new ArrayList<>();
if (gsd.shouldIncludeLocal()) {
Repository repo = gsd.getRepository();
Map<String, Change> stagedChanges = StagedChangeCache.build(repo);
GitModelCache gitCache = new GitModelCache(this, repo,
stagedChanges);
int gitCacheLen = gitCache.getChildren().length;
Map<String, Change> workingChanges = WorkingTreeChangeCache.build(repo);
GitModelWorkingTree gitWorkingTree = new GitModelWorkingTree(this,
repo, workingChanges);
int gitWorkingTreeLen = gitWorkingTree.getChildren().length;
if (gitCacheLen > 0 || gitWorkingTreeLen > 0) {
result.add(gitCache);
result.add(gitWorkingTree);
}
}
return result;
}
/**
* @return repository
*/
public Repository getRepository() {
return gsd.getRepository();
}
private void disposeOldChildren() {
if (children == null)
return;
for (GitModelObject child : children)
child.dispose();
}
}