|
1 | | -import itertools |
| 1 | +# encoding: utf-8 |
| 2 | +from __future__ import unicode_literals |
2 | 3 | import os |
3 | 4 | import shutil |
4 | | - |
5 | 5 | import pytest |
6 | 6 |
|
7 | 7 | from dvc.exceptions import DvcIgnoreInCollectedDirError |
8 | | -from dvc.ignore import DvcIgnore |
9 | | -from dvc.ignore import DvcIgnoreDirs |
10 | | -from dvc.ignore import DvcIgnoreFilter |
11 | | -from dvc.ignore import DvcIgnorePatterns |
| 8 | +from dvc.ignore import DvcIgnore, DvcIgnoreDirs, DvcIgnorePatterns |
12 | 9 | from dvc.scm.tree import WorkingTree |
13 | | -from dvc.utils.compat import cast_bytes |
| 10 | +from dvc.utils import walk_files |
| 11 | +from dvc.utils.compat import fspath |
14 | 12 | from dvc.utils.fs import get_mtime_and_size |
15 | | -from tests.basic_env import TestDvc |
16 | | -from tests.utils import to_posixpath |
17 | | - |
18 | 13 |
|
19 | | -class TestDvcIgnore(TestDvc): |
20 | | - def setUp(self): |
21 | | - super(TestDvcIgnore, self).setUp() |
22 | | - |
23 | | - def _get_all_paths(self): |
24 | | - |
25 | | - paths = [] |
26 | | - for root, dirs, files in self.dvc.tree.walk( |
27 | | - self.dvc.root_dir, dvcignore=self.dvc.dvcignore |
28 | | - ): |
29 | | - for dname in dirs: |
30 | | - paths.append(os.path.join(root, dname)) |
| 14 | +from tests.utils import to_posixpath |
31 | 15 |
|
32 | | - for fname in files: |
33 | | - paths.append(os.path.join(root, fname)) |
34 | 16 |
|
35 | | - return paths |
| 17 | +def test_ignore(tmp_dir, dvc, monkeypatch): |
| 18 | + tmp_dir.gen({"dir": {"ignored": "text", "other": "text2"}}) |
| 19 | + tmp_dir.gen(DvcIgnore.DVCIGNORE_FILE, "dir/ignored") |
36 | 20 |
|
37 | | - def test_ignore_in_child_dir(self): |
38 | | - ignore_file = os.path.join(self.dvc.root_dir, DvcIgnore.DVCIGNORE_FILE) |
39 | | - with open(ignore_file, "w") as fobj: |
40 | | - fobj.write("data_dir/data") |
| 21 | + assert _files_set("dir", dvc.dvcignore) == {"dir/other"} |
41 | 22 |
|
42 | | - forbidden_path = os.path.join(self.dvc.root_dir, self.DATA) |
43 | | - all_paths = self._get_all_paths() |
| 23 | + monkeypatch.chdir("dir") |
| 24 | + assert _files_set(".", dvc.dvcignore) == {"./other"} |
44 | 25 |
|
45 | | - self.assertNotIn(forbidden_path, all_paths) |
46 | 26 |
|
47 | | - def test_ignore_in_child_dir_unicode(self): |
48 | | - ignore_file = os.path.join(self.dvc.root_dir, DvcIgnore.DVCIGNORE_FILE) |
49 | | - with open(ignore_file, "wb") as fobj: |
50 | | - fobj.write(cast_bytes(self.UNICODE, "utf-8")) |
| 27 | +def test_ignore_unicode(tmp_dir, dvc): |
| 28 | + tmp_dir.gen({"dir": {"other": "text"}}) |
| 29 | + # Path() doesn't handle unicode paths in Windows/Python 2 |
| 30 | + # I don't know to debug it further, waiting till Python 2 EOL |
| 31 | + with open("dir/тест", "wb") as fd: |
| 32 | + fd.write("проверка".encode("utf-8")) |
51 | 33 |
|
52 | | - forbidden_path = os.path.join(self.dvc.root_dir, self.UNICODE) |
53 | | - all_paths = self._get_all_paths() |
| 34 | + tmp_dir.gen(DvcIgnore.DVCIGNORE_FILE, "dir/тест") |
54 | 35 |
|
55 | | - self.assertNotIn(forbidden_path, all_paths) |
| 36 | + assert _files_set("dir", dvc.dvcignore) == {"dir/other"} |
56 | 37 |
|
57 | | - def test_ignore_in_parent_dir(self): |
58 | | - ignore_file = os.path.join(self.dvc.root_dir, DvcIgnore.DVCIGNORE_FILE) |
59 | | - with open(ignore_file, "w") as fobj: |
60 | | - fobj.write("data_dir/data") |
61 | 38 |
|
62 | | - os.chdir(self.DATA_DIR) |
| 39 | +def test_rename_ignored_file(tmp_dir, dvc): |
| 40 | + tmp_dir.gen({"dir": {"ignored": "...", "other": "text"}}) |
63 | 41 |
|
64 | | - forbidden_path = os.path.join(self.dvc.root_dir, self.DATA) |
65 | | - all_paths = self._get_all_paths() |
| 42 | + tmp_dir.gen(DvcIgnore.DVCIGNORE_FILE, "ignored*") |
| 43 | + mtime, size = get_mtime_and_size("dir", dvc.dvcignore) |
66 | 44 |
|
67 | | - self.assertNotIn(forbidden_path, all_paths) |
| 45 | + shutil.move("dir/ignored", "dir/ignored_new") |
| 46 | + new_mtime, new_size = get_mtime_and_size("dir", dvc.dvcignore) |
68 | 47 |
|
| 48 | + assert new_mtime == mtime and new_size == size |
69 | 49 |
|
70 | | -def test_metadata_unchanged_when_moving_ignored_file(dvc_repo, repo_dir): |
71 | | - new_data_path = repo_dir.DATA_SUB + "_new" |
72 | 50 |
|
73 | | - ignore_file = os.path.join(dvc_repo.root_dir, DvcIgnore.DVCIGNORE_FILE) |
74 | | - repo_dir.create( |
75 | | - ignore_file, |
76 | | - "\n".join( |
77 | | - [to_posixpath(repo_dir.DATA_SUB), to_posixpath(new_data_path)] |
78 | | - ), |
79 | | - ) |
| 51 | +def test_rename_file(tmp_dir, dvc): |
| 52 | + tmp_dir.gen({"dir": {"foo": "foo", "bar": "bar"}}) |
| 53 | + mtime, size = get_mtime_and_size("dir", dvc.dvcignore) |
80 | 54 |
|
81 | | - mtime_sig, size = get_mtime_and_size(repo_dir.DATA_DIR, dvc_repo.dvcignore) |
| 55 | + shutil.move("dir/foo", "dir/foo_new") |
| 56 | + new_mtime, new_size = get_mtime_and_size("dir", dvc.dvcignore) |
82 | 57 |
|
83 | | - shutil.move(repo_dir.DATA_SUB, new_data_path) |
| 58 | + assert new_mtime != mtime and new_size == size |
84 | 59 |
|
85 | | - new_mtime_sig, new_size = get_mtime_and_size( |
86 | | - repo_dir.DATA_DIR, dvc_repo.dvcignore |
87 | | - ) |
88 | 60 |
|
89 | | - assert new_mtime_sig == mtime_sig |
90 | | - assert new_size == size |
| 61 | +def test_remove_ignored_file(tmp_dir, dvc): |
| 62 | + tmp_dir.gen({"dir": {"ignored": "...", "other": "text"}}) |
| 63 | + tmp_dir.gen(DvcIgnore.DVCIGNORE_FILE, "dir/ignored") |
91 | 64 |
|
| 65 | + mtime, size = get_mtime_and_size("dir", dvc.dvcignore) |
92 | 66 |
|
93 | | -def test_mtime_changed_when_moving_non_ignored_file(dvc_repo, repo_dir): |
94 | | - new_data_path = repo_dir.DATA_SUB + "_new" |
95 | | - mtime, size = get_mtime_and_size(repo_dir.DATA_DIR, dvc_repo.dvcignore) |
| 67 | + os.remove("dir/ignored") |
| 68 | + new_mtime, new_size = get_mtime_and_size("dir", dvc.dvcignore) |
96 | 69 |
|
97 | | - shutil.move(repo_dir.DATA_SUB, new_data_path) |
98 | | - new_mtime, new_size = get_mtime_and_size( |
99 | | - repo_dir.DATA_DIR, dvc_repo.dvcignore |
100 | | - ) |
| 70 | + assert new_mtime == mtime and new_size == size |
101 | 71 |
|
102 | | - assert new_mtime != mtime |
103 | | - assert new_size == size |
104 | 72 |
|
| 73 | +def test_remove_file(tmp_dir, dvc): |
| 74 | + tmp_dir.gen({"dir": {"foo": "foo", "bar": "bar"}}) |
| 75 | + mtime, size = get_mtime_and_size("dir", dvc.dvcignore) |
105 | 76 |
|
106 | | -def test_metadata_unchanged_on_ignored_file_deletion(dvc_repo, repo_dir): |
107 | | - ignore_file = os.path.join(dvc_repo.root_dir, DvcIgnore.DVCIGNORE_FILE) |
108 | | - repo_dir.create(ignore_file, to_posixpath(repo_dir.DATA_SUB)) |
| 77 | + os.remove("dir/foo") |
| 78 | + new_mtime, new_size = get_mtime_and_size("dir", dvc.dvcignore) |
109 | 79 |
|
110 | | - mtime, size = get_mtime_and_size(repo_dir.DATA_DIR, dvc_repo.dvcignore) |
| 80 | + assert new_mtime != mtime and new_size != size |
111 | 81 |
|
112 | | - os.remove(repo_dir.DATA_SUB) |
113 | | - new_mtime, new_size = get_mtime_and_size( |
114 | | - repo_dir.DATA_DIR, dvc_repo.dvcignore |
115 | | - ) |
116 | 82 |
|
117 | | - assert new_mtime == mtime |
118 | | - assert new_size == size |
| 83 | +def test_dvcignore_in_out_dir(tmp_dir, dvc): |
| 84 | + tmp_dir.gen({"dir": {"foo": "foo", DvcIgnore.DVCIGNORE_FILE: ""}}) |
119 | 85 |
|
| 86 | + with pytest.raises(DvcIgnoreInCollectedDirError): |
| 87 | + dvc.add("dir") |
120 | 88 |
|
121 | | -def test_metadata_changed_on_non_ignored_file_deletion(dvc_repo, repo_dir): |
122 | | - mtime, size = get_mtime_and_size(repo_dir.DATA_DIR, dvc_repo.dvcignore) |
123 | 89 |
|
124 | | - os.remove(repo_dir.DATA_SUB) |
125 | | - new_mtime_sig, new_size = get_mtime_and_size( |
126 | | - repo_dir.DATA_DIR, dvc_repo.dvcignore |
127 | | - ) |
| 90 | +# @efiop why do we need to parametrize this? |
| 91 | +@pytest.mark.parametrize("dname", ["dir", "dir/subdir"]) |
| 92 | +def test_ignore_collecting_dvcignores(tmp_dir, dvc, dname): |
| 93 | + tmp_dir.gen({"dir": {"subdir": {}}}) |
128 | 94 |
|
129 | | - assert new_mtime_sig != mtime |
130 | | - assert new_size != size |
| 95 | + top_ignore_file = (tmp_dir / dname).with_name(DvcIgnore.DVCIGNORE_FILE) |
| 96 | + top_ignore_file.write_text(os.path.basename(dname)) |
131 | 97 |
|
| 98 | + ignore_file = tmp_dir / dname / DvcIgnore.DVCIGNORE_FILE |
| 99 | + ignore_file.write_text("foo") |
132 | 100 |
|
133 | | -def test_should_raise_on_dvcignore_in_out_dir(dvc_repo, repo_dir): |
134 | | - ignore_file = os.path.join(repo_dir.DATA_DIR, DvcIgnore.DVCIGNORE_FILE) |
135 | | - repo_dir.create(ignore_file, "") |
| 101 | + assert dvc.dvcignore.ignores == { |
| 102 | + DvcIgnoreDirs([".git", ".hg", ".dvc"]), |
| 103 | + DvcIgnorePatterns(fspath(top_ignore_file), WorkingTree(dvc.root_dir)), |
| 104 | + } |
136 | 105 |
|
137 | | - with pytest.raises(DvcIgnoreInCollectedDirError): |
138 | | - dvc_repo.add(repo_dir.DATA_DIR) |
139 | 106 |
|
| 107 | +def test_ignore_on_branch(tmp_dir, scm, dvc): |
| 108 | + tmp_dir.scm_gen({"foo": "foo", "bar": "bar"}, commit="add files") |
140 | 109 |
|
141 | | -@pytest.mark.parametrize("dname", [TestDvc.DATA_DIR, TestDvc.DATA_SUB_DIR]) |
142 | | -def test_ignore_collecting_dvcignores(repo_dir, dname): |
143 | | - top_ignore_file = os.path.join( |
144 | | - repo_dir.root_dir, os.path.dirname(dname), DvcIgnore.DVCIGNORE_FILE |
145 | | - ) |
146 | | - repo_dir.create(top_ignore_file, os.path.basename(dname)) |
| 110 | + scm.checkout("branch", create_new=True) |
| 111 | + tmp_dir.scm_gen(DvcIgnore.DVCIGNORE_FILE, "foo", commit="add ignore") |
147 | 112 |
|
148 | | - ignore_file = os.path.join( |
149 | | - repo_dir.root_dir, dname, DvcIgnore.DVCIGNORE_FILE |
150 | | - ) |
151 | | - repo_dir.create(ignore_file, repo_dir.FOO) |
| 113 | + scm.checkout("master") |
| 114 | + assert _files_set(".", dvc.dvcignore) == {"./foo", "./bar"} |
152 | 115 |
|
153 | | - assert DvcIgnoreFilter( |
154 | | - repo_dir.root_dir, WorkingTree(repo_dir.root_dir) |
155 | | - ).ignores == { |
156 | | - DvcIgnoreDirs([".git", ".hg", ".dvc"]), |
157 | | - DvcIgnorePatterns(top_ignore_file, WorkingTree(repo_dir.root_dir)), |
158 | | - } |
| 116 | + dvc.tree = scm.get_tree("branch") |
| 117 | + assert _files_set(".", dvc.dvcignore) == {"./bar"} |
159 | 118 |
|
160 | 119 |
|
161 | | -def test_ignore_on_branch(git, dvc_repo, repo_dir): |
162 | | - dvc_repo.add(repo_dir.DATA_DIR) |
163 | | - dvc_repo.scm.commit("add data dir") |
164 | | - |
165 | | - branch_name = "branch_one" |
166 | | - dvc_repo.scm.checkout(branch_name, create_new=True) |
167 | | - |
168 | | - repo_dir.create(DvcIgnore.DVCIGNORE_FILE, to_posixpath(repo_dir.DATA_SUB)) |
169 | | - dvc_repo.scm.add([DvcIgnore.DVCIGNORE_FILE]) |
170 | | - git.index.commit("add ignore") |
171 | | - |
172 | | - dvc_repo.scm.checkout("master") |
173 | | - |
174 | | - git_tree = dvc_repo.scm.get_tree(branch_name) |
175 | | - branch_data_files = set( |
176 | | - itertools.chain.from_iterable( |
177 | | - [ |
178 | | - files |
179 | | - for _, _, files in dvc_repo.tree.walk( |
180 | | - repo_dir.DATA_DIR, |
181 | | - dvcignore=DvcIgnoreFilter(repo_dir.root_dir, git_tree), |
182 | | - ) |
183 | | - ] |
184 | | - ) |
185 | | - ) |
186 | | - assert branch_data_files == {"data"} |
| 120 | +def _files_set(root, dvcignore): |
| 121 | + return {to_posixpath(f) for f in walk_files(root, dvcignore)} |
0 commit comments