示例#1
0
def _edit(args):
    """Edit the mapping directly using an editor."""
    if args:
        abort(USAGE + 'dtags: too many arguments')
    try:
        with TempFile(
            mode='w+t', delete=False, prefix='mapping.', dir=CFG_DIR
        ) as tfile:
            with io.open(MAPPING_FILE, 'rt') as mapping_file:
                tfile.write(EDIT_HELP_COMMENTS + mapping_file.read())
            tfile.flush()
    except (OSError, IOError) as err:
        abort('dtags: failed to edit mapping: {}'.format(err), err.errno)
    else:
        editor = shlex.split(os.environ.get('EDITOR'))
        if not editor:
            abort('dtags: undefined environment variable: ' +
                  style.bad('EDITOR'))
        try:
            sp.check_call(editor + [tfile.name])
        except sp.CalledProcessError as err:
            abort('dtags: failed to edit mapping: {}'.format(err.message))
        else:
            mapping, excluded = parse_mapping(tfile.name)
            save_mapping(mapping)
            rm_files(tfile.name)
            if excluded:
                print('Cleaned the following entries:\n' + excluded + '\n')
            finish('New entries saved successfully')
示例#2
0
def save_mapping(mapping):
    """Save the mapping (and tags for autocomplete) back to the disk.

    This function assumes that the mapping is already validated.

    :param mapping: the mapping object to save
    """
    # Create a reverse mapping (this is what gets saved to the disk)
    reverse_mapping = defaultdict(set)
    for tag, paths in mapping.items():
        for path in paths:
            reverse_mapping[path].add(tag)
    # Save the reverse mapping to a temporary file
    temp_mapping_file = NamedTemporaryFile(
        mode='w', dir=CFG_DIR, prefix='mapping.', delete=False
    )
    temp_mapping_file.close()
    try:
        with io.open(temp_mapping_file.name, 'wt') as temp_mapping_file:
            temp_mapping_file.write('\n'.join(
                path + ',' + ','.join(sorted(reverse_mapping[path])) + ','
                for path in sorted(reverse_mapping)
            ))
            temp_mapping_file.flush()
            os.fsync(temp_mapping_file.fileno())
    except (IOError, OSError) as temp_mapping_write_error:
        rm_files(temp_mapping_file.name)
        abort(
            message='Failed to write to {name}: {msg}\n'.format(
                name=temp_mapping_file.name,
                msg=temp_mapping_write_error.strerror
            ),
            exit_code=temp_mapping_write_error.errno
        )
    # Save the tags (for tab-completion) to a temporary file
    temp_tags_file = NamedTemporaryFile(
        mode='w', prefix='tags.', dir=CFG_DIR, delete=False
    )
    temp_tags_file.close()
    try:
        with io.open(temp_tags_file.name, 'wt') as temp_tags_file:
            temp_tags_file.write('\n'.join(sorted(mapping)))
            temp_tags_file.flush()
            os.fsync(temp_tags_file.fileno())
    except (IOError, OSError) as temp_tags_write_error:
        rm_files(temp_mapping_file.name, temp_tags_file.name)
        abort(
            message='Failed to write to {name}: {msg}\n'.format(
                name=temp_tags_file.name,
                msg=temp_tags_write_error.strerror
            ),
            exit_code=temp_tags_write_error.errno
        )
    try:  # Overwrite the mapping file with the temporary one
        shutil.move(temp_mapping_file.name, MAPPING_FILE)
    except (IOError, OSError) as mapping_rename_error:
        rm_files(temp_mapping_file.name, temp_tags_file.name)
        abort(
            message='Failed to move {src} to {dest}: {msg}\n'.format(
                src=temp_mapping_file.name,
                dest=MAPPING_FILE,
                msg=mapping_rename_error.strerror
            ),
            exit_code=mapping_rename_error.errno
        )
    try:  # Overwrite the tags file with the temporary one
        shutil.move(temp_tags_file.name, TAGS_FILE)
    except (IOError, OSError) as tags_rename_error:
        rm_files(temp_tags_file.name)
        abort(
            message='Failed to move {src} to {dest}: {msg}\n'.format(
                src=temp_tags_file.name,
                dest=TAGS_FILE,
                msg=tags_rename_error.strerror
            ),
            exit_code=tags_rename_error.errno
        )