Esempio n. 1
0
def _write_entry_on_external_device(metadata, file_path, ready_callback=None):
    """Create and update an entry copied from the
    DS to an external storage device.

    Besides copying the associated file a file for the preview
    and one for the metadata are stored in the hidden directory
    .Sugar-Metadata.

    This function handles renames of an entry on the
    external device and avoids name collisions. Renames are
    handled failsafe.

    """
    def _ready_cb():
        if ready_callback:
            ready_callback(metadata, file_path, destination_path)

    def _splice_cb(*args):
        created.send(None, object_id=destination_path)
        _ready_cb()

    if 'uid' in metadata and os.path.exists(metadata['uid']):
        file_path = metadata['uid']

    if not file_path or not os.path.exists(file_path):
        raise ValueError('Entries without a file cannot be copied to '
                         'removable devices')

    if not metadata.get('title'):
        metadata['title'] = _('Untitled')
    file_name = get_file_name(metadata['title'], metadata['mime_type'])

    destination_path = os.path.join(metadata['mountpoint'], file_name)
    if destination_path != file_path:
        file_name = get_unique_file_name(metadata['mountpoint'], file_name)
        destination_path = os.path.join(metadata['mountpoint'], file_name)
        clean_name, extension_ = os.path.splitext(file_name)
        metadata['title'] = clean_name

    metadata_copy = metadata.copy()
    metadata_copy.pop('mountpoint', None)
    metadata_copy.pop('uid', None)
    metadata_copy.pop('filesize', None)

    metadata_dir_path = os.path.join(metadata['mountpoint'],
                                     JOURNAL_METADATA_DIR)
    if not os.path.exists(metadata_dir_path):
        os.mkdir(metadata_dir_path)

    # Set the HIDDEN attrib even when the metadata directory already
    # exists for backward compatibility; but don't set it in ~/Documents
    if not metadata['mountpoint'] == get_documents_path():
        if not SugarExt.fat_set_hidden_attrib(metadata_dir_path):
            logging.error('Could not set hidden attribute on %s' %
                          (metadata_dir_path))

    preview = None
    if 'preview' in metadata_copy:
        preview = metadata_copy['preview']
        preview_fname = file_name + '.preview'
        metadata_copy.pop('preview', None)

    try:
        metadata_json = json.dumps(metadata_copy)
    except (UnicodeDecodeError, EnvironmentError):
        logging.error('Could not convert metadata to json.')
    else:
        (fh, fn) = tempfile.mkstemp(dir=metadata['mountpoint'])
        os.write(fh, metadata_json)
        os.close(fh)
        os.rename(fn, os.path.join(metadata_dir_path, file_name + '.metadata'))

        if preview:
            (fh, fn) = tempfile.mkstemp(dir=metadata['mountpoint'])
            os.write(fh, preview)
            os.close(fh)
            os.rename(fn, os.path.join(metadata_dir_path, preview_fname))

    if not os.path.dirname(destination_path) == os.path.dirname(file_path):
        input_stream = Gio.File.new_for_path(file_path).read(None)
        output_stream = Gio.File.new_for_path(destination_path)\
            .append_to(Gio.FileCreateFlags.PRIVATE |
                       Gio.FileCreateFlags.REPLACE_DESTINATION, None)

        # TODO: use Gio.File.copy_async, when implemented
        output_stream.splice_async(
            input_stream,
            Gio.OutputStreamSpliceFlags.CLOSE_SOURCE |
            Gio.OutputStreamSpliceFlags.CLOSE_TARGET,
            GLib.PRIORITY_LOW, None, _splice_cb, None)
    else:
        _rename_entry_on_external_device(file_path, destination_path,
                                         metadata_dir_path)
        _ready_cb()
