Skip to content

Commit 3be206a

Browse files
authored
Introduce a way to see skipped worktree files (#6)
1 parent becbc46 commit 3be206a

17 files changed

+678
-13
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ It adds the support for the next subcommands:
1818

1919
![New items in the git context menu](screenshots/screenshot_2.png)
2020

21+
![Show Skipped Worktree option](screenshots/screenshot_3.png)
22+
23+
![Show skipped worktree changes view element](screenshots/screenshot_4.png)
24+
2125
## Release History
2226
* 0.0.5
2327
* Run the commands in a background task (fixes the exception).

screenshots/screenshot_3.png

28 KB
Loading

screenshots/screenshot_4.png

52.2 KB
Loading

src/main/kotlin/com/github/monosoul/git/updateindex/extended/ExtendedUpdateIndexTask.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class ExtendedUpdateIndexTask(
2525
.mapNotNull { fileToVcsRoot(it) }
2626
.groupBy({ (_, vcsRoot) -> vcsRoot }, { (file, _) -> file })
2727
.onEach { (vcsRoot, files) ->
28-
gitLineHandlerFactory(command, vcsRoot, files).runAndLog()
28+
updateIndexLineHandlerFactory(command, vcsRoot, files).runAndLog()
2929
files.forEach(vcsDirtyScopeManager::fileDirty)
3030
}
3131
}
@@ -36,8 +36,8 @@ class ExtendedUpdateIndexTask(
3636
?.let(GitCommandResult::getErrorOutput)
3737
?.forEach(logger::error)
3838

39-
private val Project.gitLineHandlerFactory: GitLineHandlerFactory
40-
get() = getService(GitLineHandlerFactory::class.java)
39+
private val Project.updateIndexLineHandlerFactory: UpdateIndexLineHandlerFactory
40+
get() = getService(UpdateIndexLineHandlerFactory::class.java)
4141

4242
private val Project.vcsDirtyScopeManager: VcsDirtyScopeManager
4343
get() = VcsDirtyScopeManager.getInstance(this)

src/main/kotlin/com/github/monosoul/git/updateindex/extended/GitLineHandlerFactory.kt renamed to src/main/kotlin/com/github/monosoul/git/updateindex/extended/UpdateIndexLineHandlerFactory.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import git4idea.commands.GitCommand.UPDATE_INDEX
99
import git4idea.commands.GitLineHandler
1010

1111
@Service
12-
class GitLineHandlerFactory(private val project: Project) {
12+
class UpdateIndexLineHandlerFactory(private val project: Project) {
1313

1414
private val logger by Slf4j
1515

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.github.monosoul.git.updateindex.extended.changes.view
2+
3+
import com.intellij.openapi.project.Project
4+
import com.intellij.openapi.vcs.FilePath
5+
import com.intellij.openapi.vcs.changes.IgnoredViewDialog
6+
import com.intellij.openapi.vcs.changes.ui.ChangesBrowserNode.Tag
7+
import com.intellij.openapi.vcs.changes.ui.ChangesBrowserSpecificFilePathsNode
8+
9+
class ChangesBrowserSkippedWorktreeNode(
10+
project: Project,
11+
files: Collection<FilePath>
12+
) : ChangesBrowserSpecificFilePathsNode<Tag>(
13+
TagImpl("Skipped Worktree"),
14+
files,
15+
{ if (!project.isDisposed) IgnoredViewDialog(project).show() }
16+
) {
17+
override fun getTextPresentation() = getUserObject().toString()
18+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.github.monosoul.git.updateindex.extended.changes.view
2+
3+
object Constants {
4+
const val PROPERTY = "com.github.monosoul.git-extended-update-index-plugin.showSkipped"
5+
const val SKIPPED_FILE = "S"
6+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.github.monosoul.git.updateindex.extended.changes.view
2+
3+
import com.github.monosoul.git.updateindex.extended.changes.view.Constants.SKIPPED_FILE
4+
import com.intellij.openapi.progress.ProgressIndicator
5+
import com.intellij.openapi.progress.Task.WithResult
6+
import com.intellij.openapi.project.Project
7+
import com.intellij.openapi.vcs.FilePath
8+
import com.intellij.openapi.vcs.ProjectLevelVcsManager
9+
import com.intellij.openapi.vcs.VcsException
10+
import com.intellij.openapi.vcs.VcsRoot
11+
import com.intellij.vcsUtil.VcsUtil
12+
import git4idea.GitUtil
13+
import git4idea.commands.Git
14+
import git4idea.commands.GitAuthenticationMode.NONE
15+
import git4idea.commands.GitCommand.LS_FILES
16+
import git4idea.commands.GitCommandResult
17+
import git4idea.commands.GitLineHandler
18+
19+
class GetSkippedWorktreeFilesTask(
20+
project: Project
21+
) : WithResult<List<FilePath>, RuntimeException>(project, "Getting Skipped Files", false) {
22+
23+
override fun compute(indicator: ProgressIndicator): List<FilePath> {
24+
val vcsManager = ProjectLevelVcsManager.getInstance(project) ?: return emptyList()
25+
26+
return vcsManager.allVcsRoots.map(VcsRoot::getPath).map { vcsRoot ->
27+
GitLineHandler(project, vcsRoot, LS_FILES).apply {
28+
addParameters("-v")
29+
ignoreAuthenticationMode = NONE
30+
}.let(Git.getInstance()::runCommand).mapOrThrow { result ->
31+
result.filter {
32+
it.startsWith(SKIPPED_FILE)
33+
}.map {
34+
it.removePrefix("$SKIPPED_FILE ")
35+
}.map {
36+
VcsUtil.getFilePath(vcsRoot, GitUtil.unescapePath(it))
37+
}
38+
}
39+
}.flatten()
40+
}
41+
42+
@Throws(VcsException::class)
43+
private fun <T> GitCommandResult.mapOrThrow(mapper: (List<String>) -> T): T {
44+
throwOnError()
45+
46+
return mapper(output)
47+
}
48+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.github.monosoul.git.updateindex.extended.changes.view
2+
3+
import com.github.monosoul.git.updateindex.extended.changes.view.Constants.PROPERTY
4+
import com.github.monosoul.git.updateindex.extended.logging.Slf4j
5+
import com.intellij.ide.util.PropertiesComponent
6+
import com.intellij.openapi.progress.ProgressManager
7+
import com.intellij.openapi.project.Project
8+
import com.intellij.openapi.vcs.changes.ChangesViewModifier
9+
import com.intellij.openapi.vcs.changes.ui.ChangesViewModelBuilder
10+
11+
class SkippedWorktreeChangesViewModifier(private val project: Project) : ChangesViewModifier {
12+
13+
private val logger by Slf4j
14+
15+
override fun modifyTreeModelBuilder(modelBuilder: ChangesViewModelBuilder) {
16+
val showSkippedTree = PropertiesComponent.getInstance().getBoolean(PROPERTY, false)
17+
if (!showSkippedTree) {
18+
logger.debug("Show skipped files is turned off. Doing nothing.")
19+
return
20+
}
21+
22+
val skippedFiles = ProgressManager.getInstance().run(GetSkippedWorktreeFilesTask(project))
23+
24+
logger.debug("Skipped files: {}", skippedFiles)
25+
26+
val rootNode = ChangesBrowserSkippedWorktreeNode(project, skippedFiles)
27+
modelBuilder.insertSubtreeRoot(rootNode)
28+
modelBuilder.insertFilesIntoNode(skippedFiles.mapNotNull { it.virtualFile }, rootNode)
29+
}
30+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.github.monosoul.git.updateindex.extended.changes.view
2+
3+
import com.github.monosoul.git.updateindex.extended.changes.view.Constants.PROPERTY
4+
import com.github.monosoul.git.updateindex.extended.logging.Slf4j
5+
import com.github.monosoul.git.updateindex.extended.support.PresentationUpdater
6+
import com.intellij.ide.util.PropertiesComponent
7+
import com.intellij.openapi.actionSystem.AnActionEvent
8+
import com.intellij.openapi.actionSystem.Presentation
9+
import com.intellij.openapi.actionSystem.ToggleAction
10+
import com.intellij.openapi.project.Project
11+
import com.intellij.openapi.vcs.changes.ChangesViewManager
12+
13+
class ToggleSkippedWorktreeAction : ToggleAction() {
14+
15+
private val logger by Slf4j
16+
17+
override fun update(event: AnActionEvent) {
18+
super.update(event)
19+
event.run {
20+
project?.updatePresentation(presentation)
21+
}
22+
}
23+
24+
override fun isSelected(event: AnActionEvent): Boolean {
25+
return PropertiesComponent.getInstance().getBoolean(PROPERTY, false).also {
26+
logger.debug("Get property value: {}", it)
27+
}
28+
}
29+
30+
override fun setSelected(event: AnActionEvent, state: Boolean) {
31+
PropertiesComponent.getInstance().setValue(PROPERTY, state)
32+
logger.debug("Set property value: {}", state)
33+
val project = event.project ?: return
34+
35+
ChangesViewManager.getInstanceEx(project).refreshImmediately()
36+
}
37+
38+
private fun Project.updatePresentation(presentation: Presentation) {
39+
logger.debug("Updating presentation")
40+
getService(PresentationUpdater::class.java)?.invoke(presentation)
41+
}
42+
}

0 commit comments

Comments
 (0)