aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/main
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-11-02 12:59:30 +0100
committerDanilo M. <danix@danix.xyz>2026-11-02 12:59:30 +0100
commit5972d8bb6ab2369e298be0e6641d92ab8f1b2f7a (patch)
tree5a3b5fe9dfaf9d88965dfb23b857d1f7fef087eb /app/src/main
parentd5df91b3c63ca0445035c957c2bb07dc156ec2a8 (diff)
downloadHardenedPass-5972d8bb6ab2369e298be0e6641d92ab8f1b2f7a.tar.gz
HardenedPass-5972d8bb6ab2369e298be0e6641d92ab8f1b2f7a.zip
build(deps): update JGit from 4.5.7 to 5.13.5
JGit 4.5.7 dates from 2019. 5.13 is the last line that needs only Java 8 APIs, so it works with Android's desugaring; it also fixes GHSA-3p86-9955-h393 (arbitrary file overwrite on checkout). GHSA-vrpq-qp53-qv56 (XXE in repo manifest parsing) has no 5.x fix but the app never parses repo manifests. API changes: - SshSessionFactory now requires getType(). - CheckoutCommand.setForce is deprecated; setForceRefUpdate is its documented replacement with the same meaning. JGit 5 references java.lang.management and javax.management, which Android lacks; R8 flagged them. Both paths are made unreachable rather than only silenced: - WindowCache registers JMX statistics by default; Application.onCreate now installs a WindowCacheConfig with exposeStatsViaJmx = false. - GC.gc() takes a PID lock that queries ManagementFactory and would throw NoClassDefFoundError on a device. GcOperation now runs the GC steps (packRefs, repack, prune) directly; the lock only guards against concurrent gc processes, which cannot happen in the app. Aggressive packing is dropped. The R8 -dontwarn rules and the lint baseline entries are added only for those two now-unreachable references. JGitBehaviourTest covers the operations' command chains plus the GC steps and passes on 5.13.5. It now ignores the developer's global git config, which JGit 5 reads (commit.gpgsign made test commits try to sign). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'app/src/main')
-rw-r--r--app/src/main/java/app/passwordstore/Application.kt3
-rw-r--r--app/src/main/java/app/passwordstore/util/git/operation/GcOperation.kt19
-rw-r--r--app/src/main/java/app/passwordstore/util/git/operation/ResetToRemoteOperation.kt2
-rw-r--r--app/src/main/java/app/passwordstore/util/git/sshj/SshjSessionFactory.kt2
4 files changed, 24 insertions, 2 deletions
diff --git a/app/src/main/java/app/passwordstore/Application.kt b/app/src/main/java/app/passwordstore/Application.kt
index 794dea10..9bc4c83e 100644
--- a/app/src/main/java/app/passwordstore/Application.kt
+++ b/app/src/main/java/app/passwordstore/Application.kt
@@ -35,6 +35,7 @@ import logcat.LogPriority.DEBUG
import logcat.LogPriority.VERBOSE
import logcat.LogcatLogger
import logcat.logcat
+import org.eclipse.jgit.storage.file.WindowCacheConfig
@Suppress("Unused")
@HiltAndroidApp
@@ -51,6 +52,8 @@ class Application : android.app.Application(), SharedPreferences.OnSharedPrefere
override fun onCreate() {
super.onCreate()
instance = this
+ // JGit registers its pack cache statistics with JMX by default; Android has no JMX.
+ WindowCacheConfig().apply { exposeStatsViaJmx = false }.install()
if (
BuildConfig.ENABLE_DEBUG_FEATURES ||
prefs.getBoolean(PreferenceKeys.ENABLE_DEBUG_LOGGING, false)
diff --git a/app/src/main/java/app/passwordstore/util/git/operation/GcOperation.kt b/app/src/main/java/app/passwordstore/util/git/operation/GcOperation.kt
index cf6ab1c4..c1487fbf 100644
--- a/app/src/main/java/app/passwordstore/util/git/operation/GcOperation.kt
+++ b/app/src/main/java/app/passwordstore/util/git/operation/GcOperation.kt
@@ -7,6 +7,8 @@ package app.passwordstore.util.git.operation
import androidx.appcompat.app.AppCompatActivity
import org.eclipse.jgit.api.GitCommand
+import org.eclipse.jgit.internal.storage.file.FileRepository
+import org.eclipse.jgit.internal.storage.file.GC
/**
* Run an aggressive garbage collection job on the repository, expiring every loose object to
@@ -16,5 +18,20 @@ class GcOperation(callingActivity: AppCompatActivity) : GitOperation(callingActi
override val requiresAuth: Boolean = false
override val commands: Array<GitCommand<out Any>> =
- arrayOf(git.gc().setAggressive(true).setExpire(null))
+ arrayOf(
+ object : GitCommand<Unit>(repository) {
+ // ponytail: JGit's GC.gc() takes a PID lock that calls java.lang.management, which
+ // Android lacks, so run its steps directly. The lock only guards against concurrent gc
+ // processes on one repository, which cannot happen here. No aggressive packing either:
+ // too slow on a phone for a password store's size.
+ override fun call() {
+ GC(repository as FileRepository).run {
+ setExpire(null)
+ packRefs()
+ repack()
+ prune(emptySet())
+ }
+ }
+ }
+ )
}
diff --git a/app/src/main/java/app/passwordstore/util/git/operation/ResetToRemoteOperation.kt b/app/src/main/java/app/passwordstore/util/git/operation/ResetToRemoteOperation.kt
index 17d3d3a1..7ca1282b 100644
--- a/app/src/main/java/app/passwordstore/util/git/operation/ResetToRemoteOperation.kt
+++ b/app/src/main/java/app/passwordstore/util/git/operation/ResetToRemoteOperation.kt
@@ -19,7 +19,7 @@ class ResetToRemoteOperation(callingActivity: AppCompatActivity, remoteBranch: S
// Force-create $remoteBranch if it doesn't exist. This covers the case where a branch name is
// changed.
git.branchCreate().setName(remoteBranch).setForce(true),
- git.checkout().setName(remoteBranch).setForce(true).setUpstreamMode(TRACK),
+ git.checkout().setName(remoteBranch).setForceRefUpdate(true).setUpstreamMode(TRACK),
// Do a hard reset to the remote branch. Equivalent to git reset --hard
// origin/$remoteBranch
git.reset().setRef("origin/$remoteBranch").setMode(ResetCommand.ResetType.HARD),
diff --git a/app/src/main/java/app/passwordstore/util/git/sshj/SshjSessionFactory.kt b/app/src/main/java/app/passwordstore/util/git/sshj/SshjSessionFactory.kt
index 325ed1ad..51657b02 100644
--- a/app/src/main/java/app/passwordstore/util/git/sshj/SshjSessionFactory.kt
+++ b/app/src/main/java/app/passwordstore/util/git/sshj/SshjSessionFactory.kt
@@ -75,6 +75,8 @@ class SshjSessionFactory(
private var currentSession: SshjSession? = null
+ override fun getType() = "sshj"
+
override fun getSession(
uri: URIish,
credentialsProvider: CredentialsProvider?,