JetpackDuba / Gitnuro

A FOSS Git multiplatform client for newbies and pros
https://gitnuro.com/
GNU General Public License v3.0
946 stars 46 forks source link

Nearly infinite "Changes detected, partial refresh" every second on Windows #163

Closed Escain closed 11 months ago

Escain commented 1 year ago

Describe the bug On Windows, just after opening Gitnuro and for some 30s or so, the content of the repo refresh every second. In the log, it shows:

INFO slf4j:8 - TabViewModel - Changes detected, partial refresh

To Reproduce Open Gitnuro with any repo visible in it.

Observe how the central view is refreshing every second. Eventually, this stops after a while.

Expected behavior Refresh should not happens without any reason and that often.

Screenshots

image

image

Desktop (please complete the following information):

JetpackDuba commented 1 year ago

I saw it once but never been able to reproduce it again. Does it happen always? Try restarting gitnuro. If it happens always, I'd like to ask you to help me debug it.

Escain commented 1 year ago

Yes, it happens each time I start Gitnuro. Let me know what I can do to help.

JetpackDuba commented 1 year ago

Can you run this portable version from CLI and share the logs? https://we.tl/t-AGFepNwD5u (WeTransfer because the file is too big for GH, the link will expire in 1 week).

I've added some prints of what file/dir changes are triggering the refresh.

Escain commented 1 year ago

Hi!

Great! I had a little bit of troubles, because launching the application through CLI was making the issue to disappear.

I manged to reproduce the issue with PowerShell (./Gitnuro.exe | Out-File ./log.txt)

Two things happens:

1: A Network drive was inaccessible:

2023-09-27 11:15:13 ERROR FileSnapshot:329 - U:\.gitconfig: The network name cannot be found
java.nio.file.FileSystemException: U:\.gitconfig: The network name cannot be found
    at java.base/sun.nio.fs.WindowsException.translateToIOException(Unknown Source)
    at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
    at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
    at java.base/sun.nio.fs.WindowsFileAttributeViews$Basic.readAttributes(Unknown Source)
    at java.base/sun.nio.fs.WindowsFileAttributeViews$Basic.readAttributes(Unknown Source)
    at java.base/sun.nio.fs.WindowsFileSystemProvider.readAttributes(Unknown Source)
    at java.base/java.nio.file.Files.readAttributes(Unknown Source)
    at org.eclipse.jgit.util.FileUtils.fileAttributes(FileUtils.java:820)
    at org.eclipse.jgit.util.FS.fileAttributes(FS.java:1282)
    at org.eclipse.jgit.internal.storage.file.FileSnapshot.isModified(FileSnapshot.java:320)
    at org.eclipse.jgit.storage.file.FileBasedConfig.isOutdated(FileBasedConfig.java:242)
    at org.eclipse.jgit.storage.file.UserConfigFile.isOutdated(UserConfigFile.java:87)
    at org.eclipse.jgit.util.SystemReader.updateAll(SystemReader.java:434)
    at org.eclipse.jgit.util.SystemReader.getUserConfig(SystemReader.java:332)
    at org.eclipse.jgit.internal.storage.file.FileRepository.getConfig(FileRepository.java:346)
    at org.eclipse.jgit.internal.storage.file.FileRepository.getConfig(FileRepository.java:1)
    at org.eclipse.jgit.treewalk.FileTreeIterator.<init>(FileTreeIterator.java:71)
    at org.eclipse.jgit.lib.IndexDiff.diff(IndexDiff.java:610)
    at org.eclipse.jgit.lib.IndexDiff.diff(IndexDiff.java:384)
    at org.eclipse.jgit.lib.IndexDiff.diff(IndexDiff.java:358)
    at org.eclipse.jgit.api.StatusCommand.call(StatusCommand.java:122)
    at com.jetpackduba.gitnuro.git.workspace.GetStatusUseCase$invoke$2.invokeSuspend(GetStatusUseCase.kt:14)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
    at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
    at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
    at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)

I don't know why Gitnuro tries to access that device, as it is not related with the GIT repo.

After removing the network drive, the visual reloading (Image in my first report) was gone.

2: Many updates in the log:

After removing the inaccessible network drive, I still have many lines like:

Event: Ok(Event { kind: Modify(Any), paths: ["C:\\Users\\xxxxxxxxxx\\.git\\.probe-95ba1f7f-66e4-4d85-9ad7-86722f13bdff"], attr:tracker: None, attr:flag: None, attr:info: None, attr:source: None })

Note: Path is replaced by "xxxxxxxx"

JetpackDuba commented 1 year ago
  1. Not really sure, it's internal JGit stuff. Perhaps the network drive it's in the PATH and it tries to search for it? I'd have to do more research about it.

  2. Apparently these files are created by JGit, I've found a commit mentioning it:

Delete .probe files on JVM shutdown -- they are created in daemon threads that may terminate abruptly, not executing the "finally" clause that normally removes these files.

I'll add a rule to the watcher to ignore such files. There is also a small issue related to the iNotify limit that I'd like to fix, so I may do a bugfix release this saturday.

Escain commented 1 year ago

I wonder if you can just ignore all ".git" folder: Gitnuro probably wont show files changed in that folder anyway.

JetpackDuba commented 1 year ago

