Code cleanup

This commit is contained in:
Abdelilah El Aissaoui 2023-12-24 21:30:09 +01:00
parent 13f00e22aa
commit 9e31145a86
No known key found for this signature in database
GPG Key ID: 7587FC860F594869
81 changed files with 289 additions and 148 deletions

2
.github/FUNDING.yml vendored
View File

@ -1,6 +1,6 @@
# These are supported funding model platforms
github: [JetpackDuba] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
github: [ JetpackDuba ] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username

View File

@ -2,12 +2,16 @@
## Requirements
- **JDK 17 or higher**: You don't need this if you only use the JDK installed by IntelliJ IDEA. If you want to build using the CLI, check this [section](#alternative-setting-up-jdk-for-use-on-cli).
- **Rust:** Gitnuro is mainly written in Kotlin (JVM) but also uses Rust for some specific tasks. To set up your Rust environment,
please read [its documentation](https://www.rust-lang.org/). `cargo` and `rustc` must be available in the path in order to build Gitnuro properly.
- **JDK 17 or higher**: You don't need this if you only use the JDK installed by IntelliJ IDEA. If you want to build
using the CLI, check this [section](#alternative-setting-up-jdk-for-use-on-cli).
- **Rust:** Gitnuro is mainly written in Kotlin (JVM) but also uses Rust for some specific tasks. To set up your Rust
environment,
please read [its documentation](https://www.rust-lang.org/). `cargo` and `rustc` must be available in the path in
order to build Gitnuro properly.
- **Perl:** Perl is required to build openssl (which is required for LibSSH to work).
- **Packages for Linux ARM64/aarch64**: You need to install the `aarch64-linux-gnu-gcc` package to cross compile the
Rust components to ARM from x86_64. You will also need to use `rustup` to add a new target: `rustup target add aarch64-unknown-linux-gnu`
- **Packages for Linux ARM64/aarch64**: You need to install the `aarch64-linux-gnu-gcc` package to cross compile the
Rust components to ARM from x86_64. You will also need to use `rustup` to add a new
target: `rustup target add aarch64-unknown-linux-gnu`
## Setting up an IDE
@ -16,9 +20,12 @@ If you don't have another preference, the recommendation is to download and inst
(possibly through the JetBrains Toolbox, if you have it already). The recommended plugins to improve the DX are:
- [Compose Multiplatform IDE Support](https://plugins.jetbrains.com/plugin/16541-compose-multiplatform-ide-support)
- [Rust Plugin](https://plugins.jetbrains.com/plugin/8182-rust) (deprecated due to [RustRover IDE](https://blog.jetbrains.com/rust/2023/09/13/introducing-rustrover-a-standalone-rust-ide-by-jetbrains/) but still works).
- [Rust Plugin](https://plugins.jetbrains.com/plugin/8182-rust) (deprecated due
to [RustRover IDE](https://blog.jetbrains.com/rust/2023/09/13/introducing-rustrover-a-standalone-rust-ide-by-jetbrains/)
but still works).
By default, the JDK used by "IntelliJ IDEA Community Edition (2023.1.3)" is "JetBrains Runtime version 21" which is not currently supported by the project.
By default, the JDK used by "IntelliJ IDEA Community Edition (2023.1.3)" is "JetBrains Runtime version 21" which is not
currently supported by the project.
## Alternative: Setting up JDK for use on CLI
@ -32,7 +39,8 @@ sudo apt install openjdk-17-jre openjdk-17-jdk
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
```
Once it works (e.g. `./gradlew build`). On Linux, you may want to add that latter line to your `/etc/environment` or user-specific files such as `.profile` or `.bashrc`.
Once it works (e.g. `./gradlew build`). On Linux, you may want to add that latter line to your `/etc/environment` or
user-specific files such as `.profile` or `.bashrc`.
## Running the app / unit tests

View File

@ -14,8 +14,9 @@ can use it nor relying on web technologies.
Linux:
- Available as Flatpak [here](https://flathub.org/apps/details/com.jetpackduba.Gitnuro) or by
running `flatpak install com.jetpackduba.Gitnuro` if you have Flatpak & Flathub already setup.
- If Flathub is not set up, you can add the source with the following command `flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo`.
running `flatpak install com.jetpackduba.Gitnuro` if you have Flatpak & Flathub already setup.
- If Flathub is not set up, you can add the source with the following
command `flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo`.
- JAR file can be executed as a portable version (Requires JRE 17).
Windows:
@ -139,6 +140,7 @@ it if it's a very requested feature but not for now.
> Authentication has failed. What's wrong?
Currently there are some limitations regarding this topic. Here are some known problematic setups:
- Multicast DNS remote URL (https://github.com/JetpackDuba/Gitnuro/issues/19) with this
workaround (https://github.com/JetpackDuba/Gitnuro/issues/19#issuecomment-1374431720).
- Self signed server certificate (https://github.com/JetpackDuba/Gitnuro/issues/48)

View File

@ -11,10 +11,10 @@ name = "gitnuro_rs"
uniffi = { version = "0.25.0" }
notify = "6.0.1"
thiserror = "1.0.43"
libssh-rs = { version = "0.2.2", features = [ "vendored", "vendored-openssl" ] }
libssh-rs = { version = "0.2.2", features = ["vendored", "vendored-openssl"] }
[build-dependencies]
uniffi = { version = "0.25.0", features = [ "build" ] }
uniffi = { version = "0.25.0", features = ["build"] }
[[bin]]
name = "uniffi-bindgen"

View File

@ -1,9 +1,10 @@
mod ssh;
mod watch_directory;
use watch_directory::{ * };
use ssh::{ * };
#[allow(unused_imports)] // Needed to map it to the enum in the UDL file
use libssh_rs::AuthStatus;
use ssh::{*};
use watch_directory::{*};
mod ssh;
mod watch_directory;
uniffi::include_scaffolding!("gitnuro");

View File

@ -1,6 +1,7 @@
use libssh_rs::{AuthStatus, PollStatus, SshOption};
use std::io::Write;
use std::sync::{Arc, RwLock};
use std::io::{Write};
use libssh_rs::{AuthStatus, PollStatus, SshOption};
const ACCEPTED_SSH_TYPES: &str = "ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-rsa,rsa-sha2-512,rsa-sha2-256,ssh-dss";
@ -63,6 +64,7 @@ pub struct Channel {
}
unsafe impl Send for Channel {}
unsafe impl Sync for Channel {}
impl Channel {
@ -105,7 +107,7 @@ impl Channel {
}
}
pub fn read(&self, is_stderr: bool, len: u64) -> ReadResult {
pub fn read(&self, is_stderr: bool, len: u64) -> ReadResult {
let ulen = len as usize;
let channel = self.channel.write().unwrap();

View File

@ -4,6 +4,7 @@ use std::fmt::Debug;
use std::path::{Path, PathBuf};
use std::sync::mpsc::{channel, RecvTimeoutError};
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use notify::{Config, Error, ErrorKind, Event, RecommendedWatcher, RecursiveMode, Watcher};
const MIN_TIME_IN_MS_BETWEEN_REFRESHES: u128 = 500;

View File

@ -2,7 +2,8 @@
package com.jetpackduba.gitnuro
import androidx.compose.foundation.*
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.LocalTextContextMenu
import androidx.compose.material.MaterialTheme
@ -17,7 +18,9 @@ import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.*
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import androidx.compose.ui.window.rememberWindowState
import com.jetpackduba.gitnuro.di.DaggerAppComponent
import com.jetpackduba.gitnuro.extensions.preferenceValue
import com.jetpackduba.gitnuro.extensions.toWindowPlacement
@ -44,7 +47,6 @@ import java.io.File
import java.net.Authenticator
import java.net.PasswordAuthentication
import java.nio.file.Paths
import java.util.*
import javax.inject.Inject

View File

@ -15,6 +15,7 @@ private const val KEY_LENGTH = 16
class CredentialsCacheRepository @Inject constructor() {
private val credentialsCached = mutableListOf<CredentialsType>()
private val credentialsLock = Mutex(false)
// having a random key to encrypt the password may help in case of a memory dump attack
private val encryptionKey = getRandomKey()

View File

@ -19,7 +19,7 @@ class GSessionManager @Inject constructor(
class MySessionFactory @Inject constructor(
private val sessionProvider: Provider<SshRemoteSession>
) : SshSessionFactory(), CredentialsCache {
) : SshSessionFactory(), CredentialsCache {
override fun getSession(
uri: URIish,
credentialsProvider: CredentialsProvider?,

View File

@ -11,9 +11,7 @@ import org.eclipse.jgit.api.Git
import org.eclipse.jgit.internal.JGitText
import org.eclipse.jgit.lib.Config
import org.eclipse.jgit.transport.CredentialItem
import org.eclipse.jgit.transport.CredentialItem.Password
import org.eclipse.jgit.transport.CredentialItem.Username
import org.eclipse.jgit.transport.CredentialItem.YesNoType
import org.eclipse.jgit.transport.CredentialItem.*
import org.eclipse.jgit.transport.CredentialsProvider
import org.eclipse.jgit.transport.URIish
import java.io.*

View File

@ -1,7 +1,5 @@
package com.jetpackduba.gitnuro.di
import com.jetpackduba.gitnuro.di.modules.NetworkModule
import com.jetpackduba.gitnuro.di.modules.ShellModule
import com.jetpackduba.gitnuro.di.modules.TabModule
import com.jetpackduba.gitnuro.ui.components.TabInformation
import dagger.Component

View File

@ -1,3 +1,3 @@
package com.jetpackduba.gitnuro.exceptions
class FetchException(msg: String): GitnuroException(msg)
class FetchException(msg: String) : GitnuroException(msg)

View File

@ -1,7 +1,10 @@
package com.jetpackduba.gitnuro.extensions
import androidx.compose.foundation.*
import androidx.compose.foundation.gestures.*
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.gestures.waitForUpOrCancellation
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
@ -95,17 +98,17 @@ fun Modifier.onDoubleClick(
@Composable
fun Modifier.onMiddleMouseButtonClick(key: Any = Unit, key2: Any = Unit, onClick: () -> Unit) =
this.pointerInput(key, key2) {
while (true) {
val lastMouseEvent = awaitPointerEventScope { awaitFirstDownEvent() }
val mouseEvent = lastMouseEvent.awtEventOrNull
while (true) {
val lastMouseEvent = awaitPointerEventScope { awaitFirstDownEvent() }
val mouseEvent = lastMouseEvent.awtEventOrNull
if (mouseEvent != null) {
if (lastMouseEvent.button.isTertiary) {
onClick()
}
if (mouseEvent != null) {
if (lastMouseEvent.button.isTertiary) {
onClick()
}
}
}
}
@Composable
private fun Modifier.hoverBackground(): Modifier {

View File

@ -1,7 +1,7 @@
package com.jetpackduba.gitnuro.git
import com.jetpackduba.gitnuro.managers.TempFilesManager
import com.jetpackduba.gitnuro.extensions.fileName
import com.jetpackduba.gitnuro.managers.TempFilesManager
import org.eclipse.jgit.diff.ContentSource
import org.eclipse.jgit.diff.DiffEntry
import org.eclipse.jgit.diff.RawText

View File

@ -1,7 +1,6 @@
package com.jetpackduba.gitnuro.git
import com.jetpackduba.gitnuro.ui.SelectedItem
import org.eclipse.jgit.revwalk.RevCommit
sealed interface TaskEvent {
data class ScrollToGraphItem(val selectedItem: SelectedItem) : TaskEvent

View File

@ -2,7 +2,6 @@ package com.jetpackduba.gitnuro.git.branches
import com.jetpackduba.gitnuro.extensions.simpleName
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.lib.Config
import org.eclipse.jgit.lib.Ref
import org.eclipse.jgit.lib.Repository
import org.eclipse.jgit.lib.StoredConfig

View File

@ -10,7 +10,8 @@ object LocalConfigConstants {
const val DEFAULT_SIGN_OFF_FORMAT_USER = "%user"
const val DEFAULT_SIGN_OFF_FORMAT_EMAIL = "%email"
const val DEFAULT_SIGN_OFF_FORMAT = "Signed-off-by: $DEFAULT_SIGN_OFF_FORMAT_USER <$DEFAULT_SIGN_OFF_FORMAT_EMAIL>"
const val DEFAULT_SIGN_OFF_FORMAT =
"Signed-off-by: $DEFAULT_SIGN_OFF_FORMAT_USER <$DEFAULT_SIGN_OFF_FORMAT_EMAIL>"
const val DEFAULT_SIGN_OFF_ENABLED = false
}
}

View File

@ -7,7 +7,7 @@ import org.eclipse.jgit.submodule.SubmoduleStatus
sealed class DiffResult(
val diffEntry: DiffEntry,
) {
sealed class TextDiff(diffEntry: DiffEntry): DiffResult(diffEntry)
sealed class TextDiff(diffEntry: DiffEntry) : DiffResult(diffEntry)
class Text(
diffEntry: DiffEntry,

View File

@ -54,7 +54,7 @@ class GetLogUseCase @Inject constructor() {
private fun cachedGraphWalk(repository: Repository): GraphWalk {
val graphWalkCached = this.graphWalkCached
return if(graphWalkCached != null) {
return if (graphWalkCached != null) {
graphWalkCached
} else {
val newGraphWalk = GraphWalk(repository)

View File

@ -23,6 +23,7 @@ class GetRebaseInteractiveStateUseCase @Inject constructor(
RebaseInteractiveState.ProcessingCommits(commitId)
}
else -> RebaseInteractiveState.AwaitingInteraction
}
}

View File

@ -1,7 +1,6 @@
package com.jetpackduba.gitnuro.git.remote_operations
import com.jetpackduba.gitnuro.exceptions.FetchException
import com.jetpackduba.gitnuro.exceptions.GitnuroException
import com.jetpackduba.gitnuro.logging.printError
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
@ -48,13 +47,13 @@ class FetchAllBranchesUseCase @Inject constructor(
} catch (ex: Exception) {
printError(TAG, "Fetch failed for remote ${remote.name} with error ${ex.message}", ex)
if(ex.message != "Cancelled authentication" && ex !is CancellationException) {
errors.add(remote to ex)
if (ex.message != "Cancelled authentication" && ex !is CancellationException) {
errors.add(remote to ex)
}
}
}
if(errors.isNotEmpty()) {
if (errors.isNotEmpty()) {
val errorText = errors.joinToString("\n") {
"Fetch failed for remote ${it.first.name}: ${it.second.message}"
}

View File

@ -15,7 +15,7 @@ class HandleTransportUseCase @Inject constructor(
suspend operator fun invoke(git: Git?, block: suspend CredentialsHandler.() -> Unit) {
var cache: CredentialsCache? = null
val credentialsHandler = object: CredentialsHandler {
val credentialsHandler = object : CredentialsHandler {
override fun handleTransport(transport: Transport?) {
cache = when (transport) {
is SshTransport -> {
@ -41,6 +41,7 @@ class HandleTransportUseCase @Inject constructor(
cache?.cacheCredentialsIfNeeded()
}
}
interface CredentialsCache {
suspend fun cacheCredentialsIfNeeded()
}

View File

@ -4,7 +4,6 @@ import com.jetpackduba.gitnuro.preferences.AppSettings
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.api.PullResult
import org.eclipse.jgit.api.RebaseResult
import org.eclipse.jgit.transport.CredentialsProvider
import javax.inject.Inject
@ -23,7 +22,7 @@ class PullBranchUseCase @Inject constructor(
handleTransportUseCase(git) {
val pullResult = git
.pull()
.setTransportConfigCallback {this.handleTransport(it) }
.setTransportConfigCallback { this.handleTransport(it) }
.setRebase(pullWithRebase)
.setCredentialsProvider(CredentialsProvider.getDefault())
.call()

View File

@ -18,7 +18,8 @@ class OpenSubmoduleRepositoryUseCase @Inject constructor(
val repository = openRepositoryUseCase(parent)
val submoduleRelativePath = directory.absolutePath.removePrefix("${repository.directory.parent}$systemSeparator")
val submoduleRelativePath =
directory.absolutePath.removePrefix("${repository.directory.parent}$systemSeparator")
return@withContext SubmoduleWalk.getSubmoduleRepository(repository, submoduleRelativePath)
?: throw InvalidDirectoryException("Invalid submodule directory. Check if the submodule has been initialized before trying to open it.")

View File

@ -3,7 +3,6 @@ package com.jetpackduba.gitnuro.git.submodules
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.lib.Config
import org.eclipse.jgit.storage.file.FileBasedConfig
import java.io.File
import javax.inject.Inject

View File

@ -25,7 +25,7 @@ class DoCommitUseCase @Inject constructor(
): RevCommit = withContext(Dispatchers.IO) {
val signOffConfig = loadSignOffConfigUseCase(git.repository)
val finalMessage = if(signOffConfig.isEnabled) {
val finalMessage = if (signOffConfig.isEnabled) {
val authorToSign = author ?: loadAuthorUseCase(git).toPersonIdent()
val signature = signOffConfig.format

View File

@ -1,6 +1,5 @@
package com.jetpackduba.gitnuro.git.workspace
import com.jetpackduba.gitnuro.extensions.lineDelimiter
import com.jetpackduba.gitnuro.git.diff.Hunk
import com.jetpackduba.gitnuro.git.diff.LineType
import kotlinx.coroutines.Dispatchers

View File

@ -1,8 +1,8 @@
package com.jetpackduba.gitnuro.managers
import com.jetpackduba.gitnuro.logging.printError
import com.jetpackduba.gitnuro.system.OS
import com.jetpackduba.gitnuro.system.currentOs
import com.jetpackduba.gitnuro.logging.printError
import java.io.File
import javax.inject.Inject

View File

@ -1,6 +1,5 @@
package com.jetpackduba.gitnuro.managers
import com.jetpackduba.gitnuro.di.TabScope
import com.jetpackduba.gitnuro.extensions.openDirectory
import java.io.File
import javax.inject.Inject

View File

@ -1,9 +1,5 @@
package com.jetpackduba.gitnuro.models
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.withContext
import org.eclipse.jgit.lib.ProgressMonitor
sealed interface ProgressMonitorInfo {
object Loading : ProgressMonitorInfo

View File

@ -40,7 +40,12 @@ class OpenFilePickerUseCase @Inject constructor(
if (isZenityInstalled) {
val command = when (pickerType) {
PickerType.FILES, PickerType.FILES_AND_DIRECTORIES -> listOf("zenity", "--file-selection", "--title=Open")
PickerType.FILES, PickerType.FILES_AND_DIRECTORIES -> listOf(
"zenity",
"--file-selection",
"--title=Open"
)
PickerType.DIRECTORIES -> listOf("zenity", "--file-selection", "--title=Open", "--directory")
}

View File

@ -19,6 +19,9 @@ class MacTerminalProvider @Inject constructor(
override fun startTerminal(terminalEmulator: TerminalEmulator, repositoryPath: String) {
// TODO Check if passing the path as argument is required for other terminal emulators
shellManager.runCommandInPath(listOf("open", "-a", terminalEmulator.path, "-n", "--args", repositoryPath), repositoryPath)
shellManager.runCommandInPath(
listOf("open", "-a", terminalEmulator.path, "-n", "--args", repositoryPath),
repositoryPath
)
}
}

View File

@ -1,7 +1,6 @@
package com.jetpackduba.gitnuro.terminal
import com.jetpackduba.gitnuro.managers.IShellManager
import java.io.File
import javax.inject.Inject
class WindowsTerminalProvider @Inject constructor(

View File

@ -27,7 +27,9 @@ import androidx.compose.ui.input.key.type
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import com.jetpackduba.gitnuro.AppIcons
import com.jetpackduba.gitnuro.extensions.*
import com.jetpackduba.gitnuro.extensions.handOnHover
import com.jetpackduba.gitnuro.extensions.lineAt
import com.jetpackduba.gitnuro.extensions.toStringWithSpaces
import com.jetpackduba.gitnuro.keybindings.KeybindingOption
import com.jetpackduba.gitnuro.keybindings.matchesBinding
import com.jetpackduba.gitnuro.theme.notoSansMonoFontFamily

View File

@ -1,11 +1,14 @@
package com.jetpackduba.gitnuro.ui
import androidx.compose.foundation.*
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
@ -23,7 +26,9 @@ import androidx.compose.ui.unit.dp
import com.jetpackduba.gitnuro.AppIcons
import com.jetpackduba.gitnuro.extensions.*
import com.jetpackduba.gitnuro.git.DiffEntryType
import com.jetpackduba.gitnuro.theme.*
import com.jetpackduba.gitnuro.theme.backgroundSelected
import com.jetpackduba.gitnuro.theme.onBackgroundSecondary
import com.jetpackduba.gitnuro.theme.tertiarySurface
import com.jetpackduba.gitnuro.ui.components.*
import com.jetpackduba.gitnuro.ui.context_menu.ContextMenu
import com.jetpackduba.gitnuro.ui.context_menu.committedChangesEntriesContextMenuItems

View File

@ -21,10 +21,10 @@ import com.jetpackduba.gitnuro.ui.dropdowns.DropDownOption
@Composable
fun FilterDropdownPreview() {
val items = listOf(
DropDownOption("","Test1"),
DropDownOption("","Test2"),
DropDownOption("","Test3"),
DropDownOption("","Test4"),
DropDownOption("", "Test1"),
DropDownOption("", "Test2"),
DropDownOption("", "Test3"),
DropDownOption("", "Test4"),
)
FilterDropdown(
@ -44,7 +44,8 @@ fun <T> FilterDropdown(
var showDropdown by remember { mutableStateOf(false) }
var filter by remember { mutableStateOf("") }
val filterFocusRequester = remember { FocusRequester() }
val filteredDropdownItems = remember(filter, dropdownItems) { dropdownItems.filter { it.optionName.lowercaseContains(filter) } }
val filteredDropdownItems =
remember(filter, dropdownItems) { dropdownItems.filter { it.optionName.lowercaseContains(filter) } }
Box {
OutlinedButton(

View File

@ -8,7 +8,10 @@ import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.v2.maxScrollOffset
import androidx.compose.material.*
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.runtime.*
@ -19,7 +22,8 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.jetpackduba.gitnuro.*
import com.jetpackduba.gitnuro.AppIcons
import com.jetpackduba.gitnuro.LocalTabScope
import com.jetpackduba.gitnuro.di.AppComponent
import com.jetpackduba.gitnuro.di.DaggerTabComponent
import com.jetpackduba.gitnuro.di.TabComponent

View File

@ -2,7 +2,8 @@
package com.jetpackduba.gitnuro.ui.components
import androidx.compose.foundation.*
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme

View File

@ -4,7 +4,6 @@ import androidx.compose.foundation.hoverable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsHoveredAsState
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember

View File

@ -61,7 +61,7 @@ fun branchContextMenuItems(
)
}
if(isLocal) {
if (isLocal) {
add(
ContextMenuElement.ContextTextEntry(
label = "Change default upstream branch",

View File

@ -24,7 +24,8 @@ import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.input.InputMode
import androidx.compose.ui.input.InputModeManager
import androidx.compose.ui.input.key.*
import androidx.compose.ui.input.pointer.*
import androidx.compose.ui.input.pointer.isSecondary
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalInputModeManager

View File

@ -56,7 +56,7 @@ fun submoduleContextMenuItems(
// )
}
if(isNotEmpty()) {
if (isNotEmpty()) {
add(
ContextMenuElement.ContextSeparator,
)

View File

@ -148,7 +148,7 @@ fun AddSubmodulesDialog(
},
)
AnimatedVisibility (error.isNotBlank()) {
AnimatedVisibility(error.isNotBlank()) {
Box(
modifier = Modifier
.fillMaxWidth()

View File

@ -7,7 +7,9 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.onClick
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier

View File

@ -5,7 +5,10 @@ import androidx.compose.foundation.layout.*
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color

View File

@ -22,7 +22,7 @@ class UpdatesRepository @Inject constructor(
fun hasUpdatesFlow() = flow {
val latestReleaseJson = updatesWebService.release(AppConstants.VERSION_CHECK_URL)
while(coroutineContext.isActive) {
while (coroutineContext.isActive) {
val update = updateJson.decodeFromString<Update?>(latestReleaseJson)
if (update != null && update.appCode > AppConstants.APP_VERSION_CODE) {

View File

@ -86,7 +86,7 @@ class CommitChangesViewModel @Inject constructor(
if (untrackedFilesCommit != null) {
val untrackedFilesChanges = getCommitDiffEntriesUseCase(git, untrackedFilesCommit)
if(untrackedFilesChanges.all { it.changeType == DiffEntry.ChangeType.ADD }) { // All files should be new
if (untrackedFilesChanges.all { it.changeType == DiffEntry.ChangeType.ADD }) { // All files should be new
changes.addAll(untrackedFilesChanges)
}
}

View File

@ -54,22 +54,22 @@ class DiffViewModel @Inject constructor(
diffTypeFlow
.drop(1) // Ignore the first time the flow triggers, we only care about updates
.collect {
val diffEntryType = this@DiffViewModel.diffEntryType
if (diffEntryType != null) {
updateDiff(diffEntryType)
val diffEntryType = this@DiffViewModel.diffEntryType
if (diffEntryType != null) {
updateDiff(diffEntryType)
}
}
}
}
tabScope.launch {
isDisplayFullFile
.drop(1) // Ignore the first time the flow triggers, we only care about updates
.collect {
val diffEntryType = this@DiffViewModel.diffEntryType
if (diffEntryType != null) {
updateDiff(diffEntryType)
val diffEntryType = this@DiffViewModel.diffEntryType
if (diffEntryType != null) {
updateDiff(diffEntryType)
}
}
}
}
tabScope.launch {

View File

@ -108,7 +108,11 @@ class HistoryViewModel @Inject constructor(
val diffEntryType = DiffEntryType.CommitDiff(diffEntry)
val diffResult = formatDiffUseCase(git, diffEntryType, false) // TODO This hardcoded false should be changed when the UI is implemented
val diffResult = formatDiffUseCase(
git,
diffEntryType,
false
) // TODO This hardcoded false should be changed when the UI is implemented
val textDiffType = settings.textDiffType
val formattedDiffResult = if (textDiffType == TextDiffType.SPLIT && diffResult is DiffResult.Text) {

View File

@ -71,7 +71,7 @@ class LogViewModel @Inject constructor(
private val appSettings: AppSettings,
private val tabScope: CoroutineScope,
private val sharedStashViewModel: SharedStashViewModel,
) : ViewModel, ISharedStashViewModel by sharedStashViewModel {
) : ViewModel, ISharedStashViewModel by sharedStashViewModel {
private val _logStatus = MutableStateFlow<LogStatus>(LogStatus.Loading)
val logStatus: StateFlow<LogStatus>

View File

@ -140,7 +140,11 @@ class SettingsViewModel @Inject constructor(
null
} catch (ex: Exception) {
ex.printStackTrace()
newErrorNow(ex, "Saving theme failed", "Failed to parse selected theme JSON. Please check if it's valid and try again.")
newErrorNow(
ex,
"Saving theme failed",
"Failed to parse selected theme JSON. Please check if it's valid and try again."
)
}
}

View File

@ -11,11 +11,12 @@ import com.jetpackduba.gitnuro.git.RefreshType
import com.jetpackduba.gitnuro.git.TabState
import com.jetpackduba.gitnuro.git.author.LoadAuthorUseCase
import com.jetpackduba.gitnuro.git.author.SaveAuthorUseCase
import com.jetpackduba.gitnuro.git.log.CheckHasPreviousCommitsUseCase
import com.jetpackduba.gitnuro.git.log.GetLastCommitMessageUseCase
import com.jetpackduba.gitnuro.git.log.GetSpecificCommitMessageUseCase
import com.jetpackduba.gitnuro.git.rebase.*
import com.jetpackduba.gitnuro.git.repository.GetRepositoryStateUseCase
import com.jetpackduba.gitnuro.git.rebase.AbortRebaseUseCase
import com.jetpackduba.gitnuro.git.rebase.ContinueRebaseUseCase
import com.jetpackduba.gitnuro.git.rebase.RebaseInteractiveState
import com.jetpackduba.gitnuro.git.rebase.SkipRebaseUseCase
import com.jetpackduba.gitnuro.git.repository.ResetRepositoryStateUseCase
import com.jetpackduba.gitnuro.git.workspace.*
import com.jetpackduba.gitnuro.models.AuthorInfo

View File

@ -201,6 +201,7 @@ class TabViewModel @Inject constructor(
_showAuthorInfo.value = false
authorViewModel = null
}
/**
* Sometimes external apps can run filesystem multiple operations in a fraction of a second.
* To prevent excessive updates, we add a slight delay between updates emission to prevent slowing down

View File

@ -24,7 +24,7 @@ class TabViewModelsHolder @Inject constructor(
private val changeDefaultUpstreamBranchViewModelProvider: Provider<ChangeDefaultUpstreamBranchViewModel>,
private val submoduleDialogViewModelProvider: Provider<SubmoduleDialogViewModel>,
private val signOffDialogViewModelProvider: Provider<SignOffDialogViewModel>,
) {
) {
val viewModels = mapOf(
logViewModel::class to logViewModel,
sidePanelViewModel::class to sidePanelViewModel,
@ -38,7 +38,7 @@ class TabViewModelsHolder @Inject constructor(
// TODO Call this when required
fun dynamicViewModel(type: KClass<*>): Any {
return when(type) {
return when (type) {
DiffViewModel::class -> diffViewModelProvider.get()
HistoryViewModel::class -> historyViewModelProvider.get()
AuthorViewModel::class -> authorViewModelProvider.get()

View File

@ -9,7 +9,6 @@ import com.jetpackduba.gitnuro.viewmodels.SharedStashViewModel
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import org.eclipse.jgit.api.Git

View File

@ -2,8 +2,10 @@ package com.jetpackduba.gitnuro.viewmodels.sidepanel
import com.jetpackduba.gitnuro.git.RefreshType
import com.jetpackduba.gitnuro.git.TabState
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import org.eclipse.jgit.transport.URIish
import java.io.File
import javax.inject.Inject

View File

@ -43,7 +43,11 @@ class SubmodulesViewModel @AssistedInject constructor(
init {
tabScope.launch {
tabState.refreshFlowFiltered(RefreshType.ALL_DATA, RefreshType.UNCOMMITTED_CHANGES, RefreshType.SUBMODULES) {
tabState.refreshFlowFiltered(
RefreshType.ALL_DATA,
RefreshType.UNCOMMITTED_CHANGES,
RefreshType.SUBMODULES
) {
refresh(tabState.git)
}
}

View File

@ -1 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/>
</svg>

Before

Width:  |  Height:  |  Size: 284 B

After

Width:  |  Height:  |  Size: 295 B

View File

@ -1 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><circle cx="6" cy="18" fill="none" r="2"/><circle cx="12" cy="12" fill="none" r=".5"/><circle cx="6" cy="6" fill="none" r="2"/><path d="M9.64 7.64c.23-.5.36-1.05.36-1.64 0-2.21-1.79-4-4-4S2 3.79 2 6s1.79 4 4 4c.59 0 1.14-.13 1.64-.36L10 12l-2.36 2.36C7.14 14.13 6.59 14 6 14c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4c0-.59-.13-1.14-.36-1.64L12 14l7 7h3v-1L9.64 7.64zM6 8c-1.1 0-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2zm0 12c-1.1 0-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2zm6-7.5c-.28 0-.5-.22-.5-.5s.22-.5.5-.5.5.22.5.5-.22.5-.5.5zM19 3l-6 6 2 2 7-7V3z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
<path d="M0 0h24v24H0z" fill="none"/>
<circle cx="6" cy="18" fill="none" r="2"/>
<circle cx="12" cy="12" fill="none" r=".5"/>
<circle cx="6" cy="6" fill="none" r="2"/>
<path d="M9.64 7.64c.23-.5.36-1.05.36-1.64 0-2.21-1.79-4-4-4S2 3.79 2 6s1.79 4 4 4c.59 0 1.14-.13 1.64-.36L10 12l-2.36 2.36C7.14 14.13 6.59 14 6 14c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4c0-.59-.13-1.14-.36-1.64L12 14l7 7h3v-1L9.64 7.64zM6 8c-1.1 0-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2zm0 12c-1.1 0-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2zm6-7.5c-.28 0-.5-.22-.5-.5s.22-.5.5-.5.5.22.5.5-.22.5-.5.5zM19 3l-6 6 2 2 7-7V3z"/>
</svg>

Before

Width:  |  Height:  |  Size: 694 B

After

Width:  |  Height:  |  Size: 720 B

View File

@ -1 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M8 16h8v2H8zm0-4h8v2H8zm6-10H6c-1.1 0-2 .9-2 2v16c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm4 18H6V4h7v5h5v11z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
<path d="M0 0h24v24H0V0z" fill="none"/>
<path d="M8 16h8v2H8zm0-4h8v2H8zm6-10H6c-1.1 0-2 .9-2 2v16c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm4 18H6V4h7v5h5v11z"/>
</svg>

Before

Width:  |  Height:  |  Size: 271 B

After

Width:  |  Height:  |  Size: 282 B

View File

@ -1 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M18 7l-1.41-1.41-6.34 6.34 1.41 1.41L18 7zm4.24-1.41L11.66 16.17 7.48 12l-1.41 1.41L11.66 19l12-12-1.42-1.41zM.41 13.41L6 19l1.41-1.41L1.83 12 .41 13.41z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M18 7l-1.41-1.41-6.34 6.34 1.41 1.41L18 7zm4.24-1.41L11.66 16.17 7.48 12l-1.41 1.41L11.66 19l12-12-1.42-1.41zM.41 13.41L6 19l1.41-1.41L1.83 12 .41 13.41z"/>
</svg>

Before

Width:  |  Height:  |  Size: 310 B

After

Width:  |  Height:  |  Size: 321 B

View File

@ -1 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path d="M160-390v-60h640v60H160Zm0-120v-60h640v60H160Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48">
<path d="M160-390v-60h640v60H160Zm0-120v-60h640v60H160Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 152 B

After

Width:  |  Height:  |  Size: 158 B

View File

@ -1 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M19 15v2H5v-2h14m2-10H3v2h18V5zm0 4H3v2h18V9zm0 4H3v6h18v-6z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
<path d="M0 0h24v24H0V0z" fill="none"/>
<path d="M19 15v2H5v-2h14m2-10H3v2h18V5zm0 4H3v2h18V9zm0 4H3v6h18v-6z"/>
</svg>

Before

Width:  |  Height:  |  Size: 219 B

After

Width:  |  Height:  |  Size: 230 B

View File

@ -1 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><rect fill="none" height="24" width="24"/><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M5,19V5h6v14H5z M19,19h-6v-7h6V19z M19,10h-6V5h6V10z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px"
fill="#000000">
<rect fill="none" height="24" width="24"/>
<path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M5,19V5h6v14H5z M19,19h-6v-7h6V19z M19,10h-6V5h6V10z"/>
</svg>

Before

Width:  |  Height:  |  Size: 332 B

After

Width:  |  Height:  |  Size: 348 B

View File

@ -1 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g fill="none"><path d="M0 0h24v24H0V0z"/><path d="M0 0h24v24H0V0z" opacity=".87"/></g><path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7zm-4 6h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
<g fill="none">
<path d="M0 0h24v24H0V0z"/>
<path d="M0 0h24v24H0V0z" opacity=".87"/>
</g>
<path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7zm-4 6h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7z"/>
</svg>

Before

Width:  |  Height:  |  Size: 379 B

After

Width:  |  Height:  |  Size: 413 B

View File

@ -1 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM4 12c0-.61.08-1.21.21-1.78L8.99 15v1c0 1.1.9 2 2 2v1.93C7.06 19.43 4 16.07 4 12zm13.89 5.4c-.26-.81-1-1.4-1.9-1.4h-1v-3c0-.55-.45-1-1-1h-6v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41C17.92 5.77 20 8.65 20 12c0 2.08-.81 3.98-2.11 5.4z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
<path d="M0 0h24v24H0V0z" fill="none"/>
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM4 12c0-.61.08-1.21.21-1.78L8.99 15v1c0 1.1.9 2 2 2v1.93C7.06 19.43 4 16.07 4 12zm13.89 5.4c-.26-.81-1-1.4-1.9-1.4h-1v-3c0-.55-.45-1-1-1h-6v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41C17.92 5.77 20 8.65 20 12c0 2.08-.81 3.98-2.11 5.4z"/>
</svg>

Before

Width:  |  Height:  |  Size: 460 B

After

Width:  |  Height:  |  Size: 471 B

View File

@ -1 +1,19 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/></g><g><g><g><g><path d="M12,22C6.49,22,2,17.51,2,12S6.49,2,12,2s10,4.04,10,9c0,3.31-2.69,6-6,6h-1.77c-0.28,0-0.5,0.22-0.5,0.5 c0,0.12,0.05,0.23,0.13,0.33c0.41,0.47,0.64,1.06,0.64,1.67C14.5,20.88,13.38,22,12,22z M12,4c-4.41,0-8,3.59-8,8s3.59,8,8,8 c0.28,0,0.5-0.22,0.5-0.5c0-0.16-0.08-0.28-0.14-0.35c-0.41-0.46-0.63-1.05-0.63-1.65c0-1.38,1.12-2.5,2.5-2.5H16 c2.21,0,4-1.79,4-4C20,7.14,16.41,4,12,4z"/><circle cx="6.5" cy="11.5" r="1.5"/><circle cx="9.5" cy="7.5" r="1.5"/><circle cx="14.5" cy="7.5" r="1.5"/><circle cx="17.5" cy="11.5" r="1.5"/></g></g></g></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px"
fill="#000000">
<g>
<rect fill="none" height="24" width="24"/>
</g>
<g>
<g>
<g>
<g>
<path d="M12,22C6.49,22,2,17.51,2,12S6.49,2,12,2s10,4.04,10,9c0,3.31-2.69,6-6,6h-1.77c-0.28,0-0.5,0.22-0.5,0.5 c0,0.12,0.05,0.23,0.13,0.33c0.41,0.47,0.64,1.06,0.64,1.67C14.5,20.88,13.38,22,12,22z M12,4c-4.41,0-8,3.59-8,8s3.59,8,8,8 c0.28,0,0.5-0.22,0.5-0.5c0-0.16-0.08-0.28-0.14-0.35c-0.41-0.46-0.63-1.05-0.63-1.65c0-1.38,1.12-2.5,2.5-2.5H16 c2.21,0,4-1.79,4-4C20,7.14,16.41,4,12,4z"/>
<circle cx="6.5" cy="11.5" r="1.5"/>
<circle cx="9.5" cy="7.5" r="1.5"/>
<circle cx="14.5" cy="7.5" r="1.5"/>
<circle cx="17.5" cy="11.5" r="1.5"/>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 748 B

After

Width:  |  Height:  |  Size: 966 B

View File

@ -1 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path d="M80-200v-61h800v61H80Zm38-254-40-22 40-68H40v-45h78l-40-68 40-22 38 67 38-67 40 22-40 68h78v45h-78l40 68-40 22-38-67-38 67Zm324 0-40-24 40-68h-78v-45h78l-40-68 40-22 38 67 38-67 40 22-40 68h78v45h-78l40 68-40 24-38-67-38 67Zm324 0-40-24 40-68h-78v-45h78l-40-68 40-22 38 67 38-67 40 22-40 68h78v45h-78l40 68-40 24-38-67-38 67Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48">
<path d="M80-200v-61h800v61H80Zm38-254-40-22 40-68H40v-45h78l-40-68 40-22 38 67 38-67 40 22-40 68h78v45h-78l40 68-40 22-38-67-38 67Zm324 0-40-24 40-68h-78v-45h78l-40-68 40-22 38 67 38-67 40 22-40 68h78v45h-78l40 68-40 24-38-67-38 67Zm324 0-40-24 40-68h-78v-45h78l-40-68 40-22 38 67 38-67 40 22-40 68h78v45h-78l40 68-40 24-38-67-38 67Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 431 B

After

Width:  |  Height:  |  Size: 437 B

View File

@ -1 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 2h-4.18C14.4.84 13.3 0 12 0c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm7 18H5V4h2v3h10V4h2v16z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M19 2h-4.18C14.4.84 13.3 0 12 0c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm7 18H5V4h2v3h10V4h2v16z"/>
</svg>

Before

Width:  |  Height:  |  Size: 357 B

After

Width:  |  Height:  |  Size: 368 B

View File

@ -1 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0zm0 0h24v24H0V0z" fill="none"/><path d="M1.79 12l5.58 5.59L5.96 19 .37 13.41 1.79 12zm.45-7.78L12.9 14.89l-1.28 1.28L7.44 12l-1.41 1.41L11.62 19l2.69-2.69 4.89 4.89 1.41-1.41L3.65 2.81 2.24 4.22zm14.9 9.27L23.62 7 22.2 5.59l-6.48 6.48 1.42 1.42zM17.96 7l-1.41-1.41-3.65 3.66 1.41 1.41L17.96 7z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
<path d="M0 0h24v24H0zm0 0h24v24H0V0z" fill="none"/>
<path d="M1.79 12l5.58 5.59L5.96 19 .37 13.41 1.79 12zm.45-7.78L12.9 14.89l-1.28 1.28L7.44 12l-1.41 1.41L11.62 19l2.69-2.69 4.89 4.89 1.41-1.41L3.65 2.81 2.24 4.22zm14.9 9.27L23.62 7 22.2 5.59l-6.48 6.48 1.42 1.42zM17.96 7l-1.41-1.41-3.65 3.66 1.41 1.41L17.96 7z"/>
</svg>

Before

Width:  |  Height:  |  Size: 425 B

After

Width:  |  Height:  |  Size: 436 B

View File

@ -1 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M480-80q-139-35-229.5-159.5T160-516v-244l320-120 320 120v244q0 152-90.5 276.5T480-80Zm0-84q97-30 162-118.5T718-480H480v-315l-240 90v207q0 7 2 18h238v316Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24">
<path d="M480-80q-139-35-229.5-159.5T160-516v-244l320-120 320 120v244q0 152-90.5 276.5T480-80Zm0-84q97-30 162-118.5T718-480H480v-315l-240 90v207q0 7 2 18h238v316Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 259 B

After

Width:  |  Height:  |  Size: 265 B

View File

@ -1 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/></g><g><g><path d="M16.81,8.94l-3.75-3.75L4,14.25V18h3.75L16.81,8.94z M6,16v-0.92l7.06-7.06l0.92,0.92L6.92,16H6z"/><path d="M19.71,6.04c0.39-0.39,0.39-1.02,0-1.41l-2.34-2.34C17.17,2.09,16.92,2,16.66,2c-0.25,0-0.51,0.1-0.7,0.29l-1.83,1.83 l3.75,3.75L19.71,6.04z"/><rect height="4" width="20" x="2" y="20"/></g></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px"
fill="#000000">
<g>
<rect fill="none" height="24" width="24"/>
</g>
<g>
<g>
<path d="M16.81,8.94l-3.75-3.75L4,14.25V18h3.75L16.81,8.94z M6,16v-0.92l7.06-7.06l0.92,0.92L6.92,16H6z"/>
<path d="M19.71,6.04c0.39-0.39,0.39-1.02,0-1.41l-2.34-2.34C17.17,2.09,16.92,2,16.66,2c-0.25,0-0.51,0.1-0.7,0.29l-1.83,1.83 l3.75,3.75L19.71,6.04z"/>
<rect height="4" width="20" x="2" y="20"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 500 B

After

Width:  |  Height:  |  Size: 592 B

View File

@ -1 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z"/>
</svg>

Before

Width:  |  Height:  |  Size: 380 B

After

Width:  |  Height:  |  Size: 391 B

View File

@ -1,10 +1,10 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_402_2142)">
<path d="M4 13H20V15H4V13ZM4 17H20V19H4V17ZM4 9H20V11H4V9ZM4 5H20V7H4V5Z" fill="black"/>
</g>
<defs>
<clipPath id="clip0_402_2142">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
<g clip-path="url(#clip0_402_2142)">
<path d="M4 13H20V15H4V13ZM4 17H20V19H4V17ZM4 9H20V11H4V9ZM4 5H20V7H4V5Z" fill="black"/>
</g>
<defs>
<clipPath id="clip0_402_2142">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 336 B

After

Width:  |  Height:  |  Size: 388 B

View File

@ -1 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24" x="0"/></g><g><g><g><path d="M21,10.12h-6.78l2.74-2.82c-2.73-2.7-7.15-2.8-9.88-0.1c-2.73,2.71-2.73,7.08,0,9.79s7.15,2.71,9.88,0 C18.32,15.65,19,14.08,19,12.1h2c0,1.98-0.88,4.55-2.64,6.29c-3.51,3.48-9.21,3.48-12.72,0c-3.5-3.47-3.53-9.11-0.02-12.58 s9.14-3.47,12.65,0L21,3V10.12z M12.5,8v4.25l3.5,2.08l-0.72,1.21L11,13V8H12.5z"/></g></g></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px"
fill="#000000">
<g>
<rect fill="none" height="24" width="24" x="0"/>
</g>
<g>
<g>
<g>
<path d="M21,10.12h-6.78l2.74-2.82c-2.73-2.7-7.15-2.8-9.88-0.1c-2.73,2.71-2.73,7.08,0,9.79s7.15,2.71,9.88,0 C18.32,15.65,19,14.08,19,12.1h2c0,1.98-0.88,4.55-2.64,6.29c-3.51,3.48-9.21,3.48-12.72,0c-3.5-3.47-3.53-9.11-0.02-12.58 s9.14-3.47,12.65,0L21,3V10.12z M12.5,8v4.25l3.5,2.08l-0.72,1.21L11,13V8H12.5z"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 525 B

After

Width:  |  Height:  |  Size: 621 B

View File

@ -1,11 +1,11 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_402_2113)">
<path d="M3 13H11V15H3V13ZM3 17H11V19H3V17ZM3 9H11V11H3V9ZM3 5H11V7H3V5Z" fill="black"/>
<path d="M13 13H21V15H13V13ZM13 17H21V19H13V17ZM13 9H21V11H13V9ZM13 5H21V7H13V5Z" fill="black"/>
</g>
<defs>
<clipPath id="clip0_402_2113">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
<g clip-path="url(#clip0_402_2113)">
<path d="M3 13H11V15H3V13ZM3 17H11V19H3V17ZM3 9H11V11H3V9ZM3 5H11V7H3V5Z" fill="black"/>
<path d="M13 13H21V15H13V13ZM13 17H21V19H13V17ZM13 9H21V11H13V9ZM13 5H21V7H13V5Z" fill="black"/>
</g>
<defs>
<clipPath id="clip0_402_2113">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 433 B

After

Width:  |  Height:  |  Size: 493 B

View File

@ -1 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M12 6c3.79 0 7.17 2.13 8.82 5.5C19.17 14.87 15.79 17 12 17s-7.17-2.13-8.82-5.5C4.83 8.13 8.21 6 12 6m0-2C7 4 2.73 7.11 1 11.5 2.73 15.89 7 19 12 19s9.27-3.11 11-7.5C21.27 7.11 17 4 12 4zm0 5c1.38 0 2.5 1.12 2.5 2.5S13.38 14 12 14s-2.5-1.12-2.5-2.5S10.62 9 12 9m0-2c-2.48 0-4.5 2.02-4.5 4.5S9.52 16 12 16s4.5-2.02 4.5-4.5S14.48 7 12 7z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
<path d="M0 0h24v24H0V0z" fill="none"/>
<path d="M12 6c3.79 0 7.17 2.13 8.82 5.5C19.17 14.87 15.79 17 12 17s-7.17-2.13-8.82-5.5C4.83 8.13 8.21 6 12 6m0-2C7 4 2.73 7.11 1 11.5 2.73 15.89 7 19 12 19s9.27-3.11 11-7.5C21.27 7.11 17 4 12 4zm0 5c1.38 0 2.5 1.12 2.5 2.5S13.38 14 12 14s-2.5-1.12-2.5-2.5S10.62 9 12 9m0-2c-2.48 0-4.5 2.02-4.5 4.5S9.52 16 12 16s4.5-2.02 4.5-4.5S14.48 7 12 7z"/>
</svg>

Before

Width:  |  Height:  |  Size: 493 B

After

Width:  |  Height:  |  Size: 504 B

View File

@ -1 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0zm0 0h24v24H0V0zm0 0h24v24H0V0zm0 0h24v24H0V0z" fill="none"/><path d="M12 6c3.79 0 7.17 2.13 8.82 5.5-.59 1.22-1.42 2.27-2.41 3.12l1.41 1.41c1.39-1.23 2.49-2.77 3.18-4.53C21.27 7.11 17 4 12 4c-1.27 0-2.49.2-3.64.57l1.65 1.65C10.66 6.09 11.32 6 12 6zm-1.07 1.14L13 9.21c.57.25 1.03.71 1.28 1.28l2.07 2.07c.08-.34.14-.7.14-1.07C16.5 9.01 14.48 7 12 7c-.37 0-.72.05-1.07.14zM2.01 3.87l2.68 2.68C3.06 7.83 1.77 9.53 1 11.5 2.73 15.89 7 19 12 19c1.52 0 2.98-.29 4.32-.82l3.42 3.42 1.41-1.41L3.42 2.45 2.01 3.87zm7.5 7.5l2.61 2.61c-.04.01-.08.02-.12.02-1.38 0-2.5-1.12-2.5-2.5 0-.05.01-.08.01-.13zm-3.4-3.4l1.75 1.75c-.23.55-.36 1.15-.36 1.78 0 2.48 2.02 4.5 4.5 4.5.63 0 1.23-.13 1.77-.36l.98.98c-.88.24-1.8.38-2.75.38-3.79 0-7.17-2.13-8.82-5.5.7-1.43 1.72-2.61 2.93-3.53z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
<path d="M0 0h24v24H0V0zm0 0h24v24H0V0zm0 0h24v24H0V0zm0 0h24v24H0V0z" fill="none"/>
<path d="M12 6c3.79 0 7.17 2.13 8.82 5.5-.59 1.22-1.42 2.27-2.41 3.12l1.41 1.41c1.39-1.23 2.49-2.77 3.18-4.53C21.27 7.11 17 4 12 4c-1.27 0-2.49.2-3.64.57l1.65 1.65C10.66 6.09 11.32 6 12 6zm-1.07 1.14L13 9.21c.57.25 1.03.71 1.28 1.28l2.07 2.07c.08-.34.14-.7.14-1.07C16.5 9.01 14.48 7 12 7c-.37 0-.72.05-1.07.14zM2.01 3.87l2.68 2.68C3.06 7.83 1.77 9.53 1 11.5 2.73 15.89 7 19 12 19c1.52 0 2.98-.29 4.32-.82l3.42 3.42 1.41-1.41L3.42 2.45 2.01 3.87zm7.5 7.5l2.61 2.61c-.04.01-.08.02-.12.02-1.38 0-2.5-1.12-2.5-2.5 0-.05.01-.08.01-.13zm-3.4-3.4l1.75 1.75c-.23.55-.36 1.15-.36 1.78 0 2.48 2.02 4.5 4.5 4.5.63 0 1.23-.13 1.77-.36l.98.98c-.88.24-1.8.38-2.75.38-3.79 0-7.17-2.13-8.82-5.5.7-1.43 1.72-2.61 2.93-3.53z"/>
</svg>

Before

Width:  |  Height:  |  Size: 901 B

After

Width:  |  Height:  |  Size: 912 B

View File

@ -1,14 +1,13 @@
package com.jetpackduba.gitnuro.git.branches
import com.jetpackduba.gitnuro.extensions.isBranch
import com.jetpackduba.gitnuro.extensions.simpleName
import io.mockk.*
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import kotlinx.coroutines.runBlocking
import org.eclipse.jgit.api.CheckoutCommand
import org.eclipse.jgit.api.CreateBranchCommand
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.lib.ObjectIdRef
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
class CheckoutRefUseCaseTest {
@ -18,7 +17,7 @@ class CheckoutRefUseCaseTest {
@Test
fun `invokes git checkout when ref is a local branch`() {
val checkoutCommand = mockk<CheckoutCommand>(relaxed = true)
val branchName ="refs/heads/feature-branch"
val branchName = "refs/heads/feature-branch"
every { refMock.name } returns branchName
every { gitMock.checkout() } returns checkoutCommand

View File

@ -1,10 +1,9 @@
package com.jetpackduba.gitnuro.git.diff
import io.mockk.mockk
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Assertions.*
class GenerateSplitHunkFromDiffResultUseCaseTest {
private val generateSplitHunkFromDiffResultUseCase = GenerateSplitHunkFromDiffResultUseCase()