Skip to content

Commit

Permalink
Merge pull request #5 from y0ung3r/f/initial
Browse files Browse the repository at this point in the history
Release v0.0.1
  • Loading branch information
y0ung3r authored Nov 19, 2023
2 parents d975cd5 + 3be25ec commit debe0a9
Show file tree
Hide file tree
Showing 43 changed files with 945 additions and 153 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ jobs:
with:
gradle-home-cache-cleanup: true

# Set git config variables
- name: Set Git Config Variables
run: git config --global user.name 'Nikita Velikiy'

# Run tests
- name: Run Tests
run: ./gradlew check
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
.idea
.qodana
build
src/test/testData/hooks
out
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@
# GitGlobalHooksLocator Changelog

## [Unreleased]
### Added
- Initial scaffold created from [IntelliJ Platform Plugin Template](https://github.com/JetBrains/intellij-platform-plugin-template)

## [0.0.1]

- Initial release
28 changes: 4 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,11 @@
[![Version](https://img.shields.io/jetbrains/plugin/v/PLUGIN_ID.svg)](https://plugins.jetbrains.com/plugin/PLUGIN_ID)
[![Downloads](https://img.shields.io/jetbrains/plugin/d/PLUGIN_ID.svg)](https://plugins.jetbrains.com/plugin/PLUGIN_ID)

## Template ToDo list
- [x] Create a new [IntelliJ Platform Plugin Template][template] project.
- [ ] Get familiar with the [template documentation][template].
- [ ] Adjust the [pluginGroup](./gradle.properties), [plugin ID](./src/main/resources/META-INF/plugin.xml) and [sources package](./src/main/kotlin).
- [ ] Adjust the plugin description in `README` (see [Tips][docs:plugin-description])
- [ ] Review the [Legal Agreements](https://plugins.jetbrains.com/docs/marketplace/legal-agreements.html?from=IJPluginTemplate).
- [ ] [Publish a plugin manually](https://plugins.jetbrains.com/docs/intellij/publishing-plugin.html?from=IJPluginTemplate) for the first time.
- [ ] Set the `PLUGIN_ID` in the above README badges.
- [ ] Set the [Plugin Signing](https://plugins.jetbrains.com/docs/intellij/plugin-signing.html?from=IJPluginTemplate) related [secrets](https://github.com/JetBrains/intellij-platform-plugin-template#environment-variables).
- [ ] Set the [Deployment Token](https://plugins.jetbrains.com/docs/marketplace/plugin-upload.html?from=IJPluginTemplate).
- [ ] Click the <kbd>Watch</kbd> button on the top of the [IntelliJ Platform Plugin Template][template] to be notified about releases containing new features and fixes.
## Description

<!-- Plugin description -->
This Fancy IntelliJ Platform Plugin is going to be your implementation of the brilliant ideas that you have.

This specific section is a source for the [plugin.xml](/src/main/resources/META-INF/plugin.xml) file which will be extracted by the [Gradle](/build.gradle.kts) during the build process.

To keep everything working, do not remove `<!-- ... -->` sections.
Intellij plugin to enable or disable global Git hooks
![Git Global Hooks Locator](src/main/resources/description.png)
<!-- Plugin description end -->

## Installation
Expand All @@ -34,11 +21,4 @@ To keep everything working, do not remove `<!-- ... -->` sections.
- Manually:

Download the [latest release](https://github.com/y0ung3r/GitGlobalHooksLocator/releases/latest) and install it manually using
<kbd>Settings/Preferences</kbd> > <kbd>Plugins</kbd> > <kbd>⚙️</kbd> > <kbd>Install plugin from disk...</kbd>


---
Plugin based on the [IntelliJ Platform Plugin Template][template].

[template]: https://github.com/JetBrains/intellij-platform-plugin-template
[docs:plugin-description]: https://plugins.jetbrains.com/docs/intellij/plugin-user-experience.html#plugin-description-and-presentation
<kbd>Settings/Preferences</kbd> > <kbd>Plugins</kbd> > <kbd>⚙️</kbd> > <kbd>Install plugin from disk...</kbd>
3 changes: 1 addition & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ pluginVersion = 0.0.1

# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
pluginSinceBuild = 223
pluginUntilBuild = 233.*

# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
platformType = IC
Expand All @@ -19,7 +18,7 @@ platformVersion = 2022.3.3
platformPlugins =

# Gradle Releases -> https://github.com/gradle/gradle/releases
gradleVersion = 8.4
gradleVersion = 9.0

# Opt-out flag for bundling Kotlin standard library -> https://jb.gg/intellij-platform-kotlin-stdlib
kotlin.stdlib.default.dependency = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import org.jetbrains.annotations.NonNls
import org.jetbrains.annotations.PropertyKey

@NonNls
private const val BUNDLE = "messages.MyBundle"
private const val BUNDLE = "messages.LocatorBundle"

object MyBundle : DynamicBundle(BUNDLE) {
object LocatorBundle : DynamicBundle(BUNDLE) {

@JvmStatic
fun message(@PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any) =

Check warning on line 13 in src/main/kotlin/com/github/y0ung3r/gitglobalhookslocator/LocatorBundle.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unused symbol

Function "message" is never used
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.github.y0ung3r.gitglobalhookslocator.git

import com.github.y0ung3r.gitglobalhookslocator.git.cli.DefaultCliCommandExecutor
import com.github.y0ung3r.gitglobalhookslocator.git.cli.NotFoundCliResponse
import com.github.y0ung3r.gitglobalhookslocator.git.exceptions.GitCommandNotFoundException
import com.github.y0ung3r.gitglobalhookslocator.git.exceptions.GitIsNotInstalledException
import com.github.y0ung3r.gitglobalhookslocator.git.exceptions.GitVersionIsNotSupportedException
import com.github.y0ung3r.gitglobalhookslocator.git.extensions.toGitResponse
import com.github.y0ung3r.gitglobalhookslocator.git.cli.interfaces.CliCommandExecutor

class Git(private val commandExecutor: CliCommandExecutor) {
companion object {
private const val GIT_COMMAND = "git"
private const val GIT_VERSION_COMMAND = "version"
const val GIT_CONFIG_COMMAND = "config"
const val GIT_GLOBAL_COMMAND = "--global"
const val GIT_CONFIG_GET_COMMAND = "--get"
const val GIT_HOOKS_PATH_SECTION = "core.hooksPath"

@JvmStatic
val minRequiredVersion = SemanticVersion(2, 9, 0)

@JvmStatic
val instance = Git(DefaultCliCommandExecutor())
}

init {
if (getInstalledVersion() < minRequiredVersion) {
throw GitVersionIsNotSupportedException()
}
}

fun executeCommand(vararg params: String): GitResponse {
val processBuilder = ProcessBuilder(
ArrayList<String>().apply {
add(GIT_COMMAND)
addAll(params)
}
)

processBuilder.redirectErrorStream(true)

return when (val response = commandExecutor.execute(processBuilder)) {
is NotFoundCliResponse -> throw GitCommandNotFoundException(*params)
else -> response.toGitResponse()
}
}

fun getInstalledVersion() : SemanticVersion {
val installedVersion = executeCommand(GIT_VERSION_COMMAND)

return when {
!installedVersion.isEmpty() -> SemanticVersion.parse(installedVersion.value)
else -> throw GitIsNotInstalledException()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.github.y0ung3r.gitglobalhookslocator.git

import com.github.y0ung3r.gitglobalhookslocator.git.cli.CliResponse
import com.github.y0ung3r.gitglobalhookslocator.git.cli.EmptyCliResponse

class GitResponse(private val cliResponse: CliResponse) {
val value = cliResponse.value
fun isEmpty() = cliResponse is EmptyCliResponse
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.github.y0ung3r.gitglobalhookslocator.git

import com.github.y0ung3r.gitglobalhookslocator.git.exceptions.HookNotFoundException
import java.io.File
import java.nio.file.Path

class HookEntry(private var file: File) {
companion object {
@JvmStatic
fun load(filePath: Path): HookEntry {
val file = filePath.toFile()

if (!file.exists()) {
throw HookNotFoundException(file.name.toString())
}

return HookEntry(file)
}
}

val name: String
= HooksFolder
.availableHooks
.first { file.nameWithoutExtension.contains(it) }

fun isDisabled()
= HooksFolder
.availableHooks
.all { it != file.nameWithoutExtension }

fun enable() {
if (!isDisabled()) {
return
}

renameFile(name)
}

fun disable() {
if (isDisabled()) {
return
}

renameFile("_${file.name}")
}

private fun renameFile(newName: String) {
file = Path
.of(file.parent, newName)
.toFile()
.let {
file.renameTo(it)
it
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.github.y0ung3r.gitglobalhookslocator.git

import com.github.y0ung3r.gitglobalhookslocator.git.extensions.getGlobalHooksPath
import com.intellij.openapi.diagnostic.thisLogger
import java.nio.file.Files
import java.nio.file.Path
import kotlin.io.path.nameWithoutExtension
import java.nio.file.NoSuchFileException

class HooksFolder(git: Git) {
companion object {
@JvmStatic
val availableHooks = arrayOf(
"pre-commit",
"prepare-commit-msg",
"commit-msg",
"post-commit",
"applypatch-msg",
"pre-applypatch",
"post-applypatch",
"pre-rebase",
"post-rewrite",
"post-checkout",
"post-merge",
"pre-push",
"pre-auto-gc"
)
}

val hooks: List<HookEntry>
val path: Path

fun isEmpty(): Boolean
= hooks.isEmpty()

init {
path = Path.of(git.getGlobalHooksPath())

val files = try {
Files.list(path)
}
catch (exception: NoSuchFileException) {
thisLogger()
.info("Provided hooks path doesn't exists", exception)

emptyList<Path>()
.stream()
}

hooks = files
.filter {
availableHooks
.any { hookName ->
it.fileName.nameWithoutExtension.contains(hookName) }
}
.map { HookEntry.load(it) }
.toList()
}

fun isAllDisabled()
= hooks.all { it.isDisabled() }

fun enableAll()
= hooks.forEach { it.enable() }

fun disableAll()
= hooks.forEach { it.disable() }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.github.y0ung3r.gitglobalhookslocator.git

import com.github.y0ung3r.gitglobalhookslocator.git.exceptions.ProvidedSemanticVersionIsInvalidException

class SemanticVersion(val major: Int, val minor: Int, val patch: Int) : Comparable<SemanticVersion> {

Check notice on line 5 in src/main/kotlin/com/github/y0ung3r/gitglobalhookslocator/git/SemanticVersion.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Class member can have 'private' visibility

Property 'major' could be private

Check notice on line 5 in src/main/kotlin/com/github/y0ung3r/gitglobalhookslocator/git/SemanticVersion.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Class member can have 'private' visibility

Property 'minor' could be private

Check notice on line 5 in src/main/kotlin/com/github/y0ung3r/gitglobalhookslocator/git/SemanticVersion.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Class member can have 'private' visibility

Property 'patch' could be private
companion object {
private const val COMPONENTS_DELIMITER = '.'
private const val VERSION_PATTERN = "(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)?"

@JvmStatic
fun parse(version: String): SemanticVersion {
val match = Regex(VERSION_PATTERN).findAll(version).firstOrNull()
?: throw ProvidedSemanticVersionIsInvalidException(version)

return match.value.split(COMPONENTS_DELIMITER).let {
SemanticVersion(it[0].toInt(), it[1].toInt(), it[2].toInt())
}
}
}

override fun compareTo(other: SemanticVersion): Int =
when {
major > other.major -> 1
major < other.major -> -1
minor > other.minor -> 1
minor < other.minor -> -1
patch > other.patch -> 1
patch < other.patch -> -1
else -> 0
}

override fun equals(other: Any?): Boolean {
val version = other as? SemanticVersion

return when {
version == null -> false
compareTo(version) == 0 -> true
else -> false
}
}

override fun hashCode(): Int
= major.hashCode() * 31 + minor.hashCode() * 31 + patch.hashCode()

override fun toString(): String
= "$major.$minor.$patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.github.y0ung3r.gitglobalhookslocator.git.cli

open class CliResponse(value: String) {
val value: String = value.trim()
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.github.y0ung3r.gitglobalhookslocator.git.cli

import com.github.y0ung3r.gitglobalhookslocator.git.cli.interfaces.CliCommandExecutor
import java.io.BufferedReader
import java.io.InputStreamReader
import java.nio.charset.StandardCharsets

class DefaultCliCommandExecutor : CliCommandExecutor {
private companion object {
const val TERMINATION_EXIT_CODE = 0
}

override fun execute(processBuilder: ProcessBuilder) : CliResponse {
val process = processBuilder.start()
val streamReader = InputStreamReader(process.inputStream, StandardCharsets.UTF_8)
val bufferedReader = BufferedReader(streamReader)

val response = StringBuilder()
var line: String? = bufferedReader.readLine()

while (line != null) {
response.append(line)
response.append(System.lineSeparator())
line = bufferedReader.readLine()
}

return when (process.waitFor()) {
TERMINATION_EXIT_CODE -> CliResponse(response.toString())
else -> NotFoundCliResponse(response.toString())
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.github.y0ung3r.gitglobalhookslocator.git.cli

class EmptyCliResponse
: CliResponse("")
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.github.y0ung3r.gitglobalhookslocator.git.cli

class NotFoundCliResponse(details: String)
: CliResponse(details)
Loading

0 comments on commit debe0a9

Please sign in to comment.