Java tutorial
/******************************************************************************* * Copyright (c) 2014 Obeo. * 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: * Obeo - initial API and implementation *******************************************************************************/ package org.eclipse.emf.compare.git.pgm.internal.app; import java.io.ByteArrayOutputStream; import java.io.OutputStream; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.resources.mapping.RemoteResourceMappingContext; import org.eclipse.core.resources.mapping.ResourceMapping; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.emf.common.util.BasicMonitor; import org.eclipse.emf.compare.Comparison; import org.eclipse.emf.compare.EMFCompare; import org.eclipse.emf.compare.git.pgm.Returns; import org.eclipse.emf.compare.git.pgm.internal.args.PathFilterHandler; import org.eclipse.emf.compare.git.pgm.internal.args.RefOptionHandler; import org.eclipse.emf.compare.ide.ui.internal.logical.ComparisonScopeBuilder; import org.eclipse.emf.compare.ide.ui.internal.logical.EMFResourceMapping; import org.eclipse.emf.compare.ide.ui.internal.logical.IdenticalResourceMinimizer; import org.eclipse.emf.compare.ide.ui.logical.IModelMinimizer; import org.eclipse.emf.compare.ide.ui.logical.SynchronizationModel; import org.eclipse.emf.compare.scope.IComparisonScope; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.EcoreUtil.Copier; import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl; import org.eclipse.jgit.api.DiffCommand; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.diff.DiffEntry; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.treewalk.filter.PathFilter; import org.eclipse.jgit.treewalk.filter.TreeFilter; import org.kohsuke.args4j.Argument; import org.kohsuke.args4j.Option; /** * Logical diff application. <h3>Name</h3> * <p> * logicaldiff - Git Logical Diff * </p> * <h4>Synopsis</h4> * <p> * logicaldiff <setup> <commit> [<compareWithCommit>] [ -- <paths...>] * </p> * <h4>Description</h4> * <p> * The logical diff is used to display differences using logical model. * </p> * </p> * * @author <a href="mailto:axel.richard@obeo.fr">Axel Richard</a> */ @SuppressWarnings({ "restriction" }) public class LogicalDiffApplication extends AbstractLogicalApplication { /** * Holds the reference from which the differences should be displayed. */ @Argument(index = 2, multiValued = false, required = true, metaVar = "<commit>", usage = "Commit ID or branch name.", handler = RefOptionHandler.class) private ObjectId commit; /** * Optional reference used to view the differences between {@link #commit} and {@link #commitWith}. */ @Argument(index = 3, multiValued = false, required = false, metaVar = "<compareWithCommit>", usage = "Commit ID or branch name. This is to view the changes between <commit> and <compareWithCommit> or HEAD if not specified.", handler = RefOptionHandler.class) private ObjectId commitWith; /** * {@link TreeFilter} use to filter file on which differences should be shown. */ @Option(name = "--", metaVar = "<path...>", multiValued = false, handler = PathFilterHandler.class, usage = "This is used to limit the diff to the named paths (you can give directory names and get diff for all files under them).") private TreeFilter pathFilter; /** * {@inheritDoc}. */ @Override protected Integer performGitCommand() { try { IWorkspace ws = ResourcesPlugin.getWorkspace(); // Call JGit diff to get the files involved OutputStream out = new ByteArrayOutputStream(); DiffCommand diffCommand = Git.open(repo.getDirectory()).diff().setOutputStream(out); if (commit != null) { diffCommand = diffCommand.setOldTree(getTreeIterator(repo, commit)); } if (commitWith != null) { diffCommand = diffCommand.setNewTree(getTreeIterator(repo, commitWith)); } if (pathFilter != null) { diffCommand = diffCommand.setPathFilter(pathFilter); } Set<IFile> files = new HashSet<IFile>(); List<DiffEntry> entries = diffCommand.call(); for (DiffEntry diffEntry : entries) { String path = diffEntry.getOldPath(); if (path != null) { IFile file = ws.getRoot().getFile(new Path(path)); if (file != null) { files.add(file); } } } if (files.isEmpty()) { System.out.println("No difference to display."); return Returns.COMPLETE.code(); } for (IFile file : files) { RemoteResourceMappingContext mergeContext = createSubscriberForComparison(repo, commit, commitWith, file); if (!isEMFCompareCompliantFile(mergeContext, file)) { diffCommand.setPathFilter(PathFilter.create(file.getProjectRelativePath().toString())); diffCommand.call(); System.out.println(out.toString()); } else { final ResourceMapping[] emfMappings = getResourceMappings(mergeContext, file); for (ResourceMapping mapping : emfMappings) { if (mapping instanceof EMFResourceMapping) { /* * These two won't be used by the builder in our case since we retrieve the * already created syncModel from the resource mapping. */ final IModelMinimizer minimizer = new IdenticalResourceMinimizer(); final NullProgressMonitor nullProgressMonitor = new NullProgressMonitor(); mapping.getTraversals(mergeContext, nullProgressMonitor); final SynchronizationModel syncModel = ((EMFResourceMapping) mapping).getLatestModel(); minimizer.minimize(syncModel, nullProgressMonitor); final IComparisonScope scope = ComparisonScopeBuilder.create(syncModel, nullProgressMonitor); final Comparison comparison = EMFCompare.builder().build().compare(scope, BasicMonitor.toMonitor(nullProgressMonitor)); Resource resource = new XMIResourceImpl(); Copier copier = new Copier(false); EObject comparisonCopy = copier.copy(comparison); copier.copyReferences(); resource.getContents().add(comparisonCopy); ByteArrayOutputStream baos = new ByteArrayOutputStream(); resource.save(baos, null); System.out.println(baos.toString("UTF-8"));//$NON-NLS-1$ } } } } } catch (Exception e) { System.err.println(e.getMessage()); e.printStackTrace(); } return Returns.COMPLETE.code(); } }