Skip to content

Commit fe79910

Browse files
author
Dirk Petersen (aider)
committed
perf: delay write permission check for large hotspot files
1 parent b5c1ad8 commit fe79910

File tree

1 file changed

+79
-43
lines changed

1 file changed

+79
-43
lines changed

froster/froster.py

Lines changed: 79 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3911,14 +3911,21 @@ def archive_select_hotspots(self):
39113911
hotspot_selected = os.path.join(self.cfg.hotspots_dir, ret[0])
39123912

39133913
# Get the path to the user-specific CSV file containing only writable folders
3914-
user_hotspot_file_path = self.get_hotspot_folders(hotspot_selected) # Now returns a path
3915-
3916-
if not user_hotspot_file_path:
3917-
log(f'\nNo hotspots with write permissions found or accessible in {hotspot_selected}.\n')
3914+
path_result, filtering_skipped = self.get_hotspot_folders(hotspot_selected)
3915+
3916+
# Determine the actual path to display in the table
3917+
if path_result:
3918+
path_to_display = path_result
3919+
elif filtering_skipped:
3920+
# Filtering skipped, use the original selected file
3921+
path_to_display = hotspot_selected
3922+
else:
3923+
# Filtering attempted but failed or no writable folders found
3924+
log(f'\nNo writable hotspots found or accessible in {hotspot_selected}.\n')
39183925
return True # Indicate completion, even if nothing was archived
39193926

39203927
# Use TableHotspots to display the filtered list and select the specific folder row
3921-
app = TableHotspots(user_hotspot_file_path)
3928+
app = TableHotspots(path_to_display)
39223929
ret = app.run() # ret can be (row_data, action) or []
39233930

39243931
if not ret:
@@ -3933,6 +3940,17 @@ def archive_select_hotspots(self):
39333940
# Assuming the folder path is the 6th element (index 5)
39343941
folder_to_archive = row_data[5]
39353942

3943+
# Permission check if filtering was skipped
3944+
if filtering_skipped:
3945+
log(f"Checking write permission for selected folder: {folder_to_archive}")
3946+
has_permission = self._check_path_permissions(folder_to_archive, write_only=True)
3947+
if not has_permission:
3948+
log(f'\nError: Write permission denied for selected folder: {folder_to_archive}\n')
3949+
# Ideally, we'd go back to the table here, but for simplicity, we exit.
3950+
return False # Indicate failure
3951+
else:
3952+
log(" Permission granted.")
3953+
39363954
if action == "continue":
39373955
# Archive the selected folders
39383956
return self.archive([folder_to_archive])
@@ -4397,6 +4415,21 @@ def unmount(self, folders):
43974415
def _filter_hotspots_by_write_access(self, hotspot_csv):
43984416
# Helper function to filter hotspots based on write access and return user-specific CSV path
43994417
try:
4418+
# Count lines in the original file first
4419+
line_count = 0
4420+
try:
4421+
with open(hotspot_csv, 'r') as f_count:
4422+
# Simple line count, including header
4423+
line_count = sum(1 for _ in f_count)
4424+
except Exception as e:
4425+
log(f"Warning: Could not count lines in {hotspot_csv}: {e}", file=sys.stderr)
4426+
# Proceed assuming fewer than 5000 lines
4427+
4428+
# If line count is too high, skip filtering
4429+
if line_count >= 5000:
4430+
log(f"Skipping proactive write permission check for large file ({line_count} lines): {hotspot_csv}")
4431+
return (None, True) # Return None path, indicate filtering skipped
4432+
44004433
hsdir, hsfile = os.path.split(hotspot_csv)
44014434
# Ensure user-specific directory exists within the main hotspots dir
44024435
hsdiruser = os.path.join(self.cfg.hotspots_dir, self.cfg.whoami)
@@ -4407,7 +4440,7 @@ def _filter_hotspots_by_write_access(self, hotspot_csv):
44074440
if os.path.exists(user_csv) and os.path.getmtime(user_csv) > os.path.getmtime(hotspot_csv):
44084441
if not self.args.force:
44094442
# log(f"Using existing user hotspot file: {user_csv}") # Optional debug log
4410-
return user_csv
4443+
return (user_csv, False) # Return path, indicate filtering NOT skipped
44114444
else:
44124445
log(f"Re-filtering hotspots due to --force flag: {hotspot_csv}")
44134446

@@ -4423,7 +4456,7 @@ def _filter_hotspots_by_write_access(self, hotspot_csv):
44234456
header_list = next(reader_count, None)
44244457
if not header_list:
44254458
log(f"Error: Hotspot file is empty or has no header: {hotspot_csv}", file=sys.stderr)
4426-
return None
4459+
return (None, False)
44274460
fieldnames = header_list
44284461
try:
44294462
# Count remaining lines
@@ -4440,7 +4473,7 @@ def _filter_hotspots_by_write_access(self, hotspot_csv):
44404473

44414474
if 'Folder' not in fieldnames:
44424475
log(f"Error: 'Folder' column not found in hotspot file: {hotspot_csv}", file=sys.stderr)
4443-
return None
4476+
return (None, False)
44444477

