<commit_before>/*******************************************************************************
 * Copyright (C) 2010, 2014 <NAME> <<EMAIL>> 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.core.synchronize.dto;

import static org.eclipse.core.runtime.Assert.isNotNull;
import static org.eclipse.egit.core.RevUtils.getCommonAncestor;
import static org.eclipse.jgit.lib.Constants.R_HEADS;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.egit.core.project.RepositoryMapping;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.ObjectWalk;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
import org.eclipse.jgit.treewalk.filter.TreeFilter;

/**
 * Simple data transfer object containing all necessary information for
 * launching synchronization
 */
public class GitSynchronizeData {

	private static final IWorkspaceRoot ROOT = ResourcesPlugin.getWorkspace()
					.getRoot();

	/**
	 * Matches all strings that start from R_HEADS
	 */
	public static final Pattern BRANCH_NAME_PATTERN = Pattern.compile("^" + R_HEADS + ".*?"); //$NON-NLS-1$ //$NON-NLS-2$

	private final boolean includeLocal;

	private final Repository repo;

	private final String dstRemote;

	private final String dstMerge;

	private RevCommit srcRevCommit;

	private RevCommit dstRevCommit;

	private RevCommit ancestorRevCommit;

	private final Set<IProject> projects;

	private final String repoParentPath;

	private final String srcRev;

	private final String dstRev;

	private TreeFilter pathFilter;

	private Set<IResource> includedResources;

	private static class RemoteAndMerge {
		final String remote;
		final String merge;

		public RemoteAndMerge(String remote, String merge) {
			this.remote = remote;
			this.merge = merge;
		}
	}

	/**
	 * Constructs {@link GitSynchronizeData} object for all resources.
	 * Equivalent to
	 * <code>new GitSynchronizeData(repository, srcRev, dstRev, includeLocal, null)</code>
	 * .
	 *
	 * @param repository
	 * @param srcRev
	 * @param dstRev
	 * @param includeLocal
	 *            <code>true</code> if local changes should be included in
	 *            comparison
	 * @throws IOException
	 */
	public GitSynchronizeData(Repository repository, String srcRev,
			String dstRev, boolean includeLocal) throws IOException {
		this(repository, srcRev, dstRev, includeLocal, null);
	}

	/**
	 * Constructs a {@link GitSynchronizeData} object while restricting it to a
	 * set of resources.
	 *
	 * @param repository
	 * @param srcRev
	 * @param dstRev
	 * @param includeLocal
	 * @param includedResources
	 *            either the set of resources to include in synchronization or
	 *            {@code null} to synchronize all resources.
	 * @throws IOException
	 */
	public GitSynchronizeData(Repository repository, String srcRev,
			String dstRev, boolean includeLocal,
			Set<IResource> includedResources) throws IOException {
		isNotNull(repository);
		isNotNull(srcRev);
		isNotNull(dstRev);
		this.repo = repository;
		this.srcRev = srcRev;
		this.dstRev = dstRev;
		this.includeLocal = includeLocal;

		RemoteAndMerge dstRemoteAndMerge = extractRemoteAndMergeForDst(dstRev);

		dstRemote = dstRemoteAndMerge.remote;
		dstMerge = dstRemoteAndMerge.merge;

		repoParentPath = repo.getDirectory().getParentFile().getAbsolutePath();

		projects = new HashSet<IProject>();
		final Iterable<? extends IResource> includedResourceIterable;
		if (includedResources == null)
			// include all project in synchronization
			includedResourceIterable = Arrays.asList(ROOT.getProjects());
		else
			includedResourceIterable = includedResources;
		for (IResource res : includedResourceIterable) {
			IProject project = res.getProject();
			RepositoryMapping mapping = RepositoryMapping.getMapping(project);
			if (mapping != null && mapping.getRepository() == repo)
				projects.add(project);
		}

		// do not set field if includedResources is null, some methods expect
		// #getIncludedResources() to return <null> to know it should
		// synchronize all resources.
		if (includedResources != null)
			setIncludedResources(includedResources);

		updateRevs();
	}

	/**
	 * Recalculates source, destination and ancestor Rev commits
	 *
	 * @throws IOException
	 */
	public void updateRevs() throws IOException {
		try (ObjectWalk ow = new ObjectWalk(repo)) {
			srcRevCommit = getCommit(srcRev, ow);
			dstRevCommit = getCommit(dstRev, ow);
		}

		if (this.dstRevCommit != null && this.srcRevCommit != null)
			this.ancestorRevCommit = getCommonAncestor(repo, this.srcRevCommit,
					this.dstRevCommit);
		else
			this.ancestorRevCommit = null;
	}

	/**
	 * @return instance of repository that should be synchronized
	 */
	public Repository getRepository() {
		return repo;
	}

