~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to doc/developers/commit.txt

  • Committer: Martin Pool
  • Date: 2005-09-21 08:57:13 UTC
  • Revision ID: mbp@sourcefrog.net-20050921085713-541dec922df6225d
- remove dead code from bzrlib.check

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
Commit Performance Notes
2
 
========================
3
 
 
4
 
Changes to commit
5
 
-----------------
6
 
 
7
 
We want to improve the commit code in two phases.
8
 
 
9
 
Phase one is to have a better separation from the format-specific logic,
10
 
the user interface, and the general process of committing.
11
 
 
12
 
Phase two is to have better interfaces by which a good workingtree format
13
 
can efficiently pass data to a good storage format.  If we get phase one
14
 
right, it will be relatively easy and non-disruptive to bring this in.
15
 
 
16
 
 
17
 
 
18
 
Commit: The Minimum Work Required
19
 
---------------------------------
20
 
 
21
 
Here is a description of the minimum work that commit must do.  We
22
 
want to make sure that our design doesn't cost too much more than this
23
 
minimum.  I am trying to do this without making too many assumptions
24
 
about the underlying storage, but am assuming that the ui and basic
25
 
architecture (wt, branch, repo) stays about the same.
26
 
 
27
 
The basic purpose of commit is to:
28
 
 
29
 
1. create and store a new revision based on the contents of the working tree
30
 
2. make this the new basis revision for the working tree
31
 
 
32
 
We can do a selected commit of only some files or subtrees.
33
 
 
34
 
The best performance we could hope for is:
35
 
- stat each versioned selected working file once
36
 
- read from the workingtree and write into the repository any new file texts
37
 
- in general, do work proportional to the size of the shape (eg
38
 
inventory) of the old and new selected trees, and to the total size of
39
 
the modified files
40
 
 
41
 
In more detail:
42
 
 
43
 
1.0 - Store new file texts: if a versioned file contains a new text
44
 
there is no avoiding storing it.  To determine which ones have changed
45
 
we must go over the workingtree and at least stat each file.  If the
46
 
file is modified since it was last hashed, it must be read in.
47
 
Ideally we would read it only once, and either notice that it has not
48
 
changed, or store it at that point.
49
 
 
50
 
On the other hand we want new code to be able to handle files that are
51
 
larger than will fit in memory.  We may then need to read each file up
52
 
to two times: once to determine if there is a new text and calculate
53
 
its hash, and again to store it.
54
 
 
55
 
1.1 - Store a tree-shape description (ie inventory or similar.)  This
56
 
describes the non-file objects, and provides a reference from the
57
 
Revision to the texts within it.
58
 
 
59
 
1.2 - Generate and store a new revision object.
60
 
 
61
 
1.3 - Do delta-compression on the stored objects.  (git notably does
62
 
not do this at commit time, deferring this entirely until later.)
63
 
This requires finding the appropriate basis for each modified file: in
64
 
the current scheme we get the file id, last-revision from the
65
 
dirstate, look into the knit for that text, extract that text in
66
 
total, generate a delta, then store that into the knit.  Most delta
67
 
operations are O(n**2) to O(n**3) in the size of the modified files.
68
 
 
69
 
1.4 - Cache annotation information for the changes: at the moment this
70
 
is done as part of the delta storage.  There are some flaws in that
71
 
approach, such as that it is not updated when ghosts are filled, and
72
 
the annotation can't be re-run with new diff parameters.
73
 
 
74
 
2.1 - Make the new revision the basis for the tree, and clear the list
75
 
of parents.  Strictly this is all that's logically necessary, unless
76
 
the working tree format requires more work.
77
 
 
78
 
The dirstate format does require more work, because it caches the
79
 
parent tree data for each file within the working tree data.  In
80
 
practice this means that every commit rewrites the entire dirstate
81
 
file - we could try to avoid rewriting the whole file but this may be
82
 
difficult because variable-length data (the last-changed revision id)
83
 
is inserted into many rows.
84
 
 
85
 
