summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/git/test_actor.py8
-rw-r--r--test/git/test_commit.py13
-rw-r--r--test/git/test_index.py243
-rw-r--r--test/git/test_refs.py108
-rw-r--r--test/git/test_repo.py6
5 files changed, 359 insertions, 19 deletions
diff --git a/test/git/test_actor.py b/test/git/test_actor.py
index b7c2af7c..2941468d 100644
--- a/test/git/test_actor.py
+++ b/test/git/test_actor.py
@@ -13,6 +13,14 @@ class TestActor(object):
a = Actor._from_string("Michael Trier <mtrier@example.com>")
assert_equal("Michael Trier", a.name)
assert_equal("mtrier@example.com", a.email)
+
+ # base type capabilities
+ assert a == a
+ assert not ( a != a )
+ m = set()
+ m.add(a)
+ m.add(a)
+ assert len(m) == 1
def test_from_string_should_handle_just_name(self):
a = Actor._from_string("Michael Trier")
diff --git a/test/git/test_commit.py b/test/git/test_commit.py
index 251387bd..af952ed1 100644
--- a/test/git/test_commit.py
+++ b/test/git/test_commit.py
@@ -16,6 +16,9 @@ class TestCommit(TestBase):
assert_equal("Sebastian Thiel", commit.author.name)
assert_equal("byronimo@gmail.com", commit.author.email)
+ assert commit.author == commit.committer
+ assert isinstance(commit.authored_date, int) and isinstance(commit.committed_date, int)
+ assert commit.message == "Added missing information to docstrings of commit and stats module"
def test_stats(self):
@@ -37,6 +40,14 @@ class TestCommit(TestBase):
check_entries(d)
# END for each stated file
+ # assure data is parsed properly
+ michael = Actor._from_string("Michael Trier <mtrier@gmail.com>")
+ assert commit.author == michael
+ assert commit.committer == michael
+ assert commit.authored_date == 1210193388
+ assert commit.committed_date == 1210193388
+ assert commit.message == "initial project"
+
@patch_object(Git, '_call_process')
def test_rev_list_bisect_all(self, git):
"""
@@ -52,7 +63,7 @@ class TestCommit(TestBase):
bisect_all=True)
assert_true(git.called)
- commits = Commit._iter_from_process_or_stream(self.rorepo, ListProcessAdapter(revs))
+ commits = Commit._iter_from_process_or_stream(self.rorepo, ListProcessAdapter(revs), True)
expected_ids = (
'cf37099ea8d1d8c7fbf9b6d12d7ec0249d3acb8b',
'33ebe7acec14b25c5f84f35a664803fcab2f7781',
diff --git a/test/git/test_index.py b/test/git/test_index.py
index 7bc2ad7e..3312abe1 100644
--- a/test/git/test_index.py
+++ b/test/git/test_index.py
@@ -8,13 +8,16 @@ from test.testlib import *
from git import *
import inspect
import os
+import sys
import tempfile
+import glob
+from stat import *
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
@@ -26,21 +29,22 @@ 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 = 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 +59,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 +106,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)
@@ -144,3 +148,208 @@ class TestTree(TestBase):
# against something unusual
self.failUnlessRaises(ValueError, index.diff, int)
+
+ # 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()
+
+ # 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):
+ 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
+
+
+ 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
+ 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():
+ 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"])
+
+ # TEST COMMITTING
+ # commit changed index
+ cur_commit = cur_head.commit
+ commit_message = "commit default head"
+
+ new_commit = index.commit(commit_message, head=False)
+ assert new_commit.message == commit_message
+ assert new_commit.parents[0] == cur_commit
+ 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
+ # 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))
+
+ # 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])
+
diff --git a/test/git/test_refs.py b/test/git/test_refs.py
index 1562310a..979165ef 100644
--- a/test/git/test_refs.py
+++ b/test/git/test_refs.py
@@ -108,3 +108,111 @@ class TestRefs(TestBase):
# type check
self.failUnlessRaises(ValueError, setattr, cur_head, "reference", "that")
+
+ # head handling
+ commit = 'HEAD'
+ prev_head_commit = cur_head.commit
+ for count, new_name in enumerate(("my_new_head", "feature/feature1")):
+ actual_commit = commit+"^"*count
+ new_head = Head.create(rw_repo, new_name, actual_commit)
+ assert cur_head.commit == prev_head_commit
+ assert isinstance(new_head, Head)
+ # already exists
+ self.failUnlessRaises(GitCommandError, Head.create, rw_repo, new_name)
+
+ # force it
+ new_head = Head.create(rw_repo, new_name, actual_commit, force=True)
+ old_path = new_head.path
+ old_name = new_head.name
+
+ assert new_head.rename("hello").name == "hello"
+ assert new_head.rename("hello/world").name == "hello/world"
+ assert new_head.rename(old_name).name == old_name and new_head.path == old_path
+
+ # rename with force
+ tmp_head = Head.create(rw_repo, "tmphead")
+ self.failUnlessRaises(GitCommandError, tmp_head.rename, new_head)
+ tmp_head.rename(new_head, force=True)
+ assert tmp_head == new_head and tmp_head.object == new_head.object
+
+ Head.delete(rw_repo, tmp_head)
+ heads = rw_repo.heads
+ assert tmp_head not in heads and new_head not in heads
+ # force on deletion testing would be missing here, code looks okay though ;)
+ # END for each new head name
+ self.failUnlessRaises(TypeError, RemoteReference.create, rw_repo, "some_name")
+
+ # tag ref
+ tag_name = "1.0.2"
+ light_tag = TagReference.create(rw_repo, tag_name)
+ self.failUnlessRaises(GitCommandError, TagReference.create, rw_repo, tag_name)
+ light_tag = TagReference.create(rw_repo, tag_name, "HEAD~1", force = True)
+ assert isinstance(light_tag, TagReference)
+ assert light_tag.name == tag_name
+ assert light_tag.commit == cur_head.commit.parents[0]
+ assert light_tag.tag is None
+
+ # tag with tag object
+ other_tag_name = "releases/1.0.2RC"
+ msg = "my mighty tag\nsecond line"
+ obj_tag = TagReference.create(rw_repo, other_tag_name, message=msg)
+ assert isinstance(obj_tag, TagReference)
+ assert obj_tag.name == other_tag_name
+ assert obj_tag.commit == cur_head.commit
+ assert obj_tag.tag is not None
+
+ TagReference.delete(rw_repo, light_tag, obj_tag)
+ tags = rw_repo.tags
+ assert light_tag not in tags and obj_tag not in tags
+
+ # remote deletion
+ remote_refs_so_far = 0
+ remotes = rw_repo.remotes
+ assert remotes
+ for remote in remotes:
+ refs = remote.refs
+ RemoteReference.delete(rw_repo, *refs)
+ remote_refs_so_far += len(refs)
+ # END for each ref to delete
+ assert remote_refs_so_far
+
+ for remote in remotes:
+ # remotes without references throw
+ self.failUnlessRaises(AssertionError, getattr, remote, 'refs')
+ # END for each remote
+
+ # change where the active head points to
+ if cur_head.is_detached:
+ cur_head.reference = rw_repo.heads[0]
+
+ head = cur_head.reference
+ old_commit = head.commit
+ head.commit = old_commit.parents[0]
+ assert head.commit == old_commit.parents[0]
+ assert head.commit == cur_head.commit
+ head.commit = old_commit
+
+ # setting a non-commit as commit fails, but succeeds as object
+ head_tree = head.commit.tree
+ self.failUnlessRaises(TypeError, setattr, head, 'commit', head_tree)
+ assert head.commit == old_commit # and the ref did not change
+ head.object = head_tree
+ assert head.object == head_tree
+ self.failUnlessRaises(TypeError, getattr, head, 'commit') # object is a tree, not a commit
+
+ # set the commit directly using the head. This would never detach the head
+ assert not cur_head.is_detached
+ head.object = old_commit
+ cur_head.reference = head.commit
+ assert cur_head.is_detached
+ parent_commit = head.commit.parents[0]
+ assert cur_head.is_detached
+ cur_head.commit = parent_commit
+ assert cur_head.is_detached and cur_head.commit == parent_commit
+
+ cur_head.reference = head
+ assert not cur_head.is_detached
+ cur_head.commit = parent_commit
+ assert not cur_head.is_detached
+ assert head.commit == parent_commit
+
diff --git a/test/git/test_repo.py b/test/git/test_repo.py
index b02610f4..4995d901 100644
--- a/test/git/test_repo.py
+++ b/test/git/test_repo.py
@@ -170,7 +170,11 @@ class TestRepo(TestBase):
def test_head(self):
assert self.rorepo.head.reference.object == self.rorepo.active_branch.object
-
+
+ def test_index(self):
+ index = self.rorepo.index
+ assert isinstance(index, IndexFile)
+
def test_tag(self):
assert self.rorepo.tag('refs/tags/0.1.5').commit