From d5be2eb1523eab6e47522447d0d3ee8e5bbc77c9 Mon Sep 17 00:00:00 2001 From: Forbes Date: Sat, 31 Jan 2026 19:13:09 -0600 Subject: [PATCH] fix: push detects locally modified files, renumber migration to 010 - Fix FreeCAD Push command: compare local file mtime against server's latest file revision timestamp instead of just checking file existence. Previously, any file already uploaded (even at an older revision) was skipped, causing 'All local files are already uploaded' when local files were newer. - Add SiloClient.latest_file_revision() helper method - Renumber 009_item_extended_fields.sql to 010 to avoid collision with 009_auth.sql from the auth system --- ...ields.sql => 010_item_extended_fields.sql} | 0 pkg/freecad/silo_commands.py | 40 +++++++++++++++++-- 2 files changed, 37 insertions(+), 3 deletions(-) rename migrations/{009_item_extended_fields.sql => 010_item_extended_fields.sql} (100%) diff --git a/migrations/009_item_extended_fields.sql b/migrations/010_item_extended_fields.sql similarity index 100% rename from migrations/009_item_extended_fields.sql rename to migrations/010_item_extended_fields.sql diff --git a/pkg/freecad/silo_commands.py b/pkg/freecad/silo_commands.py index 9e7c698..0e465dd 100644 --- a/pkg/freecad/silo_commands.py +++ b/pkg/freecad/silo_commands.py @@ -534,6 +534,17 @@ class SiloClient: except Exception: return False, None + def latest_file_revision(self, part_number: str) -> Optional[Dict]: + """Return the most recent revision that has a file attached, or None.""" + try: + revisions = self.get_revisions(part_number) + for rev in revisions: # revisions come newest-first from the API + if rev.get("file_key"): + return rev + return None + except Exception: + return None + def compare_revisions( self, part_number: str, from_rev: int, to_rev: int ) -> Dict[str, Any]: @@ -1757,9 +1768,11 @@ class Silo_Push: } def Activated(self): + from datetime import datetime, timezone + from PySide import QtGui - # Find unuploaded files + # Find files that need uploading (no server file, or local is newer) local_files = search_local_files() unuploaded = [] @@ -1767,9 +1780,30 @@ class Silo_Push: pn = lf["part_number"] try: _client.get_item(pn) # Check if in DB - has_file, _ = _client.has_file(pn) - if not has_file: + server_rev = _client.latest_file_revision(pn) + if not server_rev: + # No file on server at all unuploaded.append(lf) + else: + # Compare local mtime against server revision timestamp + try: + local_mtime = os.path.getmtime(lf["path"]) + server_time_str = server_rev.get("created_at", "") + if server_time_str: + server_dt = datetime.fromisoformat( + server_time_str.replace("Z", "+00:00") + ) + local_dt = datetime.fromtimestamp( + local_mtime, tz=timezone.utc + ) + if local_dt > server_dt: + unuploaded.append(lf) + else: + # Can't parse server time, assume needs upload + unuploaded.append(lf) + except Exception: + # On any comparison error, include it + unuploaded.append(lf) except Exception: pass # Not in DB, skip