Don't overwrite config files. And retain file permissions when upgrading config.

This commit is contained in:
Dan Helfman 2017-07-10 10:37:11 -07:00
parent 3b1b058ffe
commit 9cc7c77ba9
3 changed files with 18 additions and 0 deletions

View file

@ -78,6 +78,7 @@ def main(): # pragma: no cover
args = parse_arguments(*sys.argv[1:])
schema = yaml.round_trip_load(open(validate.schema_filename()).read())
source_config = legacy.parse_configuration(args.source_config_filename, legacy.CONFIG_FORMAT)
source_config_file_mode = os.stat(args.source_config_filename).st_mode
source_excludes = (
open(args.source_excludes_filename).read().splitlines()
if args.source_excludes_filename
@ -87,6 +88,7 @@ def main(): # pragma: no cover
destination_config = convert.convert_legacy_parsed_config(source_config, source_excludes, schema)
generate.write_configuration(args.destination_config_filename, destination_config)
os.chmod(args.destination_config_filename, source_config_file_mode)
# TODO: As a backstop, check that the written config can actually be read and parsed, and
# that it matches the destination config data structure that was written.

View file

@ -1,4 +1,5 @@
from collections import OrderedDict
import os
from ruamel import yaml
@ -44,6 +45,9 @@ def write_configuration(config_filename, config):
Given a target config filename and a config data structure of nested OrderedDicts, write out the
config to file as YAML.
'''
if os.path.exists(config_filename):
raise FileExistsError('{} already exists. Aborting.'.format(config_filename))
with open(config_filename, 'w') as config_file:
config_file.write(yaml.round_trip_dump(config, indent=INDENT, block_seq_indent=INDENT))

View file

@ -1,7 +1,9 @@
from io import StringIO
import os
import sys
from flexmock import flexmock
import pytest
from borgmatic.config import generate as module
@ -15,12 +17,22 @@ def test_insert_newline_before_comment_does_not_raise():
def test_write_configuration_does_not_raise():
flexmock(os.path).should_receive('exists').and_return(False)
builtins = flexmock(sys.modules['builtins'])
builtins.should_receive('open').and_return(StringIO())
module.write_configuration('config.yaml', {})
def test_write_configuration_with_already_existing_file_raises():
flexmock(os.path).should_receive('exists').and_return(True)
builtins = flexmock(sys.modules['builtins'])
builtins.should_receive('open').and_return(StringIO())
with pytest.raises(FileExistsError):
module.write_configuration('config.yaml', {})
def test_add_comments_to_configuration_does_not_raise():
# Ensure that it can deal with fields both in the schema and missing from the schema.
config = module.yaml.comments.CommentedMap([('foo', 33), ('bar', 44), ('baz', 55)])