Esempio n. 2
0
def _write_entry_on_external_device(metadata, file_path):
    """Create and update an entry copied from the
    DS to an external storage device.

    Besides copying the associated file a file for the preview
    and one for the metadata are stored in the hidden directory
    .Sugar-Metadata.

    This function handles renames of an entry on the
    external device and avoids name collisions. Renames are
    handled failsafe.

    """
    if 'uid' in metadata and os.path.exists(metadata['uid']):
        file_path = metadata['uid']

    if not file_path or not os.path.exists(file_path):
        raise ValueError('Entries without a file cannot be copied to '
                         'removable devices')

    if not metadata.get('title'):
        metadata['title'] = _('Untitled')
    file_name = get_file_name(metadata['title'], metadata['mime_type'])

    destination_path = os.path.join(metadata['mountpoint'], file_name)
    if destination_path != file_path:
        file_name = get_unique_file_name(metadata['mountpoint'], file_name)
        destination_path = os.path.join(metadata['mountpoint'], file_name)
        clean_name, extension_ = os.path.splitext(file_name)
        metadata['title'] = clean_name

    metadata_copy = metadata.copy()
    metadata_copy.pop('mountpoint', None)
    metadata_copy.pop('uid', None)
    metadata_copy.pop('filesize', None)

    metadata_dir_path = os.path.join(metadata['mountpoint'],
                                     JOURNAL_METADATA_DIR)
    if not os.path.exists(metadata_dir_path):
        os.mkdir(metadata_dir_path)

    # Set the HIDDEN attrib even when the metadata directory already
    # exists for backward compatibility.
    if not SugarExt.fat_set_hidden_attrib(metadata_dir_path):
        logging.error('Could not set hidden attribute on %s' %
                      (metadata_dir_path))

    preview = None
    if 'preview' in metadata_copy:
        preview = metadata_copy['preview']
        preview_fname = file_name + '.preview'
        metadata_copy.pop('preview', None)

    try:
        metadata_json = json.dumps(metadata_copy)
    except (UnicodeDecodeError, EnvironmentError):
        logging.error('Could not convert metadata to json.')
    else:
        (fh, fn) = tempfile.mkstemp(dir=metadata['mountpoint'])
        os.write(fh, metadata_json)
        os.close(fh)
        os.rename(fn, os.path.join(metadata_dir_path, file_name + '.metadata'))

        if preview:
            (fh, fn) = tempfile.mkstemp(dir=metadata['mountpoint'])
            os.write(fh, preview)
            os.close(fh)
            os.rename(fn, os.path.join(metadata_dir_path, preview_fname))

    if not os.path.dirname(destination_path) == os.path.dirname(file_path):
        shutil.copy(file_path, destination_path)
    else:
        _rename_entry_on_external_device(file_path, destination_path,
                                         metadata_dir_path)

    object_id = destination_path
    created.send(None, object_id=object_id)

    return object_id
Esempio n. 3
0
def _write_entry_on_external_device(metadata, file_path, ready_callback=None):
    """Create and update an entry copied from the
    DS to an external storage device.

    Besides copying the associated file a file for the preview
    and one for the metadata are stored in the hidden directory
    .Sugar-Metadata.

    This function handles renames of an entry on the
    external device and avoids name collisions. Renames are
    handled failsafe.

    """
    def _ready_cb():
        if ready_callback:
            ready_callback(metadata, file_path, destination_path)

    def _updated_cb(*args):
        updated.send(None, object_id=destination_path)
        _ready_cb()

    def _splice_cb(*args):
        created.send(None, object_id=destination_path)
        _ready_cb()

    if 'uid' in metadata and os.path.exists(metadata['uid']):
        file_path = metadata['uid']

    if not file_path or not os.path.exists(file_path):
        raise ValueError('Entries without a file cannot be copied to '
                         'removable devices')

    if not metadata.get('title'):
        metadata['title'] = _('Untitled')

    original_file_name = os.path.basename(file_path)
    original_dir_name = os.path.dirname(file_path)
    # if is a file in the exernal device or Documents
    # and the title is equal to the file name don't change it
    if original_file_name == metadata['title'] and \
            original_dir_name.startswith(metadata['mountpoint']):
        destination_path = file_path
        file_name = original_file_name
    else:
        file_name = metadata['title']
        # only change the extension if the title don't have a good extension
        clean_name, extension = os.path.splitext(file_name)
        extension = extension.replace('.', '').lower()
        mime_extensions = mime.get_extensions_by_mimetype(
            metadata['mime_type'])
        if extension not in mime_extensions:
            file_name = get_file_name(metadata['title'], metadata['mime_type'])

        destination_path = os.path.join(metadata['mountpoint'], file_name)
        if destination_path != file_path:
            file_name = get_unique_file_name(metadata['mountpoint'], file_name)
            destination_path = os.path.join(metadata['mountpoint'], file_name)
            metadata['title'] = file_name

    metadata_copy = metadata.copy()
    metadata_copy.pop('mountpoint', None)
    metadata_copy.pop('uid', None)
    metadata_copy.pop('filesize', None)

    metadata_dir_path = os.path.join(metadata['mountpoint'],
                                     JOURNAL_METADATA_DIR)
    # check if the file is in a subdirectory in Documents or device
    if original_dir_name.startswith(metadata['mountpoint']) and \
            original_dir_name != metadata['mountpoint']:
        subdir = os.path.relpath(original_dir_name, metadata['mountpoint'])
        metadata_dir_path = os.path.join(metadata_dir_path, subdir)
    if not os.path.exists(metadata_dir_path):
        os.makedirs(metadata_dir_path)

    # Set the HIDDEN attrib even when the metadata directory already
    # exists for backward compatibility; but don't set it in ~/Documents
    if not metadata['mountpoint'] == get_documents_path():
        if not SugarExt.fat_set_hidden_attrib(metadata_dir_path):
            logging.error('Could not set hidden attribute on %s' %
                          (metadata_dir_path))

    preview = None
    if 'preview' in metadata_copy:
        preview = metadata_copy['preview']
        preview_fname = file_name + '.preview'
        metadata_copy.pop('preview', None)

    try:
        metadata_json = json.dumps(metadata_copy)
    except (UnicodeDecodeError, EnvironmentError):
        logging.error('Could not convert metadata to json.')
    else:
        (fh, fn) = tempfile.mkstemp(dir=metadata['mountpoint'])
        os.write(fh, metadata_json)
        os.close(fh)
        os.rename(fn, os.path.join(metadata_dir_path, file_name + '.metadata'))

        if preview:
            (fh, fn) = tempfile.mkstemp(dir=metadata['mountpoint'])
            os.write(fh, preview)
            os.close(fh)
            os.rename(fn, os.path.join(metadata_dir_path, preview_fname))

    if not os.path.dirname(destination_path) == os.path.dirname(file_path):
        input_stream = Gio.File.new_for_path(file_path).read(None)
        output_stream = Gio.File.new_for_path(destination_path)\
            .append_to(Gio.FileCreateFlags.PRIVATE |
                       Gio.FileCreateFlags.REPLACE_DESTINATION, None)

        # TODO: use Gio.File.copy_async, when implemented
        output_stream.splice_async(
            input_stream, Gio.OutputStreamSpliceFlags.CLOSE_SOURCE
            | Gio.OutputStreamSpliceFlags.CLOSE_TARGET, GLib.PRIORITY_LOW,
            None, _splice_cb, None)
    else:
        _rename_entry_on_external_device(file_path, destination_path,
                                         metadata_dir_path)
        _updated_cb()
