53
59
If null (default), a time/random revision id is generated.
56
import os, time, tempfile
58
from inventory import Inventory
59
from osutils import isdir, isfile, sha_string, quotefn, \
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
74
# First walk over the working inventory; and both update that
75
# and also build a new revision inventory. The revision
76
# inventory needs to hold the text-id, sha1 and size of the
77
# actual file versions committed in the revision. (These are
78
# not present in the working inventory.) We also need to
79
# detect missing/deleted files, and remove them from the
82
work_tree = branch.working_tree()
83
work_inv = work_tree.inventory
84
basis = branch.basis_tree()
85
basis_inv = basis.inventory
88
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()
103
for file_id in missing_ids:
104
# Any files that have been deleted are now removed from the
105
# working inventory. Files that were not selected for commit
106
# are left as they were in the working inventory and ommitted
107
# from the revision inventory.
109
# have to do this later so we don't mess up the iterator.
110
# since parents may be removed before their children we
113
# FIXME: There's probably a better way to do this; perhaps
114
# the workingtree should know how to filter itbranch.
115
if work_inv.has_id(file_id):
116
del work_inv[file_id]
119
rev_id = _gen_revision_id(branch, time.time())
122
inv_tmp = tempfile.TemporaryFile()
123
pack_xml(new_inv, inv_tmp)
125
branch.inventory_store.add(inv_tmp, inv_id)
126
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
branch._write_inventory(work_inv)
135
if timestamp == None:
136
timestamp = time.time()
138
if committer == None:
139
committer = username(branch)
142
timezone = local_time_offset()
144
mutter("building commit log message")
145
rev = Revision(timestamp=timestamp,
150
inventory_sha1=inv_sha1,
154
precursor_id = branch.last_patch()
156
precursor_sha1 = branch.get_revision_sha1(precursor_id)
157
rev.parents.append(RevisionReference(precursor_id, precursor_sha1))
158
for merge_rev in pending_merges:
159
rev.parents.append(RevisionReference(merge_rev))
161
rev_tmp = tempfile.TemporaryFile()
162
pack_xml(rev, rev_tmp)
164
branch.revision_store.add(rev_tmp, rev_id)
165
mutter("new revision_id is {%s}" % rev_id)
167
## XXX: Everything up to here can simply be orphaned if we abort
168
## the commit; it will leave junk files behind but that doesn't
171
## TODO: Read back the just-generated changeset, and make sure it
172
## applies and recreates the right state.
174
## TODO: Also calculate and store the inventory SHA1
175
mutter("committing patch r%d" % (branch.revno() + 1))
177
branch.append_revision(rev_id)
179
branch.set_pending_merges([])
182
note("commited r%d" % branch.revno())
188
def _gen_revision_id(branch, when):
189
"""Return new revision-id."""
190
from binascii import hexlify
191
from bzrlib.osutils import rand_bytes, compact_date, user_email
193
s = '%s-%s-' % (user_email(branch), compact_date(when))
194
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, \
60
214
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
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
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)
85
note('looking for changes...')
87
225
for path, entry in work_inv.iter_entries():
88
226
## TODO: Check that the file kind has not changed from the previous
89
227
## revision of this file (if any).
93
229
p = branch.abspath(path)
94
230
file_id = entry.file_id
95
231
mutter('commit prep file %s, id %r ' % (p, file_id))
97
233
if specific_files and not is_inside_any(specific_files, path):
234
mutter(' skipping file excluded from commit')
98
235
if basis_inv.has_id(file_id):
99
236
# carry over with previous state
100
237
inv.add(basis_inv[file_id].copy())
148
290
entry.text_id = gen_file_id(entry.name)
149
291
branch.text_store.add(content, entry.text_id)
150
292
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())
230
def _gen_revision_id(when):
231
"""Return new revision-id."""
232
from binascii import hexlify
233
from osutils import rand_bytes, compact_date, user_email
235
s = '%s-%s-' % (user_email(), compact_date(when))
236
s += hexlify(rand_bytes(8))
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