Allow passing in relative paths to porcelain.add().
authorJelmer Vernooij <jelmer@jelmer.uk>
Thu, 26 Jan 2017 20:51:30 +0000 (20:51 +0000)
committerJelmer Vernooij <jelmer@jelmer.uk>
Thu, 26 Jan 2017 20:51:30 +0000 (20:51 +0000)
NEWS
dulwich/porcelain.py
dulwich/repo.py
dulwich/tests/test_porcelain.py
dulwich/tests/test_repository.py

diff --git a/NEWS b/NEWS
index 7c70ca63a649503cc6c89123265a0705bf947a7f..420d1fd175c4b04641a9f69e81c578fcd284f0f4 100644 (file)
--- a/NEWS
+++ b/NEWS
  * Implement MemoryRepo.{set_description,get_description}.
    (Jelmer Vernooij)
 
+ * Raise exception in Repo.stage() when absolute paths are
+   passed in. Allow passing in relative paths to
+   porcelain.add().(Jelmer Vernooij)
+
 0.16.3 2016-01-14
 
  TEST FIXES
index 3d39ace8683d8b10b67c2b4a5d229c731921c8d5..bcf230737837761ae7c7ccb505b7c368dec624a3 100644 (file)
@@ -304,7 +304,6 @@ def add(repo=".", paths=None):
     :param repo: Repository for the files
     :param paths: Paths to add.  No value passed stages all modified files.
     """
-    # FIXME: Support patterns, directories.
     with open_repo_closing(repo) as r:
         if not paths:
             # If nothing is specified, add all non-ignored files.
@@ -315,7 +314,18 @@ def add(repo=".", paths=None):
                     dirnames.remove('.git')
                 for filename in filenames:
                     paths.append(os.path.join(dirpath[len(r.path)+1:], filename))
-        r.stage(paths)
+        # TODO(jelmer): Possibly allow passing in absolute paths?
+        relpaths = []
+        if not isinstance(paths, list):
+            paths = [paths]
+        for p in paths:
+            # FIXME: Support patterns, directories.
+            if os.path.isabs(p) and p.startswith(repo.path):
+                relpath = os.path.relpath(p, repo.path)
+            else:
+                relpath = p
+            relpaths.append(relpath)
+        r.stage(relpaths)
 
 
 def rm(repo=".", paths=None):
index 94f676638accfb5c98629d707d45bc9a3d55e420..0b1beedffabd532c30f121afdd10c09adfa09a0c 100644 (file)
@@ -850,6 +850,10 @@ class Repo(BaseRepo):
         for fs_path in fs_paths:
             if not isinstance(fs_path, bytes):
                 fs_path = fs_path.encode(sys.getfilesystemencoding())
+            if os.path.isabs(fs_path):
+                raise ValueError(
+                    "path %r should be relative to "
+                    "repository root, not absolute" % fs_path)
             tree_path = _fs_to_tree_path(fs_path)
             full_path = os.path.join(root_path_bytes, fs_path)
             try:
@@ -1044,7 +1048,7 @@ class Repo(BaseRepo):
     def init_bare(cls, path):
         """Create a new bare repository.
 
-        ``path`` should already exist and be an emty directory.
+        ``path`` should already exist and be an empty directory.
 
         :param path: Path to create bare repository in
         :return: a `Repo` instance
index 2198df13b4655e9734fab0cf8eca458a2d9a25b9..fa3b1257b797f508301ef4503ccf5fdf17d89bb4 100644 (file)
@@ -230,6 +230,14 @@ class AddTests(PorcelainTestCase):
         with open(os.path.join(self.repo.path, 'foo'), 'w') as f:
             f.write("BAR")
         porcelain.add(self.repo.path, paths=["foo"])
+        self.assertIn("foo", self.repo.open_index())
+
+    def test_add_file_absolute_path(self):
+        # Absolute paths are (not yet) supported
+        with open(os.path.join(self.repo.path, 'foo'), 'w') as f:
+            f.write("BAR")
+        porcelain.add(self.repo, paths=[os.path.join(self.repo.path, "foo")])
+        self.assertIn("foo", self.repo.open_index())
 
 
 class RemoveTests(PorcelainTestCase):
index 034ad2d25f359301b58cc02f1101faf010d2ceef..9c853576605874844f35cce160f30a93fc1d5793 100644 (file)
@@ -813,6 +813,11 @@ class BuildRepoRootTests(TestCase):
         self.assertEqual([self._root_commit], r[commit_sha].parents)
         self.assertEqual(old_refs, r.get_refs())
 
+    def test_stage_absolute(self):
+        r = self._repo
+        os.remove(os.path.join(r.path, 'a'))
+        self.assertRaises(ValueError, r.stage, [os.path.join(r.path, 'a')])
+
     def test_stage_deleted(self):
         r = self._repo
         os.remove(os.path.join(r.path, 'a'))