Esempio n. 4
0
def _write_entry_on_external_device(metadata, file_path):
    """Create and update an entry copied from the
    DS to an external storage device.

    Besides copying the associated file a file for the preview
    and one for the metadata are stored in the hidden directory
    .Sugar-Metadata.

    This function handles renames of an entry on the
    external device and avoids name collisions. Renames are
    handled failsafe.

    """
    if 'uid' in metadata and os.path.exists(metadata['uid']):
        file_path = metadata['uid']

    if not file_path or not os.path.exists(file_path):
        raise ValueError('Entries without a file cannot be copied to '
                         'removable devices')

    if not metadata.get('title'):
        metadata['title'] = _('Untitled')
    file_name = get_file_name(metadata['title'], metadata['mime_type'])

    destination_path = os.path.join(metadata['mountpoint'], file_name)
    if destination_path != file_path:
        file_name = get_unique_file_name(metadata['mountpoint'], file_name)
        destination_path = os.path.join(metadata['mountpoint'], file_name)
        clean_name, extension_ = os.path.splitext(file_name)
        metadata['title'] = clean_name

    metadata_copy = metadata.copy()
    metadata_copy.pop('mountpoint', None)
    metadata_copy.pop('uid', None)
    metadata_copy.pop('filesize', None)

    metadata_dir_path = os.path.join(metadata['mountpoint'],
                                     JOURNAL_METADATA_DIR)
    if not os.path.exists(metadata_dir_path):
        os.mkdir(metadata_dir_path)

    # Set the HIDDEN attrib even when the metadata directory already
    # exists for backward compatibility.
    if not SugarExt.fat_set_hidden_attrib(metadata_dir_path):
        logging.error('Could not set hidden attribute on %s' %
                      (metadata_dir_path))

    preview = None
    if 'preview' in metadata_copy:
        preview = metadata_copy['preview']
        preview_fname = file_name + '.preview'
        metadata_copy.pop('preview', None)

    try:
        metadata_json = json.dumps(metadata_copy)
    except (UnicodeDecodeError, EnvironmentError):
        logging.error('Could not convert metadata to json.')
    else:
        (fh, fn) = tempfile.mkstemp(dir=metadata['mountpoint'])
        os.write(fh, metadata_json)
        os.close(fh)
        os.rename(fn, os.path.join(metadata_dir_path, file_name + '.metadata'))

        if preview:
            (fh, fn) = tempfile.mkstemp(dir=metadata['mountpoint'])
            os.write(fh, preview)
            os.close(fh)
            os.rename(fn, os.path.join(metadata_dir_path, preview_fname))

    if not os.path.dirname(destination_path) == os.path.dirname(file_path):
        shutil.copy(file_path, destination_path)
    else:
        _rename_entry_on_external_device(file_path, destination_path,
                                         metadata_dir_path)

    object_id = destination_path
    created.send(None, object_id=object_id)

    return object_id