Version in base suite: 0.8.10-1 Base version: vorta_0.8.10-1 Target version: vorta_0.8.10-1+deb12u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/v/vorta/vorta_0.8.10-1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/v/vorta/vorta_0.8.10-1+deb12u1.dsc changelog | 8 patches/0006-Handle-ctime-and-mtime-diff-changes-1675.patch | 452 ++++++++++++ patches/series | 1 3 files changed, 461 insertions(+) diff -Nru vorta-0.8.10/debian/changelog vorta-0.8.10/debian/changelog --- vorta-0.8.10/debian/changelog 2023-01-23 20:06:42.000000000 +0000 +++ vorta-0.8.10/debian/changelog 2023-07-31 15:10:53.000000000 +0000 @@ -1,3 +1,11 @@ +vorta (0.8.10-1+deb12u1) bookworm; urgency=medium + + * Add 0006-Handle-ctime-and-mtime-diff-changes-1675.patch, which is a + cherry-picked fix from upstream that adapts Vorta 0.8.10 to Borg 1.2.4 + (Closes: #1042671). + + -- Nicholas D Steeves Mon, 31 Jul 2023 11:10:53 -0400 + vorta (0.8.10-1) unstable; urgency=medium * New upstream release. diff -Nru vorta-0.8.10/debian/patches/0006-Handle-ctime-and-mtime-diff-changes-1675.patch vorta-0.8.10/debian/patches/0006-Handle-ctime-and-mtime-diff-changes-1675.patch --- vorta-0.8.10/debian/patches/0006-Handle-ctime-and-mtime-diff-changes-1675.patch 1970-01-01 00:00:00.000000000 +0000 +++ vorta-0.8.10/debian/patches/0006-Handle-ctime-and-mtime-diff-changes-1675.patch 2023-07-31 15:10:53.000000000 +0000 @@ -0,0 +1,452 @@ +From: Henry Spanka +Date: Sat, 1 Apr 2023 21:10:56 +0200 +Subject: Handle ctime and mtime diff changes (#1675) + +Bug: https://github.com/borgbase/vorta/issues/1672 +Bug-Debian: https://bugs.debian.org/1042671 +Applied-Upstream: 0.8.11, https://github.com/borgbase/vorta/commit/e3451ed49e4a760d2a0d037ef45f22155eeb2ed9 + +Borg v1.2.4 added new change types called `mtime` and `ctime` for the modification and the creation time of a file. +Our diff json parser doesn't support these changes yet. +The plain text parser doesn't need to be updated since it is only used for earlier versions of borg. +This also extends the tooltip in the diff view to show changes in `ctime` or `mtime` in a localised manner. + +* src/vorta/views/diff_result.py (ChangeType): Add `CTIME` and `MTIME` linking to `MODIFIED`. + +* src/vorta/views/diff_result.py (DiffData): Add fields `ctime_change` and `mtime_change`. + +* src/vorta/views/diff_result.py (parse_diff_json): Parse the new change types. + +* src/vorta/views/diff_result.py (DiffTree.data): Add time changes to tooltip in a human readable format. + +* tests/test_diff.py : Update test data to include new change types. Add additional test cases for unittesting the new change types. +--- + src/vorta/views/diff_result.py | 55 ++++++++++++- + tests/test_diff.py | 176 ++++++++++++++++++++++++++++++++++++++--- + 2 files changed, 217 insertions(+), 14 deletions(-) + +diff --git a/src/vorta/views/diff_result.py b/src/vorta/views/diff_result.py +index 6a8e5ba..cf8b936 100644 +--- a/src/vorta/views/diff_result.py ++++ b/src/vorta/views/diff_result.py +@@ -6,7 +6,7 @@ + from pathlib import PurePath + from typing import List, Optional, Tuple + from PyQt5 import uic +-from PyQt5.QtCore import QMimeData, QModelIndex, QPoint, Qt, QThread, QUrl ++from PyQt5.QtCore import QDateTime, QLocale, QMimeData, QModelIndex, QPoint, Qt, QThread, QUrl + from PyQt5.QtGui import QColor, QKeySequence + from PyQt5.QtWidgets import QApplication, QHeaderView, QMenu, QShortcut, QTreeView + from vorta.utils import get_asset, pretty_bytes, uses_dark_mode +@@ -206,6 +206,8 @@ def parse_diff_json(diffs: List[dict], model: 'DiffTree'): + change_type: ChangeType = None + mode_change: Optional[Tuple[str, str]] = None + owner_change: Optional[Tuple[str, str, str, str]] = None ++ ctime_change: Optional[Tuple[QDateTime, QDateTime]] = None ++ mtime_change: Optional[Tuple[QDateTime, QDateTime]] = None + modified: Optional[Tuple[int, int]] = None + + # added link, removed link, changed link +@@ -213,6 +215,8 @@ def parse_diff_json(diffs: List[dict], model: 'DiffTree'): + # added directory, removed directory + # owner (old_user, new_user, old_group, new_group)) + # mode (old_mode, new_mode) ++ # ctime (old_ctime, new_ctime) ++ # mtime (old_mtime, new_mtime) + for change in item['changes']: + # if more than one type of change has happened for this file/dir/link, then report the most important + # (higher priority) +@@ -269,6 +273,22 @@ def parse_diff_json(diffs: List[dict], model: 'DiffTree'): + change['new_user'], + change['new_group'], + ) ++ ++ elif change['type'] == 'ctime': ++ # ctime change can occur along with previous changes ++ change_type = ChangeType.MODIFIED ++ ctime_change = ( ++ QDateTime.fromString(change['old_ctime'], Qt.DateFormat.ISODateWithMs), ++ QDateTime.fromString(change['new_ctime'], Qt.DateFormat.ISODateWithMs), ++ ) ++ elif change['type'] == 'mtime': ++ # mtime change can occur along with previous changes ++ change_type = ChangeType.MODIFIED ++ mtime_change = ( ++ QDateTime.fromString(change['old_mtime'], Qt.DateFormat.ISODateWithMs), ++ QDateTime.fromString(change['new_mtime'], Qt.DateFormat.ISODateWithMs), ++ ) ++ + else: + raise Exception('Unknown change type: {}'.format(change['type'])) + +@@ -282,6 +302,8 @@ def parse_diff_json(diffs: List[dict], model: 'DiffTree'): + size=size, + mode_change=mode_change, + owner_change=owner_change, ++ ctime_change=ctime_change, ++ mtime_change=mtime_change, + modified=modified, + ), + ) +@@ -492,6 +514,8 @@ class ChangeType(enum.Enum): + such as - a file is deleted and replaced with + a directory of the same name. + owner - user and/or group ownership changed. ++ ctime - creation time changed. ++ mtime - modification time changed. + + size: + If type == `added` or `removed`, +@@ -518,6 +542,14 @@ class ChangeType(enum.Enum): + See old_user property. + new_group: + See old_user property. ++ old_ctime: ++ If type == `ctime`, then old_ctime and new_ctime provide creation time changes. ++ new_ctime: ++ See old_ctime property. ++ old_mtime: ++ If type == `mtime`, then old_mtime and new_mtime provide modification time changes. ++ new_mtime: ++ See old_mtime property. + """ + + NONE = 0 # no change +@@ -531,6 +563,8 @@ class ChangeType(enum.Enum): + CHANGED_LINK = MODIFIED + MODE = MODIFIED # changed permissions + OWNER = MODIFIED ++ CTIME = MODIFIED ++ MTIME = MODIFIED + + def short(self): + """Get a short identifier for the change type.""" +@@ -588,6 +622,8 @@ class DiffData: + size: int # size change (disk usage) + mode_change: Optional[Tuple[str, str]] = None + owner_change: Optional[Tuple[str, str, str, str]] = None ++ ctime_change: Optional[Tuple[QDateTime, QDateTime]] = None ++ mtime_change: Optional[Tuple[QDateTime, QDateTime]] = None + modified: Optional[Tuple[int, int]] = None + + +@@ -798,6 +834,7 @@ def data(self, index: QModelIndex, role: int = Qt.ItemDataRole.DisplayRole): + + modified_template = self.tr("Added {}, deleted {}") + owner_template = "{: <10} -> {: >10}" ++ time_template = "{}: {} -> {}" + permission_template = "{} -> {}" + + # format +@@ -844,4 +881,20 @@ def data(self, index: QModelIndex, role: int = Qt.ItemDataRole.DisplayRole): + "{}:{}".format(item.data.owner_change[2], item.data.owner_change[3]), + ) + ++ if item.data.ctime_change: ++ tooltip += '\n' ++ tooltip += time_template.format( ++ "Creation Time", ++ QLocale.system().toString(item.data.ctime_change[0], QLocale.FormatType.ShortFormat), ++ QLocale.system().toString(item.data.ctime_change[1], QLocale.FormatType.ShortFormat), ++ ) ++ ++ if item.data.mtime_change: ++ tooltip += '\n' ++ tooltip += time_template.format( ++ "Modification Time", ++ QLocale.system().toString(item.data.mtime_change[0], QLocale.FormatType.ShortFormat), ++ QLocale.system().toString(item.data.mtime_change[1], QLocale.FormatType.ShortFormat), ++ ) ++ + return tooltip +diff --git a/tests/test_diff.py b/tests/test_diff.py +index a4e265d..7392977 100644 +--- a/tests/test_diff.py ++++ b/tests/test_diff.py +@@ -1,6 +1,6 @@ + from pathlib import PurePath + import pytest +-from PyQt5.QtCore import QItemSelectionModel ++from PyQt5.QtCore import QDateTime, QItemSelectionModel, Qt + import vorta.borg + import vorta.utils + import vorta.views.archive_tab +@@ -56,11 +56,22 @@ def check(feature_name): + [ + ( + 'changed link some/changed/link', +- ('some/changed/link', FileType.LINK, ChangeType.CHANGED_LINK, 0, 0, None, None, None), ++ ('some/changed/link', FileType.LINK, ChangeType.CHANGED_LINK, 0, 0, None, None, None, None, None), + ), + ( + ' +77.8 kB -77.8 kB some/changed/file', +- ('some/changed/file', FileType.FILE, ChangeType.MODIFIED, 2 * 77800, 0, None, None, (77800, 77800)), ++ ( ++ 'some/changed/file', ++ FileType.FILE, ++ ChangeType.MODIFIED, ++ 2 * 77800, ++ 0, ++ None, ++ None, ++ None, ++ None, ++ (77800, 77800), ++ ), + ), + ( + ' +77.8 kB -77.8 kB [-rw-rw-rw- -> -rw-r--r--] some/changed/file', +@@ -72,20 +83,33 @@ def check(feature_name): + 0, + ('-rw-rw-rw-', '-rw-r--r--'), + None, ++ None, ++ None, + (77800, 77800), + ), + ), + ( + '[-rw-rw-rw- -> -rw-r--r--] some/changed/file', +- ('some/changed/file', FileType.FILE, ChangeType.MODE, 0, 0, ('-rw-rw-rw-', '-rw-r--r--'), None, None), ++ ( ++ 'some/changed/file', ++ FileType.FILE, ++ ChangeType.MODE, ++ 0, ++ 0, ++ ('-rw-rw-rw-', '-rw-r--r--'), ++ None, ++ None, ++ None, ++ None, ++ ), + ), + ( + 'added directory some/changed/dir', +- ('some/changed/dir', FileType.DIRECTORY, ChangeType.ADDED, 0, 0, None, None, None), ++ ('some/changed/dir', FileType.DIRECTORY, ChangeType.ADDED, 0, 0, None, None, None, None, None), + ), + ( + 'removed directory some/changed/dir', +- ('some/changed/dir', FileType.DIRECTORY, ChangeType.REMOVED_DIR, 0, 0, None, None, None), ++ ('some/changed/dir', FileType.DIRECTORY, ChangeType.REMOVED_DIR, 0, 0, None, None, None, None, None), + ), + # Example from https://github.com/borgbase/vorta/issues/521 + ( +@@ -99,12 +123,25 @@ def check(feature_name): + None, + ('user', 'user', 'nfsnobody', 'nfsnobody'), + None, ++ None, ++ None, + ), + ), + # Very short owner change, to check stripping whitespace from file path + ( + '[a:a -> b:b] home/user/arrays/test.txt', +- ('home/user/arrays/test.txt', FileType.FILE, ChangeType.OWNER, 0, 0, None, ('a', 'a', 'b', 'b'), None), ++ ( ++ 'home/user/arrays/test.txt', ++ FileType.FILE, ++ ChangeType.OWNER, ++ 0, ++ 0, ++ None, ++ ('a', 'a', 'b', 'b'), ++ None, ++ None, ++ None, ++ ), + ), + # All file-related changes in one test + ( +@@ -117,6 +154,8 @@ def check(feature_name): + 77000, + ('-rw-rw-rw-', '-rw-r--r--'), + ('user', 'user', 'nfsnobody', 'nfsnobody'), ++ None, ++ None, + (77800, 800), + ), + ), +@@ -139,11 +178,22 @@ def test_archive_diff_parser(line, expected): + [ + ( + {'path': 'some/changed/link', 'changes': [{'type': 'changed link'}]}, +- ('some/changed/link', FileType.LINK, ChangeType.CHANGED_LINK, 0, 0, None, None, None), ++ ('some/changed/link', FileType.LINK, ChangeType.CHANGED_LINK, 0, 0, None, None, None, None, None), + ), + ( + {'path': 'some/changed/file', 'changes': [{'type': 'modified', 'added': 77800, 'removed': 77800}]}, +- ('some/changed/file', FileType.FILE, ChangeType.MODIFIED, 2 * 77800, 0, None, None, (77800, 77800)), ++ ( ++ 'some/changed/file', ++ FileType.FILE, ++ ChangeType.MODIFIED, ++ 2 * 77800, ++ 0, ++ None, ++ None, ++ None, ++ None, ++ (77800, 77800), ++ ), + ), + ( + { +@@ -161,6 +211,8 @@ def test_archive_diff_parser(line, expected): + 77000, + ('-rw-rw-rw-', '-rw-r--r--'), + None, ++ None, ++ None, + (77800, 800), + ), + ), +@@ -169,15 +221,26 @@ def test_archive_diff_parser(line, expected): + 'path': 'some/changed/file', + 'changes': [{'type': 'mode', 'old_mode': '-rw-rw-rw-', 'new_mode': '-rw-r--r--'}], + }, +- ('some/changed/file', FileType.FILE, ChangeType.MODE, 0, 0, ('-rw-rw-rw-', '-rw-r--r--'), None, None), ++ ( ++ 'some/changed/file', ++ FileType.FILE, ++ ChangeType.MODE, ++ 0, ++ 0, ++ ('-rw-rw-rw-', '-rw-r--r--'), ++ None, ++ None, ++ None, ++ None, ++ ), + ), + ( + {'path': 'some/changed/dir', 'changes': [{'type': 'added directory'}]}, +- ('some/changed/dir', FileType.DIRECTORY, ChangeType.ADDED, 0, 0, None, None, None), ++ ('some/changed/dir', FileType.DIRECTORY, ChangeType.ADDED, 0, 0, None, None, None, None, None), + ), + ( + {'path': 'some/changed/dir', 'changes': [{'type': 'removed directory'}]}, +- ('some/changed/dir', FileType.DIRECTORY, ChangeType.REMOVED_DIR, 0, 0, None, None, None), ++ ('some/changed/dir', FileType.DIRECTORY, ChangeType.REMOVED_DIR, 0, 0, None, None, None, None, None), + ), + # Example from https://github.com/borgbase/vorta/issues/521 + ( +@@ -202,6 +265,8 @@ def test_archive_diff_parser(line, expected): + None, + ('user', 'user', 'nfsnobody', 'nfsnobody'), + None, ++ None, ++ None, + ), + ), + # Very short owner change, to check stripping whitespace from file path +@@ -210,7 +275,74 @@ def test_archive_diff_parser(line, expected): + 'path': 'home/user/arrays/test.txt', + 'changes': [{'type': 'owner', 'old_user': 'a', 'new_user': 'b', 'old_group': 'a', 'new_group': 'b'}], + }, +- ('home/user/arrays/test.txt', FileType.FILE, ChangeType.OWNER, 0, 0, None, ('a', 'a', 'b', 'b'), None), ++ ( ++ 'home/user/arrays/test.txt', ++ FileType.FILE, ++ ChangeType.OWNER, ++ 0, ++ 0, ++ None, ++ ('a', 'a', 'b', 'b'), ++ None, ++ None, ++ None, ++ ), ++ ), ++ # Short ctime change ++ ( ++ { ++ 'path': 'home/user/arrays', ++ 'changes': [ ++ { ++ 'new_ctime': '2023-04-01T17:23:14.104630', ++ 'old_ctime': '2023-03-03T23:40:17.073948', ++ 'type': 'ctime', ++ } ++ ], ++ }, ++ ( ++ 'home/user/arrays', ++ FileType.FILE, ++ ChangeType.MODIFIED, ++ 0, ++ 0, ++ None, ++ None, ++ ( ++ QDateTime.fromString('2023-03-03T23:40:17.073948', Qt.DateFormat.ISODateWithMs), ++ QDateTime.fromString('2023-04-01T17:23:14.104630', Qt.DateFormat.ISODateWithMs), ++ ), ++ None, ++ None, ++ ), ++ ), ++ # Short mtime change ++ ( ++ { ++ 'path': 'home/user/arrays', ++ 'changes': [ ++ { ++ 'new_mtime': '2023-04-01T17:23:14.104630', ++ 'old_mtime': '2023-03-03T23:40:17.073948', ++ 'type': 'mtime', ++ } ++ ], ++ }, ++ ( ++ 'home/user/arrays', ++ FileType.FILE, ++ ChangeType.MODIFIED, ++ 0, ++ 0, ++ None, ++ None, ++ None, ++ ( ++ QDateTime.fromString('2023-03-03T23:40:17.073948', Qt.DateFormat.ISODateWithMs), ++ QDateTime.fromString('2023-04-01T17:23:14.104630', Qt.DateFormat.ISODateWithMs), ++ ), ++ None, ++ ), + ), + # All file-related changes in one test + ( +@@ -226,6 +358,16 @@ def test_archive_diff_parser(line, expected): + 'old_group': 'user', + 'new_group': 'nfsnobody', + }, ++ { ++ 'new_ctime': '2023-04-01T17:23:14.104630', ++ 'old_ctime': '2023-03-03T23:40:17.073948', ++ 'type': 'ctime', ++ }, ++ { ++ 'new_mtime': '2023-04-01T17:15:50.290565', ++ 'old_mtime': '2023-03-05T00:24:00.359045', ++ 'type': 'mtime', ++ }, + ], + }, + ( +@@ -236,6 +378,14 @@ def test_archive_diff_parser(line, expected): + 0, + ('-rw-rw-rw-', '-rw-r--r--'), + ('user', 'user', 'nfsnobody', 'nfsnobody'), ++ ( ++ QDateTime.fromString('2023-03-03T23:40:17.073948', Qt.DateFormat.ISODateWithMs), ++ QDateTime.fromString('2023-04-01T17:23:14.104630', Qt.DateFormat.ISODateWithMs), ++ ), ++ ( ++ QDateTime.fromString('2023-03-05T00:24:00.359045', Qt.DateFormat.ISODateWithMs), ++ QDateTime.fromString('2023-04-01T17:15:50.290565', Qt.DateFormat.ISODateWithMs), ++ ), + (77800, 77800), + ), + ), diff -Nru vorta-0.8.10/debian/patches/series vorta-0.8.10/debian/patches/series --- vorta-0.8.10/debian/patches/series 2023-01-23 20:06:42.000000000 +0000 +++ vorta-0.8.10/debian/patches/series 2023-07-31 15:10:53.000000000 +0000 @@ -3,3 +3,4 @@ 0003-fix-generic-privacy-breach-in-appdata.patch 0004-use-python3-in-Makefile.patch 0005-enable-colour-icon-in-notifications.patch +0006-Handle-ctime-and-mtime-diff-changes-1675.patch