/*******************************************************************************
* Copyright (C) 2011, 2012 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.actions;
import static org.eclipse.egit.core.synchronize.dto.GitSynchronizeData.BRANCH_NAME_PATTERN;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_BRANCH_SECTION;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_MERGE;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_REMOTE;
import static org.eclipse.jgit.lib.Constants.HEAD;
import static org.eclipse.jgit.lib.Constants.R_HEADS;
import static org.eclipse.jgit.lib.Constants.R_REMOTES;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.egit.core.project.RepositoryMapping;
import org.eclipse.egit.core.synchronize.dto.GitSynchronizeData;
import org.eclipse.egit.core.synchronize.dto.GitSynchronizeDataSet;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.UIPreferences;
import org.eclipse.egit.ui.internal.synchronize.GitModelSynchronize;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
/**
* An action that launch synchronization with selected repository
*/
public class SynchronizeWorkspaceActionHandler extends RepositoryActionHandler {
@Override
public boolean isEnabled() {
return true;
}
public Object execute(ExecutionEvent event) throws ExecutionException {
IResource[] resources = getSelectedResources(event);
Map<Repository, Set<IResource>> containerMap = mapContainerResources(resources);
if (containerMap.isEmpty())
return null;
boolean launchFetch = Activator.getDefault().getPreferenceStore()
.getBoolean(UIPreferences.SYNC_VIEW_FETCH_BEFORE_LAUNCH);
GitSynchronizeDataSet gsdSet = new GitSynchronizeDataSet();
for (Entry<Repository, Set<IResource>> entry : containerMap.entrySet())
try {
Repository repo = entry.getKey();
String dstRef = getDstRef(repo, launchFetch);
GitSynchronizeData data = new GitSynchronizeData(repo, HEAD, dstRef, true);
Set<IResource> containers = entry.getValue();
if (!containers.isEmpty())
data.setIncludedResources(containers);
gsdSet.add(data);
} catch (IOException e) {
Activator.handleError(e.getMessage(), e, true);
}
GitModelSynchronize.launch(gsdSet, getSelectedResources(event));
return null;
}
private Map<Repository, Set<IResource>> mapContainerResources(
IResource[] resources) {
Map<Repository, Set<IResource>> result = new HashMap<Repository, Set<IResource>>();
for (IResource resource : resources) {
RepositoryMapping rm = RepositoryMapping.getMapping(resource);
if (rm == null)
continue; // Linked resources may not be in a repo
if (resource instanceof IProject)
result.put(rm.getRepository(), new HashSet<IResource>());
else if (resource instanceof IContainer) {
Set<IResource> containers = result.get(rm.getRepository());
if (containers == null) {
containers = new HashSet<IResource>();
result.put(rm.getRepository(), containers);
containers.add(resource);
} else if (containers.size() > 0)
containers.add(resource);
}
}
return result;
}
private String getDstRef(Repository repo, boolean launchFetch) {
if (launchFetch) {
String realName = getRealBranchName(repo);
String name = BRANCH_NAME_PATTERN.matcher(realName).replaceAll(""); //$NON-NLS-1$
StoredConfig config = repo.getConfig();
String remote = config.getString(CONFIG_BRANCH_SECTION, name,
CONFIG_KEY_REMOTE);
String merge = config.getString(CONFIG_BRANCH_SECTION, name,
CONFIG_KEY_MERGE);
if (remote == null || merge == null)
return HEAD;
String mergeBranchName = merge.replace(R_HEADS, ""); //$NON-NLS-1$
return R_REMOTES + remote + "/" + mergeBranchName; //$NON-NLS-1$
} else
return HEAD;
}
private String getRealBranchName(Repository repo) {
Ref ref;
try {
ref = repo.getRef(HEAD);
} catch (IOException e) {
ref = null;
}
if (ref != null && ref.isSymbolic())
return ref.getTarget().getName();
else
return HEAD;
}
}