1
0
Fork 0
mirror of synced 2024-11-09 10:38:57 -05:00
dotbot/tests/test_copy.py

676 lines
18 KiB
Python

import os
import stat
import pytest
def test_copy(home, dotfiles, run_dotbot):
"""
Test that we can copy a file
"""
expected = "apple"
dotfiles.write("source", expected)
dest_file = os.path.join(home, ".dest")
config = [
{
"copy": {
"~/.dest": {
"path": "source",
},
}
}
]
dotfiles.write_config(config)
run_dotbot()
with open(dest_file, "r") as file:
assert file.read() == expected
def test_copy_with_mode(home, dotfiles, run_dotbot):
"""
Test that we can copy a file and set it's mode
"""
expected = "apple"
expected_mode = 0o600
dotfiles.write("source", expected)
dest_file = os.path.join(home, ".dest")
config = [
{
"copy": {
"~/.dest": {
"path": "source",
"mode": expected_mode,
},
}
}
]
dotfiles.write_config(config)
run_dotbot()
st = os.stat(dest_file)
current_mode = stat.S_IMODE(st.st_mode)
assert current_mode == expected_mode
with open(dest_file, "r") as file:
assert file.read() == expected
def test_copy_dryrun(home, dotfiles, run_dotbot):
"""
Test that with nothing is copied with `dryrun` enabled
"""
expected = "apple"
dotfiles.write("source", expected)
dest_file = os.path.join(home, ".dest")
config = [
{
"copy": {
"~/.dest": {
"path": "source",
"dryrun": True,
},
}
}
]
dotfiles.write_config(config)
run_dotbot()
assert os.path.exists(dest_file) == False
def test_copy_overwrite(home, dotfiles, run_dotbot):
"""
Test that we overwrite files when `overwite` is set
"""
expected = "apple"
dotfiles.write("source", expected)
with open(os.path.join(home, ".dest"), "w") as file:
file.write("grape")
config = [
{
"copy": {
"~/.dest": {
"path": "source",
"overwrite": True,
},
}
}
]
dotfiles.write_config(config)
run_dotbot()
with open(os.path.join(home, ".dest"), "r") as file:
assert file.read() == expected
def test_copy_backup(home, dotfiles, run_dotbot):
"""
Test that we backup destination files when `backup` is set.
"""
expected = "apple"
dotfiles.write("source", expected)
with open(os.path.join(home, ".dest"), "w") as file:
file.write("grape")
config = [
{
"copy": {
"~/.dest": {
"path": "source",
"overwrite": True, # force a copy, as this check would trigger before a backup is made
"backup": True,
},
}
}
]
dotfiles.write_config(config)
run_dotbot()
with open(os.path.join(home, ".dest"), "r") as file:
assert file.read() == expected
assert os.path.exists(os.path.join(home, ".dest.BAK")) == True
def test_copy_backup_extension(home, dotfiles, run_dotbot):
"""
Test that we backup destination files with custom extension when `backup` is set.
"""
expected = "apple"
dotfiles.write("source", expected)
with open(os.path.join(home, ".dest"), "w") as file:
file.write("grape")
config = [
{
"copy": {
"~/.dest": {
"path": "source",
"overwrite": True,
"backup": "BACKUP",
},
}
}
]
dotfiles.write_config(config)
run_dotbot()
with open(os.path.join(home, ".dest"), "r") as file:
assert file.read() == expected
assert os.path.exists(os.path.join(home, ".dest.BACKUP")) == True
def test_copy_without_overwrite(home, dotfiles, run_dotbot):
"""
Test that we do not overwrite files when `overwrite` is not set
"""
content = "apple"
expected = "grape"
dotfiles.write("source", content)
with open(os.path.join(home, ".dest"), "w") as file:
file.write(expected)
config = [
{
"copy": {
"~/.dest": {
"path": "source",
"overwrite": False,
},
}
}
]
dotfiles.write_config(config)
run_dotbot()
with open(os.path.join(home, ".dest"), "r") as file:
assert file.read() == expected
def test_copy_without_overwrite_with_check_content(home, dotfiles, run_dotbot):
"""
Test that `check-content` works when `overwrite` is not set
"""
content = "apple"
expected = "grape"
dotfiles.write("source", expected)
with open(os.path.join(home, ".dest"), "w") as file:
file.write(content)
config = [
{
"copy": {
"~/.dest": {
"path": "source",
"overwrite": False,
"check-content":True,
},
}
}
]
dotfiles.write_config(config)
run_dotbot()
with open(os.path.join(home, ".dest"), "r") as file:
assert file.read() == expected
def test_copy_follow_links(home, dotfiles, run_dotbot):
"""
Test that copies will follow pre-existing destination links when `follow-links` is set
"""
# Create source
# Create a destination link
# Create config and run dotbot
# Check link destination == source
expected = "apple"
dotfiles.write("source", expected)
dest_link = os.path.join(home, ".dest")
dest_file = os.path.join(home, "dest_file")
os.symlink(dest_file, dest_link)
config = [
{
"copy": {
"~/.dest": {
"path": "source",
"follow-links":True,
},
}
}
]
dotfiles.write_config(config)
run_dotbot()
with open(dest_file, "r") as file:
assert file.read() == expected
def test_copy_not_follow_links(home, dotfiles, run_dotbot):
"""
Test that copies will not follow pre-existing destination links when `follow-links` is set
"""
# Create source
# Create a link
# Create link destination w/ content different than source
# Create config and run dotbot
# Check link destination != source
expected = "apple"
content = "grape"
dotfiles.write("source", expected)
dest_link = os.path.join(home, ".dest")
dest_file = os.path.join(home, "dest_file")
os.symlink(dest_file, dest_link)
with open(dest_file, "w") as file:
file.write(content)
config = [
{
"copy": {
"~/.dest": {
"path": "source",
"follow-links":True,
},
}
}
]
dotfiles.write_config(config)
run_dotbot()
with open(dest_file, "r") as file:
assert file.read() != expected
@pytest.mark.skipif(
"sys.platform[:5] != 'win32'",
reason="These if commands only run on Windows.",
)
def test_copy_if(home, dotfiles, run_dotbot):
"""
Verify 'if' directives are checked when copying.
(Lifted from test_link.py)
"""
os.mkdir(os.path.join(home, "d"))
dotfiles.write("f", "apple")
dotfiles.write_config(
[
{
"link": {
"~/.f": {"path": "f", "if": "true"},
"~/.g": {"path": "f", "if": "false"},
"~/.h": {"path": "f", "if": "[ -d ~/d ]"},
"~/.i": {"path": "f", "if": "badcommand"},
},
}
]
)
run_dotbot()
assert not os.path.exists(os.path.join(home, ".g"))
assert not os.path.exists(os.path.join(home, ".i"))
with open(os.path.join(home, ".f")) as file:
assert file.read() == "apple"
with open(os.path.join(home, ".h")) as file:
assert file.read() == "apple"
def test_copy_glob_1(home, dotfiles, run_dotbot):
"""
Verify globbing works.
(Lifted from test_link.py)
"""
dotfiles.write("bin/a", "apple")
dotfiles.write("bin/b", "banana")
dotfiles.write("bin/c", "cherry")
dotfiles.write_config(
[
{"copy": {
"~/bin": {
"path": "bin/*",
"create": True,
}
}
}
]
)
run_dotbot()
with open(os.path.join(home, "bin", "a")) as file:
assert file.read() == "apple"
with open(os.path.join(home, "bin", "b")) as file:
assert file.read() == "banana"
with open(os.path.join(home, "bin", "c")) as file:
assert file.read() == "cherry"
def test_copy_recursive_glob(home, dotfiles, run_dotbot):
"""
Verify recursive globbing ("**") works.
(Lifted from test_link.py)
"""
dotfiles.write("bin/one/a", "apple")
dotfiles.write("bin/b", "banana")
dotfiles.write("bin/two/c", "cherry")
dotfiles.write_config(
[
{"copy": {
"~/bin": {
"path": "bin/**",
"create": True,
}
}
}
]
)
run_dotbot()
with open(os.path.join(home, "bin/one/a")) as file:
assert file.read() == "apple"
with open(os.path.join(home, "bin/b")) as file:
assert file.read() == "banana"
with open(os.path.join(home, "bin/two/c")) as file:
assert file.read() == "cherry"
def test_copy_glob_2(home, dotfiles, run_dotbot):
"""
Verify globbing works with a trailing slash in the source.
(Lifted from test_link.py)
"""
dotfiles.write("bin/a", "apple")
dotfiles.write("bin/b", "banana")
dotfiles.write("bin/c", "cherry")
dotfiles.write_config(
[
{"defaults": {
"copy": {
"create": True
}
}
},
{"copy": {
"~/bin/": "bin/*"
}
},
]
)
run_dotbot()
with open(os.path.join(home, "bin", "a")) as file:
assert file.read() == "apple"
with open(os.path.join(home, "bin", "b")) as file:
assert file.read() == "banana"
with open(os.path.join(home, "bin", "c")) as file:
assert file.read() == "cherry"
def test_copy_with_create(home, dotfiles, run_dotbot):
"""
Test that destination directories are created when `create` is set
"""
expected = "apple"
dest_file = "dest_parent/dest_dir/dest_dir2/file"
dest_target = "~/" + dest_file
dotfiles.write("source", expected)
dest_file = os.path.join(home, dest_file)
config = [
{
"copy": {
"~/dest_parent/dest_dir/dest_dir2/file": {
"path": "source",
"create": True,
},
}
}
]
dotfiles.write_config(config)
run_dotbot()
assert os.path.isdir(os.path.normpath(os.path.join(dest_file, ".."))) == True
assert os.path.isfile(dest_file) == True
def test_copy_with_create_and_dir_mode(home, dotfiles, run_dotbot):
"""
Test that destination directories are created and have their mode set correctly when
`create` and `dir_mode` are set
"""
expected = "apple"
expected_mode = 0o700
dest = "dest_parent/dest_dir/dest_dir2/file"
dest_target = "~/" + dest
dotfiles.write("source", expected)
dest_file = os.path.join(home, dest)
config = [
{
"copy": {
dest_target: {
"path": "source",
"create": True,
"dir-mode": expected_mode
},
},
}
]
dotfiles.write_config(config)
run_dotbot()
# Check that the file was copied
assert os.path.isfile(dest_file) == True
# Check the mode of each directory in the path
partial_path = os.path.dirname(os.path.normpath(dest))
parts = partial_path.split(os.sep)
current_path = home
for part in parts:
current_path = os.path.join(current_path, part)
assert os.path.isdir(current_path) == True
assert stat.S_IMODE(os.stat(current_path).st_mode) == expected_mode
def test_copy_excludes(home, dotfiles, run_dotbot):
"""
Verify excludes works
"""
dotfiles.write("bin/a.doc", "apple")
dotfiles.write("bin/b.txt", "banana")
dotfiles.write("bin/c.doc", "cherry")
dotfiles.write("bin/d.txt", "dates")
dotfiles.write_config(
[
{"defaults": {
"copy": {
"create": True
}
}
},
{"copy": {
"~/bin/": {
"path": "bin/*",
"exclude": "*.doc",
},
},
}
]
)
run_dotbot()
assert os.path.exists(os.path.join(home, "bin/a.doc")) == False
assert os.path.exists(os.path.join(home, "bin/b.txt")) == True
assert os.path.exists(os.path.join(home, "bin/c.doc")) == False
assert os.path.exists(os.path.join(home, "bin/d.txt")) == True
def test_copy_excludes_with_globs(home, dotfiles, run_dotbot):
"""
Verify excludes works with globs
"""
dotfiles.write("bin/one/a.doc", "apple")
dotfiles.write("bin/b.txt", "banana")
dotfiles.write("bin/c.doc", "cherry")
dotfiles.write("bin/two/d.txt", "dates")
dotfiles.write_config(
[
{"defaults": {
"copy": {
"create": True
}
}
},
{"copy": {
"~/bin/": {
"path": "bin/**",
"exclude": "*.doc",
},
},
}
]
)
run_dotbot()
assert os.path.exists(os.path.join(home, "bin/one/a.doc")) == False
assert os.path.exists(os.path.join(home, "bin/b.txt")) == True
assert os.path.exists(os.path.join(home, "bin/c.doc")) == False
assert os.path.exists(os.path.join(home, "bin/two/d.txt")) == True
def test_copy_excludes_with_globs_2(home, dotfiles, run_dotbot):
"""
Verify deep globbing with multiple globbed exclusions.
(Lifted directly from link_test.py)
"""
dotfiles.write("config/foo/a", "apple")
dotfiles.write("config/bar/b", "banana")
dotfiles.write("config/bar/c", "cherry")
dotfiles.write("config/baz/d", "donut")
dotfiles.write("config/baz/buzz/e", "egg")
dotfiles.write("config/baz/bizz/g", "grape")
dotfiles.write("config/fiz/f", "fig")
dotfiles.write_config(
[
{
"defaults": {
"copy": {
"create": True,
},
},
},
{
"copy": {
"~/.config/": {
"path": "config/*/*",
"exclude": ["config/baz/*", "config/fiz/*"],
},
},
},
]
)
run_dotbot()
assert not os.path.exists(os.path.join(home, ".config", "baz"))
assert not os.path.exists(os.path.join(home, ".config", "fiz"))
assert not os.path.isfile(os.path.join(home, ".config"))
assert not os.path.isfile(os.path.join(home, ".config", "foo"))
assert not os.path.isfile(os.path.join(home, ".config", "bar"))
assert os.path.isfile(os.path.join(home, ".config", "foo", "a"))
with open(os.path.join(home, ".config", "foo", "a")) as file:
assert file.read() == "apple"
with open(os.path.join(home, ".config", "bar", "b")) as file:
assert file.read() == "banana"
with open(os.path.join(home, ".config", "bar", "c")) as file:
assert file.read() == "cherry"
def test_copy_glob_with_prefix(home, dotfiles, run_dotbot):
"""
Verify globbing works with hidden ("period-prefixed") files.
(Lifted from test_link.py)
"""
dotfiles.write("bin/.a", "dot-apple")
dotfiles.write("bin/.b", "dot-banana")
dotfiles.write("bin/.c", "dot-cherry")
dotfiles.write_config(
[
{"defaults": {"copy": {"create": True}}},
{"copy": {"~/bin/": "bin/.*"}},
]
)
run_dotbot()
with open(os.path.join(home, "bin", ".a")) as file:
assert file.read() == "dot-apple"
with open(os.path.join(home, "bin", ".b")) as file:
assert file.read() == "dot-banana"
with open(os.path.join(home, "bin", ".c")) as file:
assert file.read() == "dot-cherry"
def test_copy_ignore_missing_true(home, dotfiles, run_dotbot):
"""
Test that ignore-missing does so.
"""
dotfiles.write("a", "apple")
# don't create b
dotfiles.write("c", "cherry")
dotfiles.write_config(
[
{
"defaults": {
"copy": {
"ignore-missing": True,
}
}
},
{
"copy": {
"~/a": "a",
"~/b": "b",
"~/c": "c"
}
}
])
run_dotbot()
assert os.path.exists(os.path.join(home, "a")) == True
assert os.path.exists(os.path.join(home, "b")) == False
assert os.path.exists(os.path.join(home, "c")) == True
def test_copy_prefix(home, dotfiles, run_dotbot):
"""
Verify copy prefixes are prepended.
(Lifted from test_link.py)
"""
dotfiles.write("conf/a", "apple")
dotfiles.write("conf/b", "banana")
dotfiles.write("conf/c", "cherry")
dotfiles.write("conf/dir/one", "one")
dotfiles.write_config(
[
{
"copy": {
"~/": {
"path": "conf/**",
"prefix": ".",
"create": True,
},
},
}
]
)
run_dotbot()
with open(os.path.join(home, ".a")) as file:
assert file.read() == "apple"
with open(os.path.join(home, ".b")) as file:
assert file.read() == "banana"
with open(os.path.join(home, ".c")) as file:
assert file.read() == "cherry"
assert os.path.exists(os.path.join(home, ".dir/one")) == True