From 0f0d1994e589b4f2b2603c882f52c79e2307a4f7 Mon Sep 17 00:00:00 2001
From: Nosweh <62889203+Nosweh@users.noreply.github.com>
Date: Fri, 28 Aug 2020 17:31:40 +0200
Subject: [PATCH] Add Activity to view the Git commit log (#1056)
---
CHANGELOG.md | 2 +-
app/src/main/AndroidManifest.xml | 4 ++
.../java/com/zeapo/pwdstore/PasswordStore.kt | 1 +
.../zeapo/pwdstore/git/GitConfigActivity.kt | 68 ++++++++++++++-----
.../com/zeapo/pwdstore/git/log/GitCommit.kt | 18 +++++
.../zeapo/pwdstore/git/log/GitLogActivity.kt | 38 +++++++++++
.../zeapo/pwdstore/git/log/GitLogAdapter.kt | 56 +++++++++++++++
.../com/zeapo/pwdstore/git/log/GitLogModel.kt | 53 +++++++++++++++
.../com/zeapo/pwdstore/utils/Extensions.kt | 23 +++++++
.../main/res/layout/activity_git_config.xml | 40 ++++++-----
app/src/main/res/layout/activity_git_log.xml | 22 ++++++
.../main/res/layout/git_log_row_layout.xml | 45 ++++++++++++
app/src/main/res/values-de/strings.xml | 2 +
app/src/main/res/values-es/strings.xml | 2 -
app/src/main/res/values-fr/strings.xml | 2 -
app/src/main/res/values-pt-rBR/strings.xml | 2 -
app/src/main/res/values-ru/strings.xml | 2 -
app/src/main/res/values/strings.xml | 14 ++--
18 files changed, 342 insertions(+), 52 deletions(-)
create mode 100644 app/src/main/java/com/zeapo/pwdstore/git/log/GitCommit.kt
create mode 100644 app/src/main/java/com/zeapo/pwdstore/git/log/GitLogActivity.kt
create mode 100644 app/src/main/java/com/zeapo/pwdstore/git/log/GitLogAdapter.kt
create mode 100644 app/src/main/java/com/zeapo/pwdstore/git/log/GitLogModel.kt
create mode 100644 app/src/main/res/layout/activity_git_log.xml
create mode 100644 app/src/main/res/layout/git_log_row_layout.xml
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a0067ecb..96ecff35 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
- Allow sorting by recently used
- Add [Bromite](https://www.bromite.org/) and [Ungoogled Chromium](https://git.droidware.info/wchen342/ungoogled-chromium-android) to supported browsers list for Autofill
+- Add ability to view the Git commit log
### Changed
@@ -17,7 +18,6 @@ All notable changes to this project will be documented in this file.
### Fixed
-- Password creation UI will scroll if it does not fit on the screen
- Git server protocol and authentication mode are only updated when explicitly saved
- Remember HTTPS password during a sync operation
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index dae4466b..cbacda10 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -65,6 +65,10 @@
android:label="@string/title_activity_git_config"
android:windowSoftInputMode="adjustResize" />
+
+
() {
+
+ private val model = GitLogModel()
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val inflater = LayoutInflater.from(parent.context)
+ val binding = GitLogRowLayoutBinding.inflate(inflater, parent, false)
+ return ViewHolder(binding)
+ }
+
+ override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
+ val commit = model.get(position)
+ if (commit == null) {
+ e { "There is no git commit for view holder at position $position." }
+ return
+ }
+ viewHolder.bind(commit)
+ }
+
+ override fun getItemCount() = model.size
+
+ class ViewHolder(private val binding: GitLogRowLayoutBinding) : RecyclerView.ViewHolder(binding.root) {
+
+ fun bind(commit: GitCommit) = with(binding) {
+ gitLogRowMessage.text = commit.shortMessage
+ gitLogRowHash.text = shortHash(commit.hash)
+ gitLogRowTime.text = stringFrom(commit.time)
+ }
+ }
+}
diff --git a/app/src/main/java/com/zeapo/pwdstore/git/log/GitLogModel.kt b/app/src/main/java/com/zeapo/pwdstore/git/log/GitLogModel.kt
new file mode 100644
index 00000000..22c1ec78
--- /dev/null
+++ b/app/src/main/java/com/zeapo/pwdstore/git/log/GitLogModel.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+package com.zeapo.pwdstore.git.log
+
+import com.github.ajalt.timberkt.e
+import com.zeapo.pwdstore.utils.PasswordRepository
+import com.zeapo.pwdstore.utils.hash
+import com.zeapo.pwdstore.utils.time
+import org.eclipse.jgit.api.Git
+import org.eclipse.jgit.revwalk.RevCommit
+
+private fun commits(): Iterable {
+ val repo = PasswordRepository.getRepository(null)
+ if (repo == null) {
+ e { "Could not access git repository" }
+ return listOf()
+ }
+ return try {
+ Git(repo).log().call()
+ } catch (exc: Exception) {
+ e(exc) { "Failed to obtain git commits" }
+ listOf()
+ }
+}
+
+/**
+ * Provides [GitCommit]s from a git-log of the password git repository.
+ *
+ * All commits are acquired on the first request to this object.
+ */
+class GitLogModel {
+
+ // All commits are acquired here at once. Acquiring the commits in batches would not have been
+ // entirely sensible because the amount of computation required to obtain commit number n from
+ // the log includes the amount of computation required to obtain commit number n-1 from the log.
+ // This is because the commit graph is walked from HEAD to the last commit to obtain.
+ // Additionally, tests with 1000 commits in the log have not produced a significant delay in the
+ // user experience.
+ private val cache: MutableList by lazy {
+ commits().map {
+ GitCommit(it.hash, it.shortMessage, it.authorIdent.name, it.time)
+ }.toMutableList()
+ }
+ val size = cache.size
+
+ fun get(index: Int): GitCommit? {
+ if (index >= size) e { "Cannot get git commit with index $index. There are only $size." }
+ return cache.getOrNull(index)
+ }
+}
diff --git a/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt b/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt
index 561b8d99..edc01776 100644
--- a/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt
@@ -28,6 +28,9 @@ import com.zeapo.pwdstore.git.GitCommandExecutor
import com.zeapo.pwdstore.git.operation.GitOperation
import com.zeapo.pwdstore.utils.PasswordRepository.Companion.getRepositoryDirectory
import java.io.File
+import java.util.Date
+import org.eclipse.jgit.lib.ObjectId
+import org.eclipse.jgit.revwalk.RevCommit
const val OPENPGP_PROVIDER = "org.sufficientlysecure.keychain"
@@ -162,3 +165,23 @@ val Context.autofillManager: AutofillManager?
fun File.isInsideRepository(): Boolean {
return canonicalPath.contains(getRepositoryDirectory().canonicalPath)
}
+
+/**
+ * Unique SHA-1 hash of this commit as hexadecimal string.
+ *
+ * @see RevCommit.id
+ */
+val RevCommit.hash: String
+ get() = ObjectId.toString(id)
+
+/**
+ * Time this commit was made with second precision.
+ *
+ * @see RevCommit.commitTime
+ */
+val RevCommit.time: Date
+ get() {
+ val epochSeconds = commitTime.toLong()
+ val epochMilliseconds = epochSeconds * 1000
+ return Date(epochMilliseconds)
+ }
diff --git a/app/src/main/res/layout/activity_git_config.xml b/app/src/main/res/layout/activity_git_config.xml
index df1874a9..1d495250 100644
--- a/app/src/main/res/layout/activity_git_config.xml
+++ b/app/src/main/res/layout/activity_git_config.xml
@@ -17,7 +17,7 @@
android:id="@+id/username_input_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_margin="8dp"
+ android:layout_margin="@dimen/normal_margin"
android:hint="@string/git_user_name_hint"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
@@ -35,7 +35,7 @@
android:id="@+id/email_input_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_margin="8dp"
+ android:layout_margin="@dimen/normal_margin"
android:hint="@string/git_user_email"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/username_input_layout">
@@ -52,7 +52,7 @@
android:id="@+id/save_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_margin="8dp"
+ android:layout_margin="@dimen/normal_margin"
android:text="@string/crypto_save"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/email_input_layout" />
@@ -62,45 +62,43 @@
style="@style/TextAppearance.MaterialComponents.Headline5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_margin="8dp"
- android:text="@string/hackish_tools"
+ android:layout_margin="@dimen/normal_margin"
+ android:text="@string/git_tools"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/save_button" />
-
-
+ tools:text="HEAD status" />
+
+
+ app:layout_constraintTop_toBottomOf="@+id/git_log" />
diff --git a/app/src/main/res/layout/activity_git_log.xml b/app/src/main/res/layout/activity_git_log.xml
new file mode 100644
index 00000000..96b28487
--- /dev/null
+++ b/app/src/main/res/layout/activity_git_log.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/git_log_row_layout.xml b/app/src/main/res/layout/git_log_row_layout.xml
new file mode 100644
index 00000000..5a29f241
--- /dev/null
+++ b/app/src/main/res/layout/git_log_row_layout.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index fd94c8a9..d5abea1a 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -11,6 +11,7 @@
Ordner löschen
Abbruch
Repository Informationen
+ Commit-Log
Bitte klone oder erstelle ein neues Repository, bevor du versuchst ein Passwort hinzuzufügen oder jegliche Synchronisation-Operation durchführst.
Verschieben
@@ -121,6 +122,7 @@
Synchronisiere Repository
Git Pull
Git Push
+ Commit-Log anzeigen
Zeige das Password
Soll das entschlüsselte Passwort sichtbar sein? Dies deaktiviert nicht das Kopieren.
Zeige weiteren Inhalt
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index ff04cf3e..03e153e9 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -178,7 +178,5 @@
El envío fue rechazado por el servidor, la razón:
Ocurrió un error durante el envío:
Recordar contraseñagit (inseguro)
- Hackish tools
Abortar rebase
- Hash del commit
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 9f9e1768..db98bfd8 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -178,6 +178,4 @@
Pousser au dépôt distant sans avance rapide rejetée. Vérifiez la variable receive.denyNonFastForwards dans le fichier de configuration du répertoire de destination.
Une erreur s\'est produite lors de l\'opération de poussée:
Se rappeler de la phrase secrète dans la configuration de l\'application (peu sûr)
- Outils de hack
- Commettre la clé
diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml
index a7f3e046..2e07190a 100644
--- a/app/src/main/res/values-pt-rBR/strings.xml
+++ b/app/src/main/res/values-pt-rBR/strings.xml
@@ -248,10 +248,8 @@
Limpar a frase secreta salva para chave SSH local
Limpar senha HTTPS salva
Lembrar senha da chave
- Ferramentas de hackers
Abortar rebase e realizar push do novo branch
Hard reset no branch remoto
- Commit hash
Falha ao conectar ao serviço de API SSH do OpenKeychain.
Nenhum provedor de API SSH encontrado. O OpenKeychain está instalado?
SSH API pendente falhou
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 3fab8cf9..d1fbc215 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -233,10 +233,8 @@
Удаленный репозиторий отклонил запись изменений без быстрой перемотки вперед. Проверьте переменную receive.denyNonFastForwards в файле конфигурации репозитория назначения.
В хоте операции записи изменений возникла ошибка:
Заполнить парольную фразу в конфигурации приложнеия (небезопасно)
- Костыльные инструменты
Прервать перебазирование и записать изменения в новую ветку
Полный сброс до состояния удаленной ветки
- Хэш-сумма изменений
Ошибка при подключении к сервису OpenKeychain SSH API
Не найдено SSH API провайдеров. OpenKeychain установлен?
Ожидаемое намерение SSH API не удалось
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index a6e33047..72d4d5db 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -20,6 +20,7 @@
Cancel
Repository information
Git configuration
+ Commit log
Please clone or create a new repository below before trying to add a password or running any synchronization operation.
@@ -117,8 +118,8 @@
Repository
- Edit git server settings
- Git utils
+ Edit Git server settings
+ Local Git config & utilities
Import SSH key
Generate SSH key pair
View generated public SSH key
@@ -217,6 +218,7 @@
Pull from remote
Push to remote
Everything up-to-date
+ Show commit log
Show the password
Control the visibility of the passwords once decrypted. This does not disable copying to clipboard.
Show extra content
@@ -281,10 +283,12 @@
Clear saved passphrase for local SSH key
Clear saved HTTPS password
Remember key passphrase
- Hackish tools
+ Utilities
Abort rebase and push new branch
Hard reset to remote branch
- Commit hash
+ On branch %1$s
+ HEAD detached at %1$s
+ Unable to locate HEAD
Failed to connect to OpenKeychain SSH API service.
No SSH API provider found. Is OpenKeychain installed?
SSH API pending intent failed
@@ -393,6 +397,6 @@
A file by that name already exists
A folder by that name already exists
- Digits/Symbols (d/s)
+ Digits/Symbols (d/s)
ds