59
53
If null (default), a time/random revision id is generated.
64
from bzrlib.osutils import local_time_offset, username
65
from bzrlib.branch import gen_file_id
66
from bzrlib.errors import BzrError, PointlessCommit
67
from bzrlib.revision import Revision, RevisionReference
68
from bzrlib.trace import mutter, note
69
from bzrlib.xml import pack_xml
56
import os, time, tempfile
58
from inventory import Inventory
59
from osutils import isdir, isfile, sha_string, quotefn, \
60
local_time_offset, username, kind_marker, is_inside_any
62
from branch import gen_file_id
63
from errors import BzrError
64
from revision import Revision
65
from trace import mutter, note
74
70
# First walk over the working inventory; and both update that
82
78
work_tree = branch.working_tree()
83
79
work_inv = work_tree.inventory
84
81
basis = branch.basis_tree()
85
82
basis_inv = basis.inventory
88
86
note('looking for changes...')
90
pending_merges = branch.pending_merges()
92
missing_ids, new_inv, any_changes = \
93
_gather_commit(branch,
100
if not (any_changes or allow_pointless or pending_merges):
101
raise PointlessCommit()
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)
116
if basis_inv.has_id(file_id):
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)
103
162
for file_id in missing_ids:
104
163
# Any files that have been deleted are now removed from the
115
174
if work_inv.has_id(file_id):
116
175
del work_inv[file_id]
118
178
if rev_id is None:
119
rev_id = _gen_revision_id(branch, time.time())
179
rev_id = _gen_revision_id(time.time())
122
182
inv_tmp = tempfile.TemporaryFile()
123
pack_xml(new_inv, inv_tmp)
183
inv.write_xml(inv_tmp)
125
185
branch.inventory_store.add(inv_tmp, inv_id)
126
186
mutter('new inventory_id is {%s}' % inv_id)
128
# We could also just sha hash the inv_tmp file
129
# however, in the case that branch.inventory_store.add()
130
# ever actually does anything special
131
inv_sha1 = branch.get_inventory_sha1(inv_id)
133
188
branch._write_inventory(work_inv)
135
190
if timestamp == None:
136
191
timestamp = time.time()
138
193
if committer == None:
139
committer = username(branch)
194
committer = username()
141
196
if timezone == None:
142
197
timezone = local_time_offset()
188
def _gen_revision_id(branch, when):
233
def _gen_revision_id(when):
189
234
"""Return new revision-id."""
190
235
from binascii import hexlify
191
from bzrlib.osutils import rand_bytes, compact_date, user_email
236
from osutils import rand_bytes, compact_date, user_email
193
s = '%s-%s-' % (user_email(branch), compact_date(when))
238
s = '%s-%s-' % (user_email(), compact_date(when))
194
239
s += hexlify(rand_bytes(8))
198
def _gather_commit(branch, work_tree, work_inv, basis_inv, specific_files,
200
"""Build inventory preparatory to commit.
202
Returns missing_ids, new_inv, any_changes.
204
This adds any changed files into the text store, and sets their
205
test-id, sha and size in the returned inventory appropriately.
208
Modified to hold a list of files that have been deleted from
209
the working directory; these should be removed from the
212
from bzrlib.inventory import Inventory
213
from bzrlib.osutils import isdir, isfile, sha_string, quotefn, \
214
local_time_offset, username, kind_marker, is_inside_any
216
from bzrlib.branch import gen_file_id
217
from bzrlib.errors import BzrError
218
from bzrlib.revision import Revision
219
from bzrlib.trace import mutter, note
222
inv = Inventory(work_inv.root.file_id)
225
for path, entry in work_inv.iter_entries():
226
## TODO: Check that the file kind has not changed from the previous
227
## revision of this file (if any).
229
p = branch.abspath(path)
230
file_id = entry.file_id
231
mutter('commit prep file %s, id %r ' % (p, file_id))
233
if specific_files and not is_inside_any(specific_files, path):
234
mutter(' skipping file excluded from commit')
235
if basis_inv.has_id(file_id):
236
# carry over with previous state
237
inv.add(basis_inv[file_id].copy())
239
# omit this from committed inventory
243
if not work_tree.has_id(file_id):
245
print('deleted %s%s' % (path, kind_marker(entry.kind)))
247
mutter(" file is missing, removing from inventory")
248
missing_ids.append(file_id)
251
# this is present in the new inventory; may be new, modified or
253
old_ie = basis_inv.has_id(file_id) and basis_inv[file_id]
259
old_kind = old_ie.kind
260
if old_kind != entry.kind:
261
raise BzrError("entry %r changed kind from %r to %r"
262
% (file_id, old_kind, entry.kind))
264
if entry.kind == 'directory':
266
raise BzrError("%s is entered as directory but not a directory"
268
elif entry.kind == 'file':
270
raise BzrError("%s is entered as file but is not a file" % quotefn(p))
272
new_sha1 = work_tree.get_file_sha1(file_id)
275
and old_ie.text_sha1 == new_sha1):
276
## assert content == basis.get_file(file_id).read()
277
entry.text_id = old_ie.text_id
278
entry.text_sha1 = new_sha1
279
entry.text_size = old_ie.text_size
280
mutter(' unchanged from previous text_id {%s}' %
283
content = file(p, 'rb').read()
285
# calculate the sha again, just in case the file contents
286
# changed since we updated the cache
287
entry.text_sha1 = sha_string(content)
288
entry.text_size = len(content)
290
entry.text_id = gen_file_id(entry.name)
291
branch.text_store.add(content, entry.text_id)
292
mutter(' stored with text_id {%s}' % entry.text_id)
295
marked = path + kind_marker(entry.kind)
297
print 'added', marked
299
elif old_ie == entry:
301
elif (old_ie.name == entry.name
302
and old_ie.parent_id == entry.parent_id):
303
print 'modified', marked
306
print 'renamed', marked
309
return missing_ids, inv, any_changes