feat: add path tracking to items and improve checkout/checkin logic with discard support
This commit is contained in:
@@ -1751,7 +1751,8 @@ class SharePointApp(wx.Frame):
|
||||
self.list_ctrl.SetItem(i, 3, "") # Sidst ændret
|
||||
self.current_items.append({
|
||||
"type": "SITE", "id": site['id'], "name": name,
|
||||
"size": None, "modified": "", "web_url": site.get('webUrl')
|
||||
"size": None, "modified": "", "web_url": site.get('webUrl'),
|
||||
"path": ["SharePoint", name]
|
||||
})
|
||||
|
||||
def on_tree_expanding(self, event):
|
||||
@@ -1873,10 +1874,12 @@ class SharePointApp(wx.Frame):
|
||||
drives = res.json().get('value', [])
|
||||
drives.sort(key=lambda x: x.get('name', '').lower())
|
||||
for drive in drives:
|
||||
name = drive.get('name', '')
|
||||
items_data.append({
|
||||
"type": "DRIVE", "id": drive['id'], "name": drive.get('name', ''),
|
||||
"type": "DRIVE", "id": drive['id'], "name": name,
|
||||
"drive_id": drive['id'], "modified": "", "size": None,
|
||||
"web_url": drive.get('webUrl')
|
||||
"web_url": drive.get('webUrl'),
|
||||
"path": data['path'] + [name]
|
||||
})
|
||||
elif data['type'] in ["DRIVE", "FOLDER"]:
|
||||
drive_id = data['drive_id']
|
||||
@@ -1898,7 +1901,8 @@ class SharePointApp(wx.Frame):
|
||||
"drive_id": drive_id, "modified": modified,
|
||||
"size": item.get('size') if not is_folder else None,
|
||||
"web_url": item.get('webUrl'),
|
||||
"hash": item.get('file', {}).get('hashes', {}).get('quickXorHash') if not is_folder else None
|
||||
"hash": item.get('file', {}).get('hashes', {}).get('quickXorHash') if not is_folder else None,
|
||||
"path": data['path'] + [item['name']]
|
||||
})
|
||||
|
||||
wx.CallAfter(self._populate_list_ctrl, items_data, data)
|
||||
@@ -2192,14 +2196,20 @@ class SharePointApp(wx.Frame):
|
||||
if remote_hash and ENABLE_HASH_VALIDATION:
|
||||
file_size = os.path.getsize(get_long_path(local_path))
|
||||
if file_size <= (HASH_THRESHOLD_MB * 1024 * 1024):
|
||||
original_hash = quickxorhash(local_path)
|
||||
if original_hash != remote_hash:
|
||||
logger.warning(f"Hash mismatch for {file_name}: local={original_hash}, remote={remote_hash}")
|
||||
# Vi bruger fjern-hash direkte som vores 'original', hvis den er tilgængelig.
|
||||
# Vi tjekker dog lige at downloaden rent faktisk matchede.
|
||||
local_check = quickxorhash(local_path)
|
||||
if local_check == remote_hash:
|
||||
original_hash = remote_hash
|
||||
logger.info(f"Download ok for {file_name}. Bruger XOR hash til ændrings-detektering.")
|
||||
else:
|
||||
logger.warning(f"Hash mismatch efter download af {file_name}!")
|
||||
self.show_info(f"Advarsel: Filens integritet kunne ikke bekræftes (XorHash mismatch)", wx.ICON_WARNING)
|
||||
|
||||
original_hash = local_check
|
||||
|
||||
# Hvis vi ikke beregnede hash pga. størrelse eller manglende remote_hash, gør det nu for lokal detektering
|
||||
if original_hash is None:
|
||||
# Her bruger vi SHA256 af hastighedsårsager hvis XOR ikke er absolut nødvendig til lokal sammenligning
|
||||
# Her bruger vi SHA256 af hastighedsårsager til lokal sammenligning (før/efter)
|
||||
sha256 = hashlib.sha256()
|
||||
with open(get_long_path(local_path), 'rb') as f:
|
||||
while True:
|
||||
@@ -2207,9 +2217,16 @@ class SharePointApp(wx.Frame):
|
||||
if not chunk: break
|
||||
sha256.update(chunk)
|
||||
original_hash = "SHA256:" + sha256.hexdigest()
|
||||
logger.info(f"Bruger lokal SHA256 til ændrings-detektering for {file_name}")
|
||||
|
||||
# Checkout
|
||||
requests.post(f"{base_url}/checkout", headers=self.headers)
|
||||
is_checked_out = False
|
||||
checkout_res = requests.post(f"{base_url}/checkout", headers=self.headers)
|
||||
if checkout_res.status_code in [200, 201, 204]:
|
||||
is_checked_out = True
|
||||
logger.info(f"Fil {file_name} udtjekket succesfuldt.")
|
||||
else:
|
||||
logger.warning(f"Kunne ikke udtjekke {file_name} (Status: {checkout_res.status_code}). Fortsætter dog...")
|
||||
|
||||
# 3. Åbn & Overvåg
|
||||
self.set_status(self.get_txt("msg_opening_file", name=file_name))
|
||||
@@ -2259,18 +2276,29 @@ class SharePointApp(wx.Frame):
|
||||
new_hash = quickxorhash(local_path)
|
||||
|
||||
if original_hash == new_hash:
|
||||
logger.info(f"Ingen ændringer fundet i {file_name}. (Hash: {new_hash[:16]}...) Springer upload over.")
|
||||
self.set_status(self.get_txt("msg_file_unchanged"))
|
||||
|
||||
if is_checked_out:
|
||||
logger.info(f"Annullerer udtjekning (discardCheckout) for {file_name}...")
|
||||
res = requests.post(f"{base_url}/discardCheckout", headers=self.headers)
|
||||
if res.status_code in [200, 204]:
|
||||
is_checked_out = False
|
||||
else:
|
||||
# 5. Upload (kun hvis ændret)
|
||||
logger.info(f"Ændring fundet! Uploader {file_name}...")
|
||||
self.set_status(self.get_txt("msg_updating_changes"))
|
||||
with open(local_path, 'rb') as f:
|
||||
upload_res = requests.put(f"{base_url}/content", headers=self.headers, data=f)
|
||||
if upload_res.status_code not in [200, 201]:
|
||||
raise Exception(f"{self.get_txt('msg_update_failed_code', code=upload_res.status_code)}")
|
||||
|
||||
# 6. Checkin (Uanset om ændret eller ej, for at frigive lås)
|
||||
self.set_status(self.get_txt("msg_checking_in", name=file_name))
|
||||
requests.post(f"{base_url}/checkin", headers=self.headers, json={"comment": "SP Explorer Edit"})
|
||||
|
||||
# 6. Checkin (Kun hvis vi faktisk uploadede noget)
|
||||
if is_checked_out:
|
||||
self.set_status(self.get_txt("msg_checking_in", name=file_name))
|
||||
res = requests.post(f"{base_url}/checkin", headers=self.headers, json={"comment": "SP Explorer Edit"})
|
||||
if res.status_code in [200, 201, 204]:
|
||||
is_checked_out = False
|
||||
|
||||
# Oprydning: Slet fil og derefter mappe
|
||||
try:
|
||||
@@ -2287,6 +2315,11 @@ class SharePointApp(wx.Frame):
|
||||
self.set_status(f"{self.get_txt('msg_error')}: {str(e)}")
|
||||
self.show_info(f"{self.get_txt('msg_error')}: {e}", wx.ICON_ERROR)
|
||||
finally:
|
||||
if is_checked_out:
|
||||
# Emergency cleanup hvis vi stadig har fat i filen (f.eks. ved crash eller afbrydelse)
|
||||
logger.info(f"Rydder op: Kalder discardCheckout for {file_name}...")
|
||||
requests.post(f"{base_url}/discardCheckout", headers=self.headers)
|
||||
|
||||
if item_id in self.active_edits:
|
||||
del self.active_edits[item_id]
|
||||
self.update_edit_ui()
|
||||
|
||||
Reference in New Issue
Block a user