From 4a534eba97db3c2cfb2926368756fd633d25c056 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 20 Oct 2009 12:24:47 +0200 Subject: Added frame for index implementation and testing --- test/git/test_index.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 test/git/test_index.py (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py new file mode 100644 index 00000000..f58405d2 --- /dev/null +++ b/test/git/test_index.py @@ -0,0 +1,17 @@ +# test_index.py +# Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors +# +# This module is part of GitPython and is released under +# the BSD License: http://www.opensource.org/licenses/bsd-license.php + +from test.testlib import * +from git import * + +class TestTree(TestCase): + + @classmethod + def setUpAll(cls): + cls.repo = Repo(GIT_REPO) + + def test_base(self): + self.fail("TODO") -- cgit v1.2.1 From 50a9920b1bd9e6e8cf452c774c499b0b9014ccef Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 20 Oct 2009 17:04:23 +0200 Subject: Added initial version of the index reading from file - IndexEntry interface is to be improved though, writing needs to be implemented as well --- test/git/test_index.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index f58405d2..272e68b3 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -14,4 +14,6 @@ class TestTree(TestCase): cls.repo = Repo(GIT_REPO) def test_base(self): - self.fail("TODO") + index = Index.from_file(fixture_path("index")) + assert index.entries + assert index.version > 0 -- cgit v1.2.1 From 56823868efddd3bdbc0b624cdc79adc3a2e94a75 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 20 Oct 2009 21:32:00 +0200 Subject: Improved tuple access of EntryIndex class including test, stage and type access still needs to be decoded though --- test/git/test_index.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index 272e68b3..91ce22fd 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -6,6 +6,7 @@ from test.testlib import * from git import * +import inspect class TestTree(TestCase): @@ -14,6 +15,19 @@ class TestTree(TestCase): cls.repo = Repo(GIT_REPO) def test_base(self): + # read from file index = Index.from_file(fixture_path("index")) assert index.entries assert index.version > 0 + + # test entry + last_val = None + entry = index.entries.itervalues().next() + for name, method in inspect.getmembers(entry,inspect.ismethod): + val = method(entry) + assert val != last_val + last_val = val + # END for each method + + # write + self.fail("writing, object type and stage") -- cgit v1.2.1 From 152bab7eb64e249122fefab0d5531db1e065f539 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 20 Oct 2009 22:05:51 +0200 Subject: improved IndexEntry type and added test for parsing of the stage --- test/git/test_index.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index 91ce22fd..86bde655 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -23,11 +23,15 @@ class TestTree(TestCase): # test entry last_val = None entry = index.entries.itervalues().next() - for name, method in inspect.getmembers(entry,inspect.ismethod): - val = method(entry) - assert val != last_val - last_val = val + for attr in ("path","ctime","mtime","dev","inode","mode","uid", + "gid","size","sha","stage"): + val = getattr(entry, attr) # END for each method + # test stage + index_merge = Index.from_file(fixture_path("index_merge")) + assert len(list(e for e in index_merge.entries.itervalues() if e.stage != 0 )) + # write - self.fail("writing, object type and stage") + self.fail("writing, what is 'size' attribute for ?") + -- cgit v1.2.1 From b9d6494f1075e5370a20e406c3edb102fca12854 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 21 Oct 2009 13:34:43 +0200 Subject: index writing added including simple test, improved docs of IndexEntry --- test/git/test_index.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index 86bde655..7a0e21eb 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -7,6 +7,7 @@ from test.testlib import * from git import * import inspect +import os class TestTree(TestCase): @@ -30,8 +31,13 @@ class TestTree(TestCase): # test stage index_merge = Index.from_file(fixture_path("index_merge")) + assert len(index_merge.entries) == 106 assert len(list(e for e in index_merge.entries.itervalues() if e.stage != 0 )) - # write - self.fail("writing, what is 'size' attribute for ?") + # write the data - it must match the original + index_output = os.tmpfile() + index_merge.write(index_output) + + index_output.seek(0) + assert index_output.read() == fixture("index_merge") -- cgit v1.2.1 From babf5765da3e328cc1060cb9b37fbdeb6fd58350 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 21 Oct 2009 16:52:25 +0200 Subject: Initial version of merge including tests for one-way, two-way and tree-way merge --- test/git/test_index.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index 7a0e21eb..ead231d1 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -41,3 +41,24 @@ class TestTree(TestCase): index_output.seek(0) assert index_output.read() == fixture("index_merge") + def test_merge(self): + common_ancestor_sha = "5117c9c8a4d3af19a9958677e45cda9269de1541" + cur_sha = "4b43ca7ff72d5f535134241e7c797ddc9c7a3573" + other_sha = "39f85c4358b7346fee22169da9cad93901ea9eb9" + + # simple index from tree + base_index = Index.from_tree(self.repo, common_ancestor_sha) + assert base_index.entries + + # merge two trees + two_way_index = Index.from_tree(self.repo, common_ancestor_sha, cur_sha) + assert two_way_index.entries + for e in two_way_index.entries.values(): + print "%i | %s" % ( e.stage, e.path ) + + # merge three trees - here we have a merge conflict + tree_way_index = Index.from_tree(self.repo, common_ancestor_sha, cur_sha, other_sha) + assert len(list(e for e in tree_way_index.entries.values() if e.stage != 0)) + + def test_custom_commit(self): + self.fail("Custom commit:write tree, make commit with custom parents") -- cgit v1.2.1 From d97afa24ad1ae453002357e5023f3a116f76fb17 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 21 Oct 2009 18:40:35 +0200 Subject: Improved testing of index against trees, tests succeed with next commit --- test/git/test_index.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index ead231d1..d256e7c0 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -41,6 +41,18 @@ class TestTree(TestCase): index_output.seek(0) assert index_output.read() == fixture("index_merge") + def _cmp_tree_index(self, tree, index): + # fail unless both objects contain the same paths and blobs + if isinstance(tree, str): + tree = self.repo.commit(tree).tree + + num_blobs = 0 + for blob in tree.traverse(predicate = lambda e: e.type == "blob"): + assert (blob.path,0) in index.entries + num_blobs += 1 + # END for each blob in tree + assert num_blobs == len(index.entries) + def test_merge(self): common_ancestor_sha = "5117c9c8a4d3af19a9958677e45cda9269de1541" cur_sha = "4b43ca7ff72d5f535134241e7c797ddc9c7a3573" @@ -49,12 +61,12 @@ class TestTree(TestCase): # simple index from tree base_index = Index.from_tree(self.repo, common_ancestor_sha) assert base_index.entries + self._cmp_tree_index(common_ancestor_sha, base_index) - # merge two trees + # merge two trees - its like a fast-forward two_way_index = Index.from_tree(self.repo, common_ancestor_sha, cur_sha) assert two_way_index.entries - for e in two_way_index.entries.values(): - print "%i | %s" % ( e.stage, e.path ) + self._cmp_tree_index(cur_sha, two_way_index) # merge three trees - here we have a merge conflict tree_way_index = Index.from_tree(self.repo, common_ancestor_sha, cur_sha, other_sha) -- cgit v1.2.1 From 6662422ba52753f8b10bc053aba82bac3f2e1b9c Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 21 Oct 2009 21:25:52 +0200 Subject: index.iter_blobs method added including tests ( which have been improved generally for more coverage ) --- test/git/test_index.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index d256e7c0..524f0778 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -8,6 +8,7 @@ from test.testlib import * from git import * import inspect import os +import tempfile class TestTree(TestCase): @@ -17,7 +18,7 @@ class TestTree(TestCase): def test_base(self): # read from file - index = Index.from_file(fixture_path("index")) + index = Index.from_file(self.repo, fixture_path("index")) assert index.entries assert index.version > 0 @@ -30,7 +31,7 @@ class TestTree(TestCase): # END for each method # test stage - index_merge = Index.from_file(fixture_path("index_merge")) + index_merge = Index.from_file(self.repo, fixture_path("index_merge")) assert len(index_merge.entries) == 106 assert len(list(e for e in index_merge.entries.itervalues() if e.stage != 0 )) @@ -40,6 +41,11 @@ class TestTree(TestCase): index_output.seek(0) assert index_output.read() == fixture("index_merge") + + tmpfile = tempfile.mktemp() + Index.to_file(index_merge, tmpfile) + assert os.path.isfile(tmpfile) + os.remove(tmpfile) def _cmp_tree_index(self, tree, index): # fail unless both objects contain the same paths and blobs @@ -53,7 +59,7 @@ class TestTree(TestCase): # END for each blob in tree assert num_blobs == len(index.entries) - def test_merge(self): + def test_from_tree(self): common_ancestor_sha = "5117c9c8a4d3af19a9958677e45cda9269de1541" cur_sha = "4b43ca7ff72d5f535134241e7c797ddc9c7a3573" other_sha = "39f85c4358b7346fee22169da9cad93901ea9eb9" @@ -70,7 +76,16 @@ class TestTree(TestCase): # merge three trees - here we have a merge conflict tree_way_index = Index.from_tree(self.repo, common_ancestor_sha, cur_sha, other_sha) - assert len(list(e for e in tree_way_index.entries.values() if e.stage != 0)) + assert len(list(e for e in tree_way_index.entries.values() if e.stage != 0)) + + + # ITERATE BLOBS + merge_required = lambda t: t[0] != 0 + merge_blobs = list(tree_way_index.iter_blobs(merge_required)) + assert merge_blobs + assert merge_blobs[0][0] in (1,2,3) + assert isinstance(merge_blobs[0][1], Blob) + def test_custom_commit(self): self.fail("Custom commit:write tree, make commit with custom parents") -- cgit v1.2.1 From 7b50af0a20bcc7280940ce07593007d17c5acabd Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 21 Oct 2009 23:11:40 +0200 Subject: index: Added write_tree method including test --- test/git/test_index.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index 524f0778..a4e01054 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -87,5 +87,12 @@ class TestTree(TestCase): assert isinstance(merge_blobs[0][1], Blob) + # writing a tree should fail with an unmerged index + self.failUnlessRaises(GitCommandError, tree_way_index.write_tree) + + # removed unmerged entries + self.fail("remove unmerged") + + def test_custom_commit(self): self.fail("Custom commit:write tree, make commit with custom parents") -- cgit v1.2.1 From aa921fee6014ef43bb2740240e9663e614e25662 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 22 Oct 2009 00:32:16 +0200 Subject: Implemented merge/resolve handling , but realized that index writing is not yet working properly as it is sha1 checked as well. This explains what my 20 byte 'extension_data' actually is ;) --- test/git/test_index.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index a4e01054..6208a1d9 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -75,23 +75,28 @@ class TestTree(TestCase): self._cmp_tree_index(cur_sha, two_way_index) # merge three trees - here we have a merge conflict - tree_way_index = Index.from_tree(self.repo, common_ancestor_sha, cur_sha, other_sha) - assert len(list(e for e in tree_way_index.entries.values() if e.stage != 0)) + three_way_index = Index.from_tree(self.repo, common_ancestor_sha, cur_sha, other_sha) + assert len(list(e for e in three_way_index.entries.values() if e.stage != 0)) # ITERATE BLOBS merge_required = lambda t: t[0] != 0 - merge_blobs = list(tree_way_index.iter_blobs(merge_required)) + merge_blobs = list(three_way_index.iter_blobs(merge_required)) assert merge_blobs assert merge_blobs[0][0] in (1,2,3) assert isinstance(merge_blobs[0][1], Blob) # writing a tree should fail with an unmerged index - self.failUnlessRaises(GitCommandError, tree_way_index.write_tree) + self.failUnlessRaises(GitCommandError, three_way_index.write_tree) # removed unmerged entries - self.fail("remove unmerged") + unmerged_blob_map = three_way_index.unmerged_blobs() + assert unmerged_blob_map + + # pick the first blob at the first stage we find and use it as resolved version + three_way_index.resolve_blobs( l[0][1] for l in unmerged_blob_map.itervalues() ) + three_way_index.write_tree() def test_custom_commit(self): -- cgit v1.2.1 From 30d822a468dc909aac5c83d078a59bfc85fc27aa Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 22 Oct 2009 10:15:47 +0200 Subject: index writing now creates a sha on the content making it possible to write valid indices after manually removing or altering entriesgst --- test/git/test_index.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index 6208a1d9..c8f6f4e3 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -96,7 +96,14 @@ class TestTree(TestCase): # pick the first blob at the first stage we find and use it as resolved version three_way_index.resolve_blobs( l[0][1] for l in unmerged_blob_map.itervalues() ) - three_way_index.write_tree() + tree = three_way_index.write_tree() + assert isinstance(tree, Tree) + num_blobs = 0 + for blob in tree.traverse(predicate=lambda item: item.type == "blob"): + assert (blob.path,0) in three_way_index.entries + num_blobs += 1 + # END for each blob + assert num_blobs == len(three_way_index.entries) def test_custom_commit(self): -- cgit v1.2.1 From 1f2b19de3301e76ab3a6187a49c9c93ff78bafbd Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 22 Oct 2009 13:40:56 +0200 Subject: Removed index test marker for custom commits as this boils down to a good way to add files to the index/remove them and make commits which are possibly customized with custom parents --- test/git/test_index.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index c8f6f4e3..4c17f5e5 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -104,7 +104,5 @@ class TestTree(TestCase): num_blobs += 1 # END for each blob assert num_blobs == len(three_way_index.entries) - - - def test_custom_commit(self): - self.fail("Custom commit:write tree, make commit with custom parents") + + -- cgit v1.2.1 From b197b2dbb527de9856e6e808339ab0ceaf0a512d Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 22 Oct 2009 16:20:24 +0200 Subject: Adjusted all remaining test suites to use the new TestBase class where appropriate --- test/git/test_index.py | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index 4c17f5e5..10ffb79d 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -10,15 +10,11 @@ import inspect import os import tempfile -class TestTree(TestCase): +class TestTree(TestBase): - @classmethod - def setUpAll(cls): - cls.repo = Repo(GIT_REPO) - def test_base(self): # read from file - index = Index.from_file(self.repo, fixture_path("index")) + index = Index.from_file(self.rorepo, fixture_path("index")) assert index.entries assert index.version > 0 @@ -31,7 +27,7 @@ class TestTree(TestCase): # END for each method # test stage - index_merge = Index.from_file(self.repo, fixture_path("index_merge")) + index_merge = Index.from_file(self.rorepo, fixture_path("index_merge")) assert len(index_merge.entries) == 106 assert len(list(e for e in index_merge.entries.itervalues() if e.stage != 0 )) @@ -50,7 +46,7 @@ class TestTree(TestCase): def _cmp_tree_index(self, tree, index): # fail unless both objects contain the same paths and blobs if isinstance(tree, str): - tree = self.repo.commit(tree).tree + tree = self.rorepo.commit(tree).tree num_blobs = 0 for blob in tree.traverse(predicate = lambda e: e.type == "blob"): @@ -65,17 +61,17 @@ class TestTree(TestCase): other_sha = "39f85c4358b7346fee22169da9cad93901ea9eb9" # simple index from tree - base_index = Index.from_tree(self.repo, common_ancestor_sha) + base_index = Index.from_tree(self.rorepo, common_ancestor_sha) assert base_index.entries self._cmp_tree_index(common_ancestor_sha, base_index) # merge two trees - its like a fast-forward - two_way_index = Index.from_tree(self.repo, common_ancestor_sha, cur_sha) + two_way_index = Index.from_tree(self.rorepo, common_ancestor_sha, cur_sha) assert two_way_index.entries self._cmp_tree_index(cur_sha, two_way_index) # merge three trees - here we have a merge conflict - three_way_index = Index.from_tree(self.repo, common_ancestor_sha, cur_sha, other_sha) + three_way_index = Index.from_tree(self.rorepo, common_ancestor_sha, cur_sha, other_sha) assert len(list(e for e in three_way_index.entries.values() if e.stage != 0)) -- cgit v1.2.1 From 3d9e7f1121d3bdbb08291c7164ad622350544a21 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 22 Oct 2009 18:01:52 +0200 Subject: Index now behaves more like the default index if no explicit stream is given. It will lazily read its data on first access --- test/git/test_index.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index 10ffb79d..8baf408c 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -101,4 +101,7 @@ class TestTree(TestBase): # END for each blob assert num_blobs == len(three_way_index.entries) - + def test_from_index(self): + # default Index instance points to our index + index = Index(self.rorepo) + assert len(index.entries) -- cgit v1.2.1 From 1496979cf7e9692ef869d2f99da6141756e08d25 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 22 Oct 2009 19:43:01 +0200 Subject: default index writing now writes the index of the current repository in a fashion comparable to the native implementation --- test/git/test_index.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index 8baf408c..5c643a67 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -101,7 +101,13 @@ class TestTree(TestBase): # END for each blob assert num_blobs == len(three_way_index.entries) - def test_from_index(self): + @with_rw_repo('0.1.6') + def test_from_index(self, rw_repo): # default Index instance points to our index - index = Index(self.rorepo) + index = Index(rw_repo) assert len(index.entries) + + # write the file back + index.write() + + # could sha it, or check stats -- cgit v1.2.1 From ea33fe8b21d2b02f902b131aba0d14389f2f8715 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 22 Oct 2009 22:14:02 +0200 Subject: Index: Is now diffable and appears to properly implement diffing against other items as well as the working tree Diff.Diffable: added callback allowing superclasses to preprocess diff arguments Diff.Diff: added eq, ne and hash methods, string methods would be nice --- test/git/test_index.py | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index 5c643a67..257acf10 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -102,12 +102,45 @@ class TestTree(TestBase): assert num_blobs == len(three_way_index.entries) @with_rw_repo('0.1.6') - def test_from_index(self, rw_repo): + def test_from_index_and_diff(self, rw_repo): # default Index instance points to our index index = Index(rw_repo) + assert index.path is not None assert len(index.entries) # write the file back index.write() # could sha it, or check stats + + # test diff + # resetting the head will leave the index in a different state, and the + # diff will yield a few changes + cur_head_commit = rw_repo.head.commit + ref = rw_repo.head.reset(rw_repo, 'HEAD~6', index=True, working_tree=False) + + # diff against same index is 0 + diff = index.diff() + assert len(diff) == 0 + + # against HEAD as string, must be the same as it matches index + diff = index.diff('HEAD') + assert len(diff) == 0 + + # against previous head, there must be a difference + diff = index.diff(cur_head_commit) + assert len(diff) + + # we reverse the result + adiff = index.diff(str(cur_head_commit), R=True) + odiff = index.diff(cur_head_commit, R=False) # now its not reversed anymore + assert adiff != odiff + assert odiff == diff # both unreversed diffs against HEAD + + # against working copy - its still at cur_commit + wdiff = index.diff(None) + assert wdiff != adiff + assert wdiff != odiff + + # against something unusual + self.failUnlessRaises(ValueError, index.diff, int) -- cgit v1.2.1 From b7a5c05875a760c0bf83af6617c68061bda6cfc5 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 22 Oct 2009 23:31:26 +0200 Subject: Adjusted tests to deal with API changes --- test/git/test_index.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index 257acf10..7bc2ad7e 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -116,8 +116,8 @@ class TestTree(TestBase): # test diff # resetting the head will leave the index in a different state, and the # diff will yield a few changes - cur_head_commit = rw_repo.head.commit - ref = rw_repo.head.reset(rw_repo, 'HEAD~6', index=True, working_tree=False) + cur_head_commit = rw_repo.head.reference.commit + ref = rw_repo.head.reset('HEAD~6', index=True, working_tree=False) # diff against same index is 0 diff = index.diff() -- cgit v1.2.1 From a10aa36bc6a82bd50df6f3df7d6b7ce04a7070f1 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Fri, 23 Oct 2009 10:42:26 +0200 Subject: Renamed Index to IndexFile, adjusted tests, it will only operate on physical files, not on streams, as Indices are not streamed by any git command ( at least not in raw format ) --- test/git/test_index.py | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index 7bc2ad7e..6fd3133a 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -12,9 +12,9 @@ import tempfile class TestTree(TestBase): - def test_base(self): + def test_index_file_base(self): # read from file - index = Index.from_file(self.rorepo, fixture_path("index")) + index = IndexFile(self.rorepo, fixture_path("index")) assert index.entries assert index.version > 0 @@ -27,20 +27,16 @@ class TestTree(TestBase): # END for each method # test stage - index_merge = Index.from_file(self.rorepo, fixture_path("index_merge")) + index_merge = IndexFile(self.rorepo, fixture_path("index_merge")) assert len(index_merge.entries) == 106 assert len(list(e for e in index_merge.entries.itervalues() if e.stage != 0 )) # write the data - it must match the original - index_output = os.tmpfile() - index_merge.write(index_output) - - index_output.seek(0) - assert index_output.read() == fixture("index_merge") - tmpfile = tempfile.mktemp() - Index.to_file(index_merge, tmpfile) - assert os.path.isfile(tmpfile) + index_merge.write(tmpfile) + fp = open(tmpfile, 'r') + assert fp.read() == fixture("index_merge") + fp.close() os.remove(tmpfile) def _cmp_tree_index(self, tree, index): @@ -55,23 +51,23 @@ class TestTree(TestBase): # END for each blob in tree assert num_blobs == len(index.entries) - def test_from_tree(self): + def test_index_file_from_tree(self): common_ancestor_sha = "5117c9c8a4d3af19a9958677e45cda9269de1541" cur_sha = "4b43ca7ff72d5f535134241e7c797ddc9c7a3573" other_sha = "39f85c4358b7346fee22169da9cad93901ea9eb9" # simple index from tree - base_index = Index.from_tree(self.rorepo, common_ancestor_sha) + base_index = IndexFile.from_tree(self.rorepo, common_ancestor_sha) assert base_index.entries self._cmp_tree_index(common_ancestor_sha, base_index) # merge two trees - its like a fast-forward - two_way_index = Index.from_tree(self.rorepo, common_ancestor_sha, cur_sha) + two_way_index = IndexFile.from_tree(self.rorepo, common_ancestor_sha, cur_sha) assert two_way_index.entries self._cmp_tree_index(cur_sha, two_way_index) # merge three trees - here we have a merge conflict - three_way_index = Index.from_tree(self.rorepo, common_ancestor_sha, cur_sha, other_sha) + three_way_index = IndexFile.from_tree(self.rorepo, common_ancestor_sha, cur_sha, other_sha) assert len(list(e for e in three_way_index.entries.values() if e.stage != 0)) @@ -102,9 +98,9 @@ class TestTree(TestBase): assert num_blobs == len(three_way_index.entries) @with_rw_repo('0.1.6') - def test_from_index_and_diff(self, rw_repo): + def test_index_file_diffing(self, rw_repo): # default Index instance points to our index - index = Index(rw_repo) + index = IndexFile(rw_repo) assert index.path is not None assert len(index.entries) -- cgit v1.2.1 From a7a4388eeaa4b6b94192dce67257a34c4a6cbd26 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Fri, 23 Oct 2009 12:14:22 +0200 Subject: Added frame for IndexFile add/remove/commit methods and respective test markers --- test/git/test_index.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index 6fd3133a..36e57d5c 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -26,6 +26,11 @@ class TestTree(TestBase): val = getattr(entry, attr) # END for each method + # test update + entries = index.entries + assert isinstance(index.update(), IndexFile) + assert entries is not index.entries + # test stage index_merge = IndexFile(self.rorepo, fixture_path("index_merge")) assert len(index_merge.entries) == 106 @@ -140,3 +145,11 @@ class TestTree(TestBase): # against something unusual self.failUnlessRaises(ValueError, index.diff, int) + + self.fail( "Test IndexFile.reset" ) + + @with_rw_repo('0.1.6') + def test_index_mutation(self, rw_repo): + # add / remove / commit / Working Tree Handling + self.fail( "add, remove, commit, working tree handling" ) + -- cgit v1.2.1 From 13a26d4f9c22695033040dfcd8c76fd94187035b Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Fri, 23 Oct 2009 17:55:33 +0200 Subject: Implemented index.reset method including test --- test/git/test_index.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index 36e57d5c..7236aad9 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -146,7 +146,33 @@ class TestTree(TestBase): # against something unusual self.failUnlessRaises(ValueError, index.diff, int) - self.fail( "Test IndexFile.reset" ) + # adjust the index to match an old revision + cur_branch = rw_repo.active_branch + cur_commit = cur_branch.commit + rev_head_parent = 'HEAD~1' + assert index.reset(rev_head_parent) is index + + assert cur_branch == rw_repo.active_branch + assert cur_commit == rw_repo.head.commit + + # there must be differences towards the working tree which is in the 'future' + assert index.diff(None) + + # reset the working copy as well to current head,to pull 'back' as well + new_data = "will be reverted" + file_path = os.path.join(rw_repo.git.git_dir, "CHANGES") + fp = open(file_path, "w") + fp.write(new_data) + fp.close() + index.reset(rev_head_parent, working_tree=True) + assert not index.diff(None) + assert cur_branch == rw_repo.active_branch + assert cur_commit == rw_repo.head.commit + fp = open(file_path) + try: + assert fp.read() != new_data + finally: + fp.close() @with_rw_repo('0.1.6') def test_index_mutation(self, rw_repo): -- cgit v1.2.1 From 0cd09bd306486028f5442c56ef2e947355a06282 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Fri, 23 Oct 2009 21:49:13 +0200 Subject: index.remove implemented including throrough test --- test/git/test_index.py | 64 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index 7236aad9..2f8fed32 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -9,6 +9,7 @@ from git import * import inspect import os import tempfile +import glob class TestTree(TestBase): @@ -174,8 +175,67 @@ class TestTree(TestBase): finally: fp.close() + + def _count_existing(self, repo, files): + existing = 0 + basedir = repo.git.git_dir + for f in files: + existing += os.path.isfile(os.path.join(basedir, f)) + # END for each deleted file + return existing + # END num existing helper + + + @with_rw_repo('0.1.6') def test_index_mutation(self, rw_repo): - # add / remove / commit / Working Tree Handling - self.fail( "add, remove, commit, working tree handling" ) + index = rw_repo.index + num_entries = len(index.entries) + # remove all of the files, provide a wild mix of paths, BaseIndexEntries, + # IndexEntries + def mixed_iterator(): + count = 0 + for entry in index.entries.itervalues(): + type_id = count % 4 + if type_id == 0: # path + yield entry.path + elif type_id == 1: # blob + yield Blob(rw_repo, entry.sha, entry.mode, entry.path) + elif type_id == 2: # BaseIndexEntry + yield BaseIndexEntry(entry[:4]) + elif type_id == 3: # IndexEntry + yield entry + else: + raise AssertionError("Invalid Type") + count += 1 + # END for each entry + # END mixed iterator + deleted_files = index.remove(mixed_iterator(), working_tree=False) + assert deleted_files + assert self._count_existing(rw_repo, deleted_files) == len(deleted_files) + assert len(index.entries) == 0 + + # reset the index to undo our changes + index.reset() + assert len(index.entries) == num_entries + + # remove with working copy + deleted_files = index.remove(mixed_iterator(), working_tree=True) + assert deleted_files + assert self._count_existing(rw_repo, deleted_files) == 0 + + # reset everything + index.reset(working_tree=True) + assert self._count_existing(rw_repo, deleted_files) == len(deleted_files) + + # invalid type + self.failUnlessRaises(TypeError, index.remove, [1]) + + # absolute path + deleted_files = index.remove([os.path.join(rw_repo.git.git_dir,"lib")], r=True) + assert len(deleted_files) > 1 + self.failUnlessRaises(ValueError, index.remove, ["/doesnt/exists"]) + + # re-add all files in lib + self.fail( "add, commit, working tree handling" ) -- cgit v1.2.1 From f9cec00938d9059882bb8eabdaf2f775943e00e5 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Sat, 24 Oct 2009 00:08:33 +0200 Subject: index.commit: implemented initial version, but in fact some more changes are required to have a nice API. Tests are not yet fully done either --- test/git/test_index.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index 2f8fed32..0a5f4c35 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -236,6 +236,18 @@ class TestTree(TestBase): assert len(deleted_files) > 1 self.failUnlessRaises(ValueError, index.remove, ["/doesnt/exists"]) + # test committing + # commit changed index + cur_commit = rw_repo.head.commit + commit_message = "commit default head" + new_commit = index.commit(commit_message) + assert new_commit.message == commit_message + assert new_commit.parents[0] == cur_commit + + self.fail("commit with no parents") + self.fail("commit multiple parents") + + # re-add all files in lib self.fail( "add, commit, working tree handling" ) -- cgit v1.2.1 From 5ba2aef8f59009756567a53daaf918afa851c304 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 26 Oct 2009 11:25:45 +0100 Subject: added head kwarg to reset and commit method, allowing to automatically change the head to the given commit, which makes the methods more versatile --- test/git/test_index.py | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index 0a5f4c35..e25f3d2e 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -191,6 +191,8 @@ class TestTree(TestBase): def test_index_mutation(self, rw_repo): index = rw_repo.index num_entries = len(index.entries) + cur_head = rw_repo.head + # remove all of the files, provide a wild mix of paths, BaseIndexEntries, # IndexEntries def mixed_iterator(): @@ -236,18 +238,39 @@ class TestTree(TestBase): assert len(deleted_files) > 1 self.failUnlessRaises(ValueError, index.remove, ["/doesnt/exists"]) - # test committing + # TEST COMMITTING # commit changed index - cur_commit = rw_repo.head.commit + cur_commit = cur_head.commit commit_message = "commit default head" - new_commit = index.commit(commit_message) + + new_commit = index.commit(commit_message, head=False) assert new_commit.message == commit_message assert new_commit.parents[0] == cur_commit - - self.fail("commit with no parents") - self.fail("commit multiple parents") - + assert len(new_commit.parents) == 1 + assert cur_head.commit == cur_commit + + # same index, no parents + commit_message = "index without parents" + commit_no_parents = index.commit(commit_message, parent_commits=list(), head=True) + assert commit_no_parents.message == commit_message + assert len(commit_no_parents.parents) == 0 + assert cur_head.commit == commit_no_parents + + # same index, multiple parents + commit_message = "Index with multiple parents\n commit with another line" + commit_multi_parent = index.commit(commit_message,parent_commits=(commit_no_parents, new_commit)) + assert commit_multi_parent.message == commit_message + assert len(commit_multi_parent.parents) == 2 + assert commit_multi_parent.parents[0] == commit_no_parents + assert commit_multi_parent.parents[1] == new_commit + assert cur_head.commit == commit_multi_parent # re-add all files in lib - self.fail( "add, commit, working tree handling" ) + # get the lib folder back on disk, but get an index without it + index.reset(new_commit.parents[0], working_tree=True).reset(new_commit, working_tree=False) + lib_file_path = "lib/git/__init__.py" + assert (lib_file_path, 0) not in index.entries + assert os.path.isfile(os.path.join(rw_repo.git.git_dir, lib_file_path)) + + self.fail( "add file using simple path, blob, blob as symlink, entries with stages" ) -- cgit v1.2.1 From 0ef1f89abe5b2334705ee8f1a6da231b0b6c9a50 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 26 Oct 2009 22:37:48 +0100 Subject: index.add: Finished implemenation including through tests index.checkout: added simple method allowing to checkout files from the index, including simple test --- test/git/test_index.py | 81 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index e25f3d2e..3312abe1 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -8,8 +8,10 @@ from test.testlib import * from git import * import inspect import os +import sys import tempfile import glob +from stat import * class TestTree(TestBase): @@ -174,6 +176,26 @@ class TestTree(TestBase): assert fp.read() != new_data finally: fp.close() + + # test full checkout + test_file = os.path.join(rw_repo.git.git_dir, "CHANGES") + os.remove(test_file) + index.checkout(None, force=True) + assert os.path.isfile(test_file) + + os.remove(test_file) + index.checkout(None, force=False) + assert os.path.isfile(test_file) + + # individual file + os.remove(test_file) + index.checkout(test_file) + assert os.path.exists(test_file) + + + + # currently it ignore non-existing paths + index.checkout(paths=["doesnt/exist"]) def _count_existing(self, repo, files): @@ -186,6 +208,17 @@ class TestTree(TestBase): # END num existing helper + def _make_file(self, rela_path, data, repo=None): + """ + Create a file at the given path relative to our repository, filled + with the given data. Returns absolute path to created file. + """ + repo = repo or self.rorepo + abs_path = os.path.join(repo.git.git_dir, rela_path) + fp = open(abs_path, "w") + fp.write(data) + fp.close() + return abs_path @with_rw_repo('0.1.6') def test_index_mutation(self, rw_repo): @@ -272,5 +305,51 @@ class TestTree(TestBase): assert (lib_file_path, 0) not in index.entries assert os.path.isfile(os.path.join(rw_repo.git.git_dir, lib_file_path)) - self.fail( "add file using simple path, blob, blob as symlink, entries with stages" ) + # directory + entries = index.add(['lib']) + assert len(entries)>1 + + # glob + entries = index.reset(new_commit).add(['lib/*.py']) + assert len(entries) == 14 + + # missing path + self.failUnlessRaises(GitCommandError, index.reset(new_commit).add, ['doesnt/exist/must/raise']) + + # blob from older revision overrides current index revision + old_blob = new_commit.parents[0].tree.blobs[0] + entries = index.reset(new_commit).add([old_blob]) + assert index.entries[(old_blob.path,0)].sha == old_blob.id and len(entries) == 1 + + # mode 0 not allowed + null_sha = "0"*40 + self.failUnlessRaises(ValueError, index.reset(new_commit).add, [BaseIndexEntry((0, null_sha,0,"doesntmatter"))]) + + # add new file + new_file_relapath = "my_new_file" + new_file_path = self._make_file(new_file_relapath, "hello world", rw_repo) + entries = index.reset(new_commit).add([BaseIndexEntry((010644, null_sha, 0, new_file_relapath))]) + assert len(entries) == 1 and entries[0].sha != null_sha + + # add symlink + if sys.platform != "win32": + link_file = os.path.join(rw_repo.git.git_dir, "my_real_symlink") + os.symlink("/etc/that", link_file) + entries = index.reset(new_commit).add([link_file]) + assert len(entries) == 1 and S_ISLNK(entries[0].mode) + print "%o" % entries[0].mode + # END real symlink test + + # add fake symlink and assure it checks-our as symlink + fake_symlink_relapath = "my_fake_symlink" + fake_symlink_path = self._make_file(fake_symlink_relapath, "/etc/that", rw_repo) + fake_entry = BaseIndexEntry((0120000, null_sha, 0, fake_symlink_relapath)) + entries = index.reset(new_commit).add([fake_entry]) + assert len(entries) == 1 and S_ISLNK(entries[0].mode) + + # checkout the fakelink, should be a link then + assert not S_ISLNK(os.stat(fake_symlink_path)[ST_MODE]) + os.remove(fake_symlink_path) + index.checkout(fake_symlink_path) + assert S_ISLNK(os.lstat(fake_symlink_path)[ST_MODE]) -- cgit v1.2.1 From 22757ed7b58862cccef64fdc09f93ea1ac72b1d2 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 27 Oct 2009 11:58:20 +0100 Subject: put _make_file helper method into TestBase class remote: prepared FetchInfo class to be returned by fetch and pull. About to implement tests --- test/git/test_index.py | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index 3312abe1..3345949b 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -199,6 +199,9 @@ class TestTree(TestBase): def _count_existing(self, repo, files): + """ + Returns count of files that actually exist in the repository directory. + """ existing = 0 basedir = repo.git.git_dir for f in files: @@ -207,19 +210,6 @@ class TestTree(TestBase): return existing # END num existing helper - - def _make_file(self, rela_path, data, repo=None): - """ - Create a file at the given path relative to our repository, filled - with the given data. Returns absolute path to created file. - """ - repo = repo or self.rorepo - abs_path = os.path.join(repo.git.git_dir, rela_path) - fp = open(abs_path, "w") - fp.write(data) - fp.close() - return abs_path - @with_rw_repo('0.1.6') def test_index_mutation(self, rw_repo): index = rw_repo.index -- cgit v1.2.1 From 3cb5ba18ab1a875ef6b62c65342de476be47871b Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 3 Nov 2009 16:35:33 +0100 Subject: object: renamed id attribute to sha as it in fact is always being rewritten as sha, even if the passed in id was a ref. This is done to assure objects are uniquely identified and will compare correctly --- test/git/test_index.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/git/test_index.py') diff --git a/test/git/test_index.py b/test/git/test_index.py index 3345949b..e9541232 100644 --- a/test/git/test_index.py +++ b/test/git/test_index.py @@ -309,7 +309,7 @@ class TestTree(TestBase): # blob from older revision overrides current index revision old_blob = new_commit.parents[0].tree.blobs[0] entries = index.reset(new_commit).add([old_blob]) - assert index.entries[(old_blob.path,0)].sha == old_blob.id and len(entries) == 1 + assert index.entries[(old_blob.path,0)].sha == old_blob.sha and len(entries) == 1 # mode 0 not allowed null_sha = "0"*40 -- cgit v1.2.1