/* license-start * * Copyright (C) 2008 - 2013 Crispico, <http://www.crispico.com/>. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details, at <http://www.gnu.org/licenses/>. * * Contributors: * Crispico - Initial API and implementation * * license-end */ package org.flowerplatform.web.git.operation; import java.io.File; import java.util.List; import org.eclipse.jgit.api.CheckoutCommand; import org.eclipse.jgit.api.CheckoutResult; import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.transport.URIish; import org.flowerplatform.common.CommonPlugin; import org.flowerplatform.communication.channel.CommunicationChannel; import org.flowerplatform.communication.command.DisplaySimpleMessageClientCommand; import org.flowerplatform.communication.progress_monitor.ProgressMonitor; import org.flowerplatform.web.git.GitPlugin; import org.flowerplatform.web.git.GitUtils; import org.flowerplatform.web.git.remote.dto.GitRef; import org.flowerplatform.web.git.remote.dto.RemoteConfig; /** * @author Cristina Constantinescu */ public class CheckoutOperation { private Object node; private Repository repository; private String name; private RemoteConfig remote; private GitRef upstreamBranch; private boolean rebase; private CommunicationChannel channel; public CheckoutOperation(Object node, Repository repository, String name, RemoteConfig remote, GitRef upstreamBranch, boolean rebase, CommunicationChannel channel) { this.node = node; this.repository = repository; this.name = name; this.remote = remote; this.upstreamBranch = upstreamBranch; this.rebase = rebase; this.channel = channel; } public boolean execute() { ProgressMonitor monitor = ProgressMonitor.create(GitPlugin.getInstance().getMessage("git.checkout.monitor.title"), channel); try { monitor.beginTask(GitPlugin.getInstance().getMessage("git.checkout.monitor.message", new Object[] {name}), 4); monitor.setTaskName("Getting remote branch..."); Git git = new Git(repository); Ref ref; if (node instanceof Ref) { ref = (Ref) node; } else { // get remote branch String dst = Constants.R_REMOTES + remote.getName(); String remoteRefName = dst + "/" + upstreamBranch.getShortName(); ref = repository.getRef(remoteRefName); if (ref == null) { // doesn't exist, fetch it RefSpec refSpec = new RefSpec(); refSpec = refSpec.setForceUpdate(true); refSpec = refSpec.setSourceDestination(upstreamBranch.getName(), remoteRefName); git.fetch() .setRemote(new URIish(remote.getUri()).toPrivateString()) .setRefSpecs(refSpec) .call(); ref = repository.getRef(remoteRefName); } } monitor.worked(1); monitor.setTaskName("Creating local branch..."); // create local branch git.branchCreate(). setName(name). setStartPoint(ref.getName()). setUpstreamMode(SetupUpstreamMode.SET_UPSTREAM). call(); if (!(node instanceof Ref)) { // save upstream configuration StoredConfig config = repository.getConfig(); config.setString(ConfigConstants.CONFIG_BRANCH_SECTION, name, ConfigConstants.CONFIG_KEY_MERGE, upstreamBranch.getName()); config.setString(ConfigConstants.CONFIG_BRANCH_SECTION, name, ConfigConstants.CONFIG_KEY_REMOTE, remote.getName()); if (rebase) { config.setBoolean(ConfigConstants.CONFIG_BRANCH_SECTION, name, ConfigConstants.CONFIG_KEY_REBASE, true); } else { config.unset(ConfigConstants.CONFIG_BRANCH_SECTION, name, ConfigConstants.CONFIG_KEY_REBASE); } config.save(); } monitor.worked(1); monitor.setTaskName("Creating working directory"); // create working directory for local branch File mainRepoFile = repository.getDirectory().getParentFile(); File wdirFile = new File(mainRepoFile.getParentFile(), GitUtils.WORKING_DIRECTORY_PREFIX + name); if (wdirFile.exists()) { GitPlugin.getInstance().getUtils().delete(wdirFile); } GitPlugin.getInstance().getUtils().run_git_workdir_cmd(mainRepoFile.getAbsolutePath(), wdirFile.getAbsolutePath()); monitor.worked(1); monitor.setTaskName("Checkout branch"); // checkout local branch Repository wdirRepo = GitPlugin.getInstance().getUtils().getRepository(wdirFile); git = new Git(wdirRepo); CheckoutCommand cc = git.checkout().setName(name).setForce(true); cc.call(); // show checkout result if (cc.getResult().getStatus() == CheckoutResult.Status.CONFLICTS) channel.appendOrSendCommand( new DisplaySimpleMessageClientCommand( GitPlugin.getInstance().getMessage("git.checkout.checkoutConflicts.title"), GitPlugin.getInstance().getMessage("git.checkout.checkoutConflicts.message"), cc.getResult().getConflictList().toString(), DisplaySimpleMessageClientCommand.ICON_INFORMATION)); else if (cc.getResult().getStatus() == CheckoutResult.Status.NONDELETED) { // double-check if the files are still there boolean show = false; List<String> pathList = cc.getResult().getUndeletedList(); for (String path1 : pathList) { if (new File(wdirRepo.getWorkTree(), path1).exists()) { show = true; break; } } if (show) { channel.appendOrSendCommand( new DisplaySimpleMessageClientCommand( GitPlugin.getInstance().getMessage("git.checkout.nonDeletedFiles.title"), GitPlugin.getInstance().getMessage("git.checkout.nonDeletedFiles.message", Repository.shortenRefName(name)), cc.getResult().getUndeletedList().toString(), DisplaySimpleMessageClientCommand.ICON_ERROR)); } } else if (cc.getResult().getStatus() == CheckoutResult.Status.OK) { if (ObjectId.isId(wdirRepo.getFullBranch())) channel.appendOrSendCommand( new DisplaySimpleMessageClientCommand( GitPlugin.getInstance().getMessage("git.checkout.detachedHead.title"), GitPlugin.getInstance().getMessage("git.checkout.detachedHead.message"), DisplaySimpleMessageClientCommand.ICON_ERROR)); } monitor.worked(1); return true; } catch (Exception e) { channel.appendOrSendCommand( new DisplaySimpleMessageClientCommand( CommonPlugin.getInstance().getMessage("error"), e.getMessage(), DisplaySimpleMessageClientCommand.ICON_ERROR)); return false; } finally { monitor.done(); } } }