We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
gitignore: use unambiguous paths
E.g. `/dir` instead of `dir`.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `dvc/scm.py`
Content:
```
1 import os
2 
3 from dvc.exceptions import DvcException
4 from dvc.logger import Logger
5 from dvc.utils import fix_env
6 
7 
8 class SCMError(DvcException):
9     pass
10 
11 
12 class FileNotInRepoError(DvcException):
13     pass
14 
15 
16 class Base(object):
17     def __init__(self, root_dir=os.curdir, project=None):
18         self.project = project
19         self.root_dir = root_dir
20 
21     @property
22     def dir(self):
23         return None
24 
25     @staticmethod
26     def is_repo(root_dir):
27         return True
28 
29     @staticmethod
30     def is_submodule(root_dir):
31         return True
32 
33     def ignore(self, path):
34         pass
35 
36     def ignore_remove(self, path):
37         pass
38 
39     def ignore_file(self):
40         pass
41 
42     def ignore_list(self, p_list):
43         return [self.ignore(path) for path in p_list]
44 
45     def add(self, paths):
46         pass
47 
48     def commit(self, msg):
49         pass
50 
51     def checkout(self, branch):
52         pass
53 
54     def branch(self, branch):
55         pass
56 
57     def tag(self, tag):
58         pass
59 
60     def brancher(self,
61                  branches=None,
62                  all_branches=False,
63                  tags=None,
64                  all_tags=False):
65         if not branches and not all_branches \
66            and not tags and not all_tags:
67             yield ''
68             return
69 
70         saved = self.active_branch()
71         revs = []
72 
73         if all_branches:
74             branches = self.list_branches()
75 
76         if all_tags:
77             tags = self.list_tags()
78 
79         if branches is None:
80             revs.extend([saved])
81         else:
82             revs.extend(branches)
83 
84         if tags is not None:
85             revs.extend(tags)
86 
87         for rev in revs:
88             self.checkout(rev)
89             yield rev
90 
91         self.checkout(saved)
92 
93     def untracked_files(self):
94         pass
95 
96     def is_tracked(self, path):
97         pass
98 
99     def active_branch(self):
100         pass
101 
102     def list_branches(self):
103         pass
104 
105     def list_tags(self):
106         pass
107 
108     def install(self):
109         pass
110 
111 
112 class Git(Base):
113     GITIGNORE = '.gitignore'
114     GIT_DIR = '.git'
115 
116     def __init__(self, root_dir=os.curdir, project=None):
117         super(Git, self).__init__(root_dir, project=project)
118 
119         import git
120         from git.exc import InvalidGitRepositoryError
121         try:
122             self.repo = git.Repo(root_dir)
123         except InvalidGitRepositoryError:
124             msg = '{} is not a git repository'
125             raise SCMError(msg.format(root_dir))
126 
127         # NOTE: fixing LD_LIBRARY_PATH for binary built by PyInstaller.
128         # http://pyinstaller.readthedocs.io/en/stable/runtime-information.html
129         env = fix_env(None)
130         lp = env.get('LD_LIBRARY_PATH', None)
131         self.repo.git.update_environment(LD_LIBRARY_PATH=lp)
132 
133     @staticmethod
134     def is_repo(root_dir):
135         return os.path.isdir(Git._get_git_dir(root_dir))
136 
137     @staticmethod
138     def is_submodule(root_dir):
139         return os.path.isfile(Git._get_git_dir(root_dir))
140 
141     @staticmethod
142     def _get_git_dir(root_dir):
143         return os.path.join(root_dir, Git.GIT_DIR)
144 
145     @property
146     def dir(self):
147         return self.repo.git_dir
148 
149     def ignore_file(self):
150         return self.GITIGNORE
151 
152     def _get_gitignore(self, path):
153         assert os.path.isabs(path)
154         entry = os.path.basename(path)
155         gitignore = os.path.join(os.path.dirname(path), self.GITIGNORE)
156 
157         if not gitignore.startswith(self.root_dir):
158             raise FileNotInRepoError(path)
159 
160         return entry, gitignore
161 
162     def ignore(self, path):
163         entry, gitignore = self._get_gitignore(path)
164 
165         ignore_list = []
166         if os.path.exists(gitignore):
167             ignore_list = open(gitignore, 'r').readlines()
168             filtered = list(filter(lambda x: x.strip() == entry.strip(),
169                                    ignore_list))
170             if len(filtered) != 0:
171                 return
172 
173         msg = "Adding '{}' to '{}'.".format(os.path.relpath(path),
174                                             os.path.relpath(gitignore))
175         Logger.info(msg)
176 
177         content = entry
178         if len(ignore_list) > 0:
179             content = '\n' + content
180 
181         with open(gitignore, 'a') as fd:
182             fd.write(content)
183 
184         if self.project is not None:
185             self.project._files_to_git_add.append(os.path.relpath(gitignore))
186 
187     def ignore_remove(self, path):
188         entry, gitignore = self._get_gitignore(path)
189 
190         if not os.path.exists(gitignore):
191             return
192 
193         with open(gitignore, 'r') as fd:
194             lines = fd.readlines()
195 
196         filtered = list(filter(lambda x: x.strip() != entry.strip(), lines))
197 
198         with open(gitignore, 'w') as fd:
199             fd.writelines(filtered)
200 
201         if self.project is not None:
202             self.project._files_to_git_add.append(os.path.relpath(gitignore))
203 
204     def add(self, paths):
205         # NOTE: GitPython is not currently able to handle index version >= 3.
206         # See https://github.com/iterative/dvc/issues/610 for more details.
207         try:
208             self.repo.index.add(paths)
209         except AssertionError as exc:
210             msg = 'Failed to add \'{}\' to git. You can add those files '
211             msg += 'manually using \'git add\'. '
212             msg += 'See \'https://github.com/iterative/dvc/issues/610\' '
213             msg += 'for more details.'
214             Logger.error(msg.format(str(paths)), exc)
215 
216     def commit(self, msg):
217         self.repo.index.commit(msg)
218 
219     def checkout(self, branch, create_new=False):
220         if create_new:
221             self.repo.git.checkout('HEAD', b=branch)
222         else:
223             self.repo.git.checkout(branch)
224 
225     def branch(self, branch):
226         self.repo.git.branch(branch)
227 
228     def tag(self, tag):
229         self.repo.git.tag(tag)
230 
231     def untracked_files(self):
232         files = self.repo.untracked_files
233         return [os.path.join(self.repo.working_dir, fname) for fname in files]
234 
235     def is_tracked(self, path):
236         return len(self.repo.git.ls_files(path)) != 0
237 
238     def active_branch(self):
239         return self.repo.active_branch.name
240 
241     def list_branches(self):
242         return [h.name for h in self.repo.heads]
243 
244     def list_tags(self):
245         return [t.name for t in self.repo.tags]
246 
247     def _install_hook(self, name, cmd):
248         hook = os.path.join(self.root_dir,
249                             self.GIT_DIR,
250                             'hooks',
251                             name)
252         if os.path.isfile(hook):
253             msg = 'Git hook \'{}\' already exists.'
254             raise SCMError(msg.format(os.path.relpath(hook)))
255         with open(hook, 'w+') as fd:
256             fd.write('#!/bin/sh\nexec dvc {}\n'.format(cmd))
257         os.chmod(hook, 0o777)
258 
259     def install(self):
260         self._install_hook('post-checkout', 'checkout')
261         self._install_hook('pre-commit', 'status')
262 
263 
264 def SCM(root_dir, no_scm=False, project=None):
265     if Git.is_repo(root_dir) or Git.is_submodule(root_dir):
266         return Git(root_dir, project=project)
267 
268     return Base(root_dir, project=project)
269
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/dvc/scm.py b/dvc/scm.py
--- a/dvc/scm.py
+++ b/dvc/scm.py
@@ -151,7 +151,8 @@
 
     def _get_gitignore(self, path):
         assert os.path.isabs(path)
-        entry = os.path.basename(path)
+        # NOTE: using '/' prefix to make path unambiguous
+        entry = '/' + os.path.basename(path)
         gitignore = os.path.join(os.path.dirname(path), self.GITIGNORE)
 
         if not gitignore.startswith(self.root_dir):

{"golden_diff": "diff --git a/dvc/scm.py b/dvc/scm.py\n--- a/dvc/scm.py\n+++ b/dvc/scm.py\n@@ -151,7 +151,8 @@\n \n     def _get_gitignore(self, path):\n         assert os.path.isabs(path)\n-        entry = os.path.basename(path)\n+        # NOTE: using '/' prefix to make path unambiguous\n+        entry = '/' + os.path.basename(path)\n         gitignore = os.path.join(os.path.dirname(path), self.GITIGNORE)\n \n         if not gitignore.startswith(self.root_dir):\n", "issue": "gitignore: use unambiguous paths\nE.g. `/dir` instead of `dir`.\n", "before_files": [{"content": "import os\n\nfrom dvc.exceptions import DvcException\nfrom dvc.logger import Logger\nfrom dvc.utils import fix_env\n\n\nclass SCMError(DvcException):\n    pass\n\n\nclass FileNotInRepoError(DvcException):\n    pass\n\n\nclass Base(object):\n    def __init__(self, root_dir=os.curdir, project=None):\n        self.project = project\n        self.root_dir = root_dir\n\n    @property\n    def dir(self):\n        return None\n\n    @staticmethod\n    def is_repo(root_dir):\n        return True\n\n    @staticmethod\n    def is_submodule(root_dir):\n        return True\n\n    def ignore(self, path):\n        pass\n\n    def ignore_remove(self, path):\n        pass\n\n    def ignore_file(self):\n        pass\n\n    def ignore_list(self, p_list):\n        return [self.ignore(path) for path in p_list]\n\n    def add(self, paths):\n        pass\n\n    def commit(self, msg):\n        pass\n\n    def checkout(self, branch):\n        pass\n\n    def branch(self, branch):\n        pass\n\n    def tag(self, tag):\n        pass\n\n    def brancher(self,\n                 branches=None,\n                 all_branches=False,\n                 tags=None,\n                 all_tags=False):\n        if not branches and not all_branches \\\n           and not tags and not all_tags:\n            yield ''\n            return\n\n        saved = self.active_branch()\n        revs = []\n\n        if all_branches:\n            branches = self.list_branches()\n\n        if all_tags:\n            tags = self.list_tags()\n\n        if branches is None:\n            revs.extend([saved])\n        else:\n            revs.extend(branches)\n\n        if tags is not None:\n            revs.extend(tags)\n\n        for rev in revs:\n            self.checkout(rev)\n            yield rev\n\n        self.checkout(saved)\n\n    def untracked_files(self):\n        pass\n\n    def is_tracked(self, path):\n        pass\n\n    def active_branch(self):\n        pass\n\n    def list_branches(self):\n        pass\n\n    def list_tags(self):\n        pass\n\n    def install(self):\n        pass\n\n\nclass Git(Base):\n    GITIGNORE = '.gitignore'\n    GIT_DIR = '.git'\n\n    def __init__(self, root_dir=os.curdir, project=None):\n        super(Git, self).__init__(root_dir, project=project)\n\n        import git\n        from git.exc import InvalidGitRepositoryError\n        try:\n            self.repo = git.Repo(root_dir)\n        except InvalidGitRepositoryError:\n            msg = '{} is not a git repository'\n            raise SCMError(msg.format(root_dir))\n\n        # NOTE: fixing LD_LIBRARY_PATH for binary built by PyInstaller.\n        # http://pyinstaller.readthedocs.io/en/stable/runtime-information.html\n        env = fix_env(None)\n        lp = env.get('LD_LIBRARY_PATH', None)\n        self.repo.git.update_environment(LD_LIBRARY_PATH=lp)\n\n    @staticmethod\n    def is_repo(root_dir):\n        return os.path.isdir(Git._get_git_dir(root_dir))\n\n    @staticmethod\n    def is_submodule(root_dir):\n        return os.path.isfile(Git._get_git_dir(root_dir))\n\n    @staticmethod\n    def _get_git_dir(root_dir):\n        return os.path.join(root_dir, Git.GIT_DIR)\n\n    @property\n    def dir(self):\n        return self.repo.git_dir\n\n    def ignore_file(self):\n        return self.GITIGNORE\n\n    def _get_gitignore(self, path):\n        assert os.path.isabs(path)\n        entry = os.path.basename(path)\n        gitignore = os.path.join(os.path.dirname(path), self.GITIGNORE)\n\n        if not gitignore.startswith(self.root_dir):\n            raise FileNotInRepoError(path)\n\n        return entry, gitignore\n\n    def ignore(self, path):\n        entry, gitignore = self._get_gitignore(path)\n\n        ignore_list = []\n        if os.path.exists(gitignore):\n            ignore_list = open(gitignore, 'r').readlines()\n            filtered = list(filter(lambda x: x.strip() == entry.strip(),\n                                   ignore_list))\n            if len(filtered) != 0:\n                return\n\n        msg = \"Adding '{}' to '{}'.\".format(os.path.relpath(path),\n                                            os.path.relpath(gitignore))\n        Logger.info(msg)\n\n        content = entry\n        if len(ignore_list) > 0:\n            content = '\\n' + content\n\n        with open(gitignore, 'a') as fd:\n            fd.write(content)\n\n        if self.project is not None:\n            self.project._files_to_git_add.append(os.path.relpath(gitignore))\n\n    def ignore_remove(self, path):\n        entry, gitignore = self._get_gitignore(path)\n\n        if not os.path.exists(gitignore):\n            return\n\n        with open(gitignore, 'r') as fd:\n            lines = fd.readlines()\n\n        filtered = list(filter(lambda x: x.strip() != entry.strip(), lines))\n\n        with open(gitignore, 'w') as fd:\n            fd.writelines(filtered)\n\n        if self.project is not None:\n            self.project._files_to_git_add.append(os.path.relpath(gitignore))\n\n    def add(self, paths):\n        # NOTE: GitPython is not currently able to handle index version >= 3.\n        # See https://github.com/iterative/dvc/issues/610 for more details.\n        try:\n            self.repo.index.add(paths)\n        except AssertionError as exc:\n            msg = 'Failed to add \\'{}\\' to git. You can add those files '\n            msg += 'manually using \\'git add\\'. '\n            msg += 'See \\'https://github.com/iterative/dvc/issues/610\\' '\n            msg += 'for more details.'\n            Logger.error(msg.format(str(paths)), exc)\n\n    def commit(self, msg):\n        self.repo.index.commit(msg)\n\n    def checkout(self, branch, create_new=False):\n        if create_new:\n            self.repo.git.checkout('HEAD', b=branch)\n        else:\n            self.repo.git.checkout(branch)\n\n    def branch(self, branch):\n        self.repo.git.branch(branch)\n\n    def tag(self, tag):\n        self.repo.git.tag(tag)\n\n    def untracked_files(self):\n        files = self.repo.untracked_files\n        return [os.path.join(self.repo.working_dir, fname) for fname in files]\n\n    def is_tracked(self, path):\n        return len(self.repo.git.ls_files(path)) != 0\n\n    def active_branch(self):\n        return self.repo.active_branch.name\n\n    def list_branches(self):\n        return [h.name for h in self.repo.heads]\n\n    def list_tags(self):\n        return [t.name for t in self.repo.tags]\n\n    def _install_hook(self, name, cmd):\n        hook = os.path.join(self.root_dir,\n                            self.GIT_DIR,\n                            'hooks',\n                            name)\n        if os.path.isfile(hook):\n            msg = 'Git hook \\'{}\\' already exists.'\n            raise SCMError(msg.format(os.path.relpath(hook)))\n        with open(hook, 'w+') as fd:\n            fd.write('#!/bin/sh\\nexec dvc {}\\n'.format(cmd))\n        os.chmod(hook, 0o777)\n\n    def install(self):\n        self._install_hook('post-checkout', 'checkout')\n        self._install_hook('pre-commit', 'status')\n\n\ndef SCM(root_dir, no_scm=False, project=None):\n    if Git.is_repo(root_dir) or Git.is_submodule(root_dir):\n        return Git(root_dir, project=project)\n\n    return Base(root_dir, project=project)\n", "path": "dvc/scm.py"}], "after_files": [{"content": "import os\n\nfrom dvc.exceptions import DvcException\nfrom dvc.logger import Logger\nfrom dvc.utils import fix_env\n\n\nclass SCMError(DvcException):\n    pass\n\n\nclass FileNotInRepoError(DvcException):\n    pass\n\n\nclass Base(object):\n    def __init__(self, root_dir=os.curdir, project=None):\n        self.project = project\n        self.root_dir = root_dir\n\n    @property\n    def dir(self):\n        return None\n\n    @staticmethod\n    def is_repo(root_dir):\n        return True\n\n    @staticmethod\n    def is_submodule(root_dir):\n        return True\n\n    def ignore(self, path):\n        pass\n\n    def ignore_remove(self, path):\n        pass\n\n    def ignore_file(self):\n        pass\n\n    def ignore_list(self, p_list):\n        return [self.ignore(path) for path in p_list]\n\n    def add(self, paths):\n        pass\n\n    def commit(self, msg):\n        pass\n\n    def checkout(self, branch):\n        pass\n\n    def branch(self, branch):\n        pass\n\n    def tag(self, tag):\n        pass\n\n    def brancher(self,\n                 branches=None,\n                 all_branches=False,\n                 tags=None,\n                 all_tags=False):\n        if not branches and not all_branches \\\n           and not tags and not all_tags:\n            yield ''\n            return\n\n        saved = self.active_branch()\n        revs = []\n\n        if all_branches:\n            branches = self.list_branches()\n\n        if all_tags:\n            tags = self.list_tags()\n\n        if branches is None:\n            revs.extend([saved])\n        else:\n            revs.extend(branches)\n\n        if tags is not None:\n            revs.extend(tags)\n\n        for rev in revs:\n            self.checkout(rev)\n            yield rev\n\n        self.checkout(saved)\n\n    def untracked_files(self):\n        pass\n\n    def is_tracked(self, path):\n        pass\n\n    def active_branch(self):\n        pass\n\n    def list_branches(self):\n        pass\n\n    def list_tags(self):\n        pass\n\n    def install(self):\n        pass\n\n\nclass Git(Base):\n    GITIGNORE = '.gitignore'\n    GIT_DIR = '.git'\n\n    def __init__(self, root_dir=os.curdir, project=None):\n        super(Git, self).__init__(root_dir, project=project)\n\n        import git\n        from git.exc import InvalidGitRepositoryError\n        try:\n            self.repo = git.Repo(root_dir)\n        except InvalidGitRepositoryError:\n            msg = '{} is not a git repository'\n            raise SCMError(msg.format(root_dir))\n\n        # NOTE: fixing LD_LIBRARY_PATH for binary built by PyInstaller.\n        # http://pyinstaller.readthedocs.io/en/stable/runtime-information.html\n        env = fix_env(None)\n        lp = env.get('LD_LIBRARY_PATH', None)\n        self.repo.git.update_environment(LD_LIBRARY_PATH=lp)\n\n    @staticmethod\n    def is_repo(root_dir):\n        return os.path.isdir(Git._get_git_dir(root_dir))\n\n    @staticmethod\n    def is_submodule(root_dir):\n        return os.path.isfile(Git._get_git_dir(root_dir))\n\n    @staticmethod\n    def _get_git_dir(root_dir):\n        return os.path.join(root_dir, Git.GIT_DIR)\n\n    @property\n    def dir(self):\n        return self.repo.git_dir\n\n    def ignore_file(self):\n        return self.GITIGNORE\n\n    def _get_gitignore(self, path):\n        assert os.path.isabs(path)\n        # NOTE: using '/' prefix to make path unambiguous\n        entry = '/' + os.path.basename(path)\n        gitignore = os.path.join(os.path.dirname(path), self.GITIGNORE)\n\n        if not gitignore.startswith(self.root_dir):\n            raise FileNotInRepoError(path)\n\n        return entry, gitignore\n\n    def ignore(self, path):\n        entry, gitignore = self._get_gitignore(path)\n\n        ignore_list = []\n        if os.path.exists(gitignore):\n            ignore_list = open(gitignore, 'r').readlines()\n            filtered = list(filter(lambda x: x.strip() == entry.strip(),\n                                   ignore_list))\n            if len(filtered) != 0:\n                return\n\n        msg = \"Adding '{}' to '{}'.\".format(os.path.relpath(path),\n                                            os.path.relpath(gitignore))\n        Logger.info(msg)\n\n        content = entry\n        if len(ignore_list) > 0:\n            content = '\\n' + content\n\n        with open(gitignore, 'a') as fd:\n            fd.write(content)\n\n        if self.project is not None:\n            self.project._files_to_git_add.append(os.path.relpath(gitignore))\n\n    def ignore_remove(self, path):\n        entry, gitignore = self._get_gitignore(path)\n\n        if not os.path.exists(gitignore):\n            return\n\n        with open(gitignore, 'r') as fd:\n            lines = fd.readlines()\n\n        filtered = list(filter(lambda x: x.strip() != entry.strip(), lines))\n\n        with open(gitignore, 'w') as fd:\n            fd.writelines(filtered)\n\n        if self.project is not None:\n            self.project._files_to_git_add.append(os.path.relpath(gitignore))\n\n    def add(self, paths):\n        # NOTE: GitPython is not currently able to handle index version >= 3.\n        # See https://github.com/iterative/dvc/issues/610 for more details.\n        try:\n            self.repo.index.add(paths)\n        except AssertionError as exc:\n            msg = 'Failed to add \\'{}\\' to git. You can add those files '\n            msg += 'manually using \\'git add\\'. '\n            msg += 'See \\'https://github.com/iterative/dvc/issues/610\\' '\n            msg += 'for more details.'\n            Logger.error(msg.format(str(paths)), exc)\n\n    def commit(self, msg):\n        self.repo.index.commit(msg)\n\n    def checkout(self, branch, create_new=False):\n        if create_new:\n            self.repo.git.checkout('HEAD', b=branch)\n        else:\n            self.repo.git.checkout(branch)\n\n    def branch(self, branch):\n        self.repo.git.branch(branch)\n\n    def tag(self, tag):\n        self.repo.git.tag(tag)\n\n    def untracked_files(self):\n        files = self.repo.untracked_files\n        return [os.path.join(self.repo.working_dir, fname) for fname in files]\n\n    def is_tracked(self, path):\n        return len(self.repo.git.ls_files(path)) != 0\n\n    def active_branch(self):\n        return self.repo.active_branch.name\n\n    def list_branches(self):\n        return [h.name for h in self.repo.heads]\n\n    def list_tags(self):\n        return [t.name for t in self.repo.tags]\n\n    def _install_hook(self, name, cmd):\n        hook = os.path.join(self.root_dir,\n                            self.GIT_DIR,\n                            'hooks',\n                            name)\n        if os.path.isfile(hook):\n            msg = 'Git hook \\'{}\\' already exists.'\n            raise SCMError(msg.format(os.path.relpath(hook)))\n        with open(hook, 'w+') as fd:\n            fd.write('#!/bin/sh\\nexec dvc {}\\n'.format(cmd))\n        os.chmod(hook, 0o777)\n\n    def install(self):\n        self._install_hook('post-checkout', 'checkout')\n        self._install_hook('pre-commit', 'status')\n\n\ndef SCM(root_dir, no_scm=False, project=None):\n    if Git.is_repo(root_dir) or Git.is_submodule(root_dir):\n        return Git(root_dir, project=project)\n\n    return Base(root_dir, project=project)\n", "path": "dvc/scm.py"}]}