diff --git a/plugins/git4idea/git4idea.iml b/plugins/git4idea/git4idea.iml index b0ecaa1607db..9871c3cff054 100644 --- a/plugins/git4idea/git4idea.iml +++ b/plugins/git4idea/git4idea.iml @@ -76,7 +76,7 @@ - + diff --git a/plugins/git4idea/test-features/git4idea/CherryPickeStepdefs.groovy b/plugins/git4idea/test-features/git4idea/CherryPickeStepdefs.groovy deleted file mode 100644 index 8cdca56d25b5..000000000000 --- a/plugins/git4idea/test-features/git4idea/CherryPickeStepdefs.groovy +++ /dev/null @@ -1,88 +0,0 @@ -package git4idea -import com.intellij.dvcs.test.MockVirtualFile -import com.intellij.notification.Notification -import com.intellij.openapi.vcs.FilePathImpl -import com.intellij.openapi.vcs.changes.Change -import com.intellij.openapi.vcs.changes.ChangeListManager -import com.intellij.openapi.vcs.changes.LocalChangeList -import com.intellij.openapi.vcs.history.VcsRevisionNumber -import com.intellij.openapi.vfs.newvfs.impl.NullVirtualFile -import com.intellij.testFramework.vcs.MockChangeListManager -import com.intellij.testFramework.vcs.MockContentRevision -import git4idea.history.browser.GitCherryPicker -import git4idea.history.browser.GitCommit -import git4idea.history.browser.SHAHash -import git4idea.history.wholeTree.AbstractHash -import git4idea.test.TestNotificator - -import static com.intellij.dvcs.test.Executor.echo -import static cucumber.runtime.groovy.EN.* -import static git4idea.GitCucumberWorld.* -import static git4idea.test.GitExecutor.git -import static git4idea.test.GitScenarios.checkout -import static junit.framework.Assert.assertEquals -/** - * - * @author Kirill Likhodedov - */ - -String remCommit - -Given(~'^(enabled|disabled) auto-commit in the settings$') { String state -> - boolean enabled = state.equals("enabled") - myPlatformFacade.getSettings(myProject).setAutoCommitOnCherryPick(enabled); -} - -Given(~'^branch "([^"]*)" with commit "([^"]*)" by "([^"]*)" modifying (.+):$') { String branch, String commitMessage, String author, - String file, String content -> - checkout(myRepository, branch) - echo(file, content) - git("commit -am $commitMessage --author '$author <$author@example.com>'") - checkout(myRepository, "master") -} - -When(~'^I cherry-pick the commit "(.+)"$') { String msg -> - String hash = git("log --grep $msg --pretty=%H --all"); - remCommit = hash - new GitCherryPicker(myProject, myGit, myPlatformFacade, myPlatformFacade.getSettings(myProject).isAutoCommitOnCherryPick()) - .cherryPick(Collections.singletonMap(myRepository, Collections.singletonList(commit(hash, msg)))); -} - -private GitCommit commit(String hash, String message) { - AbstractHash ahash = AbstractHash.create(hash); - List changes = new ArrayList(); - changes.add(new Change(null, new MockContentRevision(new FilePathImpl(new MockVirtualFile("name")), VcsRevisionNumber.NULL))); - return new GitCommit(NullVirtualFile.INSTANCE, ahash, SHAHash.emulate(ahash), "John Smith", null, null, message, message, - null, null, null, null, null, null, null, changes, 0); -} - -Then(~'^the last commit is$') { String message -> - String actual = git("log -1 --pretty=%B"); - message = message.replace("#hash", remCommit) - assertEquals("Commit doesn't match", message, actual); -} - -And(~'^notification "([^"]*)" is shown$') { String title -> - assertEquals "Notification title is incorrect", title, lastNotification().title -} - -private Notification lastNotification() { - (myPlatformFacade.getNotificator(myProject) as TestNotificator).lastNotification -} - -And(~'^no new changelists are created$') {-> - assertOnlyDefaultChangelist() -} - -void assertOnlyDefaultChangelist() { - String DEFAULT = MockChangeListManager.DEFAULT_CHANGE_LIST_NAME; - assertChangeLists( [DEFAULT], DEFAULT) -} - -void assertChangeLists(Collection changeLists, String activeChangelist) { - ChangeListManager changeListManager = myPlatformFacade.getChangeListManager(myProject) - List lists = changeListManager.changeLists - Collection listNames = lists.collect { it.name } - assertEquals "Change lists are different", changeLists.toSet(), listNames.toSet() - assertEquals "Wrong active changelist", activeChangelist, changeListManager.defaultChangeList.name -} diff --git a/plugins/git4idea/test-features/git4idea/GeneralStepdefs.groovy b/plugins/git4idea/test-features/git4idea/GeneralStepdefs.groovy deleted file mode 100644 index 9ce5cd9b073a..000000000000 --- a/plugins/git4idea/test-features/git4idea/GeneralStepdefs.groovy +++ /dev/null @@ -1,47 +0,0 @@ -package git4idea -import com.intellij.dvcs.test.MockProject -import com.intellij.openapi.util.Disposer -import com.intellij.openapi.util.io.FileUtil -import git4idea.test.GitTestImpl -import git4idea.test.GitTestPlatformFacade - -import static com.intellij.dvcs.test.Executor.cd -import static com.intellij.dvcs.test.Executor.mkdir -import static com.intellij.dvcs.test.Executor.touch -import static cucumber.runtime.groovy.EN.Given -import static cucumber.runtime.groovy.Hooks.After -import static cucumber.runtime.groovy.Hooks.Before -import static git4idea.GitCucumberWorld.* -import static git4idea.test.GitExecutor.git -import static git4idea.test.GitScenarios.checkout -import static git4idea.test.GitTestInitUtil.createRepository - -/** - * General step definitions and hooks used by all cucumber tests. - * - * @author Kirill Likhodedov - */ - -Before() { - myTestRoot = FileUtil.createTempDirectory("", "").getPath() - cd myTestRoot - myProjectRoot = mkdir ("project") - myProject = new MockProject(myProjectRoot) - myPlatformFacade = new GitTestPlatformFacade() - myGit = new GitTestImpl() - - cd(myProjectRoot) - myRepository = createRepository(myProjectRoot, myPlatformFacade, myProject) -} - -After() { - FileUtil.delete(new File(myTestRoot)) - Disposer.dispose(myProject) -} - -Given(~'^file (.*) on master:$') { String filename, String content -> - checkout(myRepository, "master") - touch(filename, content) - git("add $filename") - git("commit -m 'adding $filename'") -} \ No newline at end of file diff --git a/plugins/git4idea/test-features/git4idea/cherry-pick-auto-commit.feature b/plugins/git4idea/test-features/git4idea/cherry-pick-auto-commit.feature index 92ed5c7d7866..518891090552 100644 --- a/plugins/git4idea/test-features/git4idea/cherry-pick-auto-commit.feature +++ b/plugins/git4idea/test-features/git4idea/cherry-pick-auto-commit.feature @@ -1,28 +1,37 @@ Feature: Git Cherry-Pick When Auto-Commit is selected - Background: - Given enabled auto-commit in the settings - Given file file.txt on master: - """ - first line - - last line (space is to have possibility to avoid conflicts) - """ - Given branch "feature" with commit "fix_1" by "John Bro" modifying file.txt: - """ - first line - - last line on branch feature - """ +Background: + Given enabled auto-commit in the settings + Given file file.txt "initial" on master + And commit f5027a3 on branch feature + """ + fix #1 + ----- + Author: John Bro + Changes: + M file.txt "feature changes" + """ Scenario: Simple cherry-pick - When I cherry-pick the commit "fix_1" + When I cherry-pick the commit f5027a3 Then the last commit is """ - fix_1 - (cherry picked from commit #hash) + fix #1 + (cherry picked from commit f5027a3) """ - And notification "Cherry-pick successful" is shown + And there is notification 'Cherry-pick successful' And no new changelists are created + Scenario: Dirty tree, conflicting with the commit + Given file.txt is locally modified: + """ + master + """ + When I cherry-pick the commit f5027a3 + Then nothing is committed + And error notification 'Cherry-pick failed' is shown: + """ + f5027a3 fix #1 + error: Your local changes to the following files would be overwritten by merge: + """ diff --git a/plugins/git4idea/test-stepdefs/git4idea/CommitDetails.java b/plugins/git4idea/test-stepdefs/git4idea/CommitDetails.java new file mode 100644 index 000000000000..c2737d2788b5 --- /dev/null +++ b/plugins/git4idea/test-stepdefs/git4idea/CommitDetails.java @@ -0,0 +1,188 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package git4idea; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static com.intellij.dvcs.test.Executor.echo; +import static com.intellij.dvcs.test.Executor.touch; +import static git4idea.GitCucumberWorld.virtualCommits; +import static git4idea.test.GitExecutor.git; + +/** + * + * @author Kirill Likhodedov + */ +public class CommitDetails { + + private String myHash; + private String myMessage; + private String myAuthor; + private Collection myChanges; + + private static class Change { + + public void apply() { + switch (myType) { + case MODIFIED: + echo(myFile, myContent); + break; + case ADDED: + touch(myFile, myContent); + break; + case DELETED: + throw new UnsupportedOperationException("Not implemented yet"); + case MOVED: + throw new UnsupportedOperationException("Not implemented yet"); + } + } + + enum Type { + MODIFIED, ADDED, DELETED, MOVED + } + + private final Type myType; + private final String myFile; + private final String myContent; + + Change(Type type, String filename, String content) { + myType = type; + myFile = filename; + myContent = content; + } + + } + + private enum ParsingStage { + MESSAGE, + DATA, + CHANGES + } + + /** + * Format: + *
+       commit subject
+
+       and optional description
+       -----
+       Author: John Bro
+       Changes:
+       M file.txt "feature changes"
+   * 
+ */ + public static CommitDetails parse(String hash, String details) { + CommitDetails commit = new CommitDetails(); + commit.myHash = hash; + + StringBuilder message = new StringBuilder(); + Collection changes = new ArrayList(); + ParsingStage stage = ParsingStage.MESSAGE; + for (String line : details.split("\n")) { + if (line.equals("-----")) { + stage = ParsingStage.DATA; + continue; + } + else if (line.equals("Changes:")) { + stage = ParsingStage.CHANGES; + continue; + } + + if (stage == ParsingStage.MESSAGE) { + message.append(line); + } + else if (stage == ParsingStage.CHANGES) { + changes.add(parseChange(line)); + } + else if (line.toLowerCase().startsWith("author: ")) { + commit.myAuthor = line.substring("author: ".length()); + } + } + + commit.myMessage = message.toString(); + commit.myChanges = changes; + return commit; + } + + private static Change parseChange(String change) { + int firstSpace = change.indexOf(' '); + int secondSpace = change.indexOf(' ', firstSpace + 1); + return new Change(parseType(change.substring(0, firstSpace)), + change.substring(firstSpace + 1, secondSpace), + change.substring(secondSpace + 1)); + } + + private static Change.Type parseType(String type) { + if (type.equals("M")) { + return Change.Type.MODIFIED; + } + else if (type.equals("A")) { + return Change.Type.ADDED; + } + else if (type.equals("D")) { + return Change.Type.DELETED; + } + else if (type.equals("R")) { + return Change.Type.MOVED; + } + return null; + } + + /** + * @return real commit details. + */ + public CommitDetails apply() { + for (Change change : myChanges) { + change.apply(); + } + + String commitOutput = git(String.format("commit -am '%1$s' --author '%2$s <%2$s@example.com>'", myMessage, myAuthor)); + CommitDetails realCommit = parseHashFromCommitOutput(commitOutput); + virtualCommits.register(myHash, realCommit); + return realCommit; + } + + CommitDetails parseHashFromCommitOutput(String commitOutput) { + String line = commitOutput.split("\n")[0]; + Pattern reg = Pattern.compile("^\\s*\\[.+ ([a-fA-F0-9]+)\\] (.+)$"); + Matcher matcher = reg.matcher(line); + boolean matches = matcher.matches(); + assert matches; + return new CommitDetails().hash(matcher.group(1)).message(matcher.group(2)); + } + + private CommitDetails hash(String hash) { + myHash = hash; + return this; + } + + private CommitDetails message(String message) { + myMessage = message; + return this; + } + + public String getHash() { + return myHash; + } + + public String getMessage() { + return myMessage; + } + +} diff --git a/plugins/git4idea/test-stepdefs/git4idea/GeneralStepdefs.java b/plugins/git4idea/test-stepdefs/git4idea/GeneralStepdefs.java new file mode 100644 index 000000000000..51137075adbc --- /dev/null +++ b/plugins/git4idea/test-stepdefs/git4idea/GeneralStepdefs.java @@ -0,0 +1,80 @@ +package git4idea;/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import com.intellij.dvcs.test.MockProject; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.io.FileUtil; +import cucumber.annotation.After; +import cucumber.annotation.Before; +import cucumber.annotation.en.Given; +import git4idea.test.GitTestImpl; +import git4idea.test.GitTestPlatformFacade; + +import java.io.File; +import java.io.IOException; + +import static com.intellij.dvcs.test.Executor.cd; +import static com.intellij.dvcs.test.Executor.mkdir; +import static git4idea.GitCucumberWorld.*; +import static git4idea.test.GitExecutor.git; +import static git4idea.test.GitExecutor.touch; +import static git4idea.test.GitScenarios.checkout; +import static git4idea.test.GitTestInitUtil.createRepository; + +/** + * @author Kirill Likhodedov + */ +public class GeneralStepdefs { + + @Before + public void setUpProject() throws IOException { + myTestRoot = FileUtil.createTempDirectory("", "").getPath(); + cd(myTestRoot); + myProjectRoot = mkdir("project"); + myProject = new MockProject(myProjectRoot); + myPlatformFacade = new GitTestPlatformFacade(); + myGit = new GitTestImpl(); + mySettings = myPlatformFacade.getSettings(myProject); + + cd(myProjectRoot); + myRepository = createRepository(myProjectRoot, myPlatformFacade, myProject); + + virtualCommits = new GitTestVirtualCommitsHolder(); + } + + @After + public void cleanup() { + FileUtil.delete(new File(myTestRoot)); + Disposer.dispose(myProject); + } + + @Given("^file (.*) \"(.*)\" on master$") + public void file_file_txt_on_master(String filename, String content) throws Throwable { + checkout(myRepository, "master"); + touch(filename, content); + git("add %s", filename); + git("commit -m 'adding %s'", filename); + } + + @Given("^commit (.+) on branch (.+)$") + public void commit_on_branch_feature(String hash, String branch, String commitDetails) throws Throwable { + CommitDetails commit = CommitDetails.parse(hash, commitDetails); + checkout(branch); + commit.apply(); + checkout("master"); + } + +} diff --git a/plugins/git4idea/test-stepdefs/git4idea/GitCherryPickStepdefs.java b/plugins/git4idea/test-stepdefs/git4idea/GitCherryPickStepdefs.java new file mode 100644 index 000000000000..cfcaa0f05810 --- /dev/null +++ b/plugins/git4idea/test-stepdefs/git4idea/GitCherryPickStepdefs.java @@ -0,0 +1,144 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package git4idea; + +import com.google.common.base.Function; +import com.google.common.collect.Collections2; +import com.intellij.dvcs.test.MockVirtualFile; +import com.intellij.notification.Notification; +import com.intellij.openapi.vcs.FilePathImpl; +import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vcs.changes.ChangeListManager; +import com.intellij.openapi.vcs.changes.LocalChangeList; +import com.intellij.openapi.vcs.history.VcsRevisionNumber; +import com.intellij.openapi.vfs.newvfs.impl.NullVirtualFile; +import com.intellij.testFramework.vcs.MockChangeListManager; +import com.intellij.testFramework.vcs.MockContentRevision; +import cucumber.annotation.en.And; +import cucumber.annotation.en.Given; +import cucumber.annotation.en.Then; +import cucumber.annotation.en.When; +import git4idea.history.browser.GitCherryPicker; +import git4idea.history.browser.GitCommit; +import git4idea.history.browser.SHAHash; +import git4idea.history.wholeTree.AbstractHash; +import git4idea.test.TestNotificator; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.regex.Matcher; + +import static com.intellij.dvcs.test.Executor.echo; +import static git4idea.GitCucumberWorld.*; +import static git4idea.test.GitExecutor.git; +import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +/** + * @author Kirill Likhodedov + */ + +public class GitCherryPickStepdefs { + + @Given("^(enabled|disabled) auto-commit in the settings$") + public void auto_commit_in_the_settings(String state) { + boolean enabled = state.equals("enabled"); + myPlatformFacade.getSettings(myProject).setAutoCommitOnCherryPick(enabled); + } + + @When("^I cherry-pick the commit (.+)$") + public void I_cherry_pick_the_commit(String hash) { + CommitDetails realCommit = virtualCommits.getRealCommit(hash); + new GitCherryPicker(myProject, myGit, myPlatformFacade, mySettings.isAutoCommitOnCherryPick()) + .cherryPick(Collections.singletonMap(myRepository, Collections.singletonList(mockCommit(realCommit.getHash(), realCommit.getMessage())))); + } + + private static GitCommit mockCommit(String hash, String message) { + AbstractHash ahash = AbstractHash.create(hash); + List changes = new ArrayList(); + changes.add(new Change(null, new MockContentRevision(new FilePathImpl(new MockVirtualFile("name")), VcsRevisionNumber.NULL))); + return new GitCommit(NullVirtualFile.INSTANCE, ahash, SHAHash.emulate(ahash), "John Smith", null, null, message, message, + null, null, null, null, null, null, null, changes, 0); + } + + @Then("^the last commit is$") + public void the_last_commit_is(String message) { + String actual = git("log -1 --pretty=%B"); + message = virtualCommits.replaceVirtualHashes(message); + assertEquals("Commit doesn't match", message, trimHash(actual)); + } + + @And("^there is notification '(.*)'$") + public void there_is_notification(String title) { + assertEquals("Notification title is incorrect", title, lastNotification().getTitle()); + } + + private static Notification lastNotification() { + return ((TestNotificator)myPlatformFacade.getNotificator(myProject)).getLastNotification(); + } + + @And("^no new changelists are created$") + public void no_new_changelists_are_created() { + assertOnlyDefaultChangelist(); + } + + void assertOnlyDefaultChangelist() { + String DEFAULT = MockChangeListManager.DEFAULT_CHANGE_LIST_NAME; + assertChangeLists(Collections.singleton(DEFAULT), DEFAULT); + } + + void assertChangeLists(Collection changeLists, String activeChangelist) { + ChangeListManager changeListManager = myPlatformFacade.getChangeListManager(myProject); + List lists = changeListManager.getChangeLists(); + Collection listNames = Collections2.transform(lists, new Function() { + @Override + public String apply(LocalChangeList input) { + return input.getName(); + } + }); + assertEquals("Change lists are different", new ArrayList(changeLists), new ArrayList(listNames)); + assertEquals("Wrong active changelist", activeChangelist, changeListManager.getDefaultChangeList().getName()); + } + + @Given("^(.+) is locally modified:$") + public void is_locally_modified(String filename, String content) { + echo(filename, content); + } + + String trimHash(String commitMessage) { + int hashStart = commitMessage.lastIndexOf(' ') + 1; + String hash = commitMessage.substring(hashStart); + return commitMessage.replace(hash, hash.substring(0, 7)) + ")"; + } + + @Then("^nothing is committed$") + public void nothing_is_committed() { + assertFalse("Working tree is unexpectedly clean", git("diff").trim().isEmpty()); + } + + @And("^error notification '(.+)' is shown:$") + public void error_notification_is_shown(String title, String content) { + assertEquals("Notification title is incorrect", title, lastNotification().getTitle()); + assertEquals("Notification content is incorrect", virtualCommits.replaceVirtualHashes(content), + convertNotificationHtml(lastNotification().getContent())); + } + + private static String convertNotificationHtml(String content) { + return content.replaceAll("
", Matcher.quoteReplacement("\n")); + } +} \ No newline at end of file diff --git a/plugins/git4idea/test-stepdefs/git4idea/GitCucumberWorld.java b/plugins/git4idea/test-stepdefs/git4idea/GitCucumberWorld.java index 375c000f9ce5..b92dbc55d816 100644 --- a/plugins/git4idea/test-stepdefs/git4idea/GitCucumberWorld.java +++ b/plugins/git4idea/test-stepdefs/git4idea/GitCucumberWorld.java @@ -2,6 +2,7 @@ package git4idea; import com.intellij.dvcs.test.MockProject; import git4idea.commands.Git; +import git4idea.config.GitVcsSettings; import git4idea.repo.GitRepository; /** @@ -18,5 +19,7 @@ public class GitCucumberWorld { public static GitPlatformFacade myPlatformFacade; public static Git myGit; public static GitRepository myRepository; + public static GitVcsSettings mySettings; + public static GitTestVirtualCommitsHolder virtualCommits; } diff --git a/plugins/git4idea/test-stepdefs/git4idea/GitTestVirtualCommitsHolder.java b/plugins/git4idea/test-stepdefs/git4idea/GitTestVirtualCommitsHolder.java new file mode 100644 index 000000000000..57d6c01c88c9 --- /dev/null +++ b/plugins/git4idea/test-stepdefs/git4idea/GitTestVirtualCommitsHolder.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package git4idea; + +import java.util.HashMap; +import java.util.Map; + +/** + * So called Virtual Commits are used in Cucumber feature files, so that the writer of a test could refer to commits in the natural way: + * via hashes. We can't define a hash to the commit when committing to Git, therefore to match these two sets we store them here. + * + * @author Kirill Likhodedov + */ +public class GitTestVirtualCommitsHolder { + + // virtual hash -> commit details + private Map commits = new HashMap(); + + void register(String virtualHash, CommitDetails CommitInfo) { + commits.put(virtualHash, CommitInfo); + } + + CommitDetails getRealCommit(String virtualHash) { + return commits.get(virtualHash); + } + + String replaceVirtualHashes(String message) { + for (Map.Entry entry : commits.entrySet()) { + message = message.replace(entry.getKey(), entry.getValue().getHash()); + } + return message; + } + +} diff --git a/plugins/git4idea/testFramework/git4idea/test/GitExecutor.groovy b/plugins/git4idea/testFramework/git4idea/test/GitExecutor.groovy index 3b3c3b4e5672..263aa9dd1317 100644 --- a/plugins/git4idea/testFramework/git4idea/test/GitExecutor.groovy +++ b/plugins/git4idea/testFramework/git4idea/test/GitExecutor.groovy @@ -95,10 +95,16 @@ class GitExecutor extends Executor { } public static String git(GitRepository repository, String command) { - cd repository.root.path + if (repository != null) { + cd repository.root.path + } git command } + public static String git(String formatString, String... args) { + return git(String.format(formatString, args)) + } + public static void cd(GitRepository repository) { cd repository.root.path } diff --git a/plugins/git4idea/testFramework/git4idea/test/GitScenarios.groovy b/plugins/git4idea/testFramework/git4idea/test/GitScenarios.groovy index 02d8f66c90a8..9953bce904d1 100644 --- a/plugins/git4idea/testFramework/git4idea/test/GitScenarios.groovy +++ b/plugins/git4idea/testFramework/git4idea/test/GitScenarios.groovy @@ -154,16 +154,17 @@ class GitScenarios { git("commit -m just_a_commit") } - public static boolean branchExists(GitRepository repo, String branch) { + public static boolean branchExists(GitRepository repo = null, String branch) { git(repo, "branch").contains(branch) } - public static void checkout(GitRepository repository, String branch) { - if (branchExists(repository, branch)) { + public static void checkout(GitRepository repository = null, String branch) { + if (branch.equals("master") || branchExists(repository, branch)) { git("checkout $branch") } else { git("checkout -b $branch") } } + } diff --git a/plugins/git4idea/testFramework/git4idea/test/GitTestImpl.groovy b/plugins/git4idea/testFramework/git4idea/test/GitTestImpl.groovy index fddc63797e4c..83121783cb66 100644 --- a/plugins/git4idea/testFramework/git4idea/test/GitTestImpl.groovy +++ b/plugins/git4idea/testFramework/git4idea/test/GitTestImpl.groovy @@ -32,10 +32,12 @@ import org.jetbrains.annotations.NotNull import org.jetbrains.annotations.Nullable import java.lang.reflect.Method +import static com.intellij.dvcs.test.Executor.cd; +import static GitExecutor.git; + /** * @author Kirill Likhodedov */ -@Mixin(GitExecutor) public class GitTestImpl implements Git { @NotNull @@ -197,13 +199,13 @@ public class GitTestImpl implements Git { @NotNull String hash, boolean autoCommit, @NotNull GitLineHandlerListener... listeners) { - execute(repository, "cherry-pick -x ${autoCommit ? "" : "-n"} $hash") + return execute(repository, "cherry-pick -x ${autoCommit ? "" : "-n"} $hash", listeners); } @NotNull @Override public GitCommandResult getUnmergedFiles(@NotNull GitRepository repository) { - execute(repository, "ls-files --unmerged") + return execute(repository, "ls-files --unmerged"); } @NotNull @@ -216,28 +218,41 @@ public class GitTestImpl implements Git { } private static GitCommandResult commandResult(String output) { - boolean success = !output.split("\n").collect { isError(it) }.contains(true) - return new GitCommandResult(success, 0, Collections.emptyList(), Arrays.asList(StringUtil.splitByLines(output))) + Collection err = new ArrayList<>(); + Collection out = new ArrayList<>(); + for (String line : output.split("\n")) { + if (isError(line)) { + err.add(line); + } + else { + out.add(line); + } + } + boolean success = err.isEmpty(); + return new GitCommandResult(success, 0, err, out); } private static boolean isError(String s) { // we don't want to make that method public, since it is reused only in the test. - Method m = GitImpl.class.getDeclaredMethod("isError", String.class) - m.setAccessible(true) - return m.invoke(null, s) as boolean + Method m = GitImpl.class.getDeclaredMethod("isError", String.class); + m.setAccessible(true); + return (boolean) m.invoke(null, s); } - static def feedOutput(String output, GitLineHandlerListener... listeners) { + private static void feedOutput(String output, GitLineHandlerListener... listeners) { listeners.each { GitLineHandlerListener listener -> - output.split("\n").each { listener.onLineAvailable(it, ProcessOutputTypes.STDERR) } + String split = output.split("\n") + for (String line : split) { + listener.onLineAvailable(line, ProcessOutputTypes.STDERR); + } } } - def execute(GitRepository repository, String operation, GitLineHandlerListener... listeners) { - cd repository.root.path - def out = git(operation) - feedOutput(out, listeners) - commandResult(out) + private static GitCommandResult execute(GitRepository repository, String operation, GitLineHandlerListener... listeners) { + cd(repository.getRoot().getPath()); + String out = git(operation); + feedOutput(out, listeners); + return commandResult(out); } } diff --git a/plugins/git4idea/testFramework/git4idea/test/GitTestInitUtil.groovy b/plugins/git4idea/testFramework/git4idea/test/GitTestInitUtil.groovy index 850323ee78dd..4674d988b5f3 100644 --- a/plugins/git4idea/testFramework/git4idea/test/GitTestInitUtil.groovy +++ b/plugins/git4idea/testFramework/git4idea/test/GitTestInitUtil.groovy @@ -6,6 +6,9 @@ import git4idea.GitPlatformFacade import git4idea.repo.GitRepository import git4idea.repo.GitRepositoryImpl +import static com.intellij.dvcs.test.Executor.* +import static git4idea.test.GitExecutor.* + /** * * @author Kirill Likhodedov @@ -20,17 +23,17 @@ class GitTestInitUtil { * @param repoRoot */ public static void initRepo(String repoRoot) { - com.intellij.dvcs.test.Executor.cd repoRoot - git4idea.test.GitExecutor.git("init") + cd repoRoot + git("init") setupUsername(); - com.intellij.dvcs.test.Executor.touch("initial.txt") - git4idea.test.GitExecutor.git("add initial.txt") - git4idea.test.GitExecutor.git("commit -m initial") + touch("initial.txt") + git("add initial.txt") + git("commit -m initial") } public static void setupUsername() { - git4idea.test.GitExecutor.git("config user.name $USER_NAME") - git4idea.test.GitExecutor.git("config user.email $USER_EMAIL") + git("config user.name $USER_NAME") + git("config user.email $USER_EMAIL") } public static GitRepository createRepository(String rootDir, GitPlatformFacade platformFacade, Project project) {