The current dirstate design then seems to mean that any commit of a
86
 
single file imposes a cost proportional to the size of the current
87
 
workingtree.  Maybe there are other benefits that outweigh this.
88
 
Alternatively if it was fast enough for operations to always look at
89
 
the original storage of the parent trees we could do without the
90
 
cache.
91
 
 
92
 
2.2 - Record the observed file hashes into the workingtree control
93
 
files.  For the files that we just committed, we have the information
94
 
to store a valid hash cache entry: we know their stat information and
95
 
the sha1 of the file contents.  This is not strictly necessary to the
96
 
speed of commit, but it will be useful later in avoiding reading those
97
 
files, and the only cost of doing it now is writing it out.
98
 
 
99
 
In fact there are some user interface niceties that complicate this:
100
 
 
101
 
3 - Before starting the commit proper, we prompt for a commit message
102
 
and in that commit message editor we show a list of the files that
103
 
will be committed: basically the output of bzr status.  This is
104
 
basically the same as the list of changes we detect while storing the
105
 
commit, but because the user will sometimes change the tree after
106
 
opening the commit editor and expect the final state to be committed I
107
 
think we do have to look for changes twice.  Since it takes the user a
108
 
while to enter a message this is not a big problem as long as both the
109
 
status summary and the commit are individually fast.
110
 
 
111
 
4 - As the commit proceeds (or after?) we show another status-like
112
 
summary.  Just printing the names of modified files as they're stored
113
 
would be easy.  Recording deleted and renamed files or directories is
114
 
more work: this can only be done by reference to the primary parent
115
 
tree and requires it be read in.  Worse, reporting renames requires
116
 
searching by id across the entire parent tree.   Possibly full
117
 
reporting should be a default-off verbose option because it does
118
 
require more work beyond the commit itself.
119
 
 
120
 
5 - Bazaar currently allows for missing files to be automatically
121
 
marked as removed at the time of commit.  Leaving aside the ui
122
 
consequences, this means that we have to update the working inventory
123
 
to mark these files as removed.  Since as discussed above we always
124
 
have to rewrite the dirstate on commit this is not substantial, though
125
 
we should make sure we do this in one pass, not two.  I have
126
 
previously proposed to make this behaviour a non-default option.
127
 
 
128
 
We may need to run hooks or generate signatures during commit, but
129
 
they don't seem to have substantial performance consequences.
130
 
 
131
 
If one wanted to optimize solely for the speed of commit I think
132
 
hash-addressed  file-per-text storage like in git (or bzr 0.1) is very
133
 
good.  Remarkably, it does not need to read the inventory for the
134
 
previous revision.  For each versioned file, we just need to get its
135
 
hash, either by reading the file or validating its stat data.  If that
136
 
hash is not already in the repository, the file is just copied in and
137
 
compressed.  As directories are traversed, they're turned into texts
138
 
and stored as well, and then finally the revision is too.  This does
139
 
depend on later doing some delta compression of these texts.
140
 
 
141
 
Variations on this are possible.  Rather than writing a single file
142
 
into the repository for each text, we could fold them into a single
143
 
collation or pack file.  That would create a smaller number of files
144
 
in the repository, but looking up a single text would require looking
145
 
into their indexes rather than just asking the filesystem.
146
 
 
147
 
Rather than using hashes we can use file-id/rev-id pairs as at
148
 
present, which has several consequences pro and con.
149
 
 
150
 
 
151
 
Commit vs Status
152
 
----------------
153
 
 
154
 
At first glance, commit simply stores the changes status reports. In fact,
155
 
this isn't technically correct: commit considers some files modified that
156
 
status does not. The notes below were put together by John Arbash Meinel
157
 
and Aaron Bentley in May 2007 to explain the finer details of commit to
158
 
Ian Clatworthy. They are recorded here as they are likely to be useful to
159
 
others new to Bazaar ...
160
 
 
161
 
1) **Unknown files have a different effect.** With --no-strict (the default)
162
 
   they have no effect and can be completely ignored. With --strict they
