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 618e56b2a5
commit 5ff016238e
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:]) args = parse_arguments(*sys.argv[1:])
schema = yaml.round_trip_load(open(validate.schema_filename()).read()) schema = yaml.round_trip_load(open(validate.schema_filename()).read())
source_config = legacy.parse_configuration(args.source_config_filename, legacy.CONFIG_FORMAT) 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 = ( source_excludes = (
open(args.source_excludes_filename).read().splitlines() open(args.source_excludes_filename).read().splitlines()
if args.source_excludes_filename 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) destination_config = convert.convert_legacy_parsed_config(source_config, source_excludes, schema)
generate.write_configuration(args.destination_config_filename, destination_config) 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 # 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. # that it matches the destination config data structure that was written.

View file

@ -1,4 +1,5 @@
from collections import OrderedDict from collections import OrderedDict
import os
from ruamel import yaml 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 Given a target config filename and a config data structure of nested OrderedDicts, write out the
config to file as YAML. 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: with open(config_filename, 'w') as config_file:
config_file.write(yaml.round_trip_dump(config, indent=INDENT, block_seq_indent=INDENT)) config_file.write(yaml.round_trip_dump(config, indent=INDENT, block_seq_indent=INDENT))

View file

@ -1,7 +1,9 @@
from io import StringIO from io import StringIO
import os
import sys import sys
from flexmock import flexmock from flexmock import flexmock
import pytest
from borgmatic.config import generate as module 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(): def test_write_configuration_does_not_raise():
flexmock(os.path).should_receive('exists').and_return(False)
builtins = flexmock(sys.modules['builtins']) builtins = flexmock(sys.modules['builtins'])
builtins.should_receive('open').and_return(StringIO()) builtins.should_receive('open').and_return(StringIO())
module.write_configuration('config.yaml', {}) 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(): 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. # 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)]) config = module.yaml.comments.CommentedMap([('foo', 33), ('bar', 44), ('baz', 55)])