1 /*******************************************************************************
2 * Copyright (C) 2010-2013 Dariusz Luksza <dariusz@luksza.org> and others.
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
9 * SPDX-License-Identifier: EPL-2.0
10 *******************************************************************************/
11 package org
.eclipse
.egit
.ui
.view
.synchronize
;
13 import static org
.eclipse
.egit
.ui
.internal
.UIText
.CommitDialog_Commit
;
14 import static org
.eclipse
.egit
.ui
.internal
.UIText
.CommitDialog_CommitChanges
;
15 import static org
.eclipse
.egit
.ui
.internal
.UIText
.CommitDialog_SelectAll
;
16 import static org
.eclipse
.egit
.ui
.test
.ContextMenuHelper
.clickContextMenu
;
17 import static org
.eclipse
.egit
.ui
.test
.TestUtil
.waitUntilTreeHasNodeContainsText
;
18 import static org
.eclipse
.jface
.dialogs
.MessageDialogWithToggle
.NEVER
;
19 import static org
.eclipse
.jgit
.lib
.Constants
.R_TAGS
;
20 import static org
.eclipse
.team
.internal
.ui
.IPreferenceIds
.SYNCHRONIZING_COMPLETE_PERSPECTIVE
;
21 import static org
.junit
.Assert
.assertTrue
;
23 import java
.io
.ByteArrayInputStream
;
25 import java
.io
.IOException
;
26 import java
.io
.UnsupportedEncodingException
;
27 import java
.util
.ArrayList
;
28 import java
.util
.Arrays
;
29 import java
.util
.concurrent
.TimeUnit
;
31 import org
.eclipse
.core
.resources
.IFile
;
32 import org
.eclipse
.core
.resources
.IFolder
;
33 import org
.eclipse
.core
.resources
.IProject
;
34 import org
.eclipse
.core
.resources
.IProjectDescription
;
35 import org
.eclipse
.core
.resources
.IResource
;
36 import org
.eclipse
.core
.resources
.ResourcesPlugin
;
37 import org
.eclipse
.core
.runtime
.CoreException
;
38 import org
.eclipse
.core
.runtime
.Path
;
39 import org
.eclipse
.egit
.core
.op
.CommitOperation
;
40 import org
.eclipse
.egit
.core
.op
.ConnectProviderOperation
;
41 import org
.eclipse
.egit
.core
.project
.RepositoryMapping
;
42 import org
.eclipse
.egit
.core
.synchronize
.dto
.GitSynchronizeData
;
43 import org
.eclipse
.egit
.ui
.Activator
;
44 import org
.eclipse
.egit
.ui
.JobFamilies
;
45 import org
.eclipse
.egit
.ui
.UIPreferences
;
46 import org
.eclipse
.egit
.ui
.common
.CompareEditorTester
;
47 import org
.eclipse
.egit
.ui
.common
.LocalRepositoryTestCase
;
48 import org
.eclipse
.egit
.ui
.internal
.synchronize
.GitModelSynchronize
;
49 import org
.eclipse
.egit
.ui
.test
.JobJoiner
;
50 import org
.eclipse
.egit
.ui
.test
.TestUtil
;
51 import org
.eclipse
.jdt
.ui
.JavaUI
;
52 import org
.eclipse
.jgit
.api
.Git
;
53 import org
.eclipse
.jgit
.lib
.Constants
;
54 import org
.eclipse
.jgit
.lib
.Repository
;
55 import org
.eclipse
.jgit
.storage
.file
.FileRepositoryBuilder
;
56 import org
.eclipse
.swtbot
.eclipse
.finder
.widgets
.SWTBotEditor
;
57 import org
.eclipse
.swtbot
.swt
.finder
.SWTBot
;
58 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotTree
;
59 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotTreeItem
;
60 import org
.eclipse
.team
.internal
.ui
.TeamUIPlugin
;
61 import org
.eclipse
.team
.ui
.TeamUI
;
62 import org
.eclipse
.team
.ui
.mapping
.ITeamContentProviderDescriptor
;
63 import org
.eclipse
.team
.ui
.mapping
.ITeamContentProviderManager
;
64 import org
.eclipse
.team
.ui
.synchronize
.ISynchronizeManager
;
65 import org
.eclipse
.team
.ui
.synchronize
.ISynchronizeView
;
66 import org
.junit
.After
;
67 import org
.junit
.Before
;
68 import org
.junit
.BeforeClass
;
70 @SuppressWarnings("restriction")
71 public abstract class AbstractSynchronizeViewTest
extends
72 LocalRepositoryTestCase
{
74 protected static final String INITIAL_TAG
= R_TAGS
+ "initial-tag";
76 protected static final String TEST_COMMIT_MSG
= "test commit";
78 protected static final String EMPTY_PROJECT
= "EmptyProject";
80 protected static final String EMPTY_REPOSITORY
= "EmptyRepository";
82 protected File repositoryFile
;
84 protected File childRepositoryFile
;
87 public void setupViews() {
88 Activator
.getDefault().getPreferenceStore()
89 .setValue(UIPreferences
.ALWAYS_USE_STAGING_VIEW
, false);
90 TestUtil
.showExplorerView();
94 public void closeSynchronizeView() {
95 Activator
.getDefault().getPreferenceStore()
96 .setValue(UIPreferences
.ALWAYS_USE_STAGING_VIEW
, true);
97 TestUtil
.hideView(ISynchronizeView
.VIEW_ID
);
101 public void deleteEmptyProject() throws Exception
{
102 IProject prj
= ResourcesPlugin
.getWorkspace().getRoot()
103 .getProject(EMPTY_PROJECT
);
105 prj
.delete(false, false, null);
106 TestUtil
.waitForJobs(50, 5000);
111 public void setupRepository() throws Exception
{
112 repositoryFile
= createProjectAndCommitToRepository();
113 createAndCommitDotGitignore();
115 childRepositoryFile
= createChildRepository(repositoryFile
);
117 createTag(INITIAL_TAG
);
119 Activator
.getDefault().getRepositoryUtil()
120 .addConfiguredRepository(repositoryFile
);
124 public static void setupEnvironment() throws Exception
{
125 // disable perspective synchronize selection
126 TeamUIPlugin
.getPlugin().getPreferenceStore().setValue(
127 SYNCHRONIZING_COMPLETE_PERSPECTIVE
, NEVER
);
128 Activator
.getDefault().getPreferenceStore()
129 .setValue(UIPreferences
.SYNC_VIEW_FETCH_BEFORE_LAUNCH
, false);
131 TestUtil
.showExplorerView();
134 protected void changeFilesInProject() throws Exception
{
135 SWTBot packageExlBot
= bot
.viewById(JavaUI
.ID_PACKAGES
).bot();
136 SWTBotTreeItem coreTreeItem
= selectProject(PROJ1
, packageExlBot
.tree());
137 SWTBotTreeItem rootNode
= TestUtil
.expandAndWait(coreTreeItem
);
138 rootNode
= TestUtil
.expandAndWait(rootNode
.getNode(0)).select();
139 rootNode
.getNode(0).select().doubleClick();
141 SWTBotEditor corePomEditor
= bot
.editorByTitle(FILE1
);
142 corePomEditor
.toTextEditor()
143 .insertText("<!-- EGit jUnit test case -->");
144 corePomEditor
.saveAndClose();
146 rootNode
.getNode(1).select().doubleClick();
147 SWTBotEditor uiPomEditor
= bot
.editorByTitle(FILE2
);
148 uiPomEditor
.toTextEditor().insertText("<!-- EGit jUnit test case -->");
149 uiPomEditor
.saveAndClose();
150 coreTreeItem
.collapse();
153 protected void createTag(String tagName
)
155 try (Git git
= new Git(lookupRepository(repositoryFile
))) {
156 git
.tag().setName(tagName
).setMessage(tagName
).call();
160 protected void makeChangesAndCommit(String projectName
) throws Exception
{
161 changeFilesInProject();
165 protected void deleteFileAndCommit(String projectName
) throws Exception
{
166 ResourcesPlugin
.getWorkspace().getRoot().getProject(PROJ1
)
167 .getFile(new Path("folder/test.txt")).delete(true, null);
171 protected void launchSynchronization(String srcRef
, String dstRef
,
172 boolean includeLocal
) throws IOException
{
173 launchSynchronization(PROJ1
, srcRef
, dstRef
, includeLocal
);
176 protected void launchSynchronization(String projectName
, String srcRef
,
177 String dstRef
, boolean includeLocal
) throws IOException
{
178 IProject project
= ResourcesPlugin
.getWorkspace().getRoot()
179 .getProject(projectName
);
180 RepositoryMapping mapping
= assertConnected(project
);
181 Repository repo
= mapping
.getRepository();
183 GitSynchronizeData data
= new GitSynchronizeData(repo
, srcRef
, dstRef
,
186 JobJoiner jobJoiner
= JobJoiner
.startListening(
187 ISynchronizeManager
.FAMILY_SYNCHRONIZE_OPERATION
, 60,
189 GitModelSynchronize
.launch(data
, new IResource
[] { project
});
193 protected void setEnabledModelProvider(String modelProviderId
) {
194 ITeamContentProviderManager contentProviderManager
= TeamUI
.getTeamContentProviderManager();
195 ITeamContentProviderDescriptor descriptor
= contentProviderManager
.getDescriptor(modelProviderId
);
196 contentProviderManager
.setEnabledDescriptors(new ITeamContentProviderDescriptor
[] { descriptor
});
199 // based on LocalRepositoryTestCase#createProjectAndCommitToRepository(String)
200 protected void createEmptyRepository() throws Exception
{
201 File gitDir
= new File(new File(getTestDirectory(), EMPTY_REPOSITORY
),
203 Repository myRepository
= FileRepositoryBuilder
.create(gitDir
);
204 myRepository
.create();
206 // we need to commit into master first
207 IProject firstProject
= ResourcesPlugin
.getWorkspace().getRoot()
208 .getProject(EMPTY_PROJECT
);
210 if (firstProject
.exists()) {
211 firstProject
.delete(true, null);
212 TestUtil
.waitForJobs(100, 5000);
214 IProjectDescription desc
= ResourcesPlugin
.getWorkspace()
215 .newProjectDescription(EMPTY_PROJECT
);
216 desc
.setLocation(new Path(new File(myRepository
.getWorkTree(),
217 EMPTY_PROJECT
).getPath()));
218 firstProject
.create(desc
, null);
219 firstProject
.open(null);
220 assertTrue("Project is not accessible: " + firstProject
,
221 firstProject
.isAccessible());
223 IFolder folder
= firstProject
.getFolder(FOLDER
);
224 folder
.create(false, true, null);
225 IFile textFile
= folder
.getFile(FILE1
);
226 textFile
.create(new ByteArrayInputStream("Hello, world"
227 .getBytes(firstProject
.getDefaultCharset())), false, null);
228 IFile textFile2
= folder
.getFile(FILE2
);
229 textFile2
.create(new ByteArrayInputStream("Some more content"
230 .getBytes(firstProject
.getDefaultCharset())), false, null);
231 TestUtil
.waitForJobs(50, 5000);
233 new ConnectProviderOperation(firstProject
, gitDir
).execute(null);
234 } catch (Exception e
) {
235 Activator
.logError("Failed to connect project to repository", e
);
237 assertConnected(firstProject
);
240 protected SWTBotTreeItem
waitForNodeWithText(SWTBotTree tree
, String name
) {
241 waitUntilTreeHasNodeContainsText(bot
, tree
, name
, 10000);
242 return getTreeItemContainingText(tree
.getAllItems(), name
).expand();
245 protected SWTBotTreeItem
waitForNodeWithText(SWTBotTreeItem tree
,
247 waitUntilTreeHasNodeContainsText(bot
, tree
, name
, 15000);
248 return getTreeItemContainingText(tree
.getItems(), name
).expand();
251 private static void createAndCommitDotGitignore() throws CoreException
,
252 UnsupportedEncodingException
{
253 IProject secondPoject
= ResourcesPlugin
.getWorkspace().getRoot()
256 IFile gitignore
= secondPoject
.getFile(".gitignore");
258 new ByteArrayInputStream("/.project\n".getBytes(secondPoject
259 .getDefaultCharset())), false, null);
261 IFile
[] commitables
= new IFile
[] { gitignore
};
262 ArrayList
<IFile
> untracked
= new ArrayList
<IFile
>();
263 untracked
.addAll(Arrays
.asList(commitables
));
265 CommitOperation op
= new CommitOperation(commitables
,
266 untracked
, TestUtil
.TESTAUTHOR
, TestUtil
.TESTCOMMITTER
,
267 "Add .gitignore file");
271 protected void commit(String projectName
) throws InterruptedException
{
272 showDialog(projectName
, "Team", "Commit...");
274 SWTBot shellBot
= bot
.shell(CommitDialog_CommitChanges
).bot();
275 shellBot
.styledText(0).setText(TEST_COMMIT_MSG
);
276 shellBot
.toolbarButtonWithTooltip(CommitDialog_SelectAll
).click();
277 shellBot
.button(CommitDialog_Commit
).click();
278 TestUtil
.joinJobs(JobFamilies
.COMMIT
);
281 protected CompareEditorTester
getCompareEditor(SWTBotTreeItem projectNode
,
282 final String fileName
) {
283 SWTBotTreeItem folderNode
= waitForNodeWithText(projectNode
, FOLDER
);
284 waitForNodeWithText(folderNode
, fileName
).doubleClick();
286 return CompareEditorTester
.forTitleContaining(fileName
);
289 private static void showDialog(String projectName
, String
... cmd
) {
290 SWTBotTree tree
= TestUtil
.getExplorerTree();
292 // EGit decorates the project node shown in the package explorer. The
293 // '>' decorator indicates that there are uncommitted changes present in
294 // the project. Also the repository and branch name are added as a
295 // suffix ('[<repo name> <branch name>]' suffix). To bypass this
296 // decoration we use here this loop.
297 selectProject(projectName
, tree
);
299 clickContextMenu(tree
, cmd
);
302 private static SWTBotTreeItem
selectProject(String projectName
,
304 for (SWTBotTreeItem item
: tree
.getAllItems())
305 if (item
.getText().contains(projectName
)) {
310 throw new RuntimeException("Project with name " + projectName
+
311 " was not found in given tree");
314 private SWTBotTreeItem
getTreeItemContainingText(SWTBotTreeItem
[] items
,
316 return TestUtil
.getNode(items
, text
);