44454478
# Use tqdm for progress indication
44464479
for row in tqdm.tqdm(reader, total=total_lines, desc="Checking write access", unit="folder", disable=self.output_disable):
@@ -4451,17 +4484,17 @@ def _filter_hotspots_by_write_access(self, hotspot_csv):
44514484

44524485
except FileNotFoundError:
44534486
log(f"Error: Hotspot file not found: {hotspot_csv}", file=sys.stderr)
4454-
return None
4487+
return (None, False)
44554488
except Exception as e:
44564489
print_error(f"Error reading hotspot file {hotspot_csv}: {e}")
4457-
return None
4490+
return (None, False)
44584491

44594492
# Write the filtered data (or just header if no writable folders found)
44604493
try:
44614494
with open(user_csv, mode='w', newline='') as outfile:
44624495
if not fieldnames: # Should have fieldnames if we got here
44634496
log("Error: Missing fieldnames for writing user hotspot file.", file=sys.stderr)
4464-
return None
4497+
return (None, False)
44654498
writer = csv.DictWriter(outfile, fieldnames=fieldnames)
44664499
writer.writeheader()
44674500
if writable_folders_data:
@@ -4470,50 +4503,53 @@ def _filter_hotspots_by_write_access(self, hotspot_csv):
44704503
else:
44714504
log(f"No writable folders found. Empty file created: {user_csv}")
44724505

4473-
return user_csv # Return path even if only header was written
4506+
return (user_csv, False) # Return path even if only header was written
44744507

44754508
except Exception:
44764509
print_error(f"Error writing user hotspot file: {user_csv}")
4477-
return None
4510+
return (None, False)
44784511

44794512
except Exception:
44804513
print_error("Error in _filter_hotspots_by_write_access")
4481-
return None
4514+
return (None, False)
44824515

44834516
def get_hotspot_folders(self, hotspot_file):
44844517
# This function now filters the hotspot file for writable folders
4485-
# and returns the path to the new user-specific CSV file.
4486-
# It no longer returns the list of folders directly.
4518+
# and returns the path to the new user-specific CSV file and a flag
4519+
# indicating if filtering was skipped.
44874520

44884521
# Check write permissions and create a user-specific CSV
4489-
user_csv_path = self._filter_hotspots_by_write_access(hotspot_file)
4490-
if not user_csv_path:
4491-
return None # Indicate failure or no writable folders
4492-
4493-
# Check if the user-specific CSV has any data rows besides the header
4494-
try:
4495-
with open(user_csv_path, 'r', newline='') as f:
4496-
reader = csv.reader(f)
4497-
header = next(reader, None) # Read header
4498-
if not header:
4499-
log(f"Warning: User hotspot file is empty or missing header: {user_csv_path}")
4500-
# Optionally remove empty file if desired
4501-
# os.remove(user_csv_path)
4502-
return None
4503-
first_row = next(reader, None) # Try to read the first data row
4504-
if first_row is None:
4505-
log(f"No writable hotspot folders found in: {hotspot_file}")
4506-
# Optionally remove empty file if desired
4507-
# os.remove(user_csv_path)
4508-
return None # No data rows found
4509-
except FileNotFoundError:
4510-
log(f"Error: Filtered hotspot file not found after creation: {user_csv_path}", file=sys.stderr)
4511-
return None
4512-
except Exception:
4513-
print_error(f"Error checking user hotspot file content: {user_csv_path}")
4514-
return None
4522+
path_result, filtering_skipped = self._filter_hotspots_by_write_access(hotspot_file)
4523+
4524+
if not path_result and not filtering_skipped:
4525+
# Filtering was attempted but failed or resulted in an empty file path
4526+
log(f"No writable hotspot folders found or error during filtering for: {hotspot_file}")
4527+
return (None, False) # Return None path, filtering not skipped (but failed)
4528+
elif not path_result and filtering_skipped:
4529+
# Filtering was skipped, return original path and flag
4530+
return (hotspot_file, True)
4531+
4532+
# Check if the user-specific CSV has any data rows besides the header (only if filtering happened)
4533+
if not filtering_skipped:
4534+
try:
4535+
with open(path_result, 'r', newline='') as f:
4536+
reader = csv.reader(f)
4537+
header = next(reader, None) # Read header
4538+
if not header:
4539+
log(f"Warning: User hotspot file is empty or missing header: {path_result}")
4540+
return (None, False) # Treat as failure
4541+
first_row = next(reader, None) # Try to read the first data row
4542+
if first_row is None:
4543+
log(f"No writable hotspot folders found in: {hotspot_file}")
4544+
return (None, False) # No data rows found
4545+
except FileNotFoundError:
4546+
log(f"Error: Filtered hotspot file not found after creation: {path_result}", file=sys.stderr)
4547+
return (None, False) # Treat as failure
4548+
except Exception:
4549+
print_error(f"Error checking user hotspot file content: {path_result}")
4550+
return (None, False) # Treat as failure
45154551

4516-
return user_csv_path # Return the path to the filtered CSV
4552+
return (path_result, filtering_skipped) # Return the path and the flag
45174553

45184554
def _check_path_permissions(self, path, write_only=False):
45194555
'''Check if the user has read and write permissions to the given path'''

0 commit comments

Comments
 (0)