##// END OF EJS Templates
Fixed deprecation warning on dulwich commit api + fixed commit message add blank at the end
marcink -
r2450:26193dba beta
parent child Browse files
Show More
@@ -1,193 +1,194
1 1 import time
2 2 import datetime
3 3 import posixpath
4 4 from dulwich import objects
5 5 from dulwich.repo import Repo
6 6 from rhodecode.lib.vcs.backends.base import BaseInMemoryChangeset
7 7 from rhodecode.lib.vcs.exceptions import RepositoryError
8 8 from rhodecode.lib.vcs.utils import safe_str
9 9
10 10
11 11 class GitInMemoryChangeset(BaseInMemoryChangeset):
12 12
13 13 def commit(self, message, author, parents=None, branch=None, date=None,
14 14 **kwargs):
15 15 """
16 16 Performs in-memory commit (doesn't check workdir in any way) and
17 17 returns newly created ``Changeset``. Updates repository's
18 18 ``revisions``.
19 19
20 20 :param message: message of the commit
21 21 :param author: full username, i.e. "Joe Doe <joe.doe@example.com>"
22 22 :param parents: single parent or sequence of parents from which commit
23 23 would be derieved
24 24 :param date: ``datetime.datetime`` instance. Defaults to
25 25 ``datetime.datetime.now()``.
26 26 :param branch: branch name, as string. If none given, default backend's
27 27 branch would be used.
28 28
29 29 :raises ``CommitError``: if any error occurs while committing
30 30 """
31 31 self.check_integrity(parents)
32 32
33 33 from .repository import GitRepository
34 34 if branch is None:
35 35 branch = GitRepository.DEFAULT_BRANCH_NAME
36 36
37 37 repo = self.repository._repo
38 38 object_store = repo.object_store
39 39
40 40 ENCODING = "UTF-8"
41 41 DIRMOD = 040000
42 42
43 43 # Create tree and populates it with blobs
44 44 commit_tree = self.parents[0] and repo[self.parents[0]._commit.tree] or\
45 45 objects.Tree()
46 46 for node in self.added + self.changed:
47 47 # Compute subdirs if needed
48 48 dirpath, nodename = posixpath.split(node.path)
49 49 dirnames = dirpath and dirpath.split('/') or []
50 50 parent = commit_tree
51 51 ancestors = [('', parent)]
52 52
53 53 # Tries to dig for the deepest existing tree
54 54 while dirnames:
55 55 curdir = dirnames.pop(0)
56 56 try:
57 57 dir_id = parent[curdir][1]
58 58 except KeyError:
59 59 # put curdir back into dirnames and stops
60 60 dirnames.insert(0, curdir)
61 61 break
62 62 else:
63 63 # If found, updates parent
64 64 parent = self.repository._repo[dir_id]
65 65 ancestors.append((curdir, parent))
66 66 # Now parent is deepest exising tree and we need to create subtrees
67 67 # for dirnames (in reverse order) [this only applies for nodes from added]
68 68 new_trees = []
69 69 blob = objects.Blob.from_string(node.content.encode(ENCODING))
70 70 node_path = node.name.encode(ENCODING)
71 71 if dirnames:
72 72 # If there are trees which should be created we need to build
73 73 # them now (in reverse order)
74 74 reversed_dirnames = list(reversed(dirnames))
75 75 curtree = objects.Tree()
76 76 curtree[node_path] = node.mode, blob.id
77 77 new_trees.append(curtree)
78 78 for dirname in reversed_dirnames[:-1]:
79 79 newtree = objects.Tree()
80 80 #newtree.add(DIRMOD, dirname, curtree.id)
81 81 newtree[dirname] = DIRMOD, curtree.id
82 82 new_trees.append(newtree)
83 83 curtree = newtree
84 84 parent[reversed_dirnames[-1]] = DIRMOD, curtree.id
85 85 else:
86 parent.add(node.mode, node_path, blob.id)
86 parent.add(name=node_path, mode=node.mode, hexsha=blob.id)
87
87 88 new_trees.append(parent)
88 89 # Update ancestors
89 90 for parent, tree, path in reversed([(a[1], b[1], b[0]) for a, b in
90 91 zip(ancestors, ancestors[1:])]):
91 92 parent[path] = DIRMOD, tree.id
92 93 object_store.add_object(tree)
93 94
94 95 object_store.add_object(blob)
95 96 for tree in new_trees:
96 97 object_store.add_object(tree)
97 98 for node in self.removed:
98 99 paths = node.path.split('/')
99 100 tree = commit_tree
100 101 trees = [tree]
101 102 # Traverse deep into the forest...
102 103 for path in paths:
103 104 try:
104 105 obj = self.repository._repo[tree[path][1]]
105 106 if isinstance(obj, objects.Tree):
106 107 trees.append(obj)
107 108 tree = obj
108 109 except KeyError:
109 110 break
110 111 # Cut down the blob and all rotten trees on the way back...
111 112 for path, tree in reversed(zip(paths, trees)):
112 113 del tree[path]
113 114 if tree:
114 115 # This tree still has elements - don't remove it or any
115 116 # of it's parents
116 117 break
117 118
118 119 object_store.add_object(commit_tree)
119 120
120 121 # Create commit
121 122 commit = objects.Commit()
122 123 commit.tree = commit_tree.id
123 124 commit.parents = [p._commit.id for p in self.parents if p]
124 125 commit.author = commit.committer = safe_str(author)
125 126 commit.encoding = ENCODING
126 commit.message = safe_str(message) + ' '
127 commit.message = safe_str(message)
127 128
128 129 # Compute date
129 130 if date is None:
130 131 date = time.time()
131 132 elif isinstance(date, datetime.datetime):
132 133 date = time.mktime(date.timetuple())
133 134
134 135 author_time = kwargs.pop('author_time', date)
135 136 commit.commit_time = int(date)
136 137 commit.author_time = int(author_time)
137 138 tz = time.timezone
138 139 author_tz = kwargs.pop('author_timezone', tz)
139 140 commit.commit_timezone = tz
140 141 commit.author_timezone = author_tz
141 142
142 143 object_store.add_object(commit)
143 144
144 145 ref = 'refs/heads/%s' % branch
145 146 repo.refs[ref] = commit.id
146 147 repo.refs.set_symbolic_ref('HEAD', ref)
147 148
148 149 # Update vcs repository object & recreate dulwich repo
149 150 self.repository.revisions.append(commit.id)
150 151 self.repository._repo = Repo(self.repository.path)
151 152 tip = self.repository.get_changeset()
152 153 self.reset()
153 154 return tip
154 155
155 156 def _get_missing_trees(self, path, root_tree):
156 157 """
157 158 Creates missing ``Tree`` objects for the given path.
158 159
159 160 :param path: path given as a string. It may be a path to a file node
160 161 (i.e. ``foo/bar/baz.txt``) or directory path - in that case it must
161 162 end with slash (i.e. ``foo/bar/``).
162 163 :param root_tree: ``dulwich.objects.Tree`` object from which we start
163 164 traversing (should be commit's root tree)
164 165 """
165 166 dirpath = posixpath.split(path)[0]
166 167 dirs = dirpath.split('/')
167 168 if not dirs or dirs == ['']:
168 169 return []
169 170
170 171 def get_tree_for_dir(tree, dirname):
171 172 for name, mode, id in tree.iteritems():
172 173 if name == dirname:
173 174 obj = self.repository._repo[id]
174 175 if isinstance(obj, objects.Tree):
175 176 return obj
176 177 else:
177 178 raise RepositoryError("Cannot create directory %s "
178 179 "at tree %s as path is occupied and is not a "
179 180 "Tree" % (dirname, tree))
180 181 return None
181 182
182 183 trees = []
183 184 parent = root_tree
184 185 for dirname in dirs:
185 186 tree = get_tree_for_dir(parent, dirname)
186 187 if tree is None:
187 188 tree = objects.Tree()
188 189 dirmode = 040000
189 190 parent.add(dirmode, dirname, tree.id)
190 191 parent = tree
191 192 # Always append tree
192 193 trees.append(tree)
193 194 return trees
General Comments 0
You need to be logged in to leave comments. Login now