From a07cdbae1d485fd715a5b6eca767f211770fea4d Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 19 Oct 2009 18:06:19 +0200 Subject: Added remote module and test cases - about to implement remote option handling --- test/git/test_remote.py | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 test/git/test_remote.py (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py new file mode 100644 index 00000000..6d6fcea6 --- /dev/null +++ b/test/git/test_remote.py @@ -0,0 +1,48 @@ +# test_remote.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 TestRemote(TestCase): + + @classmethod + def setUpAll(cls): + cls.repo = Repo(GIT_REPO) + + def test_base(self): + num_remotes = 0 + for remote in self.repo.remotes: + num_remotes += 1 + assert str(remote) != repr(remote) + + + refs = remote.refs + assert refs + for ref in refs: + assert ref.remote_name == remote.name + assert ref.remote_branch + # END for each ref + + # test rename + other_name = "totally_other_name" + prev_name = remote.name + assert remote.rename(other_name) == remote + assert prev_name != remote.name + # multiple times + for time in range(2): + assert remote.rename(prev_name).name == prev_name + # END for each rename ( back to prev_name ) + + remote.update() + + # END for each remote + assert num_remotes + + def test_creation_and_removal(self): + self.fail( "Test remote creation/removal" ) + + -- cgit v1.2.3 From 048acc4596dc1c6d7ed3220807b827056cb01032 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 19 Oct 2009 18:53:55 +0200 Subject: Added configuration access including tests to remote config: fixed issue that would cause it to abort reading if the file did not exist - this is valid now Test does not work as the configuration parsing does not work as expected - this must be fixed first --- test/git/test_remote.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index 6d6fcea6..24fba07c 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -19,7 +19,7 @@ class TestRemote(TestCase): num_remotes += 1 assert str(remote) != repr(remote) - + # REFS refs = remote.refs assert refs for ref in refs: @@ -27,7 +27,28 @@ class TestRemote(TestCase): assert ref.remote_branch # END for each ref - # test rename + # OPTIONS + for opt in ("url", "fetch"): + val = getattr(remote, opt) + reader = remote.config_reader + assert reader.get(opt) == val + + # unable to write with a reader + self.failUnlessRaises(IOError, reader.set, opt, "test") + + # change value + writer = remote.config_writer + new_val = "myval" + writer.set(opt, new_val) + assert writer.get(opt) == new_val + writer.set(opt, val) + assert writer.get(opt) == val + del(writer) + assert getattr(remote, opt) == val + # END + self.fail( "option testing, read/write" ) + + # RENAME other_name = "totally_other_name" prev_name = remote.name assert remote.rename(other_name) == remote -- cgit v1.2.3 From cbf957a36f5ed47c4387ee8069c56b16d1b4f558 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 19 Oct 2009 20:23:47 +0200 Subject: remote: base tests succeed now --- test/git/test_remote.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index 24fba07c..ac282908 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -15,9 +15,13 @@ class TestRemote(TestCase): def test_base(self): num_remotes = 0 + remote_set = set() for remote in self.repo.remotes: num_remotes += 1 + assert remote == remote assert str(remote) != repr(remote) + remote_set.add(remote) + remote_set.add(remote) # should already exist # REFS refs = remote.refs @@ -46,7 +50,6 @@ class TestRemote(TestCase): del(writer) assert getattr(remote, opt) == val # END - self.fail( "option testing, read/write" ) # RENAME other_name = "totally_other_name" @@ -62,6 +65,8 @@ class TestRemote(TestCase): # END for each remote assert num_remotes + assert num_remotes == len(remote_set) + def test_creation_and_removal(self): self.fail( "Test remote creation/removal" ) -- cgit v1.2.3 From 53d26977f1aff8289f13c02ee672349d78eeb2f0 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 19 Oct 2009 21:31:55 +0200 Subject: remote: added tests for creation and removal, finishing the remote interface --- test/git/test_remote.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index ac282908..2446710f 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -49,7 +49,7 @@ class TestRemote(TestCase): assert writer.get(opt) == val del(writer) assert getattr(remote, opt) == val - # END + # END for each default option key # RENAME other_name = "totally_other_name" @@ -69,6 +69,21 @@ class TestRemote(TestCase): def test_creation_and_removal(self): - self.fail( "Test remote creation/removal" ) + new_name = "test_new_one" + arg_list = (new_name, "git@server:hello.git") + remote = Remote.create(self.repo, *arg_list ) + assert remote.name == "test_new_one" + + # create same one again + self.failUnlessRaises(GitCommandError, Remote.create, self.repo, *arg_list) + + Remote.remove(self.repo, new_name) + + for remote in self.repo.remotes: + if remote.name == new_name: + raise AssertionError("Remote removal failed") + # END if deleted remote matches existing remote's name + # END for each remote + -- cgit v1.2.3 From 11b1f6edc164e2084e3ff034d3b65306c461a0be Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 19 Oct 2009 22:08:23 +0200 Subject: repo.remote method added CHANGES updated to carry information about remotes and config --- test/git/test_remote.py | 1 + 1 file changed, 1 insertion(+) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index 2446710f..8c0177fd 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -67,6 +67,7 @@ class TestRemote(TestCase): assert num_remotes assert num_remotes == len(remote_set) + origin = self.repo.remote('origin') def test_creation_and_removal(self): new_name = "test_new_one" -- cgit v1.2.3 From 989671780551b7587d57e1d7cb5eb1002ade75b4 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 19 Oct 2009 23:44:18 +0200 Subject: Implemneted IterableLists for refs, commits and remote objects including simple tests --- test/git/test_remote.py | 1 + 1 file changed, 1 insertion(+) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index 8c0177fd..4cbb0b7b 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -68,6 +68,7 @@ class TestRemote(TestCase): assert num_remotes == len(remote_set) origin = self.repo.remote('origin') + assert origin == self.repo.remotes.origin def test_creation_and_removal(self): new_name = "test_new_one" -- cgit v1.2.3 From 3c9f55dd8e6697ab2f9eaf384315abd4cbefad38 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 21 Oct 2009 22:53:51 +0200 Subject: remote: Added fetch, pull, push methods to the interface to make these operations more convenient, like repo.remotes.origin.fetch --- test/git/test_remote.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index 4cbb0b7b..aeb6b4af 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -32,7 +32,8 @@ class TestRemote(TestCase): # END for each ref # OPTIONS - for opt in ("url", "fetch"): + # cannot use 'fetch' key anymore as it is now a method + for opt in ("url", ): val = getattr(remote, opt) reader = remote.config_reader assert reader.get(opt) == val @@ -61,8 +62,10 @@ class TestRemote(TestCase): assert remote.rename(prev_name).name == prev_name # END for each rename ( back to prev_name ) + remote.fetch() + self.failUnlessRaises(GitCommandError, remote.pull) remote.update() - + self.fail("test push once there is a test-repo") # END for each remote assert num_remotes assert num_remotes == len(remote_set) -- cgit v1.2.3 From 3c770f8e98a0079497d3eb5bc31e7260cc70cc63 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 22 Oct 2009 16:06:10 +0200 Subject: Fixed decorator issue that would cause a function to be passed even though there is a default argument. This feels inconsistent as the 'argument passer' wrapper function can be called with a function or a string as first argument depending on whether the client code was explicitly passing an argument or not. That ... sucks. Now test for that case specifically and fail with a proper assertion error. I don't like it, but what can I do ... . Remote tests adjusted to use rw repositories instead. More tests to follow, and many api methods are to be implemented now these things can be tested properly. --- test/git/test_remote.py | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index aeb6b4af..ef00056d 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -7,16 +7,13 @@ from test.testlib import * from git import * -class TestRemote(TestCase): +class TestRemote(TestBase): - @classmethod - def setUpAll(cls): - cls.repo = Repo(GIT_REPO) - - def test_base(self): + @with_rw_and_rw_remote_repo('0.1.6') + def test_base(self, rw_repo, remote_repo): num_remotes = 0 remote_set = set() - for remote in self.repo.remotes: + for remote in rw_repo.remotes: num_remotes += 1 assert remote == remote assert str(remote) != repr(remote) @@ -64,27 +61,29 @@ class TestRemote(TestCase): remote.fetch() self.failUnlessRaises(GitCommandError, remote.pull) + remote.pull('master') remote.update() self.fail("test push once there is a test-repo") # END for each remote assert num_remotes assert num_remotes == len(remote_set) - origin = self.repo.remote('origin') - assert origin == self.repo.remotes.origin + origin = rw_repo.remote('origin') + assert origin == rw_repo.remotes.origin - def test_creation_and_removal(self): + @with_bare_rw_repo + def test_creation_and_removal(self, bare_rw_repo): new_name = "test_new_one" arg_list = (new_name, "git@server:hello.git") - remote = Remote.create(self.repo, *arg_list ) + remote = Remote.create(bare_rw_repo, *arg_list ) assert remote.name == "test_new_one" # create same one again - self.failUnlessRaises(GitCommandError, Remote.create, self.repo, *arg_list) + self.failUnlessRaises(GitCommandError, Remote.create, bare_rw_repo, *arg_list) - Remote.remove(self.repo, new_name) + Remote.remove(bare_rw_repo, new_name) - for remote in self.repo.remotes: + for remote in bare_rw_repo.remotes: if remote.name == new_name: raise AssertionError("Remote removal failed") # END if deleted remote matches existing remote's name -- cgit v1.2.3 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_remote.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index ef00056d..f1e25ebf 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -59,11 +59,18 @@ class TestRemote(TestBase): assert remote.rename(prev_name).name == prev_name # END for each rename ( back to prev_name ) - remote.fetch() + # FETCH TESTING + assert len(remote.fetch()) == 1 + + + self.fail("rejected parsing") + self.fail("test parsing of each individual flag") + # PULL TESTING + # fails as we did not specify a branch and there is no configuration for it self.failUnlessRaises(GitCommandError, remote.pull) remote.pull('master') remote.update() - self.fail("test push once there is a test-repo") + # END for each remote assert num_remotes assert num_remotes == len(remote_set) -- cgit v1.2.3 From 5047344a22ed824735d6ed1c91008767ea6638b7 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 27 Oct 2009 20:09:50 +0100 Subject: Added testing frame for proper fetch testing to be very sure this works as expected. Plenty of cases still to be tested --- test/git/test_remote.py | 50 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 8 deletions(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index f1e25ebf..ae828cbc 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -7,8 +7,46 @@ from test.testlib import * from git import * +import os + class TestRemote(TestBase): + def _print_fetchhead(self, repo): + fp = open(os.path.join(repo.path, "FETCH_HEAD")) + print fp.read() + fp.close() + + + def _check_fetch_results(self, results, remote): + self._print_fetchhead(remote.repo) + assert len(results) > 0 and isinstance(results[0], remote.FetchInfo) + for result in results: + assert result.flags != 0 + assert isinstance(result.remote_ref, (SymbolicReference, Reference)) + # END for each result + + def _test_fetch_info(self, repo): + self.failUnlessRaises(ValueError, Remote.FetchInfo._from_line, repo, "nonsense") + self.failUnlessRaises(ValueError, Remote.FetchInfo._from_line, repo, "? [up to date] 0.1.7RC -> origin/0.1.7RC") + + def _test_fetch(self,remote, rw_repo, remote_repo): + # specialized fetch testing to de-clutter the main test + self._test_fetch_info(rw_repo) + + fetch_result = remote.fetch() + self._check_fetch_results(fetch_result, remote) + + self.fail("rejected parsing") + self.fail("test parsing of each individual flag") + self.fail("tag handling") + + def _test_pull(self,remote, rw_repo, remote_repo): + # pull is essentially a fetch + merge, hence we just do a light + # test here, leave the reset to the actual merge testing + # fails as we did not specify a branch and there is no configuration for it + self.failUnlessRaises(GitCommandError, remote.pull) + remote.pull('master') + @with_rw_and_rw_remote_repo('0.1.6') def test_base(self, rw_repo, remote_repo): num_remotes = 0 @@ -60,18 +98,14 @@ class TestRemote(TestBase): # END for each rename ( back to prev_name ) # FETCH TESTING - assert len(remote.fetch()) == 1 - + self._test_fetch(remote, rw_repo, remote_repo) - self.fail("rejected parsing") - self.fail("test parsing of each individual flag") # PULL TESTING - # fails as we did not specify a branch and there is no configuration for it - self.failUnlessRaises(GitCommandError, remote.pull) - remote.pull('master') - remote.update() + self._test_pull(remote, rw_repo, remote_repo) + remote.update() # END for each remote + assert num_remotes assert num_remotes == len(remote_set) -- cgit v1.2.3 From 038f183313f796dc0313c03d652a2bcc1698e78e Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 27 Oct 2009 20:46:26 +0100 Subject: implemented test for rejection handling and fixed a bug when parsing remote reference paths --- test/git/test_remote.py | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index ae828cbc..3b145468 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -17,13 +17,18 @@ class TestRemote(TestBase): fp.close() - def _check_fetch_results(self, results, remote): - self._print_fetchhead(remote.repo) + def _test_fetch_result(self, results, remote): + # self._print_fetchhead(remote.repo) assert len(results) > 0 and isinstance(results[0], remote.FetchInfo) - for result in results: - assert result.flags != 0 - assert isinstance(result.remote_ref, (SymbolicReference, Reference)) - # END for each result + for info in results: + assert info.flags != 0 + assert isinstance(info.remote_ref, (SymbolicReference, Reference)) + if info.flags & info.FORCED_UPDATE: + assert isinstance(info.commit_before_forced_update, Commit) + else: + assert info.commit_before_forced_update is None + # END forced update checking + # END for each info def _test_fetch_info(self, repo): self.failUnlessRaises(ValueError, Remote.FetchInfo._from_line, repo, "nonsense") @@ -33,10 +38,20 @@ class TestRemote(TestBase): # specialized fetch testing to de-clutter the main test self._test_fetch_info(rw_repo) - fetch_result = remote.fetch() - self._check_fetch_results(fetch_result, remote) + # put remote head to master as it is garantueed to exist + remote_repo.head.reference = remote_repo.heads.master + + res = remote.fetch() + self._test_fetch_result(res, remote) + + # rewind remote head to trigger rejection + # index must be false as remote is a bare repo + remote_repo.head.reset("HEAD~2", index=False) + res = remote.fetch() + self._test_fetch_result(res, remote) + master_info = res["%s/master" % remote] + assert master_info.flags & Remote.FetchInfo.FORCED_UPDATE and master_info.note is not None - self.fail("rejected parsing") self.fail("test parsing of each individual flag") self.fail("tag handling") -- cgit v1.2.3 From 138aa2b8b413a19ebf9b2bbb39860089c4436001 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 27 Oct 2009 20:57:54 +0100 Subject: Added non-fast forward test case, fixed parsing issue caused by initial line stripping --- test/git/test_remote.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index 3b145468..1d343c74 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -43,17 +43,28 @@ class TestRemote(TestBase): res = remote.fetch() self._test_fetch_result(res, remote) + # all uptodate + for info in res: + assert info.flags & info.BRANCH_UPTODATE # rewind remote head to trigger rejection # index must be false as remote is a bare repo - remote_repo.head.reset("HEAD~2", index=False) + rhead = remote_repo.head + remote_commit = rhead.commit + rhead.reset("HEAD~2", index=False) res = remote.fetch() self._test_fetch_result(res, remote) - master_info = res["%s/master" % remote] + mkey = "%s/master" % remote + master_info = res[mkey] assert master_info.flags & Remote.FetchInfo.FORCED_UPDATE and master_info.note is not None - self.fail("test parsing of each individual flag") - self.fail("tag handling") + # normal fast forward - set head back to previous one + rhead.commit = remote_commit + res = remote.fetch() + self._test_fetch_result(res, remote) + assert res[mkey].flags & Remote.FetchInfo.FAST_FORWARD + + self.fail("tag handling, tag uptodate, new tag, new branch") def _test_pull(self,remote, rw_repo, remote_repo): # pull is essentially a fetch + merge, hence we just do a light -- cgit v1.2.3 From b1f32e231d391f8e6051957ad947d3659c196b2b Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 27 Oct 2009 22:06:18 +0100 Subject: Added remote stale_refs property including test, tested new remote branch handling and deletion of stale remote branches --- test/git/test_remote.py | 46 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index 1d343c74..047ff8f2 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -38,11 +38,19 @@ class TestRemote(TestBase): # specialized fetch testing to de-clutter the main test self._test_fetch_info(rw_repo) + def fetch_and_test(remote): + res = remote.fetch() + self._test_fetch_result(res, remote) + return res + # END fetch and check + + def get_info(res, remote, name): + return res["%s/%s"%(remote,name)] + # put remote head to master as it is garantueed to exist remote_repo.head.reference = remote_repo.heads.master - res = remote.fetch() - self._test_fetch_result(res, remote) + res = fetch_and_test(remote) # all uptodate for info in res: assert info.flags & info.BRANCH_UPTODATE @@ -52,18 +60,40 @@ class TestRemote(TestBase): rhead = remote_repo.head remote_commit = rhead.commit rhead.reset("HEAD~2", index=False) - res = remote.fetch() - self._test_fetch_result(res, remote) - mkey = "%s/master" % remote + res = fetch_and_test(remote) + mkey = "%s/%s"%(remote,'master') master_info = res[mkey] assert master_info.flags & Remote.FetchInfo.FORCED_UPDATE and master_info.note is not None # normal fast forward - set head back to previous one rhead.commit = remote_commit - res = remote.fetch() - self._test_fetch_result(res, remote) + res = fetch_and_test(remote) assert res[mkey].flags & Remote.FetchInfo.FAST_FORWARD + # new remote branch + new_remote_branch = Head.create(remote_repo, "new_branch") + res = fetch_and_test(remote) + new_branch_info = get_info(res, remote, new_remote_branch) + assert new_branch_info.flags & Remote.FetchInfo.NEW_BRANCH + + # remote branch rename ( causes creation of a new one locally ) + new_remote_branch.rename("other_branch_name") + res = fetch_and_test(remote) + other_branch_info = get_info(res, remote, new_remote_branch) + assert other_branch_info.remote_ref.commit == new_branch_info.remote_ref.commit + + # remove new branch + Head.delete(new_remote_branch.repo, new_remote_branch) + res = fetch_and_test(remote) + # deleted remote will not be fetched + self.failUnlessRaises(IndexError, get_info, res, remote, new_remote_branch) + + # prune stale tracking branches + stale_refs = remote.stale_refs + assert len(stale_refs) == 2 and isinstance(stale_refs[0], RemoteReference) + RemoteReference.delete(rw_repo, *stale_refs) + + self.fail("tag handling, tag uptodate, new tag, new branch") def _test_pull(self,remote, rw_repo, remote_repo): @@ -89,7 +119,7 @@ class TestRemote(TestBase): assert refs for ref in refs: assert ref.remote_name == remote.name - assert ref.remote_branch + assert ref.remote_head # END for each ref # OPTIONS -- cgit v1.2.3 From 29c20c147b489d873fb988157a37bcf96f96ab45 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 27 Oct 2009 22:36:41 +0100 Subject: Added special cases to test that shows we cannot yet: handle the FETCH_HEAD case and handle tags System needs to be adjusted to take the FETCH_HEAD info into account to cover the tags case --- test/git/test_remote.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index 047ff8f2..91d63ffd 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -18,7 +18,7 @@ class TestRemote(TestBase): def _test_fetch_result(self, results, remote): - # self._print_fetchhead(remote.repo) + self._print_fetchhead(remote.repo) assert len(results) > 0 and isinstance(results[0], remote.FetchInfo) for info in results: assert info.flags != 0 @@ -38,8 +38,8 @@ class TestRemote(TestBase): # specialized fetch testing to de-clutter the main test self._test_fetch_info(rw_repo) - def fetch_and_test(remote): - res = remote.fetch() + def fetch_and_test(remote, **kwargs): + res = remote.fetch(**kwargs) self._test_fetch_result(res, remote) return res # END fetch and check @@ -93,6 +93,23 @@ class TestRemote(TestBase): assert len(stale_refs) == 2 and isinstance(stale_refs[0], RemoteReference) RemoteReference.delete(rw_repo, *stale_refs) + # test single branch fetch with refspec + res = fetch_and_test(remote, refspec="master:refs/remotes/%s/master"%remote) + assert len(res) == 1 and get_info(res, remote, 'master') + + # without refspec + res = fetch_and_test(remote, refspec='master') + assert len(res) == 1 + + # add new tag reference + rtag = TagReference.create(remote_repo, "1.0-RV_hello.there") + res = fetch_and_test(remote, tags=True) + ltag = res[str(rtag)] + assert isinstance(ltag, TagReference) + + # delete tag + + # adjust tag commit self.fail("tag handling, tag uptodate, new tag, new branch") -- cgit v1.2.3 From 2f8e6f7ab1e6dbd95c268ba0fc827abc62009013 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 27 Oct 2009 23:12:10 +0100 Subject: Implemented handling of FETCH_HEAD and tags, some test cases still missing dealing with deletion and movements of remote tags ( which in fact is discouraged, but we should be able to deal with it, shouldnt we ;) --- test/git/test_remote.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index 91d63ffd..638cb103 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -18,11 +18,13 @@ class TestRemote(TestBase): def _test_fetch_result(self, results, remote): - self._print_fetchhead(remote.repo) + # self._print_fetchhead(remote.repo) assert len(results) > 0 and isinstance(results[0], remote.FetchInfo) for info in results: - assert info.flags != 0 - assert isinstance(info.remote_ref, (SymbolicReference, Reference)) + if isinstance(info.ref, Reference): + assert info.flags != 0 + # END referebce type flags handling + assert isinstance(info.ref, (SymbolicReference, Reference)) if info.flags & info.FORCED_UPDATE: assert isinstance(info.commit_before_forced_update, Commit) else: @@ -31,8 +33,8 @@ class TestRemote(TestBase): # END for each info def _test_fetch_info(self, repo): - self.failUnlessRaises(ValueError, Remote.FetchInfo._from_line, repo, "nonsense") - self.failUnlessRaises(ValueError, Remote.FetchInfo._from_line, repo, "? [up to date] 0.1.7RC -> origin/0.1.7RC") + self.failUnlessRaises(ValueError, Remote.FetchInfo._from_line, repo, "nonsense", '') + self.failUnlessRaises(ValueError, Remote.FetchInfo._from_line, repo, "? [up to date] 0.1.7RC -> origin/0.1.7RC", '') def _test_fetch(self,remote, rw_repo, remote_repo): # specialized fetch testing to de-clutter the main test @@ -80,7 +82,7 @@ class TestRemote(TestBase): new_remote_branch.rename("other_branch_name") res = fetch_and_test(remote) other_branch_info = get_info(res, remote, new_remote_branch) - assert other_branch_info.remote_ref.commit == new_branch_info.remote_ref.commit + assert other_branch_info.ref.commit == new_branch_info.ref.commit # remove new branch Head.delete(new_remote_branch.repo, new_remote_branch) @@ -93,11 +95,11 @@ class TestRemote(TestBase): assert len(stale_refs) == 2 and isinstance(stale_refs[0], RemoteReference) RemoteReference.delete(rw_repo, *stale_refs) - # test single branch fetch with refspec + # test single branch fetch with refspec including target remote res = fetch_and_test(remote, refspec="master:refs/remotes/%s/master"%remote) assert len(res) == 1 and get_info(res, remote, 'master') - # without refspec + # ... with respec and no target res = fetch_and_test(remote, refspec='master') assert len(res) == 1 @@ -105,7 +107,7 @@ class TestRemote(TestBase): rtag = TagReference.create(remote_repo, "1.0-RV_hello.there") res = fetch_and_test(remote, tags=True) ltag = res[str(rtag)] - assert isinstance(ltag, TagReference) + assert isinstance(ltag.ref, TagReference) # delete tag -- cgit v1.2.3 From 87afd252bd11026b6ba3db8525f949cfb62c90fc Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 28 Oct 2009 10:58:24 +0100 Subject: tag handling tests finished, unfortunately there is not yet a rejected case, but it will assuambly follow with the push tests --- test/git/test_remote.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index 638cb103..6870e0e5 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -106,14 +106,22 @@ class TestRemote(TestBase): # add new tag reference rtag = TagReference.create(remote_repo, "1.0-RV_hello.there") res = fetch_and_test(remote, tags=True) - ltag = res[str(rtag)] - assert isinstance(ltag.ref, TagReference) - - # delete tag + tinfo = res[str(rtag)] + assert isinstance(tinfo.ref, TagReference) and tinfo.ref.commit == rtag.commit + assert tinfo.flags & tinfo.NEW_TAG # adjust tag commit + rtag.object = rhead.commit.parents[0].parents[0] + res = fetch_and_test(remote, tags=True) + tinfo = res[str(rtag)] + assert tinfo.commit == rtag.commit + assert tinfo.flags & tinfo.TAG_UPDATE + + # delete remote tag - local one will stay + TagReference.delete(remote_repo, rtag) + res = fetch_and_test(remote, tags=True) + self.failUnlessRaises(IndexError, get_info, res, remote, str(rtag)) - self.fail("tag handling, tag uptodate, new tag, new branch") def _test_pull(self,remote, rw_repo, remote_repo): # pull is essentially a fetch + merge, hence we just do a light -- cgit v1.2.3 From 146a6fe18da94e12aa46ec74582db640e3bbb3a9 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 28 Oct 2009 12:00:58 +0100 Subject: IterableList: added support for prefix allowing remote.refs.master constructs, previously it was remote.refs['%s/master'%remote] Added first simple test for push support, which shows that much more work is needed on that side to allow just-in-time progress information --- test/git/test_remote.py | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index 6870e0e5..37ba71f9 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -23,7 +23,7 @@ class TestRemote(TestBase): for info in results: if isinstance(info.ref, Reference): assert info.flags != 0 - # END referebce type flags handling + # END reference type flags handling assert isinstance(info.ref, (SymbolicReference, Reference)) if info.flags & info.FORCED_UPDATE: assert isinstance(info.commit_before_forced_update, Commit) @@ -122,8 +122,26 @@ class TestRemote(TestBase): res = fetch_and_test(remote, tags=True) self.failUnlessRaises(IndexError, get_info, res, remote, str(rtag)) + def _test_push_and_pull(self,remote, rw_repo, remote_repo): + # push our changes + lhead = rw_repo.head + lindex = rw_repo.index + # assure we are on master and it is checked out where the remote is + lhead.reference = rw_repo.heads.master + lhead.reset(remote.refs.master, working_tree=True) + + # push without spec should fail ( without further configuration ) + # self.failUnlessRaises(GitCommandError, remote.push) + + new_file = self._make_file("new_file", "hello world", rw_repo) + lindex.add([new_file]) + lindex.commit("test commit") + remote.push(lhead.reference) + + self.fail("test --all") + self.fail("test rewind and force -push") + self.fail("test general fail due to invalid refspec") - def _test_pull(self,remote, rw_repo, remote_repo): # pull is essentially a fetch + merge, hence we just do a light # test here, leave the reset to the actual merge testing # fails as we did not specify a branch and there is no configuration for it @@ -184,7 +202,7 @@ class TestRemote(TestBase): self._test_fetch(remote, rw_repo, remote_repo) # PULL TESTING - self._test_pull(remote, rw_repo, remote_repo) + self._test_push_and_pull(remote, rw_repo, remote_repo) remote.update() # END for each remote -- cgit v1.2.3 From dc518251eb64c3ef90502697a7e08abe3f8310b2 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 28 Oct 2009 12:03:18 +0100 Subject: FetchInfo class is not a subclass of Remote class anymore, as more classes are to be added it cluttered up the view and made things more complex as well --- test/git/test_remote.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index 37ba71f9..6f43e163 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -19,7 +19,7 @@ class TestRemote(TestBase): def _test_fetch_result(self, results, remote): # self._print_fetchhead(remote.repo) - assert len(results) > 0 and isinstance(results[0], remote.FetchInfo) + assert len(results) > 0 and isinstance(results[0], FetchInfo) for info in results: if isinstance(info.ref, Reference): assert info.flags != 0 @@ -33,8 +33,8 @@ class TestRemote(TestBase): # END for each info def _test_fetch_info(self, repo): - self.failUnlessRaises(ValueError, Remote.FetchInfo._from_line, repo, "nonsense", '') - self.failUnlessRaises(ValueError, Remote.FetchInfo._from_line, repo, "? [up to date] 0.1.7RC -> origin/0.1.7RC", '') + self.failUnlessRaises(ValueError, FetchInfo._from_line, repo, "nonsense", '') + self.failUnlessRaises(ValueError, FetchInfo._from_line, repo, "? [up to date] 0.1.7RC -> origin/0.1.7RC", '') def _test_fetch(self,remote, rw_repo, remote_repo): # specialized fetch testing to de-clutter the main test @@ -65,18 +65,18 @@ class TestRemote(TestBase): res = fetch_and_test(remote) mkey = "%s/%s"%(remote,'master') master_info = res[mkey] - assert master_info.flags & Remote.FetchInfo.FORCED_UPDATE and master_info.note is not None + assert master_info.flags & FetchInfo.FORCED_UPDATE and master_info.note is not None # normal fast forward - set head back to previous one rhead.commit = remote_commit res = fetch_and_test(remote) - assert res[mkey].flags & Remote.FetchInfo.FAST_FORWARD + assert res[mkey].flags & FetchInfo.FAST_FORWARD # new remote branch new_remote_branch = Head.create(remote_repo, "new_branch") res = fetch_and_test(remote) new_branch_info = get_info(res, remote, new_remote_branch) - assert new_branch_info.flags & Remote.FetchInfo.NEW_BRANCH + assert new_branch_info.flags & FetchInfo.NEW_BRANCH # remote branch rename ( causes creation of a new one locally ) new_remote_branch.rename("other_branch_name") @@ -122,6 +122,8 @@ class TestRemote(TestBase): res = fetch_and_test(remote, tags=True) self.failUnlessRaises(IndexError, get_info, res, remote, str(rtag)) + self.fail("Test fetch with true remote side - plenty of possible output is ommitted right now") + def _test_push_and_pull(self,remote, rw_repo, remote_repo): # push our changes lhead = rw_repo.head -- cgit v1.2.3 From 4712c619ed6a2ce54b781fe404fedc269b77e5dd Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 28 Oct 2009 15:15:14 +0100 Subject: Fixed bug when listing remotes - it was based on references which is incorrect as it cannot always work --- test/git/test_remote.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index 6f43e163..152ef5ab 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -122,8 +122,6 @@ class TestRemote(TestBase): res = fetch_and_test(remote, tags=True) self.failUnlessRaises(IndexError, get_info, res, remote, str(rtag)) - self.fail("Test fetch with true remote side - plenty of possible output is ommitted right now") - def _test_push_and_pull(self,remote, rw_repo, remote_repo): # push our changes lhead = rw_repo.head @@ -151,9 +149,10 @@ class TestRemote(TestBase): remote.pull('master') @with_rw_and_rw_remote_repo('0.1.6') - def test_base(self, rw_repo, remote_repo): + def test_base(self, rw_repo, remote_repo, damon_handle): num_remotes = 0 remote_set = set() + for remote in rw_repo.remotes: num_remotes += 1 assert remote == remote @@ -221,6 +220,7 @@ class TestRemote(TestBase): arg_list = (new_name, "git@server:hello.git") remote = Remote.create(bare_rw_repo, *arg_list ) assert remote.name == "test_new_one" + assert remote in bare_rw_repo.remotes # create same one again self.failUnlessRaises(GitCommandError, Remote.create, bare_rw_repo, *arg_list) -- cgit v1.2.3 From a519942a295cc39af4eebb7ba74b184decae13fb Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 28 Oct 2009 18:09:18 +0100 Subject: Tried to use shallow repository - this works in case it is remote, but unfortunately, deepening the repository fails if the server is used. This is bad, but a workaround is to create another shared repo which pushes a changes that we fetch into our given repo. This should provide more output to properly test the fetch handling. Harder than I thought --- test/git/test_remote.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index 152ef5ab..99f64756 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -6,7 +6,8 @@ from test.testlib import * from git import * - +import tempfile +import shutil import os class TestRemote(TestBase): @@ -122,6 +123,20 @@ class TestRemote(TestBase): res = fetch_and_test(remote, tags=True) self.failUnlessRaises(IndexError, get_info, res, remote, str(rtag)) + # provoke to receive actual objects to see what kind of output we have to + # expect. Previously we did not really receive new objects + # This will only work for true remote repositories, not for local ones ! + if not remote.config_reader.get('url').startswith("git://"): + return + + shallow_repo_dir = tempfile.mktemp("shallow_repo") + shallow_repo = remote_repo.clone(shallow_repo_dir, depth=1, shared=False) + try: + res = shallow_repo.remotes.origin.fetch(depth=10) + finally: + shutil.rmtree(shallow_repo_dir) + # END test and cleanup + def _test_push_and_pull(self,remote, rw_repo, remote_repo): # push our changes lhead = rw_repo.head @@ -149,7 +164,7 @@ class TestRemote(TestBase): remote.pull('master') @with_rw_and_rw_remote_repo('0.1.6') - def test_base(self, rw_repo, remote_repo, damon_handle): + def test_base(self, rw_repo, remote_repo): num_remotes = 0 remote_set = set() -- cgit v1.2.3 From 8b5121414aaf2648b0e809e926d1016249c0222c Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 28 Oct 2009 22:17:39 +0100 Subject: Another attempt to make fetch emit progress information, but in fact its proven now that this is not happening if stderr is being redirected. A test is in place that will most likely fail in case this ever changes --- test/git/test_remote.py | 64 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 13 deletions(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index 99f64756..e4ad5638 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -9,6 +9,10 @@ from git import * import tempfile import shutil import os +import random + +# assure we have repeatable results +random.seed(0) class TestRemote(TestBase): @@ -37,6 +41,15 @@ class TestRemote(TestBase): self.failUnlessRaises(ValueError, FetchInfo._from_line, repo, "nonsense", '') self.failUnlessRaises(ValueError, FetchInfo._from_line, repo, "? [up to date] 0.1.7RC -> origin/0.1.7RC", '') + def _commit_random_file(self, repo): + #Create a file with a random name and random data and commit it to repo. + # Return the commited absolute file path + index = repo.index + new_file = self._make_file(os.path.basename(tempfile.mktemp()),str(random.random()), repo) + index.add([new_file]) + index.commit("Committing %s" % new_file) + return new_file + def _test_fetch(self,remote, rw_repo, remote_repo): # specialized fetch testing to de-clutter the main test self._test_fetch_info(rw_repo) @@ -124,20 +137,39 @@ class TestRemote(TestBase): self.failUnlessRaises(IndexError, get_info, res, remote, str(rtag)) # provoke to receive actual objects to see what kind of output we have to - # expect. Previously we did not really receive new objects - # This will only work for true remote repositories, not for local ones ! - if not remote.config_reader.get('url').startswith("git://"): - return - - shallow_repo_dir = tempfile.mktemp("shallow_repo") - shallow_repo = remote_repo.clone(shallow_repo_dir, depth=1, shared=False) + # expect. For that we need a remote transport protocol + # Create a new UN-shared repo and fetch into it after we pushed a change + # to the shared repo + other_repo_dir = tempfile.mktemp("other_repo") + # must clone with a local path for the repo implementation not to freak out + # as it wants local paths only ( which I can understand ) + other_repo = remote_repo.clone(other_repo_dir, shared=False) + remote_repo_url = "git://localhost%s"%remote_repo.path + + # put origin to git-url + other_origin = other_repo.remotes.origin + other_origin.config_writer.set("url", remote_repo_url) + # it automatically creates alternates as remote_repo is shared as well. + # It will use the transport though and ignore alternates when fetching + # assert not other_repo.alternates # this would fail + + # assure we are in the right state + rw_repo.head.reset(remote.refs.master, working_tree=True) try: - res = shallow_repo.remotes.origin.fetch(depth=10) + self._commit_random_file(rw_repo) + remote.push(rw_repo.head.reference) + + # here I would expect to see remote-information about packing + # objects and so on. Unfortunately, this does not happen + # if we are redirecting the output - git explicitly checks for this + # and only provides progress information to ttys + res = fetch_and_test(other_origin) finally: - shutil.rmtree(shallow_repo_dir) + shutil.rmtree(other_repo_dir) # END test and cleanup def _test_push_and_pull(self,remote, rw_repo, remote_repo): + return # push our changes lhead = rw_repo.head lindex = rw_repo.index @@ -146,11 +178,10 @@ class TestRemote(TestBase): lhead.reset(remote.refs.master, working_tree=True) # push without spec should fail ( without further configuration ) + # well, works # self.failUnlessRaises(GitCommandError, remote.push) - new_file = self._make_file("new_file", "hello world", rw_repo) - lindex.add([new_file]) - lindex.commit("test commit") + self._commit_random_file(rw_repo) remote.push(lhead.reference) self.fail("test --all") @@ -167,6 +198,7 @@ class TestRemote(TestBase): def test_base(self, rw_repo, remote_repo): num_remotes = 0 remote_set = set() + ran_fetch_test = False for remote in rw_repo.remotes: num_remotes += 1 @@ -215,7 +247,12 @@ class TestRemote(TestBase): # END for each rename ( back to prev_name ) # FETCH TESTING - self._test_fetch(remote, rw_repo, remote_repo) + # Only for remotes - local cases are the same or less complicated + # as additional progress information will never be emitted + if remote.name == "daemon_origin": + self._test_fetch(remote, rw_repo, remote_repo) + ran_fetch_test = True + # END fetch test # PULL TESTING self._test_push_and_pull(remote, rw_repo, remote_repo) @@ -223,6 +260,7 @@ class TestRemote(TestBase): remote.update() # END for each remote + assert ran_fetch_test assert num_remotes assert num_remotes == len(remote_set) -- cgit v1.2.3 From 461fd06e1f2d91dfbe47168b53815086212862e4 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 28 Oct 2009 23:35:41 +0100 Subject: Added frame for push testing and push implemenation --- test/git/test_remote.py | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index e4ad5638..d97bd773 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -14,6 +14,25 @@ import random # assure we have repeatable results random.seed(0) +class TestPushProgress(PushProgress): + def __init__(self): + self._seen_ops = 0 + self._stages_per_op = dict() + + def line_dropped(self, line): + print line + + def update(self, op_code, cur_count, max_count=None): + # check each stage only comes once + pass + + def make_assertion(self): + assert self._seen_ops == 3 + # must have seen all stages + for op, stages in self._stages_per_op.items(): + assert stages & self.STAGE_MASK == self.STAGE_MASK + # END for each op/stage + class TestRemote(TestBase): def _print_fetchhead(self, repo): @@ -69,7 +88,7 @@ class TestRemote(TestBase): res = fetch_and_test(remote) # all uptodate for info in res: - assert info.flags & info.BRANCH_UPTODATE + assert info.flags & info.HEAD_UPTODATE # rewind remote head to trigger rejection # index must be false as remote is a bare repo @@ -90,7 +109,7 @@ class TestRemote(TestBase): new_remote_branch = Head.create(remote_repo, "new_branch") res = fetch_and_test(remote) new_branch_info = get_info(res, remote, new_remote_branch) - assert new_branch_info.flags & FetchInfo.NEW_BRANCH + assert new_branch_info.flags & FetchInfo.NEW_HEAD # remote branch rename ( causes creation of a new one locally ) new_remote_branch.rename("other_branch_name") @@ -169,7 +188,6 @@ class TestRemote(TestBase): # END test and cleanup def _test_push_and_pull(self,remote, rw_repo, remote_repo): - return # push our changes lhead = rw_repo.head lindex = rw_repo.index @@ -182,7 +200,10 @@ class TestRemote(TestBase): # self.failUnlessRaises(GitCommandError, remote.push) self._commit_random_file(rw_repo) - remote.push(lhead.reference) + progress = TestPushProgress() + res = remote.push(lhead.reference, progress) + assert isinstance(res, IterableList) + progress.make_assertion() self.fail("test --all") self.fail("test rewind and force -push") @@ -246,6 +267,9 @@ class TestRemote(TestBase): assert remote.rename(prev_name).name == prev_name # END for each rename ( back to prev_name ) + # PUSH/PULL TESTING + self._test_push_and_pull(remote, rw_repo, remote_repo) + # FETCH TESTING # Only for remotes - local cases are the same or less complicated # as additional progress information will never be emitted @@ -254,9 +278,6 @@ class TestRemote(TestBase): ran_fetch_test = True # END fetch test - # PULL TESTING - self._test_push_and_pull(remote, rw_repo, remote_repo) - remote.update() # END for each remote -- cgit v1.2.3 From b2ccae0d7fca3a99fc6a3f85f554d162a3fdc916 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 2 Nov 2009 22:39:54 +0100 Subject: Implemented PushProgress and PushInfo class including basic test cases. Now many more test-cases need to be added to be sure we can truly deal with everything git throws at us --- test/git/test_remote.py | 54 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 6 deletions(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index d97bd773..602c74cf 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -15,19 +15,39 @@ import random random.seed(0) class TestPushProgress(PushProgress): + __slots__ = ( "_seen_lines", "_stages_per_op" ) def __init__(self): - self._seen_ops = 0 + super(TestPushProgress, self).__init__() + self._seen_lines = 0 self._stages_per_op = dict() + def _parse_progress_line(self, line): + super(TestPushProgress, self)._parse_progress_line(line) + assert len(line) > 1, "line %r too short" % line + self._seen_lines += 1 + def line_dropped(self, line): - print line + pass - def update(self, op_code, cur_count, max_count=None): + def update(self, op_code, cur_count, max_count=None, message=''): # check each stage only comes once - pass + op_id = op_code & self.OP_MASK + assert op_id in (self.COUNTING, self.COMPRESSING, self.WRITING) + + self._stages_per_op.setdefault(op_id, 0) + self._stages_per_op[ op_id ] = self._stages_per_op[ op_id ] | (op_code & self.STAGE_MASK) + + if op_code & (self.WRITING|self.END) == (self.WRITING|self.END): + assert message + # END check we get message def make_assertion(self): - assert self._seen_ops == 3 + if not self._seen_lines: + return + + assert len(self._seen_ops) == 3 + assert self._stages_per_op + # must have seen all stages for op, stages in self._stages_per_op.items(): assert stages & self.STAGE_MASK == self.STAGE_MASK @@ -56,6 +76,26 @@ class TestRemote(TestBase): # END forced update checking # END for each info + def _test_push_result(self, results, remote): + assert len(results) > 0 and isinstance(results[0], PushInfo) + for info in results: + assert info.flags + if info.old_commit is not None: + assert isinstance(info.old_commit, Commit) + if info.flags & info.ERROR: + has_one = False + for bitflag in (info.REJECTED, info.REMOTE_REJECTED, info.REMOTE_FAILURE): + has_one |= bool(info.flags & bitflag) + # END for each bitflag + assert has_one + else: + # there must be a remote commit + assert isinstance(info.local_ref, Reference) + assert type(info.remote_ref) in (TagReference, RemoteReference) + # END error checking + # END for each info + + def _test_fetch_info(self, repo): self.failUnlessRaises(ValueError, FetchInfo._from_line, repo, "nonsense", '') self.failUnlessRaises(ValueError, FetchInfo._from_line, repo, "? [up to date] 0.1.7RC -> origin/0.1.7RC", '') @@ -196,15 +236,17 @@ class TestRemote(TestBase): lhead.reset(remote.refs.master, working_tree=True) # push without spec should fail ( without further configuration ) - # well, works + # well, works nicely # self.failUnlessRaises(GitCommandError, remote.push) self._commit_random_file(rw_repo) progress = TestPushProgress() res = remote.push(lhead.reference, progress) assert isinstance(res, IterableList) + self._test_push_result(res, remote) progress.make_assertion() + self.fail("test --all") self.fail("test rewind and force -push") self.fail("test general fail due to invalid refspec") -- cgit v1.2.3 From e70f3218e910d2b3dcb8a5ab40c65b6bd7a8e9a8 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 3 Nov 2009 14:04:32 +0100 Subject: Intermediate commit with a few added and improved tests as well as many fixes --- test/git/test_remote.py | 68 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 7 deletions(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index 602c74cf..306d0da3 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -18,16 +18,21 @@ class TestPushProgress(PushProgress): __slots__ = ( "_seen_lines", "_stages_per_op" ) def __init__(self): super(TestPushProgress, self).__init__() - self._seen_lines = 0 + self._seen_lines = list() self._stages_per_op = dict() def _parse_progress_line(self, line): + # we may remove the line later if it is dropped + # Keep it for debugging + self._seen_lines.append(line) super(TestPushProgress, self)._parse_progress_line(line) assert len(line) > 1, "line %r too short" % line - self._seen_lines += 1 def line_dropped(self, line): - pass + try: + self._seen_lines.remove(line) + except ValueError: + pass def update(self, op_code, cur_count, max_count=None, message=''): # check each stage only comes once @@ -45,7 +50,8 @@ class TestPushProgress(PushProgress): if not self._seen_lines: return - assert len(self._seen_ops) == 3 + # sometimes objects are not compressed which is okay + assert len(self._seen_ops) in (2,3) assert self._stages_per_op # must have seen all stages @@ -90,7 +96,10 @@ class TestRemote(TestBase): assert has_one else: # there must be a remote commit - assert isinstance(info.local_ref, Reference) + if info.flags & info.DELETED == 0: + assert isinstance(info.local_ref, Reference) + else: + assert info.local_ref is None assert type(info.remote_ref) in (TagReference, RemoteReference) # END error checking # END for each info @@ -239,6 +248,7 @@ class TestRemote(TestBase): # well, works nicely # self.failUnlessRaises(GitCommandError, remote.push) + # simple file push self._commit_random_file(rw_repo) progress = TestPushProgress() res = remote.push(lhead.reference, progress) @@ -246,10 +256,54 @@ class TestRemote(TestBase): self._test_push_result(res, remote) progress.make_assertion() + # rejected - undo last commit + lhead.reset("HEAD~1") + res = remote.push(lhead.reference) + assert res[0].flags & PushInfo.ERROR + assert res[0].flags & PushInfo.REJECTED + self._test_push_result(res, remote) + + # force rejected pull + res = remote.push('+%s' % lhead.reference) + assert res[0].flags & PushInfo.ERROR == 0 + assert res[0].flags & PushInfo.FORCED_UPDATE + self._test_push_result(res, remote) + + # invalid refspec + res = remote.push("hellothere") + assert len(res) == 0 + + # push new tags + progress = TestPushProgress() + to_be_updated = "my_tag.1.0RV" + new_tag = TagReference.create(rw_repo, to_be_updated) + other_tag = TagReference.create(rw_repo, "my_obj_tag.2.1aRV", message="my message") + res = remote.push(progress=progress, tags=True) + assert res[-1].flags & PushInfo.NEW_TAG + progress.make_assertion() + self._test_push_result(res, remote) + + # update push new tags + # Rejection is default + new_tag = TagReference.create(rw_repo, to_be_updated, ref='HEAD~1', force=True) + res = remote.push(tags=True) + self._test_push_result(res, remote) + assert res[-1].flags & PushInfo.REJECTED and res[-1].flags & PushInfo.ERROR + + # push force this tag + res = remote.push("+%s" % new_tag.path) + assert res[-1].flags & PushInfo.ERROR == 0 and res[-1].flags & PushInfo.FORCED_UPDATE + + # delete tag - have to do it using refspec + res = remote.push(":%s" % new_tag.path) + self._test_push_result(res, remote) + assert res[0].flags & PushInfo.DELETED self.fail("test --all") - self.fail("test rewind and force -push") - self.fail("test general fail due to invalid refspec") + + # push new branch + + # delete new branch # pull is essentially a fetch + merge, hence we just do a light # test here, leave the reset to the actual merge testing -- cgit v1.2.3 From ec3d91644561ef59ecdde59ddced38660923e916 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 3 Nov 2009 14:28:22 +0100 Subject: Finished all push tests I could think of so far. More error cases should be studied, but they would be hard to 'produce' --- test/git/test_remote.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index 306d0da3..156e7764 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -299,17 +299,34 @@ class TestRemote(TestBase): self._test_push_result(res, remote) assert res[0].flags & PushInfo.DELETED - self.fail("test --all") - # push new branch + new_head = Head.create(rw_repo, "my_new_branch") + progress = TestPushProgress() + res = remote.push(new_head, progress) + assert res[0].flags & PushInfo.NEW_HEAD + progress.make_assertion() + self._test_push_result(res, remote) - # delete new branch + # delete new branch on the remote end and locally + res = remote.push(":%s" % new_head.path) + self._test_push_result(res, remote) + Head.delete(rw_repo, new_head) + assert res[-1].flags & PushInfo.DELETED + + # --all + res = remote.push(all=True) + self._test_push_result(res, remote) # pull is essentially a fetch + merge, hence we just do a light # test here, leave the reset to the actual merge testing # fails as we did not specify a branch and there is no configuration for it self.failUnlessRaises(GitCommandError, remote.pull) remote.pull('master') + + # cleanup - delete created tags and branches as we are in an innerloop on + # the same repository + TagReference.delete(rw_repo, new_tag, other_tag) + remote.push(":%s" % other_tag.path) @with_rw_and_rw_remote_repo('0.1.6') def test_base(self, rw_repo, remote_repo): -- cgit v1.2.3 From 43ab2afba68fd0e1b5d138ed99ffc788dc685e36 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 3 Nov 2009 20:59:24 +0100 Subject: refs: iter_items now imlemented natively for additional performance. We did not implement the crazy sorting feature found in git-for-each-ref though --- test/git/test_remote.py | 1 - 1 file changed, 1 deletion(-) (limited to 'test/git/test_remote.py') diff --git a/test/git/test_remote.py b/test/git/test_remote.py index 156e7764..f049f6f7 100644 --- a/test/git/test_remote.py +++ b/test/git/test_remote.py @@ -63,7 +63,6 @@ class TestRemote(TestBase): def _print_fetchhead(self, repo): fp = open(os.path.join(repo.path, "FETCH_HEAD")) - print fp.read() fp.close() -- cgit v1.2.3