diff --git a/platform/platform-api/src/com/intellij/execution/configurations/LowPriorityProcessRunner.kt b/platform/platform-api/src/com/intellij/execution/configurations/LowPriorityProcessRunner.kt new file mode 100644 index 000000000000..b96f141bf900 --- /dev/null +++ b/platform/platform-api/src/com/intellij/execution/configurations/LowPriorityProcessRunner.kt @@ -0,0 +1,41 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.execution.configurations + +import com.intellij.openapi.util.SystemInfo +import com.intellij.openapi.util.registry.Registry +import java.io.File + +/** + * @author yole + */ +fun setupLowPriorityExecution(commandLine: GeneralCommandLine, executablePath: String) { + if (!canRunLowPriority()) { + commandLine.exePath = executablePath + } + else { + if (SystemInfo.isWindows) { + // TODO + } + else { + commandLine.exePath = "/usr/bin/nice" + commandLine.addParameter("-n") + commandLine.addParameter("10") + commandLine.addParameter(executablePath) + } + } +} + +private fun canRunLowPriority(): Boolean { + if (!Registry.`is`("ide.allow.low.priority.process")) { + return false + } + if (SystemInfo.isWindows) { + return false + } + else { + if (!niceExists) return false + } + return true +} + +private val niceExists by lazy { File("/usr/bin/nice").exists() } diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 3ae5530f20a3..82072a1d08a6 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -882,6 +882,8 @@ run.processes.with.pty=false kill.windows.processes.softly=false output.reader.blocking.mode=false disable.winp=false +ide.allow.low.priority.process=true +ide.allow.low.priority.process.description=Allow running external processes with low priority when used for background operations ide.certificate.manager=true diff --git a/plugins/git4idea/src/git4idea/commands/GitHandler.java b/plugins/git4idea/src/git4idea/commands/GitHandler.java index d9c8c763e149..0feeb82c068f 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHandler.java +++ b/plugins/git4idea/src/git4idea/commands/GitHandler.java @@ -1,22 +1,9 @@ -/* - * Copyright 2000-2016 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package git4idea.commands; import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.GeneralCommandLine; +import com.intellij.execution.configurations.LowPriorityProcessRunnerKt; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; @@ -56,6 +43,7 @@ public abstract class GitHandler { private static final Logger TIME_LOG = Logger.getInstance("#time." + GitHandler.class.getName()); private final Project myProject; + @NotNull private final String myPathToExecutable; private final GitCommand myCommand; private boolean myPreValidateExecutable = true; @@ -88,11 +76,27 @@ public abstract class GitHandler { @NotNull File directory, @NotNull GitCommand command, @NotNull List configParameters) { + this(project, directory, command, configParameters, false); + } + + /** + * A constructor + * @param project a project + * @param directory a process directory + * @param command a command to execute + * @param lowPriorityProcess + */ + protected GitHandler(@NotNull Project project, + @NotNull File directory, + @NotNull GitCommand command, + @NotNull List configParameters, + boolean lowPriorityProcess) { this(project, directory, GitExecutableManager.getInstance().getPathToGit(project), command, - configParameters); + configParameters, + lowPriorityProcess); myProgressParameterAllowed = GitVersionSpecialty.ABLE_TO_USE_PROGRESS_IN_REMOTE_COMMANDS.existsIn(project); } @@ -108,31 +112,55 @@ public abstract class GitHandler { @NotNull VirtualFile vcsRoot, @NotNull GitCommand command, @NotNull List configParameters) { - this(project, VfsUtil.virtualToIoFile(vcsRoot), command, configParameters); + this(project, vcsRoot, command, configParameters, false); + } + + /** + * A constructor + * @param project a project + * @param vcsRoot a process directory + * @param command a command to execute + * @param lowPriorityProcess + */ + protected GitHandler(@NotNull Project project, + @NotNull VirtualFile vcsRoot, + @NotNull GitCommand command, + @NotNull List configParameters, + boolean lowPriorityProcess) { + this(project, VfsUtil.virtualToIoFile(vcsRoot), command, configParameters, lowPriorityProcess); } /** * A constructor for handler that can be run without project association - * - * @param project optional project + * @param project optional project * @param directory working directory * @param pathToExecutable path to git executable * @param command git command to execute * @param configParameters list of config parameters to use for this git execution + * @param lowPriorityProcess if true, the git process is started with low priority */ protected GitHandler(@Nullable Project project, @NotNull File directory, @NotNull String pathToExecutable, @NotNull GitCommand command, - @NotNull List configParameters) { + @NotNull List configParameters, + boolean lowPriorityProcess) { myProject = project; myVcs = project != null ? GitVcs.getInstance(project) : null; + myPathToExecutable = pathToExecutable; myCommand = command; myCommandLine = new GeneralCommandLine() .withWorkDirectory(directory) - .withExePath(pathToExecutable) .withCharset(CharsetToolkit.UTF8_CHARSET); + + if (lowPriorityProcess) { + LowPriorityProcessRunnerKt.setupLowPriorityExecution(myCommandLine, pathToExecutable); + } + else { + myCommandLine.setExePath(pathToExecutable); + } + for (String parameter : getConfigParameters(project, configParameters)) { myCommandLine.addParameters("-c", parameter); } @@ -180,7 +208,7 @@ public abstract class GitHandler { @NotNull String getExecutablePath() { - return myCommandLine.getExePath(); + return myPathToExecutable; } @NotNull diff --git a/plugins/git4idea/src/git4idea/commands/GitLineHandler.java b/plugins/git4idea/src/git4idea/commands/GitLineHandler.java index f9ac471fbfb5..14cc09b87ee7 100644 --- a/plugins/git4idea/src/git4idea/commands/GitLineHandler.java +++ b/plugins/git4idea/src/git4idea/commands/GitLineHandler.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2009 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package git4idea.commands; import com.intellij.execution.ExecutionException; @@ -70,7 +56,15 @@ public class GitLineHandler extends GitTextHandler { @NotNull VirtualFile vcsRoot, @NotNull GitCommand command, @NotNull List configParameters) { - super(project, vcsRoot, command, configParameters); + this(project, vcsRoot, command, configParameters, false); + } + + public GitLineHandler(@NotNull Project project, + @NotNull VirtualFile vcsRoot, + @NotNull GitCommand command, + @NotNull List configParameters, + boolean lowPriorityProcess) { + super(project, vcsRoot, command, configParameters, lowPriorityProcess); } public GitLineHandler(@Nullable Project project, diff --git a/plugins/git4idea/src/git4idea/commands/GitTextHandler.java b/plugins/git4idea/src/git4idea/commands/GitTextHandler.java index 49f088b82bbf..5e0ae4c5ede9 100644 --- a/plugins/git4idea/src/git4idea/commands/GitTextHandler.java +++ b/plugins/git4idea/src/git4idea/commands/GitTextHandler.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2016 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package git4idea.commands; import com.intellij.execution.ExecutionException; @@ -57,7 +43,15 @@ public abstract class GitTextHandler extends GitHandler { @NotNull VirtualFile vcsRoot, @NotNull GitCommand command, List configParameters) { - super(project, vcsRoot, command, configParameters); + this(project, vcsRoot, command, configParameters, false); + } + + protected GitTextHandler(@NotNull Project project, + @NotNull VirtualFile vcsRoot, + @NotNull GitCommand command, + List configParameters, + boolean lowPriorityProcess) { + super(project, vcsRoot, command, configParameters, lowPriorityProcess); } public GitTextHandler(@Nullable Project project, @@ -65,7 +59,7 @@ public abstract class GitTextHandler extends GitHandler { @NotNull String pathToExecutable, @NotNull GitCommand command, @NotNull List configParameters) { - super(project, directory, pathToExecutable, command, configParameters); + super(project, directory, pathToExecutable, command, configParameters, false); } @Nullable diff --git a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java index 6b187c02fc28..d33f8ccbfacc 100644 --- a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java +++ b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2014 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package git4idea.history; import com.intellij.openapi.project.Project; @@ -260,7 +246,7 @@ public class GitHistoryUtils { @NotNull VirtualFile root, @NotNull Consumer commitConsumer, @NotNull String... parameters) throws VcsException { - GitLogUtil.readFullDetails(project, root, commitConsumer, true, true, parameters); + GitLogUtil.readFullDetails(project, root, commitConsumer, true, true, false, parameters); } public static long getAuthorTime(@NotNull Project project, @NotNull FilePath path, @NotNull String commitsId) throws VcsException { diff --git a/plugins/git4idea/src/git4idea/history/GitLogUtil.java b/plugins/git4idea/src/git4idea/history/GitLogUtil.java index b07ea6cbfe5e..3ca176701a92 100644 --- a/plugins/git4idea/src/git4idea/history/GitLogUtil.java +++ b/plugins/git4idea/src/git4idea/history/GitLogUtil.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package git4idea.history; import com.intellij.openapi.application.ReadAction; @@ -109,7 +95,7 @@ public class GitLogUtil { return; } - GitLineHandler handler = createGitHandler(project, root); + GitLineHandler handler = createGitHandler(project, root, Collections.emptyList(), true); GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.NONE, HASH, PARENTS, COMMIT_TIME, AUTHOR_NAME, AUTHOR_EMAIL, REF_NAMES); handler.setStdoutSuppressed(true); @@ -149,6 +135,7 @@ public class GitLogUtil { @NotNull public static VcsLogProvider.DetailedLogData collectMetadata(@NotNull Project project, @NotNull VirtualFile root, + boolean lowPriorityProcess, String... params) throws VcsException { VcsLogObjectsFactory factory = getObjectsFactoryWithDisposeCheck(project); if (factory == null) { @@ -156,7 +143,7 @@ public class GitLogUtil { } Set refs = new OpenTHashSet<>(GitLogProvider.DONT_CONSIDER_SHA); List commits = - collectMetadata(project, root, record -> { + collectMetadata(project, root, lowPriorityProcess, record -> { GitCommit commit = createCommit(project, root, Collections.singletonList(record), factory); Collection refsInRecord = parseRefs(record.getRefs(), commit.getId(), factory, root); for (VcsRef ref : refsInRecord) { @@ -173,13 +160,14 @@ public class GitLogUtil { @NotNull private static List collectMetadata(@NotNull Project project, @NotNull VirtualFile root, + boolean lowPriorityProcess, @NotNull NullableFunction converter, String... parameters) throws VcsException { List commits = ContainerUtil.newArrayList(); try { - GitLineHandler handler = createGitHandler(project, root, createConfigParameters(false, false, DiffRenameLimit.GIT_CONFIG)); + GitLineHandler handler = createGitHandler(project, root, createConfigParameters(false, false, DiffRenameLimit.GIT_CONFIG), lowPriorityProcess); readRecordsFromHandler(project, root, true, false, record -> commits.add(converter.fun(record)), handler, parameters); } catch (VcsException e) { @@ -232,7 +220,7 @@ public class GitLogUtil { List commits = ContainerUtil.newArrayList(); try { - readFullDetails(project, root, commits::add, true, true, parameters); + readFullDetails(project, root, commits::add, true, true, false, parameters); } catch (VcsException e) { if (commits.isEmpty()) { @@ -248,10 +236,10 @@ public class GitLogUtil { @NotNull Consumer commitConsumer, boolean includeRootChanges, boolean preserverOrder, - @NotNull String... parameters) throws VcsException { + boolean lowPriorityProcess, @NotNull String... parameters) throws VcsException { DiffRenameLimit renameLimit = DiffRenameLimit.REGISTRY; - GitLineHandler handler = createGitHandler(project, root, createConfigParameters(true, includeRootChanges, renameLimit)); + GitLineHandler handler = createGitHandler(project, root, createConfigParameters(true, includeRootChanges, renameLimit), lowPriorityProcess); readFullDetailsFromHandler(project, root, commitConsumer, renameLimit, handler, preserverOrder, parameters); } @@ -343,7 +331,7 @@ public class GitLogUtil { @NotNull List hashes, boolean includeRootChanges, @NotNull DiffRenameLimit renameLimit) throws VcsException { - GitLineHandler handler = createGitHandler(project, root, createConfigParameters(true, includeRootChanges, renameLimit)); + GitLineHandler handler = createGitHandler(project, root, createConfigParameters(true, includeRootChanges, renameLimit), true); sendHashesToStdin(vcs, hashes, handler); readFullDetailsFromHandler(project, root, commitConsumer, renameLimit, handler, false, getNoWalkParameter(vcs), STDIN); @@ -366,14 +354,15 @@ public class GitLogUtil { @NotNull public static GitLineHandler createGitHandler(@NotNull Project project, @NotNull VirtualFile root) { - return createGitHandler(project, root, Collections.emptyList()); + return createGitHandler(project, root, Collections.emptyList(), false); } @NotNull private static GitLineHandler createGitHandler(@NotNull Project project, @NotNull VirtualFile root, - @NotNull List configParameters) { - GitLineHandler handler = new GitLineHandler(project, root, GitCommand.LOG, configParameters); + @NotNull List configParameters, + boolean lowPriorityProcess) { + GitLineHandler handler = new GitLineHandler(project, root, GitCommand.LOG, configParameters, lowPriorityProcess); handler.setWithMediator(false); return handler; } diff --git a/plugins/git4idea/src/git4idea/log/GitLogProvider.java b/plugins/git4idea/src/git4idea/log/GitLogProvider.java index c9839c44f94f..ade730dfd5c3 100644 --- a/plugins/git4idea/src/git4idea/log/GitLogProvider.java +++ b/plugins/git4idea/src/git4idea/log/GitLogProvider.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2013 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package git4idea.log; import com.intellij.openapi.Disposable; @@ -107,7 +93,7 @@ public class GitLogProvider implements VcsLogProvider { boolean refresh = requirements instanceof VcsLogProviderRequirementsEx && ((VcsLogProviderRequirementsEx)requirements).isRefresh(); - DetailedLogData data = GitLogUtil.collectMetadata(myProject, root, params); + DetailedLogData data = GitLogUtil.collectMetadata(myProject, root, true, params); Set safeRefs = data.getRefs(); Set allRefs = new OpenTHashSet<>(safeRefs, DONT_CONSIDER_SHA); @@ -296,7 +282,7 @@ public class GitLogProvider implements VcsLogProvider { Set commits = ContainerUtil.newHashSet(); VcsFileUtil.foreachChunk(new ArrayList<>(unmatchedTags), 1, tagsChunk -> { String[] parameters = ArrayUtil.toStringArray(ContainerUtil.concat(params, tagsChunk)); - DetailedLogData logData = GitLogUtil.collectMetadata(myProject, root, parameters); + DetailedLogData logData = GitLogUtil.collectMetadata(myProject, root, true, parameters); refs.addAll(logData.getRefs()); commits.addAll(logData.getCommits()); }); @@ -330,7 +316,7 @@ public class GitLogProvider implements VcsLogProvider { } GitLogUtil.readFullDetails(myProject, root, commitConsumer, shouldIncludeRootChanges(root), - false, ArrayUtil.toStringArray(GitLogUtil.LOG_ALL)); + false, true, ArrayUtil.toStringArray(GitLogUtil.LOG_ALL)); } @Override diff --git a/plugins/git4idea/src/git4idea/rebase/GitRewordOperation.kt b/plugins/git4idea/src/git4idea/rebase/GitRewordOperation.kt index c0c55a5da0e5..484ff1121344 100644 --- a/plugins/git4idea/src/git4idea/rebase/GitRewordOperation.kt +++ b/plugins/git4idea/src/git4idea/rebase/GitRewordOperation.kt @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package git4idea.rebase import com.intellij.notification.NotificationAction @@ -163,7 +149,7 @@ class GitRewordOperation(private val repository: GitRepository, private fun findNewHashOfRewordedCommit(newHead: String): Hash? { val newCommitsRange = "${commit.parents.first().asString()}..$newHead" - val newCommits = GitLogUtil.collectMetadata(project, repository.root, newCommitsRange).commits + val newCommits = GitLogUtil.collectMetadata(project, repository.root, false, newCommitsRange).commits if (newCommits.isEmpty()) { LOG.error("Couldn't find commits after reword in range $newCommitsRange") return null diff --git a/plugins/git4idea/tests/git4idea/log/GitLogUtilTest.kt b/plugins/git4idea/tests/git4idea/log/GitLogUtilTest.kt index a4ad3a88bed5..e498469d75cf 100644 --- a/plugins/git4idea/tests/git4idea/log/GitLogUtilTest.kt +++ b/plugins/git4idea/tests/git4idea/log/GitLogUtilTest.kt @@ -25,7 +25,7 @@ class GitLogUtilTest : GitSingleRepoTest() { touch("file.txt", "content") repo.addCommit(message) - GitLogUtil.readFullDetails(myProject, repo.root, CollectConsumer(details), true, true) + GitLogUtil.readFullDetails(myProject, repo.root, CollectConsumer(details), true, true, true) val lastCommit = ContainerUtil.getFirstItem(details) assertNotNull(lastCommit) diff --git a/plugins/git4idea/tests/git4idea/test/GitTestAssertions.kt b/plugins/git4idea/tests/git4idea/test/GitTestAssertions.kt index 7fad7e11f4f2..40d390d23e67 100644 --- a/plugins/git4idea/tests/git4idea/test/GitTestAssertions.kt +++ b/plugins/git4idea/tests/git4idea/test/GitTestAssertions.kt @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package git4idea.test import com.intellij.openapi.application.ApplicationManager @@ -64,7 +50,7 @@ fun GitRepository.assertLatestSubjects(vararg expectedMessages: String) { } private fun GitRepository.assertLatestHistory(mapping: (VcsCommitMetadata) -> String, vararg expectedMessages: String) { - val actualMessages = GitLogUtil.collectMetadata(project, root).commits + val actualMessages = GitLogUtil.collectMetadata(project, root, false).commits .map(mapping) .subList(0, expectedMessages.size) assertOrderedEquals("History is incorrect", actualMessages, expectedMessages.asList())