	/**<commit_msg>Ensure commit body is retained in GitSynchronizeData<commit_after>/*******************************************************************************
 * Copyright (C) 2010, 2014 <NAME> <<EMAIL>> 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.core.synchronize.dto;

import static org.eclipse.core.runtime.Assert.isNotNull;
import static org.eclipse.egit.core.RevUtils.getCommonAncestor;
import static org.eclipse.jgit.lib.Constants.R_HEADS;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.egit.core.project.RepositoryMapping;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.ObjectWalk;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
import org.eclipse.jgit.treewalk.filter.TreeFilter;

/**
 * Simple data transfer object containing all necessary information for
 * launching synchronization
 */
public class GitSynchronizeData {

	private static final IWorkspaceRoot ROOT = ResourcesPlugin.getWorkspace()
					.getRoot();

	/**
	 * Matches all strings that start from R_HEADS
	 */
	public static final Pattern BRANCH_NAME_PATTERN = Pattern.compile("^" + R_HEADS + ".*?"); //$NON-NLS-1$ //$NON-NLS-2$

	private final boolean includeLocal;

	private final Repository repo;

	private final String dstRemote;

	private final String dstMerge;

	private RevCommit srcRevCommit;

	private RevCommit dstRevCommit;

	private RevCommit ancestorRevCommit;

	private final Set<IProject> projects;

	private final String repoParentPath;

	private final String srcRev;

	private final String dstRev;

	private TreeFilter pathFilter;

	private Set<IResource> includedResources;

	private static class RemoteAndMerge {
		final String remote;
		final String merge;

		public RemoteAndMerge(String remote, String merge) {
			this.remote = remote;
			this.merge = merge;
		}
	}

	/**
	 * Constructs {@link GitSynchronizeData} object for all resources.
	 * Equivalent to
	 * <code>new GitSynchronizeData(repository, srcRev, dstRev, includeLocal, null)</code>
	 * .
	 *
	 * @param repository
	 * @param srcRev
	 * @param dstRev
	 * @param includeLocal
	 *            <code>true</code> if local changes should be included in
	 *            comparison
	 * @throws IOException
	 */
	public GitSynchronizeData(Repository repository, String srcRev,
			String dstRev, boolean includeLocal) throws IOException {
		this(repository, srcRev, dstRev, includeLocal, null);
	}

	/**
	 * Constructs a {@link GitSynchronizeData} object while restricting it to a
	 * set of resources.
	 *
	 * @param repository
	 * @param srcRev
	 * @param dstRev
	 * @param includeLocal
	 * @param includedResources
	 *            either the set of resources to include in synchronization or
	 *            {@code null} to synchronize all resources.
	 * @throws IOException
	 */
	public GitSynchronizeData(Repository repository, String srcRev,
			String dstRev, boolean includeLocal,
			Set<IResource> includedResources) throws IOException {
		isNotNull(repository);
		isNotNull(srcRev);
		isNotNull(dstRev);
		this.repo = repository;
		this.srcRev = srcRev;
		this.dstRev = dstRev;
		this.includeLocal = includeLocal;

		RemoteAndMerge dstRemoteAndMerge = extractRemoteAndMergeForDst(dstRev);

		dstRemote = dstRemoteAndMerge.remote;
		dstMerge = dstRemoteAndMerge.merge;

		repoParentPath = repo.getDirectory().getParentFile().getAbsolutePath();

		projects = new HashSet<IProject>();
		final Iterable<? extends IResource> includedResourceIterable;
		if (includedResources == null)
			// include all project in synchronization
			includedResourceIterable = Arrays.asList(ROOT.getProjects());
		else
			includedResourceIterable = includedResources;
		for (IResource res : includedResourceIterable) {
			IProject project = res.getProject();
			RepositoryMapping mapping = RepositoryMapping.getMapping(project);
			if (mapping != null && mapping.getRepository() == repo)
				projects.add(project);
		}

		// do not set field if includedResources is null, some methods expect
		// #getIncludedResources() to return <null> to know it should
		// synchronize all resources.
		if (includedResources != null)
			setIncludedResources(includedResources);

		updateRevs();
	}

	/**
	 * Recalculates source, destination and ancestor Rev commits
	 *
	 * @throws IOException
	 */
	public void updateRevs() throws IOException {
		try (ObjectWalk ow = new ObjectWalk(repo)) {
			ow.setRetainBody(true);
			srcRevCommit = getCommit(srcRev, ow);
			dstRevCommit = getCommit(dstRev, ow);
		}

		if (this.dstRevCommit != null && this.srcRevCommit != null)
			this.ancestorRevCommit = getCommonAncestor(repo, this.srcRevCommit,
					this.dstRevCommit);
		else
			this.ancestorRevCommit = null;
	}

	/**
	 * @return instance of repository that should be synchronized
	 */
	public Repository getRepository() {
		return repo;
	}

	/**
{'fraction_non_alphanumeric': 0.12024756852343059, 'fraction_numerical': 0.002475685234305924, 'mean_word_length': 4.512183235867447, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5329735', 'n_tokens_mistral': 3459, 'n_tokens_neox': 3157, 'n_words': 877}