aboutsummaryrefslogtreecommitdiffstats
path: root/app/src
diff options
context:
space:
mode:
Diffstat (limited to 'app/src')
-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
-rw-r--r--app/src/test/java/app/passwordstore/util/git/JGitBehaviourTest.kt28
5 files changed, 51 insertions, 3 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?,
diff --git a/app/src/test/java/app/passwordstore/util/git/JGitBehaviourTest.kt b/app/src/test/java/app/passwordstore/util/git/JGitBehaviourTest.kt
index 43f8b66a..b0eeb4ea 100644
--- a/app/src/test/java/app/passwordstore/util/git/JGitBehaviourTest.kt
+++ b/app/src/test/java/app/passwordstore/util/git/JGitBehaviourTest.kt
@@ -17,9 +17,12 @@ import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode.TRACK
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.api.RebaseCommand
import org.eclipse.jgit.api.ResetCommand
+import org.eclipse.jgit.internal.storage.file.FileRepository
+import org.eclipse.jgit.internal.storage.file.GC
import org.eclipse.jgit.lib.PersonIdent
import org.eclipse.jgit.lib.RepositoryState
import org.eclipse.jgit.transport.RemoteRefUpdate
+import org.eclipse.jgit.util.FS
/**
* Runs the JGit command chains the git operations in `util/git/operation` use, against a local bare
@@ -33,6 +36,8 @@ class JGitBehaviourTest {
private val identity = PersonIdent("test", "test@example.org")
init {
+ // Ignore the developer's ~/.gitconfig (e.g. commit.gpgsign); the app has no global config.
+ FS.DETECTED.setUserHome(root)
Git.init().setBare(true).setDirectory(remote).call().close()
clone("seed").use { git ->
git.write("example.org.gpg", "initial")
@@ -147,7 +152,7 @@ class JGitBehaviourTest {
// ResetToRemoteOperation
b.fetch().setRemote("origin").setRemoveDeletedRefs(true).call()
b.branchCreate().setName("master").setForce(true).call()
- b.checkout().setName("master").setForce(true).setUpstreamMode(TRACK).call()
+ b.checkout().setName("master").setForceRefUpdate(true).setUpstreamMode(TRACK).call()
b.reset().setRef("origin/master").setMode(ResetCommand.ResetType.HARD).call()
assertEquals("edited by a", b.read("example.org.gpg"))
@@ -155,4 +160,25 @@ class JGitBehaviourTest {
a.close()
b.close()
}
+
+ @Test
+ fun gcStepsPackObjectsWithoutThePidLock() {
+ clone("a").use { a ->
+ repeat(3) {
+ a.write("e$it.gpg", "entry $it")
+ a.commitAll("e$it")
+ }
+ val repo = a.repository as FileRepository
+ // GcOperation
+ GC(repo).run {
+ setExpire(null)
+ packRefs()
+ repack()
+ prune(emptySet())
+ }
+ assertEquals(0, GC(repo).statistics.numberOfLooseObjects)
+ assertTrue(GC(repo).statistics.numberOfPackedObjects > 0)
+ assertEquals("entry 2", a.read("e2.gpg"))
+ }
+ }
}