/******************************************************************************* * Copyright (c) 2015-2016 Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is 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: * Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.openshift.internal.ui.wizard.importapp; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; import org.apache.commons.collections.ListUtils; import org.apache.commons.lang.StringUtils; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jgit.lib.Repository; import org.jboss.tools.common.ui.databinding.ObservableUIPojo; import org.jboss.tools.openshift.common.core.utils.FileUtils; import org.jboss.tools.openshift.core.connection.Connection; import org.jboss.tools.openshift.egit.core.EGitUtils; import org.jboss.tools.openshift.egit.ui.util.EGitUIUtils; import org.jboss.tools.openshift.internal.core.util.ResourceUtils; import org.jboss.tools.openshift.internal.ui.treeitem.ObservableTreeItem; import org.jboss.tools.openshift.internal.ui.wizard.importapp.BuildConfigTreeItems.ConnectionTreeItem; import com.openshift.restclient.model.IBuildConfig; import com.openshift.restclient.model.IProject; import com.openshift.restclient.model.build.IGitBuildSource; /** * @author Andre Dietisheim * @author Fred Bricon * @author Jeff.Cantrill * @author Rob Stryker */ public class ImportApplicationWizardModel extends ObservableUIPojo implements IBuildConfigPageModel, IGitCloningPageModel { private Connection connection; private ConnectionTreeItem connectionItem; private Object selectedItem; private String cloneDestination; private boolean useDefaultCloneDestination; private String repoName; private IProject project; private boolean reuseGitRepo = false; private boolean checkoutBranchReusedRepo; private String repoPath; private Repository repository; private String gitContextDir; private List<ObservableTreeItem> buildConfigs = new ArrayList<>(); private boolean isRepositoryBranchGitRef; public ImportApplicationWizardModel() { this.useDefaultCloneDestination = true; this.cloneDestination = getDefaultCloneDestination(); } private void update(Connection connection, Object selectedItem, String cloneDestination, boolean useDefaultCloneDestination, IProject project, boolean reuseGitRepo, boolean checkoutBranchReusedRepo, String gitContextDir) { this.connectionItem = updateConnection(connection); this.project = project; Object oldSelectedItem = this.selectedItem; updateSelectedItem(selectedItem); updateUseDefaultCloneDestination(useDefaultCloneDestination); updateCloneDestination(cloneDestination); IBuildConfig buildConfig = getBuildConfig(selectedItem); String repoName = updateRepoName(buildConfig); String oldRepoPath = this.repoPath; String newRepoPath = updateRepoPath(cloneDestination, repoName); reuseGitRepo = updateReuseGitRepo(reuseGitRepo, newRepoPath, oldRepoPath); String gitRef = updateGitRef(getGitRef(buildConfig)); Repository repository = updateRepository(newRepoPath, oldRepoPath); boolean isRepositoryAtGitRef = updateIsRepositoryAtGitRef(gitRef, repository); updateCheckoutBranchReusedRepo(checkoutBranchReusedRepo, isRepositoryAtGitRef); updateGitContextDir(gitContextDir, buildConfig, getBuildConfig(oldSelectedItem)); } private ConnectionTreeItem updateConnection(Connection connection) { firePropertyChange(PROPERTY_CONNECTION, this.connection, this.connection = connection); return new ConnectionTreeItem(connection); } protected void updateSelectedItem(Object selectedItem) { firePropertyChange(PROPERTY_SELECTED_ITEM, this.selectedItem, this.selectedItem = selectedItem); } private String updateRepoName(IBuildConfig config) { String name = getRepoName(config); if (name == null && getProject() != null) { name = getProject().getName(); } firePropertyChange(PROPERTY_REPO_NAME, this.repoName, this.repoName = name); return name; } private static String getRepoName(IBuildConfig config) { String repoName = null; if (config != null) { repoName = ResourceUtils.getProjectNameForURI(config.getSourceURI()); } return repoName; } private void updateCloneDestination(String cloneDestination) { firePropertyChange(PROPERTY_CLONE_DESTINATION, this.cloneDestination, this.cloneDestination = cloneDestination); } private String updateRepoPath(String repositoryPath, String repoName) { String repoPath = this.repoPath; if (StringUtils.isNotBlank(repositoryPath)) { IPath cloneDestinationPath = new Path(repositoryPath); if (StringUtils.isNotBlank(repoName)) { cloneDestinationPath = cloneDestinationPath.append(new Path(repoName)); } repoPath = cloneDestinationPath.toOSString(); } firePropertyChange(PROPERTY_REPO_PATH, this.repoPath, this.repoPath = repoPath); return repoPath; } private Repository updateRepository(String newRepoPath, String oldRepoPath) { Repository repository = this.repository; if (!StringUtils.equals(newRepoPath, oldRepoPath)) { if (repository != null) { repository.close(); } repository = EGitUtils.getRepository(getCloneDestination(newRepoPath)); } return this.repository = repository; } private boolean updateIsRepositoryAtGitRef(String gitRef, Repository cloneDestination) { boolean isCloneDestinationAtGitRef = this.isRepositoryBranchGitRef; String cloneDestinationBranch = null; if (cloneDestination == null) { return false; } try { cloneDestinationBranch = EGitUtils.getCurrentBranch(cloneDestination); } catch (CoreException e) { } isCloneDestinationAtGitRef = StringUtils.equals(gitRef, cloneDestinationBranch); firePropertyChange(PROPERTY_IS_REPOSITORY_BRANCH_GIT_REF, this.isRepositoryBranchGitRef, this.isRepositoryBranchGitRef = isCloneDestinationAtGitRef); return isCloneDestinationAtGitRef; } private boolean updateReuseGitRepo(boolean reuseGitRepo, String newCloneDestination, String oldCloneloneDestination) { if (!Objects.equals(newCloneDestination, oldCloneloneDestination) && !FileUtils.exists(new File(newCloneDestination)) && reuseGitRepo) { // reset reuseGitRepo if new cloneDestination does not exist reuseGitRepo = false; } firePropertyChange(PROPERTY_REUSE_GIT_REPOSITORY, this.reuseGitRepo, this.reuseGitRepo = reuseGitRepo); return reuseGitRepo; } private void updateCheckoutBranchReusedRepo(boolean checkoutBranchReusedRepo, boolean isCloneDestinationAtGitRef) { if (isCloneDestinationAtGitRef) { // reset checkout if we're already at the branch that's required checkoutBranchReusedRepo = false; } firePropertyChange(PROPERTY_CHECKOUT_BRANCH_REUSED_REPO, this.checkoutBranchReusedRepo, this.checkoutBranchReusedRepo = checkoutBranchReusedRepo); } private void updateGitContextDir(String newGitContextDir, IBuildConfig newBuildConfig, IBuildConfig oldBuildConfig) { if (Objects.equals(newBuildConfig, oldBuildConfig)) { if (Objects.equals(newGitContextDir, this.gitContextDir)) { return; } } else { newGitContextDir = getGitContextDir(newBuildConfig); } firePropertyChange(PROPERTY_GIT_CONTEXT_DIR, this.gitContextDir, this.gitContextDir = newGitContextDir); } private String updateGitRef(String gitRef) { firePropertyChange(PROPERTY_GIT_REF, null, gitRef); return gitRef; } @Override public IBuildConfig getSelectedBuildConfig() { return getBuildConfig(selectedItem); } private IBuildConfig getBuildConfig(Object item) { if (!(item instanceof IBuildConfig)) { return null; } return (IBuildConfig) item; } @Override public String getGitUrl() { IBuildConfig config = getSelectedBuildConfig(); if (config == null) { return null; } else { return config.getSourceURI(); } } @Override public String getGitRef() { return getGitRef(getSelectedBuildConfig()); } protected String getGitRef(IBuildConfig config) { String gitRef = null; if (config != null && config.getBuildSource() instanceof IGitBuildSource) { gitRef = ((IGitBuildSource) config.getBuildSource()).getRef(); } return gitRef; } @Override public void setSelectedItem(Object selectedItem) { update(this.connection, selectedItem, this.cloneDestination, this.useDefaultCloneDestination, this.project, this.reuseGitRepo, this.checkoutBranchReusedRepo, this.gitContextDir); } @Override public Object getSelectedItem() { return selectedItem; } @Override public void setCloneDestination(String cloneDestination) { update(this.connection, this.selectedItem, cloneDestination, false, this.project, this.reuseGitRepo, this.checkoutBranchReusedRepo, this.gitContextDir); } @Override public String getCloneDestination() { return cloneDestination; } @Override public String getRepoName() { return repoName; } @Override public File getRepoPath() { return getCloneDestination(repoPath); } private File getCloneDestination(String cloneDestination) { return new Path(cloneDestination).toFile(); } @Override public Repository getRepository() { return this.repository; } @Override public boolean isRepositoryBranchGitRef() { return this.isRepositoryBranchGitRef; } @Override public void setUseDefaultCloneDestination(boolean useDefaultCloneDestination) { update(this.connection, this.selectedItem, useDefaultCloneDestination? getDefaultCloneDestination() : this.cloneDestination, useDefaultCloneDestination, this.project, this.reuseGitRepo, this.checkoutBranchReusedRepo, this.gitContextDir); } private String getDefaultCloneDestination() { return EGitUIUtils.getEGitDefaultRepositoryPath(); } private void updateUseDefaultCloneDestination(boolean useDefault) { firePropertyChange(PROPERTY_USE_DEFAULT_CLONE_DESTINATION, this.useDefaultCloneDestination, this.useDefaultCloneDestination = useDefault); } @Override public boolean isUseDefaultCloneDestination() { return useDefaultCloneDestination; } @Override public Connection getConnection() { return connection; } @Override public boolean hasConnection() { return connection != null; } @Override public void setConnection(Connection connection) { update(connection, this.selectedItem, this.cloneDestination, this.useDefaultCloneDestination, this.project, this.reuseGitRepo, this.checkoutBranchReusedRepo, this.gitContextDir); } @Override public List<ObservableTreeItem> getBuildConfigs() { return buildConfigs; } @Override public void loadBuildConfigs() { loadBuildConfigs(connectionItem); } public void loadBuildConfigs(ConnectionTreeItem connectionItem) { if (connectionItem == null) { return; } connectionItem.load(); updateBuildConfigs(filterBuildConfigs(project, connectionItem.getChildren())); } private void updateBuildConfigs(List<ObservableTreeItem> newBuildConfigs) { if (newBuildConfigs == null || ListUtils.isEqualList(newBuildConfigs, buildConfigs)) { return; } List<ObservableTreeItem> oldItems = new ArrayList<>(buildConfigs); List<ObservableTreeItem> newItems = new ArrayList<>(newBuildConfigs); buildConfigs.clear(); buildConfigs.addAll(newItems); firePropertyChange(PROPERTY_BUILDCONFIGS, oldItems, newItems); } private List<ObservableTreeItem> filterBuildConfigs(IProject project, List<ObservableTreeItem> children) { List<ObservableTreeItem> result = children; if (project != null) { result = children.stream() .filter(c -> project.equals(c.getModel())) .map(p -> p.getChildren()) .flatMap(l -> l.stream()) .collect(Collectors.toList()); } return result; } @Override public Object getContext() { return null; } @Override public String getGitContextDir() { return this.gitContextDir; } protected String getGitContextDir(IBuildConfig bc) { String gitContextDir = null; if (bc != null && bc.getBuildSource() instanceof IGitBuildSource) { gitContextDir = ((IGitBuildSource) bc.getBuildSource()).getContextDir(); } return gitContextDir; } @Override public void setGitContextDir(String gitContextDir) { update(this.connection, this.selectedItem, this.cloneDestination, this.useDefaultCloneDestination, this.project, this.reuseGitRepo, this.checkoutBranchReusedRepo, gitContextDir); } @Override public String getApplicationName() { String appName = null; IBuildConfig buildConfig = getSelectedBuildConfig(); if (buildConfig != null) { appName = buildConfig.getName(); } return appName; } @Override public IProject getProject() { return project; } @Override public void setProject(IProject project) { update(this.connection, this.selectedItem, this.cloneDestination, this.useDefaultCloneDestination, project, this.reuseGitRepo, this.checkoutBranchReusedRepo, this.gitContextDir); } @Override public boolean isReuseGitRepository() { return reuseGitRepo; } @Override public void setReuseGitRepository(boolean reuseGitRepo) { update(this.connection, this.selectedItem, this.cloneDestination, this.useDefaultCloneDestination, this.project, reuseGitRepo, reuseGitRepo, this.gitContextDir); } @Override public boolean isCheckoutBranchReusedRepo() { return checkoutBranchReusedRepo; } @Override public void setCheckoutBranchReusedRepo(boolean checkout) { update(this.connection, this.selectedItem, this.cloneDestination, this.useDefaultCloneDestination, this.project, this.reuseGitRepo, checkout, this.gitContextDir); } }