163
 
   should cause the commit to abort (so you don't forget to add the two new
164
 
   test files that you just created).
165
 
 
166
 
2) **Multiple parents.** 'status' always compares 2 trees, typically the
167
 
   last-committed tree and the current working tree. 'commit' will compare
168
 
   more trees if there has been a merge.
169
 
 
170
 
  a) The "last modified" property for files.
171
 
     A file may be marked as changed since the last commit, but that
172
 
     change may have come in from the merge, and the change could have
173
 
     happened several commits back. There are several edge cases to be
174
 
     handled here, like if both branches modified the same file, or if
175
 
     just one branch modified it.
176
 
     
177
 
  b) The trickier case is when a file appears unmodified since last
178
 
     commit, but it was modified versus one of the merged branches. I
179
 
     believe there are a few ways this can happen, like if a merged
180
 
     branch changes a file and then reverts it back (you still update
181
 
     the 'last modified' field).
182
 
     In general, if both sides disagree on the 'last-modified' flag,
183
 
     then you need to generate a new entry pointing 'last-modified' at
184
 
     this revision (because you are resolving the differences between
185
 
     the 2 parents).
186
 
 
187
 
3) **Automatic deletion of 'missing' files.** This is a point that we go
188
 
   back and forth on. I think the basic idea is that 'bzr commit' by
189
 
   default should abort if it finds a 'missing' file (in case that file was
190
 
   renamed rather than deleted), but 'bzr commit --auto' can add unknown
191
 
   files and remove missing files automatically.
192
 
 
193
 
4) **sha1 for newly added files.** status doesn't really need this: it should
194
 
   only care that the file is not present in base, but is present now. In
195
 
   some ways commit doesn't care either, since it needs to read and sha the
196
 
   file itself anyway.
197
 
 
198
 
5) **Nested trees.** status doesn't recurse into nested trees, but commit does.
199
 
   This is just because not all of the nested-trees work has been merged yet.
200
 
 
201
 
   A tree-reference is considered modified if the subtree has been
202
 
   committed since the last containing-tree commit.  But commit needs to
203
 
   recurse into every subtree, to ensure that a commit is done if the
204
 
   subtree has changed since its last commit.  _iter_changes only reports
205
 
   on tree-references that are modified, so it can't be used for doing
206
 
   subtree commits.
207
 
 
208
 
 
209
 
Avoiding Work: Smarter Change Detection
210
 
---------------------------------------
211
 
 
212
 
Commit currently walks through every file building an inventory. Here is
213
 
Aaron's brain dump on a better way ...
214
 
 
215
 
_iter_changes won't tell us about tree references that haven't changed,
216
 
