@@ -256,15 +256,60 @@ supabase_upload_survey <- function(survey_path, survey_name = NULL, conn = NULL,
256256 }
257257
258258 tryCatch({
259- # Get all files in the survey folder
259+ # STEP 1: Get all local files
260260 all_files <- list.files(survey_path , recursive = TRUE , full.names = TRUE )
261+ local_relative_paths <- vapply(all_files , function (f ) {
262+ if (dir.exists(f )) return (" " )
263+ gsub(paste0(" ^" , survey_path , " /?" ), " " , f )
264+ }, character (1 ))
265+ local_relative_paths <- local_relative_paths [local_relative_paths != " " ]
266+
267+ # STEP 2: Get all files currently in Supabase for this survey
268+ list_url <- build_list_url(conn )
269+ list_response <- httr2 :: request(list_url ) | >
270+ httr2 :: req_headers(
271+ " Authorization" = paste(" Bearer" , conn $ service_key ),
272+ " apikey" = conn $ service_key
273+ ) | >
274+ httr2 :: req_body_json(list (
275+ prefix = paste0(conn $ base_path , " /" , survey_name , " /" ),
276+ limit = 1000 ,
277+ offset = 0
278+ )) | >
279+ httr2 :: req_perform()
261280
262- if (length(all_files ) == 0 ) {
263- warning(" No files found in survey folder: " , survey_path )
264- return (FALSE )
281+ supabase_content <- httr2 :: resp_body_json(list_response )
282+ supabase_paths <- character (0 )
283+ if (length(supabase_content ) > 0 ) {
284+ supabase_full_paths <- vapply(supabase_content , function (x ) x $ name , character (1 ))
285+ # Extract relative paths
286+ supabase_paths <- gsub(paste0(" ^" , conn $ base_path , " /" , survey_name , " /" ), " " , supabase_full_paths )
287+ # Remove directory entries (paths ending in /)
288+ supabase_paths <- supabase_paths [! grepl(" /$" , supabase_paths )]
289+ }
290+
291+ # STEP 3: Delete files from Supabase that don't exist locally
292+ files_to_delete <- setdiff(supabase_paths , local_relative_paths )
293+ if (length(files_to_delete ) > 0 ) {
294+ delete_url <- paste0(conn $ url , " /storage/v1/object/" , conn $ bucket )
295+ for (rel_path in files_to_delete ) {
296+ storage_path <- paste0(conn $ base_path , " /" , survey_name , " /" , rel_path )
297+ tryCatch({
298+ httr2 :: request(delete_url ) | >
299+ httr2 :: req_headers(
300+ " Authorization" = paste(" Bearer" , conn $ service_key ),
301+ " apikey" = conn $ service_key
302+ ) | >
303+ httr2 :: req_body_json(list (prefixes = list (storage_path ))) | >
304+ httr2 :: req_method(" DELETE" ) | >
305+ httr2 :: req_perform()
306+ }, error = function (e ) {
307+ # Silently ignore delete errors
308+ })
309+ }
265310 }
266311
267- # Upload each file
312+ # STEP 4: Upload all local files (new or modified)
268313 upload_success <- TRUE
269314 for (file_path in all_files ) {
270315 # Skip directories
0 commit comments