37
37
from framework import sentry
38
38
from framework .exceptions import HTTPError
39
39
from osf .models import Node , NodeLog , Registration , BaseFileNode
40
+ from osf .models .files import TrashedFileNode
40
41
from osf .exceptions import RegistrationStuckRecoverableException , RegistrationStuckBrokenException
41
42
from api .base .utils import waterbutler_api_url_for
42
43
from scripts import utils as script_utils
@@ -280,48 +281,72 @@ def get_logs_to_revert(reg):
280
281
Q (node = reg .registered_from ) |
281
282
(Q (params__source__nid = reg .registered_from ._id ) | Q (params__destination__nid = reg .registered_from ._id ))).order_by ('-date' )
282
283
284
+ def get_file_obj_from_log (log , reg ):
285
+ try :
286
+ return BaseFileNode .objects .get (_id = log .params ['urls' ]['view' ].split ('/' )[4 ])
287
+ except KeyError :
288
+ if log .action == 'osf_storage_folder_created' :
289
+ return OsfStorageFolder .objects .get (
290
+ target_object_id = reg .registered_from .id ,
291
+ name = log .params ['path' ].split ('/' )[- 2 ]
292
+ )
293
+ elif log .action == 'osf_storage_file_removed' :
294
+ path = log .params ['path' ].split ('/' )
295
+ return TrashedFileNode .objects .get (
296
+ target_object_id = reg .registered_from .id ,
297
+ name = path [- 1 ] or path [- 2 ] # file name or folder name
298
+ )
299
+ elif log .action in ['addon_file_moved' , 'addon_file_renamed' ]:
300
+ try :
301
+ return BaseFileNode .objects .get (_id = log .params ['source' ]['path' ].rstrip ('/' ).split ('/' )[- 1 ])
302
+ except (KeyError , BaseFileNode .DoesNotExist ):
303
+ return BaseFileNode .objects .get (_id = log .params ['destination' ]['path' ].rstrip ('/' ).split ('/' )[- 1 ])
304
+ else :
305
+ # Generic fallback
306
+ path = log .params .get ('path' , '' ).split ('/' )
307
+ if len (path ) >= 2 :
308
+ name = path [- 1 ] or path [- 2 ] # file name or folder name
309
+ return BaseFileNode .objects .get (
310
+ target_object_id = reg .registered_from .id ,
311
+ name = name
312
+ )
313
+
314
+ raise ValueError (f'Cannot determine file obj for log { log ._id } [Registration id { reg ._id } ]: { log .action } ' )
315
+
316
+
317
+ def handle_file_operation (file_tree , reg , file_obj , log , obj_cache ):
318
+ logger .info (f'Reverting { log .action } { file_obj ._id } :{ file_obj .name } from { log .date } ' )
319
+
320
+ if log .action in ['osf_storage_file_added' , 'osf_storage_folder_created' ]:
321
+ return modify_file_tree_recursive (reg ._id , file_tree , file_obj , deleted = True , cached = bool (file_obj ._id in obj_cache ))
322
+ elif log .action == 'osf_storage_file_removed' :
323
+ return modify_file_tree_recursive (reg ._id , file_tree , file_obj , deleted = False , cached = bool (file_obj ._id in obj_cache ))
324
+ elif log .action == 'osf_storage_file_updated' :
325
+ return modify_file_tree_recursive (reg ._id , file_tree , file_obj , cached = bool (file_obj ._id in obj_cache ), revert = True )
326
+ elif log .action == 'addon_file_moved' :
327
+ parent = BaseFileNode .objects .get (_id__in = obj_cache , name = '/{}' .format (log .params ['source' ]['materialized' ]).rstrip ('/' ).split ('/' )[- 2 ])
328
+ return modify_file_tree_recursive (reg ._id , file_tree , file_obj , cached = bool (file_obj ._id in obj_cache ), move_under = parent )
329
+ elif log .action == 'addon_file_renamed' :
330
+ return modify_file_tree_recursive (reg ._id , file_tree , file_obj , cached = bool (file_obj ._id in obj_cache ), rename = log .params ['source' ]['name' ])
331
+ else :
332
+ raise ValueError (f'Unexpected log action: { log .action } ' )
333
+
283
334
def revert_log_actions (file_tree , reg , obj_cache , permissible_addons ):
284
335
logs_to_revert = get_logs_to_revert (reg )
336
+
285
337
if len (permissible_addons ) > 1 :
286
338
logs_to_revert = logs_to_revert .exclude (action__in = PERMISSIBLE_BLACKLIST )
339
+
287
340
for log in list (logs_to_revert ):
288
- try :
289
- file_obj = BaseFileNode .objects .get (_id = log .params ['urls' ]['view' ].split ('/' )[4 ])
290
- except KeyError :
291
- try :
292
- file_obj = BaseFileNode .objects .get (_id = log .params ['source' ]['path' ].rstrip ('/' ).split ('/' )[- 1 ])
293
- except BaseFileNode .DoesNotExist :
294
- # Bad log data
295
- file_obj = BaseFileNode .objects .get (_id = log .params ['destination' ]['path' ].rstrip ('/' ).split ('/' )[- 1 ])
341
+ file_obj = get_file_obj_from_log (log , reg )
296
342
assert file_obj .target in reg .registered_from .root .node_and_primary_descendants ()
297
- if log .action == 'osf_storage_file_added' :
298
- # Find and mark deleted
299
- logger .info (f'Reverting add { file_obj ._id } :{ file_obj .name } from { log .date } ' )
300
- file_tree , noop = modify_file_tree_recursive (reg ._id , file_tree , file_obj , deleted = True , cached = bool (file_obj ._id in obj_cache ))
301
- elif log .action == 'osf_storage_file_removed' :
302
- # Find parent and add to children, or undelete
303
- logger .info (f'Reverting delete { file_obj ._id } :{ file_obj .name } from { log .date } ' )
304
- file_tree , noop = modify_file_tree_recursive (reg ._id , file_tree , file_obj , deleted = False , cached = bool (file_obj ._id in obj_cache ))
305
- elif log .action == 'osf_storage_file_updated' :
306
- # Find file and revert version
307
- logger .info (f'Reverting update { file_obj ._id } :{ file_obj .name } from { log .date } ' )
308
- file_tree , noop = modify_file_tree_recursive (reg ._id , file_tree , file_obj , cached = bool (file_obj ._id in obj_cache ), revert = True )
309
- elif log .action == 'osf_storage_folder_created' :
310
- # Find folder and mark deleted
311
- logger .info (f'Reverting folder { file_obj ._id } :{ file_obj .name } from { log .date } ' )
312
- file_tree , noop = modify_file_tree_recursive (reg ._id , file_tree , file_obj , deleted = True , cached = bool (file_obj ._id in obj_cache ))
313
- elif log .action == 'addon_file_moved' :
314
- logger .info (f'Reverting move { file_obj ._id } :{ file_obj .name } from { log .date } ' )
315
- parent = BaseFileNode .objects .get (_id__in = obj_cache , name = '/{}' .format (log .params ['source' ]['materialized' ]).rstrip ('/' ).split ('/' )[- 2 ])
316
- file_tree , noop = modify_file_tree_recursive (reg ._id , file_tree , file_obj , cached = bool (file_obj ._id in obj_cache ), move_under = parent )
317
- elif log .action == 'addon_file_renamed' :
318
- logger .info ('Reverting rename {}:{} -> {} from {}' .format (file_obj ._id , log .params ['source' ]['name' ], file_obj .name , log .date ))
319
- file_tree , noop = modify_file_tree_recursive (reg ._id , file_tree , file_obj , cached = bool (file_obj ._id in obj_cache ), rename = log .params ['source' ]['name' ])
320
- else :
321
- raise Exception (f'Unexpected log action: { log .action } ' )
343
+
344
+ file_tree , noop = handle_file_operation (file_tree , reg , file_obj , log , obj_cache )
322
345
assert not noop , f'{ reg ._id } : Failed to revert action for NodeLog { log ._id } '
346
+
323
347
if file_obj ._id not in obj_cache :
324
348
obj_cache .add (file_obj ._id )
349
+
325
350
return file_tree
326
351
327
352
def build_file_tree (reg , node_settings , * args , ** kwargs ):
@@ -337,7 +362,20 @@ def _recurse(file_obj, node):
337
362
'version' : int (file_obj .versions .latest ('created' ).identifier ) if file_obj .versions .exists () else None
338
363
}
339
364
if not file_obj .is_file :
340
- serialized ['children' ] = [_recurse (child , node ) for child in OsfStorageFileNode .objects .filter (target_object_id = node .id , target_content_type_id = ct_id , parent_id = file_obj .id )]
365
+ nonlocal reg
366
+ all_children = OsfStorageFileNode .objects .filter (
367
+ target_object_id = node .id ,
368
+ target_content_type_id = ct_id ,
369
+ parent_id = file_obj .id
370
+ ).union (
371
+ TrashedFileNode .objects .filter (
372
+ target_object_id = node .id ,
373
+ target_content_type_id = ct_id ,
374
+ parent_id = file_obj .id ,
375
+ modified__gt = reg .archive_job .created ,
376
+ )
377
+ )
378
+ serialized ['children' ] = [_recurse (child , node ) for child in all_children ]
341
379
return serialized
342
380
343
381
current_tree = _recurse (node_settings .get_root (), n )
0 commit comments