def test_sip_arrange_create_many(db): arranges = [ models.SIPArrange(original_path=None, arrange_path="a.txt", file_uuid=None), models.SIPArrange(original_path=None, arrange_path="b.txt", file_uuid=None), ] assert not models.SIPArrange.objects.count() models.SIPArrange.create_many(arranges) assert models.SIPArrange.objects.count() == 2
def create_arrange_directories(paths): for path in paths: if not path.startswith(DEFAULT_ARRANGE_PATH): raise ValueError(_("All directories must be within the arrange directory.")) arranges = [ models.SIPArrange( original_path=None, arrange_path=os.path.join(path, ""), # ensure ends with / file_uuid=None, ) for path in paths ] models.SIPArrange.objects.bulk_create(arranges, BULK_CREATE_BATCH_SIZE)
def copy_to_arrange(request, sources=None, destinations=None, fetch_children=False): """ Add files to in-progress SIPs being arranged. Files being copied can be located in either the backlog or in another SIP being arranged. If sources or destinations are strs not a list, they will be converted into a list and fetch_children will be set to True. :param list sources: List of paths relative to this pipelines backlog. If None, will look for filepath[] or filepath :param list destinations: List of paths within arrange folder. All paths should start with DEFAULT_ARRANGE_PATH :param bool fetch_children: If True, will fetch all children of the provided path(s) to copy to the destination. """ if isinstance(sources, six.string_types) or isinstance( destinations, six.string_types ): fetch_children = True sources = [sources] destinations = [destinations] if sources is None or destinations is None: # List of sources & destinations if "filepath[]" in request.POST or "destination[]" in request.POST: sources = map(base64.b64decode, request.POST.getlist("filepath[]", [])) destinations = map( base64.b64decode, request.POST.getlist("destination[]", []) ) # Single path representing tree else: fetch_children = True sources = [base64.b64decode(request.POST.get("filepath", ""))] destinations = [base64.b64decode(request.POST.get("destination", ""))] logger.info("sources: %s", sources) logger.info("destinations: %s", destinations) # The DEFAULT_BACKLOG_PATH constant is missing a leading slash for # historical reasons; TODO change this at some point. # External paths passed into these views are in the format # /originals/, whereas copy_from_arrange_to_completed constructs # paths without a leading slash as an implementation detail # (to communicate with the Storage Service). # Possibly the constant used to refer to externally-constructed # paths and the one used solely internally should be two different # constants. if sources[0].startswith("/" + DEFAULT_BACKLOG_PATH): action = "copy" backlog_uuid = storage_service.get_location(purpose="BL")[0]["uuid"] elif sources[0].startswith(DEFAULT_ARRANGE_PATH): action = "move" else: logger.error( "Filepath %s is not in base backlog path nor arrange path", sources[0] ) return helpers.json_response( { "error": True, "message": _("%(path)s is not in base backlog path nor arrange path") % {"path": sources[0]}, } ) entries_to_copy = [] try: for source, dest in zip(sources, destinations): if action == "copy": entries = _copy_files_to_arrange( source, dest, fetch_children=fetch_children, backlog_uuid=backlog_uuid, ) for entry in entries: entries_to_copy.append( models.SIPArrange( original_path=entry["original_path"], arrange_path=entry["arrange_path"], file_uuid=entry["file_uuid"], transfer_uuid=entry["transfer_uuid"], ) ) elif action == "move": _move_files_within_arrange(source, dest) response = {"message": _("SIP files successfully moved.")} status_code = 200 if entries_to_copy: models.SIPArrange.objects.bulk_create( entries_to_copy, BULK_CREATE_BATCH_SIZE ) except ValueError as e: logger.exception("Failed copying %s to %s", source, dest) response = {"message": str(e), "error": True} status_code = 400 else: response = {"message": _("Files added to the SIP.")} status_code = 201 return helpers.json_response(response, status_code=status_code)