Show More
@@ -1,196 +1,202 b'' | |||||
1 | import time |
|
1 | import time | |
2 | import datetime |
|
2 | import datetime | |
3 | import posixpath |
|
3 | import posixpath | |
4 | from dulwich import objects |
|
4 | from dulwich import objects | |
5 | from dulwich.repo import Repo |
|
5 | from dulwich.repo import Repo | |
6 | from rhodecode.lib.vcs.backends.base import BaseInMemoryChangeset |
|
6 | from rhodecode.lib.vcs.backends.base import BaseInMemoryChangeset | |
7 | from rhodecode.lib.vcs.exceptions import RepositoryError |
|
7 | from rhodecode.lib.vcs.exceptions import RepositoryError | |
8 | from rhodecode.lib.vcs.utils import safe_str |
|
8 | from rhodecode.lib.vcs.utils import safe_str | |
9 |
|
9 | |||
10 |
|
10 | |||
11 | class GitInMemoryChangeset(BaseInMemoryChangeset): |
|
11 | class GitInMemoryChangeset(BaseInMemoryChangeset): | |
12 |
|
12 | |||
13 | def commit(self, message, author, parents=None, branch=None, date=None, |
|
13 | def commit(self, message, author, parents=None, branch=None, date=None, | |
14 | **kwargs): |
|
14 | **kwargs): | |
15 | """ |
|
15 | """ | |
16 | Performs in-memory commit (doesn't check workdir in any way) and |
|
16 | Performs in-memory commit (doesn't check workdir in any way) and | |
17 | returns newly created ``Changeset``. Updates repository's |
|
17 | returns newly created ``Changeset``. Updates repository's | |
18 | ``revisions``. |
|
18 | ``revisions``. | |
19 |
|
19 | |||
20 | :param message: message of the commit |
|
20 | :param message: message of the commit | |
21 | :param author: full username, i.e. "Joe Doe <joe.doe@example.com>" |
|
21 | :param author: full username, i.e. "Joe Doe <joe.doe@example.com>" | |
22 | :param parents: single parent or sequence of parents from which commit |
|
22 | :param parents: single parent or sequence of parents from which commit | |
23 | would be derieved |
|
23 | would be derieved | |
24 | :param date: ``datetime.datetime`` instance. Defaults to |
|
24 | :param date: ``datetime.datetime`` instance. Defaults to | |
25 | ``datetime.datetime.now()``. |
|
25 | ``datetime.datetime.now()``. | |
26 | :param branch: branch name, as string. If none given, default backend's |
|
26 | :param branch: branch name, as string. If none given, default backend's | |
27 | branch would be used. |
|
27 | branch would be used. | |
28 |
|
28 | |||
29 | :raises ``CommitError``: if any error occurs while committing |
|
29 | :raises ``CommitError``: if any error occurs while committing | |
30 | """ |
|
30 | """ | |
31 | self.check_integrity(parents) |
|
31 | self.check_integrity(parents) | |
32 |
|
32 | |||
33 | from .repository import GitRepository |
|
33 | from .repository import GitRepository | |
34 | if branch is None: |
|
34 | if branch is None: | |
35 | branch = GitRepository.DEFAULT_BRANCH_NAME |
|
35 | branch = GitRepository.DEFAULT_BRANCH_NAME | |
36 |
|
36 | |||
37 | repo = self.repository._repo |
|
37 | repo = self.repository._repo | |
38 | object_store = repo.object_store |
|
38 | object_store = repo.object_store | |
39 |
|
39 | |||
40 | ENCODING = "UTF-8" |
|
40 | ENCODING = "UTF-8" | |
41 | DIRMOD = 040000 |
|
41 | DIRMOD = 040000 | |
42 |
|
42 | |||
43 | # Create tree and populates it with blobs |
|
43 | # Create tree and populates it with blobs | |
44 | commit_tree = self.parents[0] and repo[self.parents[0]._commit.tree] or\ |
|
44 | commit_tree = self.parents[0] and repo[self.parents[0]._commit.tree] or\ | |
45 | objects.Tree() |
|
45 | objects.Tree() | |
46 | for node in self.added + self.changed: |
|
46 | for node in self.added + self.changed: | |
47 | # Compute subdirs if needed |
|
47 | # Compute subdirs if needed | |
48 | dirpath, nodename = posixpath.split(node.path) |
|
48 | dirpath, nodename = posixpath.split(node.path) | |
49 | dirnames = dirpath and dirpath.split('/') or [] |
|
49 | dirnames = dirpath and dirpath.split('/') or [] | |
50 | parent = commit_tree |
|
50 | parent = commit_tree | |
51 | ancestors = [('', parent)] |
|
51 | ancestors = [('', parent)] | |
52 |
|
52 | |||
53 | # Tries to dig for the deepest existing tree |
|
53 | # Tries to dig for the deepest existing tree | |
54 | while dirnames: |
|
54 | while dirnames: | |
55 | curdir = dirnames.pop(0) |
|
55 | curdir = dirnames.pop(0) | |
56 | try: |
|
56 | try: | |
57 | dir_id = parent[curdir][1] |
|
57 | dir_id = parent[curdir][1] | |
58 | except KeyError: |
|
58 | except KeyError: | |
59 | # put curdir back into dirnames and stops |
|
59 | # put curdir back into dirnames and stops | |
60 | dirnames.insert(0, curdir) |
|
60 | dirnames.insert(0, curdir) | |
61 | break |
|
61 | break | |
62 | else: |
|
62 | else: | |
63 | # If found, updates parent |
|
63 | # If found, updates parent | |
64 | parent = self.repository._repo[dir_id] |
|
64 | parent = self.repository._repo[dir_id] | |
65 | ancestors.append((curdir, parent)) |
|
65 | ancestors.append((curdir, parent)) | |
66 | # Now parent is deepest exising tree and we need to create subtrees |
|
66 | # Now parent is deepest existing tree and we need to create subtrees | |
67 | # for dirnames (in reverse order) [this only applies for nodes from added] |
|
67 | # for dirnames (in reverse order) [this only applies for nodes from added] | |
68 | new_trees = [] |
|
68 | new_trees = [] | |
69 | blob = objects.Blob.from_string(node.content.encode(ENCODING)) |
|
69 | ||
|
70 | if not node.is_binary: | |||
|
71 | content = node.content.encode(ENCODING) | |||
|
72 | else: | |||
|
73 | content = node.content | |||
|
74 | blob = objects.Blob.from_string(content) | |||
|
75 | ||||
70 | node_path = node.name.encode(ENCODING) |
|
76 | node_path = node.name.encode(ENCODING) | |
71 | if dirnames: |
|
77 | if dirnames: | |
72 | # If there are trees which should be created we need to build |
|
78 | # If there are trees which should be created we need to build | |
73 | # them now (in reverse order) |
|
79 | # them now (in reverse order) | |
74 | reversed_dirnames = list(reversed(dirnames)) |
|
80 | reversed_dirnames = list(reversed(dirnames)) | |
75 | curtree = objects.Tree() |
|
81 | curtree = objects.Tree() | |
76 | curtree[node_path] = node.mode, blob.id |
|
82 | curtree[node_path] = node.mode, blob.id | |
77 | new_trees.append(curtree) |
|
83 | new_trees.append(curtree) | |
78 | for dirname in reversed_dirnames[:-1]: |
|
84 | for dirname in reversed_dirnames[:-1]: | |
79 | newtree = objects.Tree() |
|
85 | newtree = objects.Tree() | |
80 | #newtree.add(DIRMOD, dirname, curtree.id) |
|
86 | #newtree.add(DIRMOD, dirname, curtree.id) | |
81 | newtree[dirname] = DIRMOD, curtree.id |
|
87 | newtree[dirname] = DIRMOD, curtree.id | |
82 | new_trees.append(newtree) |
|
88 | new_trees.append(newtree) | |
83 | curtree = newtree |
|
89 | curtree = newtree | |
84 | parent[reversed_dirnames[-1]] = DIRMOD, curtree.id |
|
90 | parent[reversed_dirnames[-1]] = DIRMOD, curtree.id | |
85 | else: |
|
91 | else: | |
86 | parent.add(name=node_path, mode=node.mode, hexsha=blob.id) |
|
92 | parent.add(name=node_path, mode=node.mode, hexsha=blob.id) | |
87 |
|
93 | |||
88 | new_trees.append(parent) |
|
94 | new_trees.append(parent) | |
89 | # Update ancestors |
|
95 | # Update ancestors | |
90 | for parent, tree, path in reversed([(a[1], b[1], b[0]) for a, b in |
|
96 | for parent, tree, path in reversed([(a[1], b[1], b[0]) for a, b in | |
91 | zip(ancestors, ancestors[1:])]): |
|
97 | zip(ancestors, ancestors[1:])]): | |
92 | parent[path] = DIRMOD, tree.id |
|
98 | parent[path] = DIRMOD, tree.id | |
93 | object_store.add_object(tree) |
|
99 | object_store.add_object(tree) | |
94 |
|
100 | |||
95 | object_store.add_object(blob) |
|
101 | object_store.add_object(blob) | |
96 | for tree in new_trees: |
|
102 | for tree in new_trees: | |
97 | object_store.add_object(tree) |
|
103 | object_store.add_object(tree) | |
98 | for node in self.removed: |
|
104 | for node in self.removed: | |
99 | paths = node.path.split('/') |
|
105 | paths = node.path.split('/') | |
100 | tree = commit_tree |
|
106 | tree = commit_tree | |
101 | trees = [tree] |
|
107 | trees = [tree] | |
102 | # Traverse deep into the forest... |
|
108 | # Traverse deep into the forest... | |
103 | for path in paths: |
|
109 | for path in paths: | |
104 | try: |
|
110 | try: | |
105 | obj = self.repository._repo[tree[path][1]] |
|
111 | obj = self.repository._repo[tree[path][1]] | |
106 | if isinstance(obj, objects.Tree): |
|
112 | if isinstance(obj, objects.Tree): | |
107 | trees.append(obj) |
|
113 | trees.append(obj) | |
108 | tree = obj |
|
114 | tree = obj | |
109 | except KeyError: |
|
115 | except KeyError: | |
110 | break |
|
116 | break | |
111 | # Cut down the blob and all rotten trees on the way back... |
|
117 | # Cut down the blob and all rotten trees on the way back... | |
112 | for path, tree in reversed(zip(paths, trees)): |
|
118 | for path, tree in reversed(zip(paths, trees)): | |
113 | del tree[path] |
|
119 | del tree[path] | |
114 | if tree: |
|
120 | if tree: | |
115 | # This tree still has elements - don't remove it or any |
|
121 | # This tree still has elements - don't remove it or any | |
116 | # of it's parents |
|
122 | # of it's parents | |
117 | break |
|
123 | break | |
118 |
|
124 | |||
119 | object_store.add_object(commit_tree) |
|
125 | object_store.add_object(commit_tree) | |
120 |
|
126 | |||
121 | # Create commit |
|
127 | # Create commit | |
122 | commit = objects.Commit() |
|
128 | commit = objects.Commit() | |
123 | commit.tree = commit_tree.id |
|
129 | commit.tree = commit_tree.id | |
124 | commit.parents = [p._commit.id for p in self.parents if p] |
|
130 | commit.parents = [p._commit.id for p in self.parents if p] | |
125 | commit.author = commit.committer = safe_str(author) |
|
131 | commit.author = commit.committer = safe_str(author) | |
126 | commit.encoding = ENCODING |
|
132 | commit.encoding = ENCODING | |
127 | commit.message = safe_str(message) |
|
133 | commit.message = safe_str(message) | |
128 |
|
134 | |||
129 | # Compute date |
|
135 | # Compute date | |
130 | if date is None: |
|
136 | if date is None: | |
131 | date = time.time() |
|
137 | date = time.time() | |
132 | elif isinstance(date, datetime.datetime): |
|
138 | elif isinstance(date, datetime.datetime): | |
133 | date = time.mktime(date.timetuple()) |
|
139 | date = time.mktime(date.timetuple()) | |
134 |
|
140 | |||
135 | author_time = kwargs.pop('author_time', date) |
|
141 | author_time = kwargs.pop('author_time', date) | |
136 | commit.commit_time = int(date) |
|
142 | commit.commit_time = int(date) | |
137 | commit.author_time = int(author_time) |
|
143 | commit.author_time = int(author_time) | |
138 | tz = time.timezone |
|
144 | tz = time.timezone | |
139 | author_tz = kwargs.pop('author_timezone', tz) |
|
145 | author_tz = kwargs.pop('author_timezone', tz) | |
140 | commit.commit_timezone = tz |
|
146 | commit.commit_timezone = tz | |
141 | commit.author_timezone = author_tz |
|
147 | commit.author_timezone = author_tz | |
142 |
|
148 | |||
143 | object_store.add_object(commit) |
|
149 | object_store.add_object(commit) | |
144 |
|
150 | |||
145 | ref = 'refs/heads/%s' % branch |
|
151 | ref = 'refs/heads/%s' % branch | |
146 | repo.refs[ref] = commit.id |
|
152 | repo.refs[ref] = commit.id | |
147 | repo.refs.set_symbolic_ref('HEAD', ref) |
|
153 | repo.refs.set_symbolic_ref('HEAD', ref) | |
148 |
|
154 | |||
149 | # Update vcs repository object & recreate dulwich repo |
|
155 | # Update vcs repository object & recreate dulwich repo | |
150 | self.repository.revisions.append(commit.id) |
|
156 | self.repository.revisions.append(commit.id) | |
151 | self.repository._repo = Repo(self.repository.path) |
|
157 | self.repository._repo = Repo(self.repository.path) | |
152 | # invalidate parsed refs after commit |
|
158 | # invalidate parsed refs after commit | |
153 | self.repository._parsed_refs = self.repository._get_parsed_refs() |
|
159 | self.repository._parsed_refs = self.repository._get_parsed_refs() | |
154 | tip = self.repository.get_changeset() |
|
160 | tip = self.repository.get_changeset() | |
155 | self.reset() |
|
161 | self.reset() | |
156 | return tip |
|
162 | return tip | |
157 |
|
163 | |||
158 | def _get_missing_trees(self, path, root_tree): |
|
164 | def _get_missing_trees(self, path, root_tree): | |
159 | """ |
|
165 | """ | |
160 | Creates missing ``Tree`` objects for the given path. |
|
166 | Creates missing ``Tree`` objects for the given path. | |
161 |
|
167 | |||
162 | :param path: path given as a string. It may be a path to a file node |
|
168 | :param path: path given as a string. It may be a path to a file node | |
163 | (i.e. ``foo/bar/baz.txt``) or directory path - in that case it must |
|
169 | (i.e. ``foo/bar/baz.txt``) or directory path - in that case it must | |
164 | end with slash (i.e. ``foo/bar/``). |
|
170 | end with slash (i.e. ``foo/bar/``). | |
165 | :param root_tree: ``dulwich.objects.Tree`` object from which we start |
|
171 | :param root_tree: ``dulwich.objects.Tree`` object from which we start | |
166 | traversing (should be commit's root tree) |
|
172 | traversing (should be commit's root tree) | |
167 | """ |
|
173 | """ | |
168 | dirpath = posixpath.split(path)[0] |
|
174 | dirpath = posixpath.split(path)[0] | |
169 | dirs = dirpath.split('/') |
|
175 | dirs = dirpath.split('/') | |
170 | if not dirs or dirs == ['']: |
|
176 | if not dirs or dirs == ['']: | |
171 | return [] |
|
177 | return [] | |
172 |
|
178 | |||
173 | def get_tree_for_dir(tree, dirname): |
|
179 | def get_tree_for_dir(tree, dirname): | |
174 | for name, mode, id in tree.iteritems(): |
|
180 | for name, mode, id in tree.iteritems(): | |
175 | if name == dirname: |
|
181 | if name == dirname: | |
176 | obj = self.repository._repo[id] |
|
182 | obj = self.repository._repo[id] | |
177 | if isinstance(obj, objects.Tree): |
|
183 | if isinstance(obj, objects.Tree): | |
178 | return obj |
|
184 | return obj | |
179 | else: |
|
185 | else: | |
180 | raise RepositoryError("Cannot create directory %s " |
|
186 | raise RepositoryError("Cannot create directory %s " | |
181 | "at tree %s as path is occupied and is not a " |
|
187 | "at tree %s as path is occupied and is not a " | |
182 | "Tree" % (dirname, tree)) |
|
188 | "Tree" % (dirname, tree)) | |
183 | return None |
|
189 | return None | |
184 |
|
190 | |||
185 | trees = [] |
|
191 | trees = [] | |
186 | parent = root_tree |
|
192 | parent = root_tree | |
187 | for dirname in dirs: |
|
193 | for dirname in dirs: | |
188 | tree = get_tree_for_dir(parent, dirname) |
|
194 | tree = get_tree_for_dir(parent, dirname) | |
189 | if tree is None: |
|
195 | if tree is None: | |
190 | tree = objects.Tree() |
|
196 | tree = objects.Tree() | |
191 | dirmode = 040000 |
|
197 | dirmode = 040000 | |
192 | parent.add(dirmode, dirname, tree.id) |
|
198 | parent.add(dirmode, dirname, tree.id) | |
193 | parent = tree |
|
199 | parent = tree | |
194 | # Always append tree |
|
200 | # Always append tree | |
195 | trees.append(tree) |
|
201 | trees.append(tree) | |
196 | return trees |
|
202 | return trees |
@@ -1,340 +1,341 b'' | |||||
1 | """ |
|
1 | """ | |
2 | Tests so called "in memory changesets" commit API of vcs. |
|
2 | Tests so called "in memory changesets" commit API of vcs. | |
3 | """ |
|
3 | """ | |
4 | from __future__ import with_statement |
|
4 | from __future__ import with_statement | |
5 |
|
5 | |||
6 | from rhodecode.lib import vcs |
|
6 | from rhodecode.lib import vcs | |
7 | import time |
|
7 | import time | |
8 | import datetime |
|
8 | import datetime | |
9 | from conf import SCM_TESTS, get_new_dir |
|
9 | from conf import SCM_TESTS, get_new_dir | |
10 | from rhodecode.lib.vcs.exceptions import EmptyRepositoryError |
|
10 | from rhodecode.lib.vcs.exceptions import EmptyRepositoryError | |
11 | from rhodecode.lib.vcs.exceptions import NodeAlreadyAddedError |
|
11 | from rhodecode.lib.vcs.exceptions import NodeAlreadyAddedError | |
12 | from rhodecode.lib.vcs.exceptions import NodeAlreadyExistsError |
|
12 | from rhodecode.lib.vcs.exceptions import NodeAlreadyExistsError | |
13 | from rhodecode.lib.vcs.exceptions import NodeAlreadyRemovedError |
|
13 | from rhodecode.lib.vcs.exceptions import NodeAlreadyRemovedError | |
14 | from rhodecode.lib.vcs.exceptions import NodeAlreadyChangedError |
|
14 | from rhodecode.lib.vcs.exceptions import NodeAlreadyChangedError | |
15 | from rhodecode.lib.vcs.exceptions import NodeDoesNotExistError |
|
15 | from rhodecode.lib.vcs.exceptions import NodeDoesNotExistError | |
16 | from rhodecode.lib.vcs.exceptions import NodeNotChangedError |
|
16 | from rhodecode.lib.vcs.exceptions import NodeNotChangedError | |
17 | from rhodecode.lib.vcs.nodes import DirNode |
|
17 | from rhodecode.lib.vcs.nodes import DirNode | |
18 | from rhodecode.lib.vcs.nodes import FileNode |
|
18 | from rhodecode.lib.vcs.nodes import FileNode | |
19 | from rhodecode.lib.vcs.utils.compat import unittest |
|
19 | from rhodecode.lib.vcs.utils.compat import unittest | |
20 |
|
20 | |||
21 |
|
21 | |||
22 | class InMemoryChangesetTestMixin(object): |
|
22 | class InMemoryChangesetTestMixin(object): | |
23 | """ |
|
23 | """ | |
24 | This is a backend independent test case class which should be created |
|
24 | This is a backend independent test case class which should be created | |
25 | with ``type`` method. |
|
25 | with ``type`` method. | |
26 |
|
26 | |||
27 | It is required to set following attributes at subclass: |
|
27 | It is required to set following attributes at subclass: | |
28 |
|
28 | |||
29 | - ``backend_alias``: alias of used backend (see ``vcs.BACKENDS``) |
|
29 | - ``backend_alias``: alias of used backend (see ``vcs.BACKENDS``) | |
30 | - ``repo_path``: path to the repository which would be created for set of |
|
30 | - ``repo_path``: path to the repository which would be created for set of | |
31 | tests |
|
31 | tests | |
32 | """ |
|
32 | """ | |
33 |
|
33 | |||
34 | def get_backend(self): |
|
34 | def get_backend(self): | |
35 | return vcs.get_backend(self.backend_alias) |
|
35 | return vcs.get_backend(self.backend_alias) | |
36 |
|
36 | |||
37 | def setUp(self): |
|
37 | def setUp(self): | |
38 | Backend = self.get_backend() |
|
38 | Backend = self.get_backend() | |
39 | self.repo_path = get_new_dir(str(time.time())) |
|
39 | self.repo_path = get_new_dir(str(time.time())) | |
40 | self.repo = Backend(self.repo_path, create=True) |
|
40 | self.repo = Backend(self.repo_path, create=True) | |
41 | self.imc = self.repo.in_memory_changeset |
|
41 | self.imc = self.repo.in_memory_changeset | |
42 | self.nodes = [ |
|
42 | self.nodes = [ | |
43 | FileNode('foobar', content='Foo & bar'), |
|
43 | FileNode('foobar', content='Foo & bar'), | |
44 | FileNode('foobar2', content='Foo & bar, doubled!'), |
|
44 | FileNode('foobar2', content='Foo & bar, doubled!'), | |
45 | FileNode('foo bar with spaces', content=''), |
|
45 | FileNode('foo bar with spaces', content=''), | |
46 | FileNode('foo/bar/baz', content='Inside'), |
|
46 | FileNode('foo/bar/baz', content='Inside'), | |
|
47 | FileNode('foo/bar/file.bin', content='\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;\x00\x03\x00\xfe\xff\t\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x18\x00\x00\x00\x01\x00\x00\x00\xfe\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'), | |||
47 | ] |
|
48 | ] | |
48 |
|
49 | |||
49 | def test_add(self): |
|
50 | def test_add(self): | |
50 | rev_count = len(self.repo.revisions) |
|
51 | rev_count = len(self.repo.revisions) | |
51 | to_add = [FileNode(node.path, content=node.content) |
|
52 | to_add = [FileNode(node.path, content=node.content) | |
52 | for node in self.nodes] |
|
53 | for node in self.nodes] | |
53 | for node in to_add: |
|
54 | for node in to_add: | |
54 | self.imc.add(node) |
|
55 | self.imc.add(node) | |
55 | message = u'Added: %s' % ', '.join((node.path for node in self.nodes)) |
|
56 | message = u'Added: %s' % ', '.join((node.path for node in self.nodes)) | |
56 | author = unicode(self.__class__) |
|
57 | author = unicode(self.__class__) | |
57 | changeset = self.imc.commit(message=message, author=author) |
|
58 | changeset = self.imc.commit(message=message, author=author) | |
58 |
|
59 | |||
59 | newtip = self.repo.get_changeset() |
|
60 | newtip = self.repo.get_changeset() | |
60 | self.assertEqual(changeset, newtip) |
|
61 | self.assertEqual(changeset, newtip) | |
61 | self.assertEqual(rev_count + 1, len(self.repo.revisions)) |
|
62 | self.assertEqual(rev_count + 1, len(self.repo.revisions)) | |
62 | self.assertEqual(newtip.message, message) |
|
63 | self.assertEqual(newtip.message, message) | |
63 | self.assertEqual(newtip.author, author) |
|
64 | self.assertEqual(newtip.author, author) | |
64 | self.assertTrue(not any((self.imc.added, self.imc.changed, |
|
65 | self.assertTrue(not any((self.imc.added, self.imc.changed, | |
65 | self.imc.removed))) |
|
66 | self.imc.removed))) | |
66 | for node in to_add: |
|
67 | for node in to_add: | |
67 | self.assertEqual(newtip.get_node(node.path).content, node.content) |
|
68 | self.assertEqual(newtip.get_node(node.path).content, node.content) | |
68 |
|
69 | |||
69 | def test_add_in_bulk(self): |
|
70 | def test_add_in_bulk(self): | |
70 | rev_count = len(self.repo.revisions) |
|
71 | rev_count = len(self.repo.revisions) | |
71 | to_add = [FileNode(node.path, content=node.content) |
|
72 | to_add = [FileNode(node.path, content=node.content) | |
72 | for node in self.nodes] |
|
73 | for node in self.nodes] | |
73 | self.imc.add(*to_add) |
|
74 | self.imc.add(*to_add) | |
74 | message = u'Added: %s' % ', '.join((node.path for node in self.nodes)) |
|
75 | message = u'Added: %s' % ', '.join((node.path for node in self.nodes)) | |
75 | author = unicode(self.__class__) |
|
76 | author = unicode(self.__class__) | |
76 | changeset = self.imc.commit(message=message, author=author) |
|
77 | changeset = self.imc.commit(message=message, author=author) | |
77 |
|
78 | |||
78 | newtip = self.repo.get_changeset() |
|
79 | newtip = self.repo.get_changeset() | |
79 | self.assertEqual(changeset, newtip) |
|
80 | self.assertEqual(changeset, newtip) | |
80 | self.assertEqual(rev_count + 1, len(self.repo.revisions)) |
|
81 | self.assertEqual(rev_count + 1, len(self.repo.revisions)) | |
81 | self.assertEqual(newtip.message, message) |
|
82 | self.assertEqual(newtip.message, message) | |
82 | self.assertEqual(newtip.author, author) |
|
83 | self.assertEqual(newtip.author, author) | |
83 | self.assertTrue(not any((self.imc.added, self.imc.changed, |
|
84 | self.assertTrue(not any((self.imc.added, self.imc.changed, | |
84 | self.imc.removed))) |
|
85 | self.imc.removed))) | |
85 | for node in to_add: |
|
86 | for node in to_add: | |
86 | self.assertEqual(newtip.get_node(node.path).content, node.content) |
|
87 | self.assertEqual(newtip.get_node(node.path).content, node.content) | |
87 |
|
88 | |||
88 | def test_add_actually_adds_all_nodes_at_second_commit_too(self): |
|
89 | def test_add_actually_adds_all_nodes_at_second_commit_too(self): | |
89 | self.imc.add(FileNode('foo/bar/image.png', content='\0')) |
|
90 | self.imc.add(FileNode('foo/bar/image.png', content='\0')) | |
90 | self.imc.add(FileNode('foo/README.txt', content='readme!')) |
|
91 | self.imc.add(FileNode('foo/README.txt', content='readme!')) | |
91 | changeset = self.imc.commit(u'Initial', u'joe.doe@example.com') |
|
92 | changeset = self.imc.commit(u'Initial', u'joe.doe@example.com') | |
92 | self.assertTrue(isinstance(changeset.get_node('foo'), DirNode)) |
|
93 | self.assertTrue(isinstance(changeset.get_node('foo'), DirNode)) | |
93 | self.assertTrue(isinstance(changeset.get_node('foo/bar'), DirNode)) |
|
94 | self.assertTrue(isinstance(changeset.get_node('foo/bar'), DirNode)) | |
94 | self.assertEqual(changeset.get_node('foo/bar/image.png').content, '\0') |
|
95 | self.assertEqual(changeset.get_node('foo/bar/image.png').content, '\0') | |
95 | self.assertEqual(changeset.get_node('foo/README.txt').content, 'readme!') |
|
96 | self.assertEqual(changeset.get_node('foo/README.txt').content, 'readme!') | |
96 |
|
97 | |||
97 | # commit some more files again |
|
98 | # commit some more files again | |
98 | to_add = [ |
|
99 | to_add = [ | |
99 | FileNode('foo/bar/foobaz/bar', content='foo'), |
|
100 | FileNode('foo/bar/foobaz/bar', content='foo'), | |
100 | FileNode('foo/bar/another/bar', content='foo'), |
|
101 | FileNode('foo/bar/another/bar', content='foo'), | |
101 | FileNode('foo/baz.txt', content='foo'), |
|
102 | FileNode('foo/baz.txt', content='foo'), | |
102 | FileNode('foobar/foobaz/file', content='foo'), |
|
103 | FileNode('foobar/foobaz/file', content='foo'), | |
103 | FileNode('foobar/barbaz', content='foo'), |
|
104 | FileNode('foobar/barbaz', content='foo'), | |
104 | ] |
|
105 | ] | |
105 | self.imc.add(*to_add) |
|
106 | self.imc.add(*to_add) | |
106 | changeset = self.imc.commit(u'Another', u'joe.doe@example.com') |
|
107 | changeset = self.imc.commit(u'Another', u'joe.doe@example.com') | |
107 | self.assertEqual(changeset.get_node('foo/bar/foobaz/bar').content, 'foo') |
|
108 | self.assertEqual(changeset.get_node('foo/bar/foobaz/bar').content, 'foo') | |
108 | self.assertEqual(changeset.get_node('foo/bar/another/bar').content, 'foo') |
|
109 | self.assertEqual(changeset.get_node('foo/bar/another/bar').content, 'foo') | |
109 | self.assertEqual(changeset.get_node('foo/baz.txt').content, 'foo') |
|
110 | self.assertEqual(changeset.get_node('foo/baz.txt').content, 'foo') | |
110 | self.assertEqual(changeset.get_node('foobar/foobaz/file').content, 'foo') |
|
111 | self.assertEqual(changeset.get_node('foobar/foobaz/file').content, 'foo') | |
111 | self.assertEqual(changeset.get_node('foobar/barbaz').content, 'foo') |
|
112 | self.assertEqual(changeset.get_node('foobar/barbaz').content, 'foo') | |
112 |
|
113 | |||
113 | def test_add_raise_already_added(self): |
|
114 | def test_add_raise_already_added(self): | |
114 | node = FileNode('foobar', content='baz') |
|
115 | node = FileNode('foobar', content='baz') | |
115 | self.imc.add(node) |
|
116 | self.imc.add(node) | |
116 | self.assertRaises(NodeAlreadyAddedError, self.imc.add, node) |
|
117 | self.assertRaises(NodeAlreadyAddedError, self.imc.add, node) | |
117 |
|
118 | |||
118 | def test_check_integrity_raise_already_exist(self): |
|
119 | def test_check_integrity_raise_already_exist(self): | |
119 | node = FileNode('foobar', content='baz') |
|
120 | node = FileNode('foobar', content='baz') | |
120 | self.imc.add(node) |
|
121 | self.imc.add(node) | |
121 | self.imc.commit(message=u'Added foobar', author=unicode(self)) |
|
122 | self.imc.commit(message=u'Added foobar', author=unicode(self)) | |
122 | self.imc.add(node) |
|
123 | self.imc.add(node) | |
123 | self.assertRaises(NodeAlreadyExistsError, self.imc.commit, |
|
124 | self.assertRaises(NodeAlreadyExistsError, self.imc.commit, | |
124 | message='new message', |
|
125 | message='new message', | |
125 | author=str(self)) |
|
126 | author=str(self)) | |
126 |
|
127 | |||
127 | def test_change(self): |
|
128 | def test_change(self): | |
128 | self.imc.add(FileNode('foo/bar/baz', content='foo')) |
|
129 | self.imc.add(FileNode('foo/bar/baz', content='foo')) | |
129 | self.imc.add(FileNode('foo/fbar', content='foobar')) |
|
130 | self.imc.add(FileNode('foo/fbar', content='foobar')) | |
130 | tip = self.imc.commit(u'Initial', u'joe.doe@example.com') |
|
131 | tip = self.imc.commit(u'Initial', u'joe.doe@example.com') | |
131 |
|
132 | |||
132 | # Change node's content |
|
133 | # Change node's content | |
133 | node = FileNode('foo/bar/baz', content='My **changed** content') |
|
134 | node = FileNode('foo/bar/baz', content='My **changed** content') | |
134 | self.imc.change(node) |
|
135 | self.imc.change(node) | |
135 | self.imc.commit(u'Changed %s' % node.path, u'joe.doe@example.com') |
|
136 | self.imc.commit(u'Changed %s' % node.path, u'joe.doe@example.com') | |
136 |
|
137 | |||
137 | newtip = self.repo.get_changeset() |
|
138 | newtip = self.repo.get_changeset() | |
138 | self.assertNotEqual(tip, newtip) |
|
139 | self.assertNotEqual(tip, newtip) | |
139 | self.assertNotEqual(tip.id, newtip.id) |
|
140 | self.assertNotEqual(tip.id, newtip.id) | |
140 | self.assertEqual(newtip.get_node('foo/bar/baz').content, |
|
141 | self.assertEqual(newtip.get_node('foo/bar/baz').content, | |
141 | 'My **changed** content') |
|
142 | 'My **changed** content') | |
142 |
|
143 | |||
143 | def test_change_raise_empty_repository(self): |
|
144 | def test_change_raise_empty_repository(self): | |
144 | node = FileNode('foobar') |
|
145 | node = FileNode('foobar') | |
145 | self.assertRaises(EmptyRepositoryError, self.imc.change, node) |
|
146 | self.assertRaises(EmptyRepositoryError, self.imc.change, node) | |
146 |
|
147 | |||
147 | def test_check_integrity_change_raise_node_does_not_exist(self): |
|
148 | def test_check_integrity_change_raise_node_does_not_exist(self): | |
148 | node = FileNode('foobar', content='baz') |
|
149 | node = FileNode('foobar', content='baz') | |
149 | self.imc.add(node) |
|
150 | self.imc.add(node) | |
150 | self.imc.commit(message=u'Added foobar', author=unicode(self)) |
|
151 | self.imc.commit(message=u'Added foobar', author=unicode(self)) | |
151 | node = FileNode('not-foobar', content='') |
|
152 | node = FileNode('not-foobar', content='') | |
152 | self.imc.change(node) |
|
153 | self.imc.change(node) | |
153 | self.assertRaises(NodeDoesNotExistError, self.imc.commit, |
|
154 | self.assertRaises(NodeDoesNotExistError, self.imc.commit, | |
154 | message='Changed not existing node', |
|
155 | message='Changed not existing node', | |
155 | author=str(self)) |
|
156 | author=str(self)) | |
156 |
|
157 | |||
157 | def test_change_raise_node_already_changed(self): |
|
158 | def test_change_raise_node_already_changed(self): | |
158 | node = FileNode('foobar', content='baz') |
|
159 | node = FileNode('foobar', content='baz') | |
159 | self.imc.add(node) |
|
160 | self.imc.add(node) | |
160 | self.imc.commit(message=u'Added foobar', author=unicode(self)) |
|
161 | self.imc.commit(message=u'Added foobar', author=unicode(self)) | |
161 | node = FileNode('foobar', content='more baz') |
|
162 | node = FileNode('foobar', content='more baz') | |
162 | self.imc.change(node) |
|
163 | self.imc.change(node) | |
163 | self.assertRaises(NodeAlreadyChangedError, self.imc.change, node) |
|
164 | self.assertRaises(NodeAlreadyChangedError, self.imc.change, node) | |
164 |
|
165 | |||
165 | def test_check_integrity_change_raise_node_not_changed(self): |
|
166 | def test_check_integrity_change_raise_node_not_changed(self): | |
166 | self.test_add() # Performs first commit |
|
167 | self.test_add() # Performs first commit | |
167 |
|
168 | |||
168 | node = FileNode(self.nodes[0].path, content=self.nodes[0].content) |
|
169 | node = FileNode(self.nodes[0].path, content=self.nodes[0].content) | |
169 | self.imc.change(node) |
|
170 | self.imc.change(node) | |
170 | self.assertRaises(NodeNotChangedError, self.imc.commit, |
|
171 | self.assertRaises(NodeNotChangedError, self.imc.commit, | |
171 | message=u'Trying to mark node as changed without touching it', |
|
172 | message=u'Trying to mark node as changed without touching it', | |
172 | author=unicode(self)) |
|
173 | author=unicode(self)) | |
173 |
|
174 | |||
174 | def test_change_raise_node_already_removed(self): |
|
175 | def test_change_raise_node_already_removed(self): | |
175 | node = FileNode('foobar', content='baz') |
|
176 | node = FileNode('foobar', content='baz') | |
176 | self.imc.add(node) |
|
177 | self.imc.add(node) | |
177 | self.imc.commit(message=u'Added foobar', author=unicode(self)) |
|
178 | self.imc.commit(message=u'Added foobar', author=unicode(self)) | |
178 | self.imc.remove(FileNode('foobar')) |
|
179 | self.imc.remove(FileNode('foobar')) | |
179 | self.assertRaises(NodeAlreadyRemovedError, self.imc.change, node) |
|
180 | self.assertRaises(NodeAlreadyRemovedError, self.imc.change, node) | |
180 |
|
181 | |||
181 | def test_remove(self): |
|
182 | def test_remove(self): | |
182 | self.test_add() # Performs first commit |
|
183 | self.test_add() # Performs first commit | |
183 |
|
184 | |||
184 | tip = self.repo.get_changeset() |
|
185 | tip = self.repo.get_changeset() | |
185 | node = self.nodes[0] |
|
186 | node = self.nodes[0] | |
186 | self.assertEqual(node.content, tip.get_node(node.path).content) |
|
187 | self.assertEqual(node.content, tip.get_node(node.path).content) | |
187 | self.imc.remove(node) |
|
188 | self.imc.remove(node) | |
188 | self.imc.commit(message=u'Removed %s' % node.path, author=unicode(self)) |
|
189 | self.imc.commit(message=u'Removed %s' % node.path, author=unicode(self)) | |
189 |
|
190 | |||
190 | newtip = self.repo.get_changeset() |
|
191 | newtip = self.repo.get_changeset() | |
191 | self.assertNotEqual(tip, newtip) |
|
192 | self.assertNotEqual(tip, newtip) | |
192 | self.assertNotEqual(tip.id, newtip.id) |
|
193 | self.assertNotEqual(tip.id, newtip.id) | |
193 | self.assertRaises(NodeDoesNotExistError, newtip.get_node, node.path) |
|
194 | self.assertRaises(NodeDoesNotExistError, newtip.get_node, node.path) | |
194 |
|
195 | |||
195 | def test_remove_last_file_from_directory(self): |
|
196 | def test_remove_last_file_from_directory(self): | |
196 | node = FileNode('omg/qwe/foo/bar', content='foobar') |
|
197 | node = FileNode('omg/qwe/foo/bar', content='foobar') | |
197 | self.imc.add(node) |
|
198 | self.imc.add(node) | |
198 | self.imc.commit(u'added', u'joe doe') |
|
199 | self.imc.commit(u'added', u'joe doe') | |
199 |
|
200 | |||
200 | self.imc.remove(node) |
|
201 | self.imc.remove(node) | |
201 | tip = self.imc.commit(u'removed', u'joe doe') |
|
202 | tip = self.imc.commit(u'removed', u'joe doe') | |
202 | self.assertRaises(NodeDoesNotExistError, tip.get_node, 'omg/qwe/foo/bar') |
|
203 | self.assertRaises(NodeDoesNotExistError, tip.get_node, 'omg/qwe/foo/bar') | |
203 |
|
204 | |||
204 | def test_remove_raise_node_does_not_exist(self): |
|
205 | def test_remove_raise_node_does_not_exist(self): | |
205 | self.imc.remove(self.nodes[0]) |
|
206 | self.imc.remove(self.nodes[0]) | |
206 | self.assertRaises(NodeDoesNotExistError, self.imc.commit, |
|
207 | self.assertRaises(NodeDoesNotExistError, self.imc.commit, | |
207 | message='Trying to remove node at empty repository', |
|
208 | message='Trying to remove node at empty repository', | |
208 | author=str(self)) |
|
209 | author=str(self)) | |
209 |
|
210 | |||
210 | def test_check_integrity_remove_raise_node_does_not_exist(self): |
|
211 | def test_check_integrity_remove_raise_node_does_not_exist(self): | |
211 | self.test_add() # Performs first commit |
|
212 | self.test_add() # Performs first commit | |
212 |
|
213 | |||
213 | node = FileNode('no-such-file') |
|
214 | node = FileNode('no-such-file') | |
214 | self.imc.remove(node) |
|
215 | self.imc.remove(node) | |
215 | self.assertRaises(NodeDoesNotExistError, self.imc.commit, |
|
216 | self.assertRaises(NodeDoesNotExistError, self.imc.commit, | |
216 | message=u'Trying to remove not existing node', |
|
217 | message=u'Trying to remove not existing node', | |
217 | author=unicode(self)) |
|
218 | author=unicode(self)) | |
218 |
|
219 | |||
219 | def test_remove_raise_node_already_removed(self): |
|
220 | def test_remove_raise_node_already_removed(self): | |
220 | self.test_add() # Performs first commit |
|
221 | self.test_add() # Performs first commit | |
221 |
|
222 | |||
222 | node = FileNode(self.nodes[0].path) |
|
223 | node = FileNode(self.nodes[0].path) | |
223 | self.imc.remove(node) |
|
224 | self.imc.remove(node) | |
224 | self.assertRaises(NodeAlreadyRemovedError, self.imc.remove, node) |
|
225 | self.assertRaises(NodeAlreadyRemovedError, self.imc.remove, node) | |
225 |
|
226 | |||
226 | def test_remove_raise_node_already_changed(self): |
|
227 | def test_remove_raise_node_already_changed(self): | |
227 | self.test_add() # Performs first commit |
|
228 | self.test_add() # Performs first commit | |
228 |
|
229 | |||
229 | node = FileNode(self.nodes[0].path, content='Bending time') |
|
230 | node = FileNode(self.nodes[0].path, content='Bending time') | |
230 | self.imc.change(node) |
|
231 | self.imc.change(node) | |
231 | self.assertRaises(NodeAlreadyChangedError, self.imc.remove, node) |
|
232 | self.assertRaises(NodeAlreadyChangedError, self.imc.remove, node) | |
232 |
|
233 | |||
233 | def test_reset(self): |
|
234 | def test_reset(self): | |
234 | self.imc.add(FileNode('foo', content='bar')) |
|
235 | self.imc.add(FileNode('foo', content='bar')) | |
235 | #self.imc.change(FileNode('baz', content='new')) |
|
236 | #self.imc.change(FileNode('baz', content='new')) | |
236 | #self.imc.remove(FileNode('qwe')) |
|
237 | #self.imc.remove(FileNode('qwe')) | |
237 | self.imc.reset() |
|
238 | self.imc.reset() | |
238 | self.assertTrue(not any((self.imc.added, self.imc.changed, |
|
239 | self.assertTrue(not any((self.imc.added, self.imc.changed, | |
239 | self.imc.removed))) |
|
240 | self.imc.removed))) | |
240 |
|
241 | |||
241 | def test_multiple_commits(self): |
|
242 | def test_multiple_commits(self): | |
242 | N = 3 # number of commits to perform |
|
243 | N = 3 # number of commits to perform | |
243 | last = None |
|
244 | last = None | |
244 | for x in xrange(N): |
|
245 | for x in xrange(N): | |
245 | fname = 'file%s' % str(x).rjust(5, '0') |
|
246 | fname = 'file%s' % str(x).rjust(5, '0') | |
246 | content = 'foobar\n' * x |
|
247 | content = 'foobar\n' * x | |
247 | node = FileNode(fname, content=content) |
|
248 | node = FileNode(fname, content=content) | |
248 | self.imc.add(node) |
|
249 | self.imc.add(node) | |
249 | commit = self.imc.commit(u"Commit no. %s" % (x + 1), author=u'vcs') |
|
250 | commit = self.imc.commit(u"Commit no. %s" % (x + 1), author=u'vcs') | |
250 | self.assertTrue(last != commit) |
|
251 | self.assertTrue(last != commit) | |
251 | last = commit |
|
252 | last = commit | |
252 |
|
253 | |||
253 | # Check commit number for same repo |
|
254 | # Check commit number for same repo | |
254 | self.assertEqual(len(self.repo.revisions), N) |
|
255 | self.assertEqual(len(self.repo.revisions), N) | |
255 |
|
256 | |||
256 | # Check commit number for recreated repo |
|
257 | # Check commit number for recreated repo | |
257 | backend = self.get_backend() |
|
258 | backend = self.get_backend() | |
258 | repo = backend(self.repo_path) |
|
259 | repo = backend(self.repo_path) | |
259 | self.assertEqual(len(repo.revisions), N) |
|
260 | self.assertEqual(len(repo.revisions), N) | |
260 |
|
261 | |||
261 | def test_date_attr(self): |
|
262 | def test_date_attr(self): | |
262 | node = FileNode('foobar.txt', content='Foobared!') |
|
263 | node = FileNode('foobar.txt', content='Foobared!') | |
263 | self.imc.add(node) |
|
264 | self.imc.add(node) | |
264 | date = datetime.datetime(1985, 1, 30, 1, 45) |
|
265 | date = datetime.datetime(1985, 1, 30, 1, 45) | |
265 | commit = self.imc.commit(u"Committed at time when I was born ;-)", |
|
266 | commit = self.imc.commit(u"Committed at time when I was born ;-)", | |
266 | author=u'lb', date=date) |
|
267 | author=u'lb', date=date) | |
267 |
|
268 | |||
268 | self.assertEqual(commit.date, date) |
|
269 | self.assertEqual(commit.date, date) | |
269 |
|
270 | |||
270 |
|
271 | |||
271 | class BackendBaseTestCase(unittest.TestCase): |
|
272 | class BackendBaseTestCase(unittest.TestCase): | |
272 | """ |
|
273 | """ | |
273 | Base test class for tests which requires repository. |
|
274 | Base test class for tests which requires repository. | |
274 | """ |
|
275 | """ | |
275 | backend_alias = 'hg' |
|
276 | backend_alias = 'hg' | |
276 | commits = [ |
|
277 | commits = [ | |
277 | { |
|
278 | { | |
278 | 'message': 'Initial commit', |
|
279 | 'message': 'Initial commit', | |
279 | 'author': 'Joe Doe <joe.doe@example.com>', |
|
280 | 'author': 'Joe Doe <joe.doe@example.com>', | |
280 | 'date': datetime.datetime(2010, 1, 1, 20), |
|
281 | 'date': datetime.datetime(2010, 1, 1, 20), | |
281 | 'added': [ |
|
282 | 'added': [ | |
282 | FileNode('foobar', content='Foobar'), |
|
283 | FileNode('foobar', content='Foobar'), | |
283 | FileNode('foobar2', content='Foobar II'), |
|
284 | FileNode('foobar2', content='Foobar II'), | |
284 | FileNode('foo/bar/baz', content='baz here!'), |
|
285 | FileNode('foo/bar/baz', content='baz here!'), | |
285 | ], |
|
286 | ], | |
286 | }, |
|
287 | }, | |
287 | ] |
|
288 | ] | |
288 |
|
289 | |||
289 | def get_backend(self): |
|
290 | def get_backend(self): | |
290 | return vcs.get_backend(self.backend_alias) |
|
291 | return vcs.get_backend(self.backend_alias) | |
291 |
|
292 | |||
292 | def get_commits(self): |
|
293 | def get_commits(self): | |
293 | """ |
|
294 | """ | |
294 | Returns list of commits which builds repository for each tests. |
|
295 | Returns list of commits which builds repository for each tests. | |
295 | """ |
|
296 | """ | |
296 | if hasattr(self, 'commits'): |
|
297 | if hasattr(self, 'commits'): | |
297 | return self.commits |
|
298 | return self.commits | |
298 |
|
299 | |||
299 | def get_new_repo_path(self): |
|
300 | def get_new_repo_path(self): | |
300 | """ |
|
301 | """ | |
301 | Returns newly created repository's directory. |
|
302 | Returns newly created repository's directory. | |
302 | """ |
|
303 | """ | |
303 | backend = self.get_backend() |
|
304 | backend = self.get_backend() | |
304 | key = '%s-%s' % (backend.alias, str(time.time())) |
|
305 | key = '%s-%s' % (backend.alias, str(time.time())) | |
305 | repo_path = get_new_dir(key) |
|
306 | repo_path = get_new_dir(key) | |
306 | return repo_path |
|
307 | return repo_path | |
307 |
|
308 | |||
308 | def setUp(self): |
|
309 | def setUp(self): | |
309 | Backend = self.get_backend() |
|
310 | Backend = self.get_backend() | |
310 | self.backend_class = Backend |
|
311 | self.backend_class = Backend | |
311 | self.repo_path = self.get_new_repo_path() |
|
312 | self.repo_path = self.get_new_repo_path() | |
312 | self.repo = Backend(self.repo_path, create=True) |
|
313 | self.repo = Backend(self.repo_path, create=True) | |
313 | self.imc = self.repo.in_memory_changeset |
|
314 | self.imc = self.repo.in_memory_changeset | |
314 |
|
315 | |||
315 | for commit in self.get_commits(): |
|
316 | for commit in self.get_commits(): | |
316 | for node in commit.get('added', []): |
|
317 | for node in commit.get('added', []): | |
317 | self.imc.add(FileNode(node.path, content=node.content)) |
|
318 | self.imc.add(FileNode(node.path, content=node.content)) | |
318 | for node in commit.get('changed', []): |
|
319 | for node in commit.get('changed', []): | |
319 | self.imc.change(FileNode(node.path, content=node.content)) |
|
320 | self.imc.change(FileNode(node.path, content=node.content)) | |
320 | for node in commit.get('removed', []): |
|
321 | for node in commit.get('removed', []): | |
321 | self.imc.remove(FileNode(node.path)) |
|
322 | self.imc.remove(FileNode(node.path)) | |
322 | self.imc.commit(message=unicode(commit['message']), |
|
323 | self.imc.commit(message=unicode(commit['message']), | |
323 | author=unicode(commit['author']), |
|
324 | author=unicode(commit['author']), | |
324 | date=commit['date']) |
|
325 | date=commit['date']) | |
325 |
|
326 | |||
326 | self.tip = self.repo.get_changeset() |
|
327 | self.tip = self.repo.get_changeset() | |
327 |
|
328 | |||
328 |
|
329 | |||
329 | # For each backend create test case class |
|
330 | # For each backend create test case class | |
330 | for alias in SCM_TESTS: |
|
331 | for alias in SCM_TESTS: | |
331 | attrs = { |
|
332 | attrs = { | |
332 | 'backend_alias': alias, |
|
333 | 'backend_alias': alias, | |
333 | } |
|
334 | } | |
334 | cls_name = ''.join(('%s in memory changeset test' % alias).title().split()) |
|
335 | cls_name = ''.join(('%s in memory changeset test' % alias).title().split()) | |
335 | bases = (InMemoryChangesetTestMixin, unittest.TestCase) |
|
336 | bases = (InMemoryChangesetTestMixin, unittest.TestCase) | |
336 | globals()[cls_name] = type(cls_name, bases, attrs) |
|
337 | globals()[cls_name] = type(cls_name, bases, attrs) | |
337 |
|
338 | |||
338 |
|
339 | |||
339 | if __name__ == '__main__': |
|
340 | if __name__ == '__main__': | |
340 | unittest.main() |
|
341 | unittest.main() |
General Comments 0
You need to be logged in to leave comments.
Login now