I'd rather not, as it's nice to detect when there have been changes outside of gitnuro (CLI for example). As Gitnuro should try to be as much up to date as possible.

The app acts differently depending on where the changes have been done.

By the way, I'll create build with fixes in a few hours if you want to test it :) I'm considering creating beta releases before the stable to get more users feedback and detect such issues before the stable release.

Edit: I'll do it tomorrow as I want to check some stuff about the notify API

JetpackDuba commented 1 year ago

Hey! Can you please try this version? https://we.tl/t-qfdOMcieZY

It ignores .probe files and it also batches IO events to prevent excessive UI updates in case there is a big movement of files (like when building, temporary files or moving files around).

Escain commented 1 year ago

Hi!

Sorry for taking time to answer, I was away those last days.

I still get this weird pattern:

1) Many "Modify" log entries (several thousands). 2) On attempt to access to "U", which doesn't exists anymore.

2023-10-02 08:17:30 INFO  slf4j:8 - TabViewModel - Trying to open repository C:\Users\xxxxxxxxx\MyRepo
2023-10-02 08:17:30 INFO  slf4j:8 - SharedRepositoryStateMa - Refreshing repository state com.jetpackduba.gitnuro.git.rebase.RebaseInteractiveState$None@697344f8
Event: Ok(Event { kind: Modify(Any), paths: ["C:\\Users\\xxxxxxxxx\\MyRepo\\.git\\.probe-398393bb-59a5-4f6e-b81e-5e3842ed3507"], attr:tracker: None, attr:flag: None, attr:info: None, attr:source: None })
Event: Ok(Event { kind: Modify(Any), paths: ["C:\\Users\\xxxxxxxxx\\MyRepo\\.git\\.probe-398393bb-59a5-4f6e-b81e-5e3842ed3507"], attr:tracker: None, attr:flag: None, attr:info: None, attr:source: None })

...

5000+ times
...
Event: Ok(Event { kind: Modify(Any), paths: ["C:\\Users\\xxxxxxxxx\\MyRepo\\.git\\.probe-398393bb-59a5-4f6e-b81e-5e3842ed3507"], attr:tracker: None, attr:flag: None, attr:info: None, attr:source: None })
Event: Ok(Event { kind: Remove(Any), paths: ["C:\\Users\\xxxxxxxxx\\MyRepo\\.git\\.probe-398393bb-59a5-4f6e-b81e-5e3842ed3507"], attr:tracker: None, attr:flag: None, attr:info: None, attr:source: None })
Event: Ok(Event { kind: Modify(Any), paths: ["C:\\Users\\xxxxxxxxx\\MyRepo\\.git"], attr:tracker: None, attr:flag: None, attr:info: None, attr:source: None })
2023-10-02 08:17:34 ERROR FS:789 - Cannot save config file 'FileBasedConfig[U:\.config\jgit\config]'
java.io.IOException: Creating directories for U:\.config\jgit failed
    at org.eclipse.jgit.util.FileUtils.mkdirs(FileUtils.java:414)
    at org.eclipse.jgit.internal.storage.file.LockFile.lock(LockFile.java:141)
    at org.eclipse.jgit.storage.file.FileBasedConfig.save(FileBasedConfig.java:203)
    at org.eclipse.jgit.util.FS$FileStoreAttributes.saveToConfig(FS.java:768)
    at org.eclipse.jgit.util.FS$FileStoreAttributes.lambda$5(FS.java:450)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.base/java.lang.Thread.run(Unknown Source)
Sending batched events to Kotlin side
2023-10-02 08:17:34 INFO  slf4j:8 - TabViewModel - Changes detected in git directory, full refresh
2023-10-02 08:17:34 INFO  slf4j:8 - SharedRepositoryStateMa - Refreshing repository state com.jetpackduba.gitnuro.git.rebase.RebaseInteractiveState$None@697344f8

I hope this helps.

JetpackDuba commented 12 months ago

Agh! Paths on windows are a pain, I'll try to build it again today.

JetpackDuba commented 11 months ago

i've looked into the event logs and are something expected, I added the print statement as a debugging tool for now but will be released in the future. However I've still noticed some inconsistencies so I've done a few tweaks. If you could test this new version, it would be awesome 😸

https://drive.google.com/file/d/1wGBcBfX4eQcTwazevIbG-IxWTFJDIFYH/view?usp=sharing

About the config in the U:\ drive I'm not so sure. Apparently JGit would usually create it on USER_DIR/.config, but for some reason in your case it tries to create it in a different drive. Can you create an issue so we can do some research about it please?

Escain commented 11 months ago

Hi :-)

The log looks mostly empty now (not sure if this is intended or not):

2023-10-12 09:29:03 INFO  slf4j:8 - TabViewModel - Trying to open repository C:\Users\...\MyGitRepo
2023-10-12 09:29:03 INFO  slf4j:8 - SharedRepositoryStateMa - Refreshing repository state com.jetpackduba.gitnuro.git.rebase.RebaseInteractiveState$None@57fc24fd

As I am not able to reproduce the U:\ access exception on the last build, I don't think it is useful to create the ticket. If I see it again, then, I would create the ticket. Does it make sense for you?

Thank you for following and fixing this issue. :-)