even if those subtrees have changed.  (Unless we ask for unchanged
217
 
files, which we don't want to do, of course.)
218
 
 
219
 
There is an iter_references method, but using it looks just as expensive
220
 
as calling kind().
221
 
 
222
 
I did some work on updating commit to use iter_changes, but found for
223
 
multi-parent trees, I had to fall back to the slow inventory comparison
224
 
approach.
225
 
 
226
 
Really, I think we need a call akin to iter_changes that handles
227
 
multiple parents, and knows to emit entries when InventoryEntry.revision
228
 
is all that's changed.
229
 
 
230
 
 
231
 
Avoiding Work: Better Layering
232
 
------------------------------
233
 
 
234
 
For each file, commit is currently doing more work than it should. Here is
235
 
John's take on a better way ...
236
 
 
237
 
Note that "_iter_changes" *does* have to touch every path on disk, but
238
 
it just can do it in a more efficient manner. (It doesn't have to create
239
 
an InventoryEntry for all the ones that haven't changed).
240
 
 
241
 
I agree with Aaron that we need something a little different than
242
 
_iter_changes. Both because of handling multiple parents, as well as we
243
 
don't want it to actually read the files if we have a stat-cache miss.
244
 
 
245
 
Specifically, the commit code *has* to read the files because it is
246
 
going to add the text to the repository, and we want it to compute the
247
 
sha1 at *that* time, so we are guaranteed to have the valid sha (rather
248
 
than just whatever the last cached one was). So we want the code to
249
 
return 'None' if it doesn't have an up-to-date sha1, rather than reading
250
 
the file and computing it, just before it returns it to the parent.
251
 
 
252
 
The commit code (0.16) should really be restructured. It's layering is
253
 
pretty wrong.
254
 
 
255
 
Specifically, calling "kind()" requires a stat of the file. But we have
256
 
to do a stat to get the size/whether the record is up-to-date, etc. So
257
 
we really need to have a "create_an_up_to_date_inventory()" function.
258
 
But because we are accessing every object on disk, we want to be working
259
 
in tuples rather than Inventory objects. And because DirState already
260
 
has the parent records next to the current working inventory, it can do
261
 
all the work to do really fast comparison and throw-away of unimportant
262
 
records.
263
 
 
264
 
The way I made "bzr status" fast is by moving the 'ignore this record'
265
 
ability as deep into the stack as I could get. Status has the property
266
 
that you don't care about most of the records, just like commit. So the
267
 
sooner you can stop evaluating the 99% that you don't care about, the
268
 
less work you do.
269
 
 
270
 
 
271
 
Avoiding work: avoiding reading parent data
272
 
-------------------------------------------
273
 
 
274
 
We would like to avoid the work of reading any data about the parent
275
 
revisions.  We should at least try to avoid reading anything from the
276
 
repository; we can also consider whether it is possible or useful to hold
277
 
less parent information in the working tree.
278
 
 
279
 
When a commit of selected files is requested, the committed snapshot is a
280
 
composite of some directories from the parent revision and some from the
281
 
working tree.  In this case it is logically necessary to have the parent
282
 
inventory information.
283
 
 
284
 
If file last-change information or per-file graph information is stored
285
 
then it must be available from the parent trees.
286
 
 
287
 
If the Branch's storage method does delta compression at commit time it
288
 
may need to retrieve file or inventory texts from the repository.
289
 
 
290
 
It is desirable to avoid roundtrips to the Repository during commit,
291
 
particularly because it may be remote.  If the WorkingTree can determine
292
 
by itself that a text was in the parent and therefore should be in the
293
 
Repository that avoids one roundtrip per file.  
294
 
 
295
 
There is a possibility here that the parent revision is not stored, or not
296
 
correctly stored, in the repository the tree is being committed into, and
297
 
so the committed tree would not be reconstructable.  We could check that
298
 
the parent revision is present in the inventory and rely on the invariant
299
 
that if a revision is present, everything to reconstruct it will be
300
 
present too.
301
 
 
302
 
 
303
 
Code structure
304
 
--------------
305
 
 
306
 
Caller starts a commit
307
 
 
308
 
>>> Branch.commit(from_tree, options)
309
 
 
310
 
This creates a CommitBuilder object matched to the Branch, Repository and
311
 
Tree.  It can vary depending on model differences or by knowledge of what
312
 
is efficient with the Repository and Tree.  Model differences might
313
 
include whether no-text-change merges need to be reported, and whether the 
314
 
 
315
 
The basic CommitBuilder.commit structure can be 
316
 
 
317
 
1. Ask the branch if it is ready to commit (up to date with master if
318
 
   any.)
319
 
 
320
 
2. Ask the tree if it is ready to commit to the branch (up to date with
321
 
   branch?), no conflicts, etc
322
 
 
323
 
3. Commit changed files; prototype implementation:
324
 
 
325
 
   a. Ask the working tree for all committable files; for each it should
326
 
      return the per-file parents, stat information, kind, etc.
327
 
 
328
 
   b. Ask the repository to store the new file text; the repository should
329
 
      return the stored sha1 and new revision id.
330
 
 
331
 
4. Commit changed inventory
332
 
 
333
 
5. Commit revision object
334
 
 
335
 
 
336
 
 
337
 
 
338
 
 
339
 
 
340
 
 
341
 
 
342
 
 
343
 
Complications of commit
344
 
-----------------------
345
 
 
346
 
Bazaar (as of 0.17) does not support selective-file commit of a merge;
347
 
this could be done if we decide how it should be recorded - is this to be
348
 
stored as an overall merge revision; as a preliminary non-merge revisions;
349
 
or will the per-file graph diverge from the revision graph.
350
 
 
351
 
There are several checks that may cause the commit to be refused, which
352
 
may be activated or deactivated by options.
353
 
 
354
 
* presence of conflicts in the tree
355
 
 
356
 
* presence of unknown files
357
 
 
358
 
* the working tree basis is up to date with the branch tip
359
 
 
360
 
* the local branch is up to date with the master branch, if there 
361
 
  is one and --local is not specified
362
 
 
363
 
* an empty commit message is given, 
364
 
 
365
 
* a hook flags an error
366
 
 
367
 
* a "pointless" commit, with no inventory changes
368
 
 
369
 
Most of these require walking the tree and can be easily done while
370
 
recording the tree shape.  This does require that it be possible to abort
371
 
the commit after the tree changes have been recorded.  It could be ok to
372
 
either leave the unreachable partly-committed records in the repository,
373
 
or to roll back.
374
 
 
375
 
Other complications:
376
 
 
377
 
* when automatically adding new files or deleting missing files during
378
 
  commit, they must be noted during commit and written into the working
379
 
  tree at some point
380
 
 
381
 
* refuse "pointless" commits with no file changes - should be easy by
382
 
  just refusing to do the final step of storing a new overall inventory
383
 
  and revision object
384
 
 
385
 
* heuristic detection of renames between add and delete (out of scope for
386
 
  this change)
387
 
 
388
 
* pushing changes to a master branch if any
389
 
 
390
 
* running hooks, pre and post commit
391
 
 
392
 
* prompting for a commit message if necessary, including a list of the
393
 
  changes that have already been observed
394
 
 
395
 
* if there are tree references and recursing into them is enabled, then
396
 
  do so
397
 
 
398
 
Commit needs to protect against duplicated file ids 
399
 
 
400
 
 
401
 
Updates that need to be made in the working tree, either on conclusion
402
 
of commit or during the scan, include
403
 
 
404
 
* Changes made to the tree shape, including automatic adds, renames or
405
 
  deletes
406
 
 
407
 
* For trees (eg dirstate) that cache parent inventories, the old parent
408
 
  information must be removed and the new one inserted
409
 
 
410
 
* The tree hashcache information should be updated to reflect the stat
411
 
  value at which the file was the same as the committed version, and the
412
 
  content hash it was observed to have.  This needs to be done carefully to
413
 
  prevent inconsistencies if the file is modified during or shortly after
414
 
  the commit.  Perhaps it would work to read the mtime of the file before we
415
 
  read its text to commit.
416
 
 
417
 
 
418
 
Interface stack
419
 
---------------
420
 
 
421
 
The commit api is invoked by the command interface, and copies information
422
 
from the tree into the branch and its repository, possibly updating the
423
 
WorkingTree afterwards.
424
 
 
425
 
The command interface passes:
426
 
 
427
 
* a commit message (from an option, if any),
428
 
* or an indication that it should be read interactively from the ui object;
429
 
* a list of files to commit
430
 
* an option for a dry-run commit
431
 
* verbose option, or callback to indicate 
432
 
* timestamp, timezone, committer, chosen revision id
433
 
* config (for what?)
434
 
* option for local-only commit on a bound branch
435
 
* option for strict commits (fail if there are unknown or missing files)
436
 
* option to allow "pointless" commits (with no tree changes)
437
 
 
438
 
(This is rather a lot of options to pass individually and just for code tidyness maybe some of them should be combine into objects.)
439
 
 
440
 
>>> Branch.commit(from_tree, message, files_to_commit, ...)
441
 
 
442
 
There will be different implementations of this for different Branch
443
 
classes, whether for foreign branches or Bazaar repositories using
444
 
different storage methods.
445
 
 
446
 
Most of the commit should occur during a single lockstep iteration across
447
 
the workingtree and parent trees.  The WorkingTree interface needs to
448
 
provide methods that give commit all it needs.  Some of these methods
449
 
(such as answering the file's last change revision) may be deprecated in
450
 
newer working trees and there we have a choice of either calculating the
451
 
value from the data that is present, or refusing to support commit to
452
 
newer repositories.
453
 
 
454
 
For a dirstate tree the iteration of changes from the parent can easily be
455
 
done within its own iter_changes.
456
 
 
457
 
Dirstate inventories may be most easily updated in a single operation at
458
 
the end; however it may be best to accumulate data as we proceed through
459
 
the tree rather than revisiting it at the end.
460
 
 
461
 
Showing a progress bar for commit may not be necessary if we report files
462
 
as they are committed.  Alternatively we could transiently show a progress
463
 
bar for each directory that's scanned, even if no changes are observed.
464
 
 
465
 
This needs to collect a list of added/changed/removed files, each of which
466
 
must have its text stored (if any) and containing directory updated.  This
467
 
can be done by calling Tree._iter_changes on the source tree, asking for
468
 
changes 
469
 
 
470
 
In the 0.17 model the commit operation needs to know the per-file parents
471
 
and per-file last-changed revision.  
472
 
 
473
 
(In this and other operations we must avoid having multiple layers walk
474
 
over the tree separately.  For example, it is no good to have the Command
475
 
layer walk the tree to generate a list of all file ids to commit, because
476
 
the tree will also be walked later.  The layers that do need to operate
477
 
per-file should probably be bound together in a per-dirblock iterator,
478
 
rather than each iterating independently.)
479
 
 
480
 
Branch->Tree interface
481
 
----------------------
482
 
 
483
 
The Branch commit code needs to ask the Tree what should be committed, in
484
 
terms of changes from the parent revisions.  If the Tree holds all the
485
 
necessary parent tree information itself it can do it single handed;
486
 
otherwise it may need to ask the Repository for parent information.
487
 
 
488
 
This should be a streaming interface, probably like iter_changes returning
489
 
information per directory block.
490
 
 
491
 
The interface should not return a block for directories that are
492
 
recursively unchanged.
493
 
 
494
 
The tree's idea of what is possibly changed may be more conservative than
495
 
that of the branch.  For example the tree may report on merges of files
496
 
where the text is identical to the parents: this must be recorded for
497
 
Bazaar branches that record per-file ancestry but is not necessary for all
498
 
branches.  If the tree is responsible for determining when directories
499
 
have been recursively modified then it will report on all the parents of
500
 
such files.  There are several implementation options:
501
 
 
502
 
1. Return all files and directories the branch might want to commit, even
503
 
if the branch ends up taking no action on them.
504
 
 
505
 
2. When starting the iteration, the branch can specify what type of change
506
 
is considered interesting.
507
 
 
508
 
Since these types of changes are probably (??) rare compared to files that
509
 
are either completely unmodified or substantially modified, the first may
510
 
be the best and simplest option.
511
 
 
512
 
The branch needs to build an inventory to commit, which must include
513
 
unchanged files within changed directories.  This should be returned from
514
 
the working tree too.  Repositories that store per-directory inventories
515
 
will want to build and store these from the lowest directories up.
516
 
For 0.17 format repositories with an all-in-one inventory it may be
517
 
easiest to accumulate inventory entries in arbitrary order into an
518
 
in-memory Inventory and then serialize it.
519
 
 
520
 
It ought to be possible to commit any Tree into a Branch, without
521
 
requiring a WorkingTree; the commit code should cope if the tree is not
522
 
interested in updating hashcache information or does not have a
523
 
``last_revision``.
524
 
 
525
 
 
526
 
Information from the tree to repository
527
 
---------------------------------------
528
 
 
529
 
The main things the tree needs to tell the Branch about are:
530
 
 
531
 
* A file is modified from its parent revision (in text, permissions,
532
 
  other), and so its text may need to be stored.  
533
 
  
534
 
  Files should also be reported if they have more than one unique parent
535
 
  revision, for repositories that store per-file graphs or last-change
536
 
  revisions.  Perhaps this behaviour should be optional.
537
 
 
538
 
  **XXX:** are renames/deletions reported here too?
539
 
 
540
 
* The complete contents of a modified directory, so that its inventory
541
 
  text may be stored.  This should be done after all the contained files
542
 
  and directories have been reported.  If there are unmodified files, 
543
 
  or unselected files carried through from 
544
 
 
545
 
  XXX: Actually perhaps not grouped by directory, but rather grouped 
546
 
  appropriately for the shape of inventory storage in the repository. 
547
 
 
548
 
  In a zoomed-in checkout the workingtree may not have all the shape data
549
 
  for the entire tree.
550
 
 
551
 
* A file is missing -- could cause either automatic removal or an aborted
552
 
  commit.
553
 
 
554
 
* Any unknown files -- can cause automatic addition, abortion of a strict
555
 
  commit, or just reporting.
556
 
 
557
 
 
558
 
Information from the repository to the tree
559
 
-------------------------------------------
560
 
 
561
 
After the commit the tree needs to be updated to the new revision.  Some
562
 
information which was accumulated during the commit must be made available
563
 
to the workingtree.  It's probably reasonable to hold it all in memory and
564
 
allow the workingtree to get it in whatever order it wants.
565
 
 
566
 
* A list of modified entries, and for each one:
567
 
 
568
 
  * The stat values observed when the file was first read.
569
 
 
570
 
  * The hash of the committed file text.
571
 
 
572
 
  * The file's last-change revision, if appropriate.
573
 
 
574
 
  This should include any entries automatically added or removed.
575
 
 
576
 
This might be construed as an enhanced version of ``set_parent_trees``.
577
 
We can avoid a stat on each file by using the value that was observed when
578
 
it was first read.
579
 
 
580
 
 
581
 
 
582
 
Selective commit
583
 
----------------
584
 
 
585
 
For a partial commit the directory contents may need to contain a mix of
586
 
entries from the working tree and parent trees.  This code probably
587
 
shouldn't live in a specific tree implementation; maybe there should be a
588
 
general filter that selects paths from one tree into another?
589
 
 
590
 
However, the tree walking code does probably need to know about selected
591
 
paths to avoid examining unselected files or directories.
592
 
 
593
 
We never refuse selective file commits (except of merges).  
594
 
 
595
 
 
596
 
 
597
 
Common commit code
598
 
------------------
599
 
 
600
 
What is common to all commit implementations, regardless of workingtree or
601
 
repository format?
602
 
 
603
 
* Prompting for a commit message?
604
 
* Strictness/conflict checks?
605
 
* Auto add/remove?
606
 
 
607
 
How should this be separated?
608
 
 
609
 
 
610
 
 
611
 
Order of traversal
612
 
------------------
613
 
 
614
 
For current and contemplated Bazaar storage formats, we can only finally
615
 
commit a directory after its contained files and directories have been
616
 
committed.
617
 
 
618
 
The dirstate workingtree format naturally iterates by directory in order
619
 
by path, yielding directories before their contents.  This may also be the
620
 
most efficient order in which to stat and read the files.
621
 
 
622
 
One option would be to construe the interface as a visitor which reports
623
 
when files are detected to be changed, and also when directories are
624
 
finished.
625
 
 
626
 
 
627
 
Open question: per-file graphs
628
 
------------------------------
629
 
 
630
 
**XXX:** If we want to retain explicitly stored per-file graphs, it would
631
 
seem that we do need to record per-file parents.  We have not yet finally
632
 
settled that we do want to remove them or treat them as a cache.  This api
633
 
stack is still ok whether we do or not, but the internals of it may
634
 
change.