64
64
from revision import Revision
65
65
from trace import mutter, note
67
branch._need_writelock()
69
# First walk over the working inventory; and both update that
70
# and also build a new revision inventory. The revision
71
# inventory needs to hold the text-id, sha1 and size of the
72
# actual file versions committed in the revision. (These are
73
# not present in the working inventory.) We also need to
74
# detect missing/deleted files, and remove them from the
77
work_tree = branch.working_tree()
78
work_inv = work_tree.inventory
80
basis = branch.basis_tree()
81
basis_inv = basis.inventory
85
note('looking for changes...')
87
for path, entry in work_inv.iter_entries():
88
## TODO: Check that the file kind has not changed from the previous
89
## revision of this file (if any).
93
p = branch.abspath(path)
94
file_id = entry.file_id
95
mutter('commit prep file %s, id %r ' % (p, file_id))
97
if specific_files and not is_inside_any(specific_files, path):
70
# First walk over the working inventory; and both update that
71
# and also build a new revision inventory. The revision
72
# inventory needs to hold the text-id, sha1 and size of the
73
# actual file versions committed in the revision. (These are
74
# not present in the working inventory.) We also need to
75
# detect missing/deleted files, and remove them from the
78
work_tree = branch.working_tree()
79
work_inv = work_tree.inventory
81
basis = branch.basis_tree()
82
basis_inv = basis.inventory
86
note('looking for changes...')
88
for path, entry in work_inv.iter_entries():
89
## TODO: Check that the file kind has not changed from the previous
90
## revision of this file (if any).
94
p = branch.abspath(path)
95
file_id = entry.file_id
96
mutter('commit prep file %s, id %r ' % (p, file_id))
98
if specific_files and not is_inside_any(specific_files, path):
99
if basis_inv.has_id(file_id):
100
# carry over with previous state
101
inv.add(basis_inv[file_id].copy())
103
# omit this from committed inventory
107
if not work_tree.has_id(file_id):
109
print('deleted %s%s' % (path, kind_marker(entry.kind)))
110
mutter(" file is missing, removing from inventory")
111
missing_ids.append(file_id)
98
116
if basis_inv.has_id(file_id):
99
# carry over with previous state
100
inv.add(basis_inv[file_id].copy())
102
# omit this from committed inventory
106
if not work_tree.has_id(file_id):
108
print('deleted %s%s' % (path, kind_marker(entry.kind)))
109
mutter(" file is missing, removing from inventory")
110
missing_ids.append(file_id)
115
if basis_inv.has_id(file_id):
116
old_kind = basis_inv[file_id].kind
117
if old_kind != entry.kind:
118
raise BzrError("entry %r changed kind from %r to %r"
119
% (file_id, old_kind, entry.kind))
121
if entry.kind == 'directory':
123
raise BzrError("%s is entered as directory but not a directory"
125
elif entry.kind == 'file':
127
raise BzrError("%s is entered as file but is not a file" % quotefn(p))
129
new_sha1 = work_tree.get_file_sha1(file_id)
131
old_ie = basis_inv.has_id(file_id) and basis_inv[file_id]
133
and old_ie.text_sha1 == new_sha1):
134
## assert content == basis.get_file(file_id).read()
135
entry.text_id = old_ie.text_id
136
entry.text_sha1 = new_sha1
137
entry.text_size = old_ie.text_size
138
mutter(' unchanged from previous text_id {%s}' %
141
content = file(p, 'rb').read()
143
# calculate the sha again, just in case the file contents
144
# changed since we updated the cache
145
entry.text_sha1 = sha_string(content)
146
entry.text_size = len(content)
148
entry.text_id = gen_file_id(entry.name)
149
branch.text_store.add(content, entry.text_id)
150
mutter(' stored with text_id {%s}' % entry.text_id)
153
print('added %s' % path)
154
elif (old_ie.name == entry.name
155
and old_ie.parent_id == entry.parent_id):
156
print('modified %s' % path)
158
print('renamed %s' % path)
161
for file_id in missing_ids:
162
# Any files that have been deleted are now removed from the
163
# working inventory. Files that were not selected for commit
164
# are left as they were in the working inventory and ommitted
165
# from the revision inventory.
167
# have to do this later so we don't mess up the iterator.
168
# since parents may be removed before their children we
171
# FIXME: There's probably a better way to do this; perhaps
172
# the workingtree should know how to filter itbranch.
173
if work_inv.has_id(file_id):
174
del work_inv[file_id]
178
rev_id = _gen_revision_id(time.time())
181
inv_tmp = tempfile.TemporaryFile()
182
inv.write_xml(inv_tmp)
184
branch.inventory_store.add(inv_tmp, inv_id)
185
mutter('new inventory_id is {%s}' % inv_id)
187
branch._write_inventory(work_inv)
189
if timestamp == None:
190
timestamp = time.time()
192
if committer == None:
193
committer = username()
196
timezone = local_time_offset()
198
mutter("building commit log message")
199
rev = Revision(timestamp=timestamp,
202
precursor = branch.last_patch(),
207
rev_tmp = tempfile.TemporaryFile()
208
rev.write_xml(rev_tmp)
210
branch.revision_store.add(rev_tmp, rev_id)
211
mutter("new revision_id is {%s}" % rev_id)
213
## XXX: Everything up to here can simply be orphaned if we abort
214
## the commit; it will leave junk files behind but that doesn't
217
## TODO: Read back the just-generated changeset, and make sure it
218
## applies and recreates the right state.
220
## TODO: Also calculate and store the inventory SHA1
221
mutter("committing patch r%d" % (branch.revno() + 1))
223
branch.append_revision(rev_id)
226
note("commited r%d" % branch.revno())
117
old_kind = basis_inv[file_id].kind
118
if old_kind != entry.kind:
119
raise BzrError("entry %r changed kind from %r to %r"
120
% (file_id, old_kind, entry.kind))
122
if entry.kind == 'directory':
124
raise BzrError("%s is entered as directory but not a directory"
126
elif entry.kind == 'file':
128
raise BzrError("%s is entered as file but is not a file" % quotefn(p))
130
new_sha1 = work_tree.get_file_sha1(file_id)
132
old_ie = basis_inv.has_id(file_id) and basis_inv[file_id]
134
and old_ie.text_sha1 == new_sha1):
135
## assert content == basis.get_file(file_id).read()
136
entry.text_id = old_ie.text_id
137
entry.text_sha1 = new_sha1
138
entry.text_size = old_ie.text_size
139
mutter(' unchanged from previous text_id {%s}' %
142
content = file(p, 'rb').read()
144
# calculate the sha again, just in case the file contents
145
# changed since we updated the cache
146
entry.text_sha1 = sha_string(content)
147
entry.text_size = len(content)
149
entry.text_id = gen_file_id(entry.name)
150
branch.text_store.add(content, entry.text_id)
151
mutter(' stored with text_id {%s}' % entry.text_id)
154
print('added %s' % path)
155
elif (old_ie.name == entry.name
156
and old_ie.parent_id == entry.parent_id):
157
print('modified %s' % path)
159
print('renamed %s' % path)
162
for file_id in missing_ids:
163
# Any files that have been deleted are now removed from the
164
# working inventory. Files that were not selected for commit
165
# are left as they were in the working inventory and ommitted
166
# from the revision inventory.
168
# have to do this later so we don't mess up the iterator.
169
# since parents may be removed before their children we
172
# FIXME: There's probably a better way to do this; perhaps
173
# the workingtree should know how to filter itbranch.
174
if work_inv.has_id(file_id):
175
del work_inv[file_id]
179
rev_id = _gen_revision_id(time.time())
182
inv_tmp = tempfile.TemporaryFile()
183
inv.write_xml(inv_tmp)
185
branch.inventory_store.add(inv_tmp, inv_id)
186
mutter('new inventory_id is {%s}' % inv_id)
188
branch._write_inventory(work_inv)
190
if timestamp == None:
191
timestamp = time.time()
193
if committer == None:
194
committer = username()
197
timezone = local_time_offset()
199
mutter("building commit log message")
200
rev = Revision(timestamp=timestamp,
203
precursor = branch.last_patch(),
208
rev_tmp = tempfile.TemporaryFile()
209
rev.write_xml(rev_tmp)
211
branch.revision_store.add(rev_tmp, rev_id)
212
mutter("new revision_id is {%s}" % rev_id)
214
## XXX: Everything up to here can simply be orphaned if we abort
215
## the commit; it will leave junk files behind but that doesn't
218
## TODO: Read back the just-generated changeset, and make sure it
219
## applies and recreates the right state.
221
## TODO: Also calculate and store the inventory SHA1
222
mutter("committing patch r%d" % (branch.revno() + 1))
224
branch.append_revision(rev_id)
227
note("commited r%d" % branch.revno())