From c9c36c20494babedcff8982e44f6da9718865b9a Mon Sep 17 00:00:00 2001 From: "Mr. Outis" Date: Sun, 29 Sep 2019 23:16:21 -0500 Subject: [PATCH] git: escape filename before ignoring it Fix #2043 --- dvc/scm/git/__init__.py | 11 +++++++++-- tests/func/test_add.py | 11 +++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/dvc/scm/git/__init__.py b/dvc/scm/git/__init__.py index 55bef9beb..4678634b2 100644 --- a/dvc/scm/git/__init__.py +++ b/dvc/scm/git/__init__.py @@ -149,8 +149,9 @@ class Git(Base): self.ignored_paths.append(path) - @staticmethod - def _add_entry_to_gitignore(entry, gitignore): + def _add_entry_to_gitignore(self, entry, gitignore): + entry = self._escape(entry) + with open(gitignore, "a+", encoding="utf-8") as fobj: fobj.seek(0, os.SEEK_END) if fobj.tell() == 0: @@ -162,6 +163,12 @@ class Git(Base): prefix = "" if last == "\n" else "\n" fobj.write("{}{}\n".format(prefix, entry)) + @staticmethod + def _escape(entry): + meta_characters = r"[]!*#" + + return "".join("\\" + x if x in meta_characters else x for x in entry) + def ignore_remove(self, path): entry, gitignore = self._get_gitignore(path) diff --git a/tests/func/test_add.py b/tests/func/test_add.py index 82e474d05..b1d639e49 100644 --- a/tests/func/test_add.py +++ b/tests/func/test_add.py @@ -634,3 +634,14 @@ def test_should_protect_on_repeated_add(link, dvc_repo, repo_dir): dvc_repo.add(repo_dir.FOO) assert not os.access(repo_dir.FOO, os.W_OK) + + +def test_escape_gitignore_entries(git, dvc_repo, repo_dir): + fname = "file!with*weird#naming_[1].txt" + ignored_fname = r"/file\!with\*weird\#naming_\[1\].txt" + + os.rename(repo_dir.FOO, fname) + + dvc_repo.add(fname) + + assert ignored_fname in get_gitignore_content()