예제 #1
0
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
예제 #2
0
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)
예제 #3
0
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)