bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
| 
2255.2.26
by John Arbash Meinel
 Use a clearer variable for num_present_parents while reading dirblocks  | 
1  | 
# Copyright (C) 2006, 2007 Canonical Ltd
 | 
| 
1852.13.6
by Robert Collins
 start hooking in the prototype dirstate serialiser.  | 
2  | 
#
 | 
3  | 
# This program is free software; you can redistribute it and/or modify
 | 
|
4  | 
# it under the terms of the GNU General Public License as published by
 | 
|
5  | 
# the Free Software Foundation; either version 2 of the License, or
 | 
|
6  | 
# (at your option) any later version.
 | 
|
7  | 
#
 | 
|
8  | 
# This program is distributed in the hope that it will be useful,
 | 
|
9  | 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|
10  | 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|
11  | 
# GNU General Public License for more details.
 | 
|
12  | 
#
 | 
|
13  | 
# You should have received a copy of the GNU General Public License
 | 
|
14  | 
# along with this program; if not, write to the Free Software
 | 
|
15  | 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
|
16  | 
||
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
17  | 
"""DirState objects record the state of a directory and its bzr metadata.
 | 
18  | 
||
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
19  | 
Pseudo EBNF grammar for the state file. Fields are separated by NULLs, and
 | 
20  | 
lines by NL. The field delimiters are ommitted in the grammar, line delimiters
 | 
|
21  | 
are not - this is done for clarity of reading. All string data is in utf8.
 | 
|
22  | 
||
| 
2255.2.172
by Martin Pool
 Recognize 't' (tree-reference) minikind in DirState._get_entry  | 
23  | 
MINIKIND = "f" | "d" | "l" | "a" | "r" | "t";
 | 
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
24  | 
NL = "\n";
 | 
25  | 
NULL = "\0";
 | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
26  | 
WHOLE_NUMBER = {digit}, digit;
 | 
27  | 
BOOLEAN = "y" | "n";
 | 
|
28  | 
REVISION_ID = a non-empty utf8 string;
 | 
|
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
29  | 
|
30  | 
dirstate format = header line, full checksum, row count, parent details,
 | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
31  | 
 ghost_details, entries;
 | 
| 
2818.2.2
by Ian Clatworthy
 review feedback  | 
32  | 
header line = "#bazaar dirstate flat format 3", NL;
 | 
| 
2255.2.239
by Robert Collins
 Change from adler to crc checksums, as adler32 in python is not stable from 32 to 64 bit systems.  | 
33  | 
full checksum = "crc32: ", ["-"], WHOLE_NUMBER, NL;
 | 
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
34  | 
row count = "num_entries: ", WHOLE_NUMBER, NL;
 | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
35  | 
parent_details = WHOLE NUMBER, {REVISION_ID}* NL;
 | 
36  | 
ghost_details = WHOLE NUMBER, {REVISION_ID}*, NL;
 | 
|
37  | 
entries = {entry};
 | 
|
38  | 
entry = entry_key, current_entry_details, {parent_entry_details};
 | 
|
39  | 
entry_key = dirname,  basename, fileid;
 | 
|
40  | 
current_entry_details = common_entry_details, working_entry_details;
 | 
|
41  | 
parent_entry_details = common_entry_details, history_entry_details;
 | 
|
42  | 
common_entry_details = MINIKIND, fingerprint, size, executable
 | 
|
43  | 
working_entry_details = packed_stat
 | 
|
44  | 
history_entry_details = REVISION_ID;
 | 
|
45  | 
executable = BOOLEAN;
 | 
|
46  | 
size = WHOLE_NUMBER;
 | 
|
47  | 
fingerprint = a nonempty utf8 sequence with meaning defined by minikind.
 | 
|
48  | 
||
49  | 
Given this definition, the following is useful to know:
 | 
|
50  | 
entry (aka row) - all the data for a given key.
 | 
|
51  | 
entry[0]: The key (dirname, basename, fileid)
 | 
|
52  | 
entry[0][0]: dirname
 | 
|
53  | 
entry[0][1]: basename
 | 
|
54  | 
entry[0][2]: fileid
 | 
|
55  | 
entry[1]: The tree(s) data for this path and id combination.
 | 
|
56  | 
entry[1][0]: The current tree
 | 
|
57  | 
entry[1][1]: The second tree
 | 
|
58  | 
||
59  | 
For an entry for a tree, we have (using tree 0 - current tree) to demonstrate:
 | 
|
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
60  | 
entry[1][0][0]: minikind
 | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
61  | 
entry[1][0][1]: fingerprint
 | 
62  | 
entry[1][0][2]: size
 | 
|
63  | 
entry[1][0][3]: executable
 | 
|
64  | 
entry[1][0][4]: packed_stat
 | 
|
65  | 
OR (for non tree-0)
 | 
|
66  | 
entry[1][1][4]: revision_id
 | 
|
67  | 
||
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
68  | 
There may be multiple rows at the root, one per id present in the root, so the
 | 
69  | 
in memory root row is now:
 | 
|
70  | 
self._dirblocks[0] -> ('', [entry ...]),
 | 
|
71  | 
and the entries in there are
 | 
|
72  | 
entries[0][0]: ''
 | 
|
73  | 
entries[0][1]: ''
 | 
|
74  | 
entries[0][2]: file_id
 | 
|
75  | 
entries[1][0]: The tree data for the current tree for this fileid at /
 | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
76  | 
etc.
 | 
77  | 
||
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
78  | 
Kinds:
 | 
79  | 
'r' is a relocated entry: This path is not present in this tree with this id,
 | 
|
80  | 
    but the id can be found at another location. The fingerprint is used to
 | 
|
81  | 
    point to the target location.
 | 
|
82  | 
'a' is an absent entry: In that tree the id is not present at this path.
 | 
|
83  | 
'd' is a directory entry: This path in this tree is a directory with the
 | 
|
84  | 
    current file id. There is no fingerprint for directories.
 | 
|
85  | 
'f' is a file entry: As for directory, but its a file. The fingerprint is a
 | 
|
86  | 
    sha1 value.
 | 
|
87  | 
'l' is a symlink entry: As for directory, but a symlink. The fingerprint is the
 | 
|
88  | 
    link target.
 | 
|
| 
2255.2.158
by Martin Pool
 Most of the integration of dirstate and subtree  | 
89  | 
't' is a reference to a nested subtree; the fingerprint is the referenced
 | 
90  | 
    revision.
 | 
|
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
91  | 
|
| 
2255.7.94
by Martin Pool
 Fix dirstate sorting bug and refine the _validate() assertions:  | 
92  | 
Ordering:
 | 
93  | 
||
94  | 
The entries on disk and in memory are ordered according to the following keys:
 | 
|
95  | 
||
96  | 
    directory, as a list of components
 | 
|
97  | 
    filename
 | 
|
98  | 
    file-id
 | 
|
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
99  | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
100  | 
--- Format 1 had the following different definition: ---
 | 
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
101  | 
rows = dirname, NULL, basename, NULL, MINIKIND, NULL, fileid_utf8, NULL,
 | 
| 
2255.2.15
by Robert Collins
 Dirstate - truncate state file fixing bug in saving a smaller file, get more tree_implementation tests passing.  | 
102  | 
    WHOLE NUMBER (* size *), NULL, packed stat, NULL, sha1|symlink target, 
 | 
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
103  | 
    {PARENT ROW}
 | 
104  | 
PARENT ROW = NULL, revision_utf8, NULL, MINIKIND, NULL, dirname, NULL,
 | 
|
105  | 
    basename, NULL, WHOLE NUMBER (* size *), NULL, "y" | "n", NULL,
 | 
|
106  | 
    SHA1
 | 
|
107  | 
||
| 
2255.2.4
by Robert Collins
 Snapshot dirstate development  | 
108  | 
PARENT ROW's are emitted for every parent that is not in the ghosts details
 | 
109  | 
line. That is, if the parents are foo, bar, baz, and the ghosts are bar, then
 | 
|
110  | 
each row will have a PARENT ROW for foo and baz, but not for bar.
 | 
|
111  | 
||
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
112  | 
|
113  | 
In any tree, a kind of 'moved' indicates that the fingerprint field
 | 
|
114  | 
(which we treat as opaque data specific to the 'kind' anyway) has the
 | 
|
115  | 
details for the id of this row in that tree.
 | 
|
116  | 
||
117  | 
I'm strongly tempted to add a id->path index as well, but I think that
 | 
|
118  | 
where we need id->path mapping; we also usually read the whole file, so
 | 
|
119  | 
I'm going to skip that for the moment, as we have the ability to locate
 | 
|
120  | 
via bisect any path in any tree, and if we lookup things by path, we can
 | 
|
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
121  | 
accumulate an id->path mapping as we go, which will tend to match what we
 | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
122  | 
looked for.
 | 
123  | 
||
124  | 
I plan to implement this asap, so please speak up now to alter/tweak the
 | 
|
125  | 
design - and once we stabilise on this, I'll update the wiki page for
 | 
|
126  | 
it.
 | 
|
127  | 
||
128  | 
The rationale for all this is that we want fast operations for the
 | 
|
129  | 
common case (diff/status/commit/merge on all files) and extremely fast
 | 
|
130  | 
operations for the less common but still occurs a lot status/diff/commit
 | 
|
131  | 
on specific files). Operations on specific files involve a scan for all
 | 
|
132  | 
the children of a path, *in every involved tree*, which the current
 | 
|
133  | 
format did not accommodate. 
 | 
|
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
134  | 
----
 | 
135  | 
||
136  | 
Design priorities:
 | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
137  | 
 1) Fast end to end use for bzr's top 5 uses cases. (commmit/diff/status/merge/???)
 | 
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
138  | 
 2) fall back current object model as needed.
 | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
139  | 
 3) scale usably to the largest trees known today - say 50K entries. (mozilla
 | 
140  | 
    is an example of this)
 | 
|
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
141  | 
|
142  | 
||
143  | 
Locking:
 | 
|
144  | 
 Eventually reuse dirstate objects across locks IFF the dirstate file has not
 | 
|
145  | 
 been modified, but will require that we flush/ignore cached stat-hit data
 | 
|
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
146  | 
 because we won't want to restat all files on disk just because a lock was
 | 
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
147  | 
 acquired, yet we cannot trust the data after the previous lock was released.
 | 
148  | 
||
149  | 
Memory representation:
 | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
150  | 
 vector of all directories, and vector of the childen ?
 | 
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
151  | 
   i.e. 
 | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
152  | 
     root_entrie = (direntry for root, [parent_direntries_for_root]), 
 | 
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
153  | 
     dirblocks = [
 | 
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
154  | 
     ('', ['data for achild', 'data for bchild', 'data for cchild'])
 | 
155  | 
     ('dir', ['achild', 'cchild', 'echild'])
 | 
|
156  | 
     ]
 | 
|
157  | 
    - single bisect to find N subtrees from a path spec
 | 
|
158  | 
    - in-order for serialisation - this is 'dirblock' grouping.
 | 
|
159  | 
    - insertion of a file '/a' affects only the '/' child-vector, that is, to
 | 
|
160  | 
      insert 10K elements from scratch does not generates O(N^2) memoves of a
 | 
|
161  | 
      single vector, rather each individual, which tends to be limited to a 
 | 
|
162  | 
      manageable number. Will scale badly on trees with 10K entries in a 
 | 
|
163  | 
      single directory. compare with Inventory.InventoryDirectory which has
 | 
|
164  | 
      a dictionary for the children. No bisect capability, can only probe for
 | 
|
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
165  | 
      exact matches, or grab all elements and sort.
 | 
166  | 
    - What's the risk of error here? Once we have the base format being processed
 | 
|
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
167  | 
      we should have a net win regardless of optimality. So we are going to 
 | 
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
168  | 
      go with what seems reasonable.
 | 
| 
2255.2.4
by Robert Collins
 Snapshot dirstate development  | 
169  | 
open questions:
 | 
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
170  | 
|
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
171  | 
Maybe we should do a test profile of the core structure - 10K simulated
 | 
172  | 
searches/lookups/etc?
 | 
|
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
173  | 
|
174  | 
Objects for each row?
 | 
|
175  | 
The lifetime of Dirstate objects is current per lock, but see above for
 | 
|
176  | 
possible extensions. The lifetime of a row from a dirstate is expected to be
 | 
|
177  | 
very short in the optimistic case: which we are optimising for. For instance,
 | 
|
178  | 
subtree status will determine from analysis of the disk data what rows need to
 | 
|
179  | 
be examined at all, and will be able to determine from a single row whether
 | 
|
180  | 
that file has altered or not, so we are aiming to process tens of thousands of
 | 
|
181  | 
entries each second within the dirstate context, before exposing anything to
 | 
|
182  | 
the larger codebase. This suggests we want the time for a single file
 | 
|
183  | 
comparison to be < 0.1 milliseconds. That would give us 10000 paths per second
 | 
|
184  | 
processed, and to scale to 100 thousand we'll another order of magnitude to do
 | 
|
185  | 
that. Now, as the lifetime for all unchanged entries is the time to parse, stat
 | 
|
186  | 
the file on disk, and then immediately discard, the overhead of object creation
 | 
|
187  | 
becomes a significant cost.
 | 
|
188  | 
||
189  | 
Figures: Creating a tuple from from 3 elements was profiled at 0.0625
 | 
|
190  | 
microseconds, whereas creating a object which is subclassed from tuple was
 | 
|
191  | 
0.500 microseconds, and creating an object with 3 elements and slots was 3
 | 
|
192  | 
microseconds long. 0.1 milliseconds is 100 microseconds, and ideally we'll get
 | 
|
193  | 
down to 10 microseconds for the total processing - having 33% of that be object
 | 
|
194  | 
creation is a huge overhead. There is a potential cost in using tuples within
 | 
|
195  | 
each row which is that the conditional code to do comparisons may be slower
 | 
|
196  | 
than method invocation, but method invocation is known to be slow due to stack
 | 
|
197  | 
frame creation, so avoiding methods in these tight inner loops in unfortunately
 | 
|
198  | 
desirable. We can consider a pyrex version of this with objects in future if
 | 
|
199  | 
desired.
 | 
|
200  | 
||
201  | 
"""
 | 
|
| 
1852.13.6
by Robert Collins
 start hooking in the prototype dirstate serialiser.  | 
202  | 
|
| 
2474.1.57
by John Arbash Meinel
 Move code around to refactor according to our pyrex extension design.  | 
203  | 
import bisect  | 
| 
2474.1.40
by John Arbash Meinel
 (python-only) Shave a bit of time off by calling binascii.b2a_base64  | 
204  | 
import binascii  | 
| 
2255.10.2
by John Arbash Meinel
 Update to dirstate locking.  | 
205  | 
import errno  | 
| 
1852.13.6
by Robert Collins
 start hooking in the prototype dirstate serialiser.  | 
206  | 
import os  | 
| 
2255.10.3
by John Arbash Meinel
 (broken) Change get_sha1_for_entry into update_entry  | 
207  | 
from stat import S_IEXEC  | 
| 
2485.3.3
by John Arbash Meinel
 Avoid extra work in inner 'DirState.update_entry' code.  | 
208  | 
import stat  | 
| 
1852.13.6
by Robert Collins
 start hooking in the prototype dirstate serialiser.  | 
209  | 
import struct  | 
| 
2255.10.7
by John Arbash Meinel
 Some updates to how we handle the executable bit. In preparation for supporting Win32  | 
210  | 
import sys  | 
| 
2255.10.1
by John Arbash Meinel
 Update WorkingTree4 so that it doesn't use a HashCache,  | 
211  | 
import time  | 
| 
1852.13.6
by Robert Collins
 start hooking in the prototype dirstate serialiser.  | 
212  | 
import zlib  | 
213  | 
||
| 
2255.2.23
by John Arbash Meinel
 When parsing the contents, ghosts are not records, so should not be included in the line parsing.  | 
214  | 
from bzrlib import (  | 
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
215  | 
cache_utf8,  | 
| 
2872.3.1
by Martin Pool
 Add -Dhashcache option; clean up dirstate sha1 code  | 
216  | 
debug,  | 
| 
2255.2.23
by John Arbash Meinel
 When parsing the contents, ghosts are not records, so should not be included in the line parsing.  | 
217  | 
errors,  | 
| 
2255.8.4
by John Arbash Meinel
 Rather than using split hunks, implement a bisect_dirblocks  | 
218  | 
inventory,  | 
| 
2255.4.2
by James Westby
 (broken) Add the locking methods.  | 
219  | 
lock,  | 
| 
2255.8.4
by John Arbash Meinel
 Rather than using split hunks, implement a bisect_dirblocks  | 
220  | 
osutils,  | 
| 
2255.2.23
by John Arbash Meinel
 When parsing the contents, ghosts are not records, so should not be included in the line parsing.  | 
221  | 
trace,  | 
222  | 
    )
 | 
|
| 
1852.13.6
by Robert Collins
 start hooking in the prototype dirstate serialiser.  | 
223  | 
|
224  | 
||
| 
2485.3.3
by John Arbash Meinel
 Avoid extra work in inner 'DirState.update_entry' code.  | 
225  | 
def pack_stat(st, _encode=binascii.b2a_base64, _pack=struct.pack):  | 
226  | 
"""Convert stat values into a packed representation."""  | 
|
227  | 
    # jam 20060614 it isn't really worth removing more entries if we
 | 
|
228  | 
    # are going to leave it in packed form.
 | 
|
229  | 
    # With only st_mtime and st_mode filesize is 5.5M and read time is 275ms
 | 
|
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
230  | 
    # With all entries, filesize is 5.9M and read time is maybe 280ms
 | 
| 
2485.3.3
by John Arbash Meinel
 Avoid extra work in inner 'DirState.update_entry' code.  | 
231  | 
    # well within the noise margin
 | 
232  | 
||
| 
2485.3.6
by John Arbash Meinel
 Delay calling pathjoin() until we've figured out we're going to use it  | 
233  | 
    # base64 encoding always adds a final newline, so strip it off
 | 
| 
2485.3.7
by John Arbash Meinel
 Comment on some alternative 'pack_stat'  | 
234  | 
    # The current version
 | 
| 
2485.3.3
by John Arbash Meinel
 Avoid extra work in inner 'DirState.update_entry' code.  | 
235  | 
return _encode(_pack('>LLLLLL'  | 
236  | 
, st.st_size, int(st.st_mtime), int(st.st_ctime)  | 
|
237  | 
, st.st_dev, st.st_ino & 0xFFFFFFFF, st.st_mode))[:-1]  | 
|
| 
2485.3.7
by John Arbash Meinel
 Comment on some alternative 'pack_stat'  | 
238  | 
    # This is 0.060s / 1.520s faster by not encoding as much information
 | 
239  | 
    # return _encode(_pack('>LL', int(st.st_mtime), st.st_mode))[:-1]
 | 
|
240  | 
    # This is not strictly faster than _encode(_pack())[:-1]
 | 
|
241  | 
    # return '%X.%X.%X.%X.%X.%X' % (
 | 
|
242  | 
    #      st.st_size, int(st.st_mtime), int(st.st_ctime),
 | 
|
243  | 
    #      st.st_dev, st.st_ino, st.st_mode)
 | 
|
244  | 
    # Similar to the _encode(_pack('>LL'))
 | 
|
245  | 
    # return '%X.%X' % (int(st.st_mtime), st.st_mode)
 | 
|
| 
2485.3.3
by John Arbash Meinel
 Avoid extra work in inner 'DirState.update_entry' code.  | 
246  | 
|
247  | 
||
| 
1852.13.6
by Robert Collins
 start hooking in the prototype dirstate serialiser.  | 
248  | 
class DirState(object):  | 
249  | 
"""Record directory and metadata state for fast access.  | 
|
250  | 
||
251  | 
    A dirstate is a specialised data structure for managing local working
 | 
|
252  | 
    tree state information. Its not yet well defined whether it is platform
 | 
|
| 
3128.1.3
by Vincent Ladeuil
 Since we are there s/parameteris.*/parameteriz&/.  | 
253  | 
    specific, and if it is how we detect/parameterize that.
 | 
| 
2255.7.93
by Martin Pool
 Add support for tree-references in dirstate  | 
254  | 
|
255  | 
    Dirstates use the usual lock_write, lock_read and unlock mechanisms.
 | 
|
256  | 
    Unlike most bzr disk formats, DirStates must be locked for reading, using
 | 
|
257  | 
    lock_read.  (This is an os file lock internally.)  This is necessary
 | 
|
258  | 
    because the file can be rewritten in place.
 | 
|
259  | 
||
260  | 
    DirStates must be explicitly written with save() to commit changes; just
 | 
|
261  | 
    unlocking them does not write the changes to disk.
 | 
|
| 
1852.13.6
by Robert Collins
 start hooking in the prototype dirstate serialiser.  | 
262  | 
    """
 | 
263  | 
||
| 
2255.2.169
by Martin Pool
 (broken) merge dirstate branch  | 
264  | 
_kind_to_minikind = {  | 
| 
2255.7.93
by Martin Pool
 Add support for tree-references in dirstate  | 
265  | 
'absent': 'a',  | 
266  | 
'file': 'f',  | 
|
267  | 
'directory': 'd',  | 
|
268  | 
'relocated': 'r',  | 
|
| 
2255.2.158
by Martin Pool
 Most of the integration of dirstate and subtree  | 
269  | 
'symlink': 'l',  | 
270  | 
'tree-reference': 't',  | 
|
271  | 
        }
 | 
|
| 
2255.7.93
by Martin Pool
 Add support for tree-references in dirstate  | 
272  | 
_minikind_to_kind = {  | 
273  | 
'a': 'absent',  | 
|
274  | 
'f': 'file',  | 
|
275  | 
'd': 'directory',  | 
|
276  | 
'l':'symlink',  | 
|
| 
2255.2.158
by Martin Pool
 Most of the integration of dirstate and subtree  | 
277  | 
'r': 'relocated',  | 
278  | 
't': 'tree-reference',  | 
|
279  | 
        }
 | 
|
| 
2485.3.3
by John Arbash Meinel
 Avoid extra work in inner 'DirState.update_entry' code.  | 
280  | 
_stat_to_minikind = {  | 
281  | 
stat.S_IFDIR:'d',  | 
|
282  | 
stat.S_IFREG:'f',  | 
|
283  | 
stat.S_IFLNK:'l',  | 
|
284  | 
    }
 | 
|
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
285  | 
_to_yesno = {True:'y', False: 'n'} # TODO profile the performance gain  | 
286  | 
     # of using int conversion rather than a dict here. AND BLAME ANDREW IF
 | 
|
287  | 
     # it is faster.
 | 
|
| 
1852.13.6
by Robert Collins
 start hooking in the prototype dirstate serialiser.  | 
288  | 
|
| 
2255.3.1
by John Arbash Meinel
 Rewrite the inner parsing loop, needs performance testing.  | 
289  | 
    # TODO: jam 20070221 Figure out what to do if we have a record that exceeds
 | 
| 
2255.2.126
by John Arbash Meinel
 Switch the bisect code to support the fact that we can have  | 
290  | 
    #       the BISECT_PAGE_SIZE. For now, we just have to make it large enough
 | 
291  | 
    #       that we are sure a single record will always fit.
 | 
|
| 
2255.3.1
by John Arbash Meinel
 Rewrite the inner parsing loop, needs performance testing.  | 
292  | 
BISECT_PAGE_SIZE = 4096  | 
293  | 
||
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
294  | 
NOT_IN_MEMORY = 0  | 
295  | 
IN_MEMORY_UNMODIFIED = 1  | 
|
296  | 
IN_MEMORY_MODIFIED = 2  | 
|
297  | 
||
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
298  | 
    # A pack_stat (the x's) that is just noise and will never match the output
 | 
299  | 
    # of base64 encode.
 | 
|
| 
2255.2.4
by Robert Collins
 Snapshot dirstate development  | 
300  | 
NULLSTAT = 'x' * 32  | 
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
301  | 
NULL_PARENT_DETAILS = ('a', '', 0, False, '')  | 
| 
2255.2.4
by Robert Collins
 Snapshot dirstate development  | 
302  | 
|
| 
2255.8.4
by John Arbash Meinel
 Rather than using split hunks, implement a bisect_dirblocks  | 
303  | 
HEADER_FORMAT_2 = '#bazaar dirstate flat format 2\n'  | 
| 
2255.8.6
by John Arbash Meinel
 Because the disk format (sorting) has now changed  | 
304  | 
HEADER_FORMAT_3 = '#bazaar dirstate flat format 3\n'  | 
| 
2255.8.4
by John Arbash Meinel
 Rather than using split hunks, implement a bisect_dirblocks  | 
305  | 
|
| 
2255.4.1
by James Westby
 Store the filename of the dirstate in an attribute.  | 
306  | 
def __init__(self, path):  | 
| 
2255.2.4
by Robert Collins
 Snapshot dirstate development  | 
307  | 
"""Create a DirState object.  | 
308  | 
||
| 
2255.4.1
by James Westby
 Store the filename of the dirstate in an attribute.  | 
309  | 
        :param path: The path at which the dirstate file on disk should live.
 | 
| 
2255.2.4
by Robert Collins
 Snapshot dirstate development  | 
310  | 
        """
 | 
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
311  | 
        # _header_state and _dirblock_state represent the current state
 | 
312  | 
        # of the dirstate metadata and the per-row data respectiely.
 | 
|
313  | 
        # NOT_IN_MEMORY indicates that no data is in memory
 | 
|
314  | 
        # IN_MEMORY_UNMODIFIED indicates that what we have in memory
 | 
|
315  | 
        #   is the same as is on disk
 | 
|
316  | 
        # IN_MEMORY_MODIFIED indicates that we have a modified version
 | 
|
317  | 
        #   of what is on disk. 
 | 
|
318  | 
        # In future we will add more granularity, for instance _dirblock_state
 | 
|
319  | 
        # will probably support partially-in-memory as a separate variable,
 | 
|
320  | 
        # allowing for partially-in-memory unmodified and partially-in-memory
 | 
|
321  | 
        # modified states.
 | 
|
322  | 
self._header_state = DirState.NOT_IN_MEMORY  | 
|
323  | 
self._dirblock_state = DirState.NOT_IN_MEMORY  | 
|
324  | 
self._dirblocks = []  | 
|
325  | 
self._ghosts = []  | 
|
| 
1852.13.19
by Robert Collins
 Get DirState objects roundtripping an add of a ghost tree.  | 
326  | 
self._parents = []  | 
| 
2255.3.2
by John Arbash Meinel
 (broken) some basic work on adding bisect functionality to dirstate.  | 
327  | 
self._state_file = None  | 
| 
2255.4.2
by James Westby
 (broken) Add the locking methods.  | 
328  | 
self._filename = path  | 
329  | 
self._lock_token = None  | 
|
| 
2255.10.2
by John Arbash Meinel
 Update to dirstate locking.  | 
330  | 
self._lock_state = None  | 
| 
2255.2.144
by John Arbash Meinel
 Simplify update_minimal a bit more, by making id_index a  | 
331  | 
self._id_index = None  | 
| 
2929.1.1
by Robert Collins
 Use a dict to access stat cache information from dirstate.  | 
332  | 
        # a map from packed_stat to sha's.
 | 
333  | 
self._packed_stat_index = None  | 
|
| 
2255.3.2
by John Arbash Meinel
 (broken) some basic work on adding bisect functionality to dirstate.  | 
334  | 
self._end_of_header = None  | 
| 
2255.10.6
by John Arbash Meinel
 Save approx 30-60ms (5-10%) on a LP tree by not calling time.time() for every entry.  | 
335  | 
self._cutoff_time = None  | 
| 
2255.7.20
by John Arbash Meinel
 update test for format 3, and enable caching of path split while lock is held.  | 
336  | 
self._split_path_cache = {}  | 
| 
2255.2.125
by John Arbash Meinel
 Initial effort at adding a basic _bisect function to DirState.  | 
337  | 
self._bisect_page_size = DirState.BISECT_PAGE_SIZE  | 
| 
2872.3.1
by Martin Pool
 Add -Dhashcache option; clean up dirstate sha1 code  | 
338  | 
if 'hashcache' in debug.debug_flags:  | 
339  | 
self._sha1_file = self._sha1_file_and_mutter  | 
|
340  | 
else:  | 
|
341  | 
self._sha1_file = osutils.sha_file_by_name  | 
|
| 
2921.1.4
by Robert Collins
 Documentation to aid our failing memory in the future.  | 
342  | 
        # These two attributes provide a simple cache for lookups into the
 | 
343  | 
        # dirstate in-memory vectors. By probing respectively for the last
 | 
|
344  | 
        # block, and for the next entry, we save nearly 2 bisections per path
 | 
|
345  | 
        # during commit.
 | 
|
| 
2921.1.1
by Robert Collins
 Add a cache for dirstate entry lookups.  | 
346  | 
self._last_block_index = None  | 
347  | 
self._last_entry_index = None  | 
|
| 
1852.13.19
by Robert Collins
 Get DirState objects roundtripping an add of a ghost tree.  | 
348  | 
|
| 
2255.2.222
by Martin Pool
 Add DirState repr so we get meaningful messages  | 
349  | 
def __repr__(self):  | 
350  | 
return "%s(%r)" % \  | 
|
351  | 
(self.__class__.__name__, self._filename)  | 
|
352  | 
||
| 
2255.2.158
by Martin Pool
 Most of the integration of dirstate and subtree  | 
353  | 
def add(self, path, file_id, kind, stat, fingerprint):  | 
| 
2255.2.8
by Robert Collins
 First DirState.add() method test passing.  | 
354  | 
"""Add a path to be tracked.  | 
355  | 
||
356  | 
        :param path: The path within the dirstate - '' is the root, 'foo' is the
 | 
|
357  | 
            path foo within the root, 'foo/bar' is the path bar within foo 
 | 
|
358  | 
            within the root.
 | 
|
359  | 
        :param file_id: The file id of the path being added.
 | 
|
| 
2255.2.158
by Martin Pool
 Most of the integration of dirstate and subtree  | 
360  | 
        :param kind: The kind of the path, as a string like 'file', 
 | 
361  | 
            'directory', etc.
 | 
|
| 
2255.10.1
by John Arbash Meinel
 Update WorkingTree4 so that it doesn't use a HashCache,  | 
362  | 
        :param stat: The output of os.lstat for the path.
 | 
| 
2255.2.158
by Martin Pool
 Most of the integration of dirstate and subtree  | 
363  | 
        :param fingerprint: The sha value of the file,
 | 
364  | 
            or the target of a symlink,
 | 
|
365  | 
            or the referenced revision id for tree-references,
 | 
|
366  | 
            or '' for directories.
 | 
|
| 
2255.2.8
by Robert Collins
 First DirState.add() method test passing.  | 
367  | 
        """
 | 
368  | 
        # adding a file:
 | 
|
369  | 
        # find the block its in. 
 | 
|
370  | 
        # find the location in the block.
 | 
|
371  | 
        # check its not there
 | 
|
372  | 
        # add it.
 | 
|
| 
2825.6.1
by Robert Collins
 * ``WorkingTree.rename_one`` will now raise an error if normalisation of the  | 
373  | 
        #------- copied from inventory.ensure_normalized_name - keep synced.
 | 
| 
2255.2.54
by Robert Collins
 Add in non-normalized filename sanity check to dirstate add().  | 
374  | 
        # --- normalized_filename wants a unicode basename only, so get one.
 | 
| 
2474.1.74
by John Arbash Meinel
 Revert the accidental removal of the Unicode normalization check code.  | 
375  | 
dirname, basename = osutils.split(path)  | 
376  | 
        # we dont import normalized_filename directly because we want to be
 | 
|
377  | 
        # able to change the implementation at runtime for tests.
 | 
|
378  | 
norm_name, can_access = osutils.normalized_filename(basename)  | 
|
379  | 
if norm_name != basename:  | 
|
380  | 
if can_access:  | 
|
381  | 
basename = norm_name  | 
|
382  | 
else:  | 
|
383  | 
raise errors.InvalidNormalization(path)  | 
|
| 
2255.2.225
by Martin Pool
 Prohibit dirstate from getting entries called ..  | 
384  | 
        # you should never have files called . or ..; just add the directory
 | 
385  | 
        # in the parent, or according to the special treatment for the root
 | 
|
386  | 
if basename == '.' or basename == '..':  | 
|
387  | 
raise errors.InvalidEntryName(path)  | 
|
| 
2255.2.54
by Robert Collins
 Add in non-normalized filename sanity check to dirstate add().  | 
388  | 
        # now that we've normalised, we need the correct utf8 path and 
 | 
389  | 
        # dirname and basename elements. This single encode and split should be
 | 
|
390  | 
        # faster than three separate encodes.
 | 
|
| 
2474.1.74
by John Arbash Meinel
 Revert the accidental removal of the Unicode normalization check code.  | 
391  | 
utf8path = (dirname + '/' + basename).strip('/').encode('utf8')  | 
392  | 
dirname, basename = osutils.split(utf8path)  | 
|
| 
2255.2.107
by John Arbash Meinel
 (working), fix dirstate to use utf8 file ids.  | 
393  | 
assert file_id.__class__ == str, \  | 
394  | 
"must be a utf8 file_id not %s" % (type(file_id))  | 
|
| 
2255.7.16
by John Arbash Meinel
 Make sure adding a duplicate file_id raises DuplicateFileId.  | 
395  | 
        # Make sure the file_id does not exist in this tree
 | 
396  | 
file_id_entry = self._get_entry(0, fileid_utf8=file_id)  | 
|
397  | 
if file_id_entry != (None, None):  | 
|
398  | 
path = osutils.pathjoin(file_id_entry[0][0], file_id_entry[0][1])  | 
|
399  | 
kind = DirState._minikind_to_kind[file_id_entry[1][0][0]]  | 
|
400  | 
info = '%s:%s' % (kind, path)  | 
|
401  | 
raise errors.DuplicateFileId(file_id, info)  | 
|
| 
2255.7.74
by Robert Collins
 Test adding of roots to trees, it was broken on WorkingTree4.  | 
402  | 
first_key = (dirname, basename, '')  | 
403  | 
block_index, present = self._find_block_index_from_key(first_key)  | 
|
404  | 
if present:  | 
|
405  | 
            # check the path is not in the tree
 | 
|
406  | 
block = self._dirblocks[block_index][1]  | 
|
407  | 
entry_index, _ = self._find_entry_index(first_key, block)  | 
|
408  | 
while (entry_index < len(block) and  | 
|
409  | 
block[entry_index][0][0:2] == first_key[0:2]):  | 
|
410  | 
if block[entry_index][1][0][0] not in 'ar':  | 
|
411  | 
                    # this path is in the dirstate in the current tree.
 | 
|
412  | 
raise Exception, "adding already added path!"  | 
|
| 
2255.7.76
by Robert Collins
 Fix _get_entry, which got broken at some point, this fixes tests now, so it should not be breakable in future.  | 
413  | 
entry_index += 1  | 
| 
2255.7.74
by Robert Collins
 Test adding of roots to trees, it was broken on WorkingTree4.  | 
414  | 
else:  | 
| 
2255.7.10
by John Arbash Meinel
 Handle the case when we are adding a file to an empty directory.  | 
415  | 
            # The block where we want to put the file is not present. But it
 | 
416  | 
            # might be because the directory was empty, or not loaded yet. Look
 | 
|
417  | 
            # for a parent entry, if not found, raise NotVersionedError
 | 
|
418  | 
parent_dir, parent_base = osutils.split(dirname)  | 
|
419  | 
parent_block_idx, parent_entry_idx, _, parent_present = \  | 
|
420  | 
self._get_block_entry_index(parent_dir, parent_base, 0)  | 
|
421  | 
if not parent_present:  | 
|
422  | 
raise errors.NotVersionedError(path, str(self))  | 
|
423  | 
self._ensure_block(parent_block_idx, parent_entry_idx, dirname)  | 
|
| 
2255.2.8
by Robert Collins
 First DirState.add() method test passing.  | 
424  | 
block = self._dirblocks[block_index][1]  | 
| 
2255.7.74
by Robert Collins
 Test adding of roots to trees, it was broken on WorkingTree4.  | 
425  | 
entry_key = (dirname, basename, file_id)  | 
| 
2255.2.43
by Robert Collins
 WorkingTree4.add must not require a file to exist to add it when kind etc is given.  | 
426  | 
if stat is None:  | 
427  | 
size = 0  | 
|
428  | 
packed_stat = DirState.NULLSTAT  | 
|
429  | 
else:  | 
|
430  | 
size = stat.st_size  | 
|
431  | 
packed_stat = pack_stat(stat)  | 
|
| 
2255.2.75
by Robert Collins
 Correct generation of revisiontree inventories to handle out of order parents.  | 
432  | 
parent_info = self._empty_parent_info()  | 
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
433  | 
minikind = DirState._kind_to_minikind[kind]  | 
| 
2255.2.14
by Robert Collins
 Dirstate: fix adding of directories to setup the next directories block, and test representation of symlinks. Also fix iter_rows to not reset the dirty bit.  | 
434  | 
if kind == 'file':  | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
435  | 
entry_data = entry_key, [  | 
| 
2255.2.158
by Martin Pool
 Most of the integration of dirstate and subtree  | 
436  | 
(minikind, fingerprint, size, False, packed_stat),  | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
437  | 
] + parent_info  | 
| 
2255.2.14
by Robert Collins
 Dirstate: fix adding of directories to setup the next directories block, and test representation of symlinks. Also fix iter_rows to not reset the dirty bit.  | 
438  | 
elif kind == 'directory':  | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
439  | 
entry_data = entry_key, [  | 
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
440  | 
(minikind, '', 0, False, packed_stat),  | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
441  | 
] + parent_info  | 
| 
2255.2.14
by Robert Collins
 Dirstate: fix adding of directories to setup the next directories block, and test representation of symlinks. Also fix iter_rows to not reset the dirty bit.  | 
442  | 
elif kind == 'symlink':  | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
443  | 
entry_data = entry_key, [  | 
| 
2255.2.158
by Martin Pool
 Most of the integration of dirstate and subtree  | 
444  | 
(minikind, fingerprint, size, False, packed_stat),  | 
445  | 
] + parent_info  | 
|
446  | 
elif kind == 'tree-reference':  | 
|
447  | 
entry_data = entry_key, [  | 
|
448  | 
(minikind, fingerprint, 0, False, packed_stat),  | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
449  | 
] + parent_info  | 
| 
2255.2.13
by Robert Collins
 Test adding of directories to the root of a dirstate.  | 
450  | 
else:  | 
| 
2255.2.14
by Robert Collins
 Dirstate: fix adding of directories to setup the next directories block, and test representation of symlinks. Also fix iter_rows to not reset the dirty bit.  | 
451  | 
raise errors.BzrError('unknown kind %r' % kind)  | 
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
452  | 
entry_index, present = self._find_entry_index(entry_key, block)  | 
| 
2323.4.1
by Robert Collins
 dirstate correctness: allow adding paths present in the basis.  | 
453  | 
if not present:  | 
454  | 
block.insert(entry_index, entry_data)  | 
|
455  | 
else:  | 
|
456  | 
assert block[entry_index][1][0][0] == 'a', " %r(%r) already added" % (basename, file_id)  | 
|
457  | 
block[entry_index][1][0] = entry_data[1][0]  | 
|
| 
2255.2.8
by Robert Collins
 First DirState.add() method test passing.  | 
458  | 
|
| 
2255.2.14
by Robert Collins
 Dirstate: fix adding of directories to setup the next directories block, and test representation of symlinks. Also fix iter_rows to not reset the dirty bit.  | 
459  | 
if kind == 'directory':  | 
460  | 
           # insert a new dirblock
 | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
461  | 
self._ensure_block(block_index, entry_index, utf8path)  | 
| 
2255.2.13
by Robert Collins
 Test adding of directories to the root of a dirstate.  | 
462  | 
self._dirblock_state = DirState.IN_MEMORY_MODIFIED  | 
| 
2255.2.147
by John Arbash Meinel
 Move fast id => path lookups down into DirState  | 
463  | 
if self._id_index:  | 
464  | 
self._id_index.setdefault(entry_key[2], set()).add(entry_key)  | 
|
| 
2255.2.8
by Robert Collins
 First DirState.add() method test passing.  | 
465  | 
|
| 
2474.1.58
by John Arbash Meinel
 (broken) Try to properly implement DirState._bisect*  | 
466  | 
def _bisect(self, paths):  | 
| 
2255.2.131
by John Arbash Meinel
 Change the return values for bisect functions so they just return  | 
467  | 
"""Bisect through the disk structure for specific rows.  | 
468  | 
||
| 
2474.1.58
by John Arbash Meinel
 (broken) Try to properly implement DirState._bisect*  | 
469  | 
        :param paths: A list of paths to find
 | 
470  | 
        :return: A dict mapping path => entries for found entries. Missing
 | 
|
| 
2255.2.131
by John Arbash Meinel
 Change the return values for bisect functions so they just return  | 
471  | 
                 entries will not be in the map.
 | 
| 
2474.1.58
by John Arbash Meinel
 (broken) Try to properly implement DirState._bisect*  | 
472  | 
                 The list is not sorted, and entries will be populated
 | 
473  | 
                 based on when they were read.
 | 
|
| 
2255.2.131
by John Arbash Meinel
 Change the return values for bisect functions so they just return  | 
474  | 
        """
 | 
| 
2255.2.125
by John Arbash Meinel
 Initial effort at adding a basic _bisect function to DirState.  | 
475  | 
self._requires_lock()  | 
476  | 
        # We need the file pointer to be right after the initial header block
 | 
|
477  | 
self._read_header_if_needed()  | 
|
478  | 
        # If _dirblock_state was in memory, we should just return info from
 | 
|
479  | 
        # there, this function is only meant to handle when we want to read
 | 
|
480  | 
        # part of the disk.
 | 
|
481  | 
assert self._dirblock_state == DirState.NOT_IN_MEMORY  | 
|
482  | 
||
483  | 
        # The disk representation is generally info + '\0\n\0' at the end. But
 | 
|
484  | 
        # for bisecting, it is easier to treat this as '\0' + info + '\0\n'
 | 
|
485  | 
        # Because it means we can sync on the '\n'
 | 
|
486  | 
state_file = self._state_file  | 
|
487  | 
file_size = os.fstat(state_file.fileno()).st_size  | 
|
| 
2255.2.126
by John Arbash Meinel
 Switch the bisect code to support the fact that we can have  | 
488  | 
        # We end up with 2 extra fields, we should have a trailing '\n' to
 | 
489  | 
        # ensure that we read the whole record, and we should have a precursur
 | 
|
490  | 
        # '' which ensures that we start after the previous '\n'
 | 
|
491  | 
entry_field_count = self._fields_per_entry() + 1  | 
|
| 
2255.2.125
by John Arbash Meinel
 Initial effort at adding a basic _bisect function to DirState.  | 
492  | 
|
493  | 
low = self._end_of_header  | 
|
494  | 
high = file_size - 1 # Ignore the final '\0'  | 
|
| 
2255.2.126
by John Arbash Meinel
 Switch the bisect code to support the fact that we can have  | 
495  | 
        # Map from (dir, name) => entry
 | 
| 
2255.2.125
by John Arbash Meinel
 Initial effort at adding a basic _bisect function to DirState.  | 
496  | 
found = {}  | 
497  | 
||
498  | 
        # Avoid infinite seeking
 | 
|
| 
2474.1.58
by John Arbash Meinel
 (broken) Try to properly implement DirState._bisect*  | 
499  | 
max_count = 30*len(paths)  | 
| 
2255.2.125
by John Arbash Meinel
 Initial effort at adding a basic _bisect function to DirState.  | 
500  | 
count = 0  | 
| 
2255.2.126
by John Arbash Meinel
 Switch the bisect code to support the fact that we can have  | 
501  | 
        # pending is a list of places to look.
 | 
502  | 
        # each entry is a tuple of low, high, dir_names
 | 
|
503  | 
        #   low -> the first byte offset to read (inclusive)
 | 
|
504  | 
        #   high -> the last byte offset (inclusive)
 | 
|
505  | 
        #   dir_names -> The list of (dir, name) pairs that should be found in
 | 
|
506  | 
        #                the [low, high] range
 | 
|
| 
2474.1.58
by John Arbash Meinel
 (broken) Try to properly implement DirState._bisect*  | 
507  | 
pending = [(low, high, paths)]  | 
| 
2255.2.125
by John Arbash Meinel
 Initial effort at adding a basic _bisect function to DirState.  | 
508  | 
|
| 
2255.2.126
by John Arbash Meinel
 Switch the bisect code to support the fact that we can have  | 
509  | 
page_size = self._bisect_page_size  | 
| 
2255.2.125
by John Arbash Meinel
 Initial effort at adding a basic _bisect function to DirState.  | 
510  | 
|
511  | 
fields_to_entry = self._get_fields_to_entry()  | 
|
512  | 
||
513  | 
while pending:  | 
|
514  | 
low, high, cur_files = pending.pop()  | 
|
515  | 
||
| 
2255.2.130
by John Arbash Meinel
 Add a very similar function which grabs everything for a particular directory block.  | 
516  | 
if not cur_files or low >= high:  | 
517  | 
                # Nothing to find
 | 
|
| 
2255.2.125
by John Arbash Meinel
 Initial effort at adding a basic _bisect function to DirState.  | 
518  | 
                continue
 | 
519  | 
||
520  | 
count += 1  | 
|
521  | 
if count > max_count:  | 
|
522  | 
raise errors.BzrError('Too many seeks, most likely a bug.')  | 
|
523  | 
||
524  | 
mid = max(low, (low+high-page_size)/2)  | 
|
525  | 
||
526  | 
state_file.seek(mid)  | 
|
| 
2255.2.126
by John Arbash Meinel
 Switch the bisect code to support the fact that we can have  | 
527  | 
            # limit the read size, so we don't end up reading data that we have
 | 
528  | 
            # already read.
 | 
|
529  | 
read_size = min(page_size, (high-mid)+1)  | 
|
530  | 
block = state_file.read(read_size)  | 
|
| 
2255.2.125
by John Arbash Meinel
 Initial effort at adding a basic _bisect function to DirState.  | 
531  | 
|
532  | 
start = mid  | 
|
| 
2255.2.126
by John Arbash Meinel
 Switch the bisect code to support the fact that we can have  | 
533  | 
entries = block.split('\n')  | 
534  | 
||
535  | 
if len(entries) < 2:  | 
|
536  | 
                # We didn't find a '\n', so we cannot have found any records.
 | 
|
537  | 
                # So put this range back and try again. But we know we have to
 | 
|
538  | 
                # increase the page size, because a single read did not contain
 | 
|
539  | 
                # a record break (so records must be larger than page_size)
 | 
|
| 
2255.2.128
by John Arbash Meinel
 Rather than falling over when the page size is to small, just increase it and try again.  | 
540  | 
page_size *= 2  | 
541  | 
pending.append((low, high, cur_files))  | 
|
542  | 
                continue
 | 
|
| 
2255.2.125
by John Arbash Meinel
 Initial effort at adding a basic _bisect function to DirState.  | 
543  | 
|
544  | 
            # Check the first and last entries, in case they are partial, or if
 | 
|
545  | 
            # we don't care about the rest of this page
 | 
|
546  | 
first_entry_num = 0  | 
|
| 
2255.2.126
by John Arbash Meinel
 Switch the bisect code to support the fact that we can have  | 
547  | 
first_fields = entries[0].split('\0')  | 
548  | 
if len(first_fields) < entry_field_count:  | 
|
| 
2255.2.125
by John Arbash Meinel
 Initial effort at adding a basic _bisect function to DirState.  | 
549  | 
                # We didn't get the complete first entry
 | 
550  | 
                # so move start, and grab the next, which
 | 
|
551  | 
                # should be a full entry
 | 
|
552  | 
start += len(entries[0])+1  | 
|
| 
2255.2.126
by John Arbash Meinel
 Switch the bisect code to support the fact that we can have  | 
553  | 
first_fields = entries[1].split('\0')  | 
| 
2255.2.125
by John Arbash Meinel
 Initial effort at adding a basic _bisect function to DirState.  | 
554  | 
first_entry_num = 1  | 
555  | 
||
| 
2255.2.126
by John Arbash Meinel
 Switch the bisect code to support the fact that we can have  | 
556  | 
if len(first_fields) <= 2:  | 
557  | 
                # We didn't even get a filename here... what do we do?
 | 
|
| 
2255.2.128
by John Arbash Meinel
 Rather than falling over when the page size is to small, just increase it and try again.  | 
558  | 
                # Try a large page size and repeat this query
 | 
559  | 
page_size *= 2  | 
|
560  | 
pending.append((low, high, cur_files))  | 
|
561  | 
                continue
 | 
|
| 
2255.2.126
by John Arbash Meinel
 Switch the bisect code to support the fact that we can have  | 
562  | 
else:  | 
563  | 
                # Find what entries we are looking for, which occur before and
 | 
|
564  | 
                # after this first record.
 | 
|
| 
2255.2.129
by John Arbash Meinel
 Start cleaning up the code, and fix one more edge case  | 
565  | 
after = start  | 
| 
2474.1.58
by John Arbash Meinel
 (broken) Try to properly implement DirState._bisect*  | 
566  | 
if first_fields[1]:  | 
567  | 
first_path = first_fields[1] + '/' + first_fields[2]  | 
|
568  | 
else:  | 
|
569  | 
first_path = first_fields[2]  | 
|
| 
2474.1.66
by John Arbash Meinel
 Some restructuring.  | 
570  | 
first_loc = _bisect_path_left(cur_files, first_path)  | 
| 
2255.2.126
by John Arbash Meinel
 Switch the bisect code to support the fact that we can have  | 
571  | 
|
572  | 
                # These exist before the current location
 | 
|
573  | 
pre = cur_files[:first_loc]  | 
|
574  | 
                # These occur after the current location, which may be in the
 | 
|
575  | 
                # data we read, or might be after the last entry
 | 
|
| 
2255.2.129
by John Arbash Meinel
 Start cleaning up the code, and fix one more edge case  | 
576  | 
post = cur_files[first_loc:]  | 
577  | 
||
578  | 
if post and len(first_fields) >= entry_field_count:  | 
|
579  | 
                # We have files after the first entry
 | 
|
| 
2255.2.125
by John Arbash Meinel
 Initial effort at adding a basic _bisect function to DirState.  | 
580  | 
|
581  | 
                # Parse the last entry
 | 
|
582  | 
last_entry_num = len(entries)-1  | 
|
| 
2255.2.126
by John Arbash Meinel
 Switch the bisect code to support the fact that we can have  | 
583  | 
last_fields = entries[last_entry_num].split('\0')  | 
584  | 
if len(last_fields) < entry_field_count:  | 
|
| 
2255.2.125
by John Arbash Meinel
 Initial effort at adding a basic _bisect function to DirState.  | 
585  | 
                    # The very last hunk was not complete,
 | 
586  | 
                    # read the previous hunk
 | 
|
| 
2255.2.129
by John Arbash Meinel
 Start cleaning up the code, and fix one more edge case  | 
587  | 
after = mid + len(block) - len(entries[-1])  | 
| 
2255.2.125
by John Arbash Meinel
 Initial effort at adding a basic _bisect function to DirState.  | 
588  | 
last_entry_num -= 1  | 
| 
2255.2.126
by John Arbash Meinel
 Switch the bisect code to support the fact that we can have  | 
589  | 
last_fields = entries[last_entry_num].split('\0')  | 
| 
2255.2.129
by John Arbash Meinel
 Start cleaning up the code, and fix one more edge case  | 
590  | 
else:  | 
591  | 
after = mid + len(block)  | 
|
| 
2255.2.125
by John Arbash Meinel
 Initial effort at adding a basic _bisect function to DirState.  | 
592  | 
|
| 
2474.1.58
by John Arbash Meinel
 (broken) Try to properly implement DirState._bisect*  | 
593  | 
if last_fields[1]:  | 
594  | 
last_path = last_fields[1] + '/' + last_fields[2]  | 
|
595  | 
else:  | 
|
596  | 
last_path = last_fields[2]  | 
|
| 
2474.1.66
by John Arbash Meinel
 Some restructuring.  | 
597  | 
last_loc = _bisect_path_right(post, last_path)  | 
| 
2255.2.125
by John Arbash Meinel
 Initial effort at adding a basic _bisect function to DirState.  | 
598  | 
|
| 
2255.2.129
by John Arbash Meinel
 Start cleaning up the code, and fix one more edge case  | 
599  | 
middle_files = post[:last_loc]  | 
600  | 
post = post[last_loc:]  | 
|
| 
2255.2.125
by John Arbash Meinel
 Initial effort at adding a basic _bisect function to DirState.  | 
601  | 
|
602  | 
if middle_files:  | 
|
603  | 
                    # We have files that should occur in this block
 | 
|
604  | 
                    # (>= first, <= last)
 | 
|
605  | 
                    # Either we will find them here, or we can mark them as
 | 
|
606  | 
                    # missing.
 | 
|
607  | 
||
| 
2474.1.58
by John Arbash Meinel
 (broken) Try to properly implement DirState._bisect*  | 
608  | 
if middle_files[0] == first_path:  | 
| 
2255.2.126
by John Arbash Meinel
 Switch the bisect code to support the fact that we can have  | 
609  | 
                        # We might need to go before this location
 | 
| 
2474.1.58
by John Arbash Meinel
 (broken) Try to properly implement DirState._bisect*  | 
610  | 
pre.append(first_path)  | 
611  | 
if middle_files[-1] == last_path:  | 
|
612  | 
post.insert(0, last_path)  | 
|
| 
2255.2.126
by John Arbash Meinel
 Switch the bisect code to support the fact that we can have  | 
613  | 
|
| 
2255.2.125
by John Arbash Meinel
 Initial effort at adding a basic _bisect function to DirState.  | 
614  | 
                    # Find out what paths we have
 | 
| 
2474.1.58
by John Arbash Meinel
 (broken) Try to properly implement DirState._bisect*  | 
615  | 
paths = {first_path:[first_fields]}  | 
616  | 
                    # last_path might == first_path so we need to be
 | 
|
| 
2255.2.129
by John Arbash Meinel
 Start cleaning up the code, and fix one more edge case  | 
617  | 
                    # careful if we should append rather than overwrite
 | 
618  | 
if last_entry_num != first_entry_num:  | 
|
| 
2474.1.58
by John Arbash Meinel
 (broken) Try to properly implement DirState._bisect*  | 
619  | 
paths.setdefault(last_path, []).append(last_fields)  | 
| 
2255.2.126
by John Arbash Meinel
 Switch the bisect code to support the fact that we can have  | 
620  | 
for num in xrange(first_entry_num+1, last_entry_num):  | 
621  | 
                        # TODO: jam 20070223 We are already splitting here, so
 | 
|
622  | 
                        #       shouldn't we just split the whole thing rather
 | 
|
623  | 
                        #       than doing the split again in add_one_record?
 | 
|
624  | 
fields = entries[num].split('\0')  | 
|
| 
2474.1.58
by John Arbash Meinel
 (broken) Try to properly implement DirState._bisect*  | 
625  | 
if fields[1]:  | 
626  | 
path = fields[1] + '/' + fields[2]  | 
|
627  | 
else:  | 
|
628  | 
path = fields[2]  | 
|
629  | 
paths.setdefault(path, []).append(fields)  | 
|
| 
2255.2.125
by John Arbash Meinel
 Initial effort at adding a basic _bisect function to DirState.  | 
630  | 
|
| 
2474.1.58
by John Arbash Meinel
 (broken) Try to properly implement DirState._bisect*  | 
631  | 
for path in middle_files:  | 
632  | 
for fields in paths.get(path, []):  | 
|
| 
2255.2.126
by John Arbash Meinel
 Switch the bisect code to support the fact that we can have  | 
633  | 
                            # offset by 1 because of the opening '\0'
 | 
634  | 
                            # consider changing fields_to_entry to avoid the
 | 
|
635  | 
                            # extra list slice
 | 
|
636  | 
entry = fields_to_entry(fields[1:])  | 
|
| 
2474.1.58
by John Arbash Meinel
 (broken) Try to properly implement DirState._bisect*  | 
637  | 
found.setdefault(path, []).append(entry)  | 
| 
2255.2.125
by John Arbash Meinel
 Initial effort at adding a basic _bisect function to DirState.  | 
638  | 
|
639  | 
            # Now we have split up everything into pre, middle, and post, and
 | 
|
640  | 
            # we have handled everything that fell in 'middle'.
 | 
|
641  | 
            # We add 'post' first, so that we prefer to seek towards the
 | 
|
642  | 
            # beginning, so that we will tend to go as early as we need, and
 | 
|
643  | 
            # then only seek forward after that.
 | 
|
644  | 
if post:  | 
|
645  | 
pending.append((after, high, post))  | 
|
646  | 
if pre:  | 
|
647  | 
pending.append((low, start-1, pre))  | 
|
648  | 
||
| 
2255.2.130
by John Arbash Meinel
 Add a very similar function which grabs everything for a particular directory block.  | 
649  | 
        # Consider that we may want to return the directory entries in sorted
 | 
650  | 
        # order. For now, we just return them in whatever order we found them,
 | 
|
651  | 
        # and leave it up to the caller if they care if it is ordered or not.
 | 
|
| 
2255.2.131
by John Arbash Meinel
 Change the return values for bisect functions so they just return  | 
652  | 
return found  | 
| 
2255.2.36
by Robert Collins
 Fix Dirstate unversioning of entries which are in a parent.  | 
653  | 
|
| 
2255.2.130
by John Arbash Meinel
 Add a very similar function which grabs everything for a particular directory block.  | 
654  | 
def _bisect_dirblocks(self, dir_list):  | 
655  | 
"""Bisect through the disk structure to find entries in given dirs.  | 
|
656  | 
||
657  | 
        _bisect_dirblocks is meant to find the contents of directories, which
 | 
|
658  | 
        differs from _bisect, which only finds individual entries.
 | 
|
659  | 
||
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
660  | 
        :param dir_list: A sorted list of directory names ['', 'dir', 'foo'].
 | 
| 
2255.2.131
by John Arbash Meinel
 Change the return values for bisect functions so they just return  | 
661  | 
        :return: A map from dir => entries_for_dir
 | 
| 
2255.2.130
by John Arbash Meinel
 Add a very similar function which grabs everything for a particular directory block.  | 
662  | 
        """
 | 
663  | 
        # TODO: jam 20070223 A lot of the bisecting logic could be shared
 | 
|
664  | 
        #       between this and _bisect. It would require parameterizing the
 | 
|
665  | 
        #       inner loop with a function, though. We should evaluate the
 | 
|
666  | 
        #       performance difference.
 | 
|
667  | 
self._requires_lock()  | 
|
668  | 
        # We need the file pointer to be right after the initial header block
 | 
|
669  | 
self._read_header_if_needed()  | 
|
670  | 
        # If _dirblock_state was in memory, we should just return info from
 | 
|
671  | 
        # there, this function is only meant to handle when we want to read
 | 
|
672  | 
        # part of the disk.
 | 
|
673  | 
assert self._dirblock_state == DirState.NOT_IN_MEMORY  | 
|
674  | 
||
675  | 
        # The disk representation is generally info + '\0\n\0' at the end. But
 | 
|
676  | 
        # for bisecting, it is easier to treat this as '\0' + info + '\0\n'
 | 
|
677  | 
        # Because it means we can sync on the '\n'
 | 
|
678  | 
state_file = self._state_file  | 
|
679  | 
file_size = os.fstat(state_file.fileno()).st_size  | 
|
680  | 
        # We end up with 2 extra fields, we should have a trailing '\n' to
 | 
|
681  | 
        # ensure that we read the whole record, and we should have a precursur
 | 
|
682  | 
        # '' which ensures that we start after the previous '\n'
 | 
|
683  | 
entry_field_count = self._fields_per_entry() + 1  | 
|
684  | 
||
685  | 
low = self._end_of_header  | 
|
686  | 
high = file_size - 1 # Ignore the final '\0'  | 
|
687  | 
        # Map from dir => entry
 | 
|
688  | 
found = {}  | 
|
689  | 
||
690  | 
        # Avoid infinite seeking
 | 
|
691  | 
max_count = 30*len(dir_list)  | 
|
692  | 
count = 0  | 
|
693  | 
        # pending is a list of places to look.
 | 
|
694  | 
        # each entry is a tuple of low, high, dir_names
 | 
|
695  | 
        #   low -> the first byte offset to read (inclusive)
 | 
|
696  | 
        #   high -> the last byte offset (inclusive)
 | 
|
697  | 
        #   dirs -> The list of directories that should be found in
 | 
|
698  | 
        #                the [low, high] range
 | 
|
699  | 
pending = [(low, high, dir_list)]  | 
|
700  | 
||
701  | 
page_size = self._bisect_page_size  | 
|
702  | 
||
703  | 
fields_to_entry = self._get_fields_to_entry()  | 
|
704  | 
||
705  | 
while pending:  | 
|
706  | 
low, high, cur_dirs = pending.pop()  | 
|
707  | 
||
708  | 
if not cur_dirs or low >= high:  | 
|
709  | 
                # Nothing to find
 | 
|
710  | 
                continue
 | 
|
711  | 
||
712  | 
count += 1  | 
|
713  | 
if count > max_count:  | 
|
714  | 
raise errors.BzrError('Too many seeks, most likely a bug.')  | 
|
715  | 
||
716  | 
mid = max(low, (low+high-page_size)/2)  | 
|
717  | 
||
718  | 
state_file.seek(mid)  | 
|
719  | 
            # limit the read size, so we don't end up reading data that we have
 | 
|
720  | 
            # already read.
 | 
|
721  | 
read_size = min(page_size, (high-mid)+1)  | 
|
722  | 
block = state_file.read(read_size)  | 
|
723  | 
||
724  | 
start = mid  | 
|
725  | 
entries = block.split('\n')  | 
|
726  | 
||
727  | 
if len(entries) < 2:  | 
|
728  | 
                # We didn't find a '\n', so we cannot have found any records.
 | 
|
729  | 
                # So put this range back and try again. But we know we have to
 | 
|
730  | 
                # increase the page size, because a single read did not contain
 | 
|
731  | 
                # a record break (so records must be larger than page_size)
 | 
|
732  | 
page_size *= 2  | 
|
733  | 
pending.append((low, high, cur_dirs))  | 
|
734  | 
                continue
 | 
|
735  | 
||
736  | 
            # Check the first and last entries, in case they are partial, or if
 | 
|
737  | 
            # we don't care about the rest of this page
 | 
|
738  | 
first_entry_num = 0  | 
|
739  | 
first_fields = entries[0].split('\0')  | 
|
740  | 
if len(first_fields) < entry_field_count:  | 
|
741  | 
                # We didn't get the complete first entry
 | 
|
742  | 
                # so move start, and grab the next, which
 | 
|
743  | 
                # should be a full entry
 | 
|
744  | 
start += len(entries[0])+1  | 
|
745  | 
first_fields = entries[1].split('\0')  | 
|
746  | 
first_entry_num = 1  | 
|
747  | 
||
748  | 
if len(first_fields) <= 1:  | 
|
749  | 
                # We didn't even get a dirname here... what do we do?
 | 
|
750  | 
                # Try a large page size and repeat this query
 | 
|
751  | 
page_size *= 2  | 
|
752  | 
pending.append((low, high, cur_dirs))  | 
|
753  | 
                continue
 | 
|
754  | 
else:  | 
|
755  | 
                # Find what entries we are looking for, which occur before and
 | 
|
756  | 
                # after this first record.
 | 
|
757  | 
after = start  | 
|
758  | 
first_dir = first_fields[1]  | 
|
| 
2474.1.61
by John Arbash Meinel
 Finish fixing DirState._bisect and the bisect tests  | 
759  | 
first_loc = bisect.bisect_left(cur_dirs, first_dir)  | 
| 
2255.2.130
by John Arbash Meinel
 Add a very similar function which grabs everything for a particular directory block.  | 
760  | 
|
761  | 
                # These exist before the current location
 | 
|
762  | 
pre = cur_dirs[:first_loc]  | 
|
763  | 
                # These occur after the current location, which may be in the
 | 
|
764  | 
                # data we read, or might be after the last entry
 | 
|
765  | 
post = cur_dirs[first_loc:]  | 
|
766  | 
||
767  | 
if post and len(first_fields) >= entry_field_count:  | 
|
768  | 
                # We have records to look at after the first entry
 | 
|
769  | 
||
770  | 
                # Parse the last entry
 | 
|
771  | 
last_entry_num = len(entries)-1  | 
|
772  | 
last_fields = entries[last_entry_num].split('\0')  | 
|
773  | 
if len(last_fields) < entry_field_count:  | 
|
774  | 
                    # The very last hunk was not complete,
 | 
|
775  | 
                    # read the previous hunk
 | 
|
776  | 
after = mid + len(block) - len(entries[-1])  | 
|
777  | 
last_entry_num -= 1  | 
|
778  | 
last_fields = entries[last_entry_num].split('\0')  | 
|
779  | 
else:  | 
|
780  | 
after = mid + len(block)  | 
|
781  | 
||
782  | 
last_dir = last_fields[1]  | 
|
| 
2474.1.61
by John Arbash Meinel
 Finish fixing DirState._bisect and the bisect tests  | 
783  | 
last_loc = bisect.bisect_right(post, last_dir)  | 
| 
2255.2.130
by John Arbash Meinel
 Add a very similar function which grabs everything for a particular directory block.  | 
784  | 
|
785  | 
middle_files = post[:last_loc]  | 
|
786  | 
post = post[last_loc:]  | 
|
787  | 
||
788  | 
if middle_files:  | 
|
789  | 
                    # We have files that should occur in this block
 | 
|
790  | 
                    # (>= first, <= last)
 | 
|
791  | 
                    # Either we will find them here, or we can mark them as
 | 
|
792  | 
                    # missing.
 | 
|
793  | 
||
794  | 
if middle_files[0] == first_dir:  | 
|
795  | 
                        # We might need to go before this location
 | 
|
796  | 
pre.append(first_dir)  | 
|
797  | 
if middle_files[-1] == last_dir:  | 
|
798  | 
post.insert(0, last_dir)  | 
|
799  | 
||
800  | 
                    # Find out what paths we have
 | 
|
801  | 
paths = {first_dir:[first_fields]}  | 
|
802  | 
                    # last_dir might == first_dir so we need to be
 | 
|
803  | 
                    # careful if we should append rather than overwrite
 | 
|
804  | 
if last_entry_num != first_entry_num:  | 
|
805  | 
paths.setdefault(last_dir, []).append(last_fields)  | 
|
806  | 
for num in xrange(first_entry_num+1, last_entry_num):  | 
|
807  | 
                        # TODO: jam 20070223 We are already splitting here, so
 | 
|
808  | 
                        #       shouldn't we just split the whole thing rather
 | 
|
809  | 
                        #       than doing the split again in add_one_record?
 | 
|
810  | 
fields = entries[num].split('\0')  | 
|
811  | 
paths.setdefault(fields[1], []).append(fields)  | 
|
812  | 
||
813  | 
for cur_dir in middle_files:  | 
|
814  | 
for fields in paths.get(cur_dir, []):  | 
|
815  | 
                            # offset by 1 because of the opening '\0'
 | 
|
816  | 
                            # consider changing fields_to_entry to avoid the
 | 
|
817  | 
                            # extra list slice
 | 
|
818  | 
entry = fields_to_entry(fields[1:])  | 
|
819  | 
found.setdefault(cur_dir, []).append(entry)  | 
|
820  | 
||
821  | 
            # Now we have split up everything into pre, middle, and post, and
 | 
|
822  | 
            # we have handled everything that fell in 'middle'.
 | 
|
823  | 
            # We add 'post' first, so that we prefer to seek towards the
 | 
|
824  | 
            # beginning, so that we will tend to go as early as we need, and
 | 
|
825  | 
            # then only seek forward after that.
 | 
|
826  | 
if post:  | 
|
827  | 
pending.append((after, high, post))  | 
|
828  | 
if pre:  | 
|
829  | 
pending.append((low, start-1, pre))  | 
|
830  | 
||
| 
2255.2.131
by John Arbash Meinel
 Change the return values for bisect functions so they just return  | 
831  | 
return found  | 
| 
2255.2.130
by John Arbash Meinel
 Add a very similar function which grabs everything for a particular directory block.  | 
832  | 
|
| 
2474.1.58
by John Arbash Meinel
 (broken) Try to properly implement DirState._bisect*  | 
833  | 
def _bisect_recursive(self, paths):  | 
| 
2255.2.132
by John Arbash Meinel
 Implement _bisect_recursive, which uses multiple bisect calls to  | 
834  | 
"""Bisect for entries for all paths and their children.  | 
835  | 
||
836  | 
        This will use bisect to find all records for the supplied paths. It
 | 
|
837  | 
        will then continue to bisect for any records which are marked as
 | 
|
838  | 
        directories. (and renames?)
 | 
|
839  | 
||
840  | 
        :param paths: A sorted list of (dir, name) pairs
 | 
|
841  | 
             eg: [('', 'a'), ('', 'f'), ('a/b', 'c')]
 | 
|
842  | 
        :return: A dictionary mapping (dir, name, file_id) => [tree_info]
 | 
|
843  | 
        """
 | 
|
844  | 
        # Map from (dir, name, file_id) => [tree_info]
 | 
|
845  | 
found = {}  | 
|
846  | 
||
847  | 
found_dir_names = set()  | 
|
848  | 
||
849  | 
        # Directories that have been read
 | 
|
850  | 
processed_dirs = set()  | 
|
851  | 
        # Get the ball rolling with the first bisect for all entries.
 | 
|
| 
2474.1.58
by John Arbash Meinel
 (broken) Try to properly implement DirState._bisect*  | 
852  | 
newly_found = self._bisect(paths)  | 
| 
2255.2.132
by John Arbash Meinel
 Implement _bisect_recursive, which uses multiple bisect calls to  | 
853  | 
|
854  | 
while newly_found:  | 
|
855  | 
            # Directories that need to be read
 | 
|
856  | 
pending_dirs = set()  | 
|
857  | 
paths_to_search = set()  | 
|
858  | 
for entry_list in newly_found.itervalues():  | 
|
859  | 
for dir_name_id, trees_info in entry_list:  | 
|
860  | 
found[dir_name_id] = trees_info  | 
|
861  | 
found_dir_names.add(dir_name_id[:2])  | 
|
862  | 
is_dir = False  | 
|
863  | 
for tree_info in trees_info:  | 
|
864  | 
minikind = tree_info[0]  | 
|
865  | 
if minikind == 'd':  | 
|
866  | 
if is_dir:  | 
|
867  | 
                                # We already processed this one as a directory,
 | 
|
868  | 
                                # we don't need to do the extra work again.
 | 
|
869  | 
                                continue
 | 
|
870  | 
subdir, name, file_id = dir_name_id  | 
|
871  | 
path = osutils.pathjoin(subdir, name)  | 
|
872  | 
is_dir = True  | 
|
873  | 
if path not in processed_dirs:  | 
|
874  | 
pending_dirs.add(path)  | 
|
875  | 
elif minikind == 'r':  | 
|
876  | 
                            # Rename, we need to directly search the target
 | 
|
877  | 
                            # which is contained in the fingerprint column
 | 
|
878  | 
dir_name = osutils.split(tree_info[1])  | 
|
879  | 
if dir_name[0] in pending_dirs:  | 
|
880  | 
                                # This entry will be found in the dir search
 | 
|
881  | 
                                continue
 | 
|
882  | 
if dir_name not in found_dir_names:  | 
|
| 
2474.1.61
by John Arbash Meinel
 Finish fixing DirState._bisect and the bisect tests  | 
883  | 
paths_to_search.add(tree_info[1])  | 
| 
2255.2.132
by John Arbash Meinel
 Implement _bisect_recursive, which uses multiple bisect calls to  | 
884  | 
            # Now we have a list of paths to look for directly, and
 | 
885  | 
            # directory blocks that need to be read.
 | 
|
886  | 
            # newly_found is mixing the keys between (dir, name) and path
 | 
|
887  | 
            # entries, but that is okay, because we only really care about the
 | 
|
888  | 
            # targets.
 | 
|
889  | 
newly_found = self._bisect(sorted(paths_to_search))  | 
|
890  | 
newly_found.update(self._bisect_dirblocks(sorted(pending_dirs)))  | 
|
891  | 
processed_dirs.update(pending_dirs)  | 
|
892  | 
return found  | 
|
893  | 
||
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
894  | 
def _discard_merge_parents(self):  | 
895  | 
"""Discard any parents trees beyond the first.  | 
|
896  | 
        
 | 
|
897  | 
        Note that if this fails the dirstate is corrupted.
 | 
|
898  | 
||
899  | 
        After this function returns the dirstate contains 2 trees, neither of
 | 
|
900  | 
        which are ghosted.
 | 
|
901  | 
        """
 | 
|
902  | 
self._read_header_if_needed()  | 
|
903  | 
parents = self.get_parent_ids()  | 
|
904  | 
if len(parents) < 1:  | 
|
905  | 
            return
 | 
|
906  | 
        # only require all dirblocks if we are doing a full-pass removal.
 | 
|
907  | 
self._read_dirblocks_if_needed()  | 
|
908  | 
dead_patterns = set([('a', 'r'), ('a', 'a'), ('r', 'r'), ('r', 'a')])  | 
|
909  | 
def iter_entries_removable():  | 
|
910  | 
for block in self._dirblocks:  | 
|
911  | 
deleted_positions = []  | 
|
912  | 
for pos, entry in enumerate(block[1]):  | 
|
913  | 
yield entry  | 
|
914  | 
if (entry[1][0][0], entry[1][1][0]) in dead_patterns:  | 
|
915  | 
deleted_positions.append(pos)  | 
|
916  | 
if deleted_positions:  | 
|
| 
2984.1.1
by John Arbash Meinel
 Fix bug #161131: Correct DirState._discard_merge_parents logic.  | 
917  | 
if len(deleted_positions) == len(block[1]):  | 
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
918  | 
del block[1][:]  | 
919  | 
else:  | 
|
920  | 
for pos in reversed(deleted_positions):  | 
|
921  | 
del block[1][pos]  | 
|
922  | 
        # if the first parent is a ghost:
 | 
|
923  | 
if parents[0] in self.get_ghosts():  | 
|
924  | 
empty_parent = [DirState.NULL_PARENT_DETAILS]  | 
|
925  | 
for entry in iter_entries_removable():  | 
|
926  | 
entry[1][1:] = empty_parent  | 
|
927  | 
else:  | 
|
928  | 
for entry in iter_entries_removable():  | 
|
929  | 
del entry[1][2:]  | 
|
930  | 
||
931  | 
self._ghosts = []  | 
|
932  | 
self._parents = [parents[0]]  | 
|
933  | 
self._dirblock_state = DirState.IN_MEMORY_MODIFIED  | 
|
934  | 
self._header_state = DirState.IN_MEMORY_MODIFIED  | 
|
935  | 
||
| 
2255.2.75
by Robert Collins
 Correct generation of revisiontree inventories to handle out of order parents.  | 
936  | 
def _empty_parent_info(self):  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
937  | 
return [DirState.NULL_PARENT_DETAILS] * (len(self._parents) -  | 
| 
2255.2.75
by Robert Collins
 Correct generation of revisiontree inventories to handle out of order parents.  | 
938  | 
len(self._ghosts))  | 
939  | 
||
| 
2255.2.59
by Robert Collins
 All WorkingTree4 and dirstate tests passing.  | 
940  | 
def _ensure_block(self, parent_block_index, parent_row_index, dirname):  | 
| 
2255.2.138
by John Arbash Meinel
 implement several new WorkingTree.move() tests  | 
941  | 
"""Ensure a block for dirname exists.  | 
942  | 
||
| 
2255.2.59
by Robert Collins
 All WorkingTree4 and dirstate tests passing.  | 
943  | 
        This function exists to let callers which know that there is a
 | 
944  | 
        directory dirname ensure that the block for it exists. This block can
 | 
|
945  | 
        fail to exist because of demand loading, or because a directory had no
 | 
|
946  | 
        children. In either case it is not an error. It is however an error to
 | 
|
947  | 
        call this if there is no parent entry for the directory, and thus the
 | 
|
948  | 
        function requires the coordinates of such an entry to be provided.
 | 
|
949  | 
||
950  | 
        The root row is special cased and can be indicated with a parent block
 | 
|
951  | 
        and row index of -1
 | 
|
952  | 
||
953  | 
        :param parent_block_index: The index of the block in which dirname's row
 | 
|
954  | 
            exists.
 | 
|
955  | 
        :param parent_row_index: The index in the parent block where the row
 | 
|
956  | 
            exists.
 | 
|
957  | 
        :param dirname: The utf8 dirname to ensure there is a block for.
 | 
|
958  | 
        :return: The index for the block.
 | 
|
959  | 
        """
 | 
|
| 
2255.2.138
by John Arbash Meinel
 implement several new WorkingTree.move() tests  | 
960  | 
if dirname == '' and parent_row_index == 0 and parent_block_index == 0:  | 
961  | 
            # This is the signature of the root row, and the
 | 
|
962  | 
            # contents-of-root row is always index 1
 | 
|
963  | 
return 1  | 
|
| 
2255.2.59
by Robert Collins
 All WorkingTree4 and dirstate tests passing.  | 
964  | 
        # the basename of the directory must be the end of its full name.
 | 
965  | 
if not (parent_block_index == -1 and  | 
|
966  | 
parent_block_index == -1 and dirname == ''):  | 
|
967  | 
assert dirname.endswith(  | 
|
968  | 
self._dirblocks[parent_block_index][1][parent_row_index][0][1])  | 
|
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
969  | 
block_index, present = self._find_block_index_from_key((dirname, '', ''))  | 
970  | 
if not present:  | 
|
971  | 
            ## In future, when doing partial parsing, this should load and 
 | 
|
972  | 
            # populate the entire block.
 | 
|
973  | 
self._dirblocks.insert(block_index, (dirname, []))  | 
|
974  | 
return block_index  | 
|
| 
2255.2.59
by Robert Collins
 All WorkingTree4 and dirstate tests passing.  | 
975  | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
976  | 
def _entries_to_current_state(self, new_entries):  | 
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
977  | 
"""Load new_entries into self.dirblocks.  | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
978  | 
|
979  | 
        Process new_entries into the current state object, making them the active
 | 
|
| 
2255.7.94
by Martin Pool
 Fix dirstate sorting bug and refine the _validate() assertions:  | 
980  | 
        state.  The entries are grouped together by directory to form dirblocks.
 | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
981  | 
|
982  | 
        :param new_entries: A sorted list of entries. This function does not sort
 | 
|
983  | 
            to prevent unneeded overhead when callers have a sorted list already.
 | 
|
984  | 
        :return: Nothing.
 | 
|
985  | 
        """
 | 
|
986  | 
assert new_entries[0][0][0:2] == ('', ''), \  | 
|
| 
2255.7.21
by John Arbash Meinel
 Get iter_changes working again, by fixing set_parent_trees to  | 
987  | 
"Missing root row %r" % (new_entries[0][0],)  | 
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
988  | 
        # The two blocks here are deliberate: the root block and the 
 | 
989  | 
        # contents-of-root block.
 | 
|
990  | 
self._dirblocks = [('', []), ('', [])]  | 
|
991  | 
current_block = self._dirblocks[0][1]  | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
992  | 
current_dirname = ''  | 
993  | 
root_key = ('', '')  | 
|
| 
2255.2.112
by John Arbash Meinel
 610ms: Optimizing _entries_to_current state brings the 'slow path' down to 610 ms (inlined and uglier fast path is 570-580ms)  | 
994  | 
append_entry = current_block.append  | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
995  | 
for entry in new_entries:  | 
996  | 
if entry[0][0] != current_dirname:  | 
|
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
997  | 
                # new block - different dirname
 | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
998  | 
current_block = []  | 
| 
2255.2.90
by Robert Collins
 Correct DirState._entries_to_current_state to group entries by directory properly.  | 
999  | 
current_dirname = entry[0][0]  | 
1000  | 
self._dirblocks.append((current_dirname, current_block))  | 
|
| 
2255.2.112
by John Arbash Meinel
 610ms: Optimizing _entries_to_current state brings the 'slow path' down to 610 ms (inlined and uglier fast path is 570-580ms)  | 
1001  | 
append_entry = current_block.append  | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1002  | 
            # append the entry to the current block
 | 
| 
2255.2.112
by John Arbash Meinel
 610ms: Optimizing _entries_to_current state brings the 'slow path' down to 610 ms (inlined and uglier fast path is 570-580ms)  | 
1003  | 
append_entry(entry)  | 
1004  | 
self._split_root_dirblock_into_contents()  | 
|
1005  | 
||
1006  | 
def _split_root_dirblock_into_contents(self):  | 
|
1007  | 
"""Split the root dirblocks into root and contents-of-root.  | 
|
1008  | 
||
1009  | 
        After parsing by path, we end up with root entries and contents-of-root
 | 
|
1010  | 
        entries in the same block. This loop splits them out again.
 | 
|
1011  | 
        """
 | 
|
1012  | 
        # The above loop leaves the "root block" entries mixed with the
 | 
|
1013  | 
        # "contents-of-root block". But we don't want an if check on
 | 
|
1014  | 
        # all entries, so instead we just fix it up here.
 | 
|
1015  | 
assert self._dirblocks[1] == ('', [])  | 
|
1016  | 
root_block = []  | 
|
1017  | 
contents_of_root_block = []  | 
|
1018  | 
for entry in self._dirblocks[0][1]:  | 
|
1019  | 
if not entry[0][1]: # This is a root entry  | 
|
1020  | 
root_block.append(entry)  | 
|
1021  | 
else:  | 
|
1022  | 
contents_of_root_block.append(entry)  | 
|
1023  | 
self._dirblocks[0] = ('', root_block)  | 
|
1024  | 
self._dirblocks[1] = ('', contents_of_root_block)  | 
|
1025  | 
||
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1026  | 
def _entry_to_line(self, entry):  | 
1027  | 
"""Serialize entry to a NULL delimited line ready for _get_output_lines.  | 
|
| 
2255.10.1
by John Arbash Meinel
 Update WorkingTree4 so that it doesn't use a HashCache,  | 
1028  | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1029  | 
        :param entry: An entry_tuple as defined in the module docstring.
 | 
1030  | 
        """
 | 
|
1031  | 
entire_entry = list(entry[0])  | 
|
1032  | 
for tree_number, tree_data in enumerate(entry[1]):  | 
|
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
1033  | 
            # (minikind, fingerprint, size, executable, tree_specific_string)
 | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1034  | 
entire_entry.extend(tree_data)  | 
1035  | 
            # 3 for the key, 5 for the fields per tree.
 | 
|
1036  | 
tree_offset = 3 + tree_number * 5  | 
|
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
1037  | 
            # minikind
 | 
1038  | 
entire_entry[tree_offset + 0] = tree_data[0]  | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1039  | 
            # size
 | 
1040  | 
entire_entry[tree_offset + 2] = str(tree_data[2])  | 
|
1041  | 
            # executable
 | 
|
1042  | 
entire_entry[tree_offset + 3] = DirState._to_yesno[tree_data[3]]  | 
|
1043  | 
return '\0'.join(entire_entry)  | 
|
1044  | 
||
| 
2255.2.126
by John Arbash Meinel
 Switch the bisect code to support the fact that we can have  | 
1045  | 
def _fields_per_entry(self):  | 
| 
2255.3.1
by John Arbash Meinel
 Rewrite the inner parsing loop, needs performance testing.  | 
1046  | 
"""How many null separated fields should be in each entry row.  | 
1047  | 
||
1048  | 
        Each line now has an extra '\n' field which is not used
 | 
|
1049  | 
        so we just skip over it
 | 
|
1050  | 
        entry size:
 | 
|
1051  | 
            3 fields for the key
 | 
|
1052  | 
            + number of fields per tree_data (5) * tree count
 | 
|
1053  | 
            + newline
 | 
|
1054  | 
         """
 | 
|
1055  | 
tree_count = 1 + self._num_present_parents()  | 
|
1056  | 
return 3 + 5 * tree_count + 1  | 
|
1057  | 
||
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
1058  | 
def _find_block(self, key, add_if_missing=False):  | 
1059  | 
"""Return the block that key should be present in.  | 
|
1060  | 
||
1061  | 
        :param key: A dirstate entry key.
 | 
|
1062  | 
        :return: The block tuple.
 | 
|
1063  | 
        """
 | 
|
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
1064  | 
block_index, present = self._find_block_index_from_key(key)  | 
1065  | 
if not present:  | 
|
| 
2255.2.99
by Robert Collins
 Dirstate - fix _find_block to create missing blocks when the parent is versioned in the current tree, and fix handling of relocated entries in _make_absent.  | 
1066  | 
if not add_if_missing:  | 
1067  | 
                # check to see if key is versioned itself - we might want to
 | 
|
1068  | 
                # add it anyway, because dirs with no entries dont get a
 | 
|
1069  | 
                # dirblock at parse time.
 | 
|
1070  | 
                # This is an uncommon branch to take: most dirs have children,
 | 
|
1071  | 
                # and most code works with versioned paths.
 | 
|
| 
2255.2.146
by John Arbash Meinel
 Implement move_directory by factoring out move_one  | 
1072  | 
parent_base, parent_name = osutils.split(key[0])  | 
| 
2255.2.99
by Robert Collins
 Dirstate - fix _find_block to create missing blocks when the parent is versioned in the current tree, and fix handling of relocated entries in _make_absent.  | 
1073  | 
if not self._get_block_entry_index(parent_base, parent_name, 0)[3]:  | 
1074  | 
                    # some parent path has not been added - its an error to add
 | 
|
1075  | 
                    # this child
 | 
|
1076  | 
raise errors.NotVersionedError(key[0:2], str(self))  | 
|
1077  | 
self._dirblocks.insert(block_index, (key[0], []))  | 
|
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
1078  | 
return self._dirblocks[block_index]  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
1079  | 
|
1080  | 
def _find_block_index_from_key(self, key):  | 
|
1081  | 
"""Find the dirblock index for a key.  | 
|
1082  | 
||
1083  | 
        :return: The block index, True if the block for the key is present.
 | 
|
1084  | 
        """
 | 
|
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
1085  | 
if key[0:2] == ('', ''):  | 
1086  | 
return 0, True  | 
|
| 
2921.1.1
by Robert Collins
 Add a cache for dirstate entry lookups.  | 
1087  | 
try:  | 
1088  | 
if (self._last_block_index is not None and  | 
|
1089  | 
self._dirblocks[self._last_block_index][0] == key[0]):  | 
|
1090  | 
return self._last_block_index, True  | 
|
1091  | 
except IndexError:  | 
|
1092  | 
            pass
 | 
|
| 
2255.7.20
by John Arbash Meinel
 update test for format 3, and enable caching of path split while lock is held.  | 
1093  | 
block_index = bisect_dirblock(self._dirblocks, key[0], 1,  | 
1094  | 
cache=self._split_path_cache)  | 
|
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
1095  | 
        # _right returns one-past-where-key is so we have to subtract
 | 
1096  | 
        # one to use it. we use _right here because there are two
 | 
|
1097  | 
        # '' blocks - the root, and the contents of root
 | 
|
1098  | 
        # we always have a minimum of 2 in self._dirblocks: root and
 | 
|
1099  | 
        # root-contents, and for '', we get 2 back, so this is 
 | 
|
1100  | 
        # simple and correct:
 | 
|
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
1101  | 
present = (block_index < len(self._dirblocks) and  | 
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
1102  | 
self._dirblocks[block_index][0] == key[0])  | 
| 
2921.1.1
by Robert Collins
 Add a cache for dirstate entry lookups.  | 
1103  | 
self._last_block_index = block_index  | 
| 
2921.1.4
by Robert Collins
 Documentation to aid our failing memory in the future.  | 
1104  | 
        # Reset the entry index cache to the beginning of the block.
 | 
| 
2921.1.2
by Robert Collins
 Reset the dirstate cache pointer for the entry on lookup of a new block, suggested by John.  | 
1105  | 
self._last_entry_index = -1  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
1106  | 
return block_index, present  | 
1107  | 
||
1108  | 
def _find_entry_index(self, key, block):  | 
|
1109  | 
"""Find the entry index for a key in a block.  | 
|
1110  | 
||
1111  | 
        :return: The entry index, True if the entry for the key is present.
 | 
|
1112  | 
        """
 | 
|
| 
2921.1.1
by Robert Collins
 Add a cache for dirstate entry lookups.  | 
1113  | 
len_block = len(block)  | 
1114  | 
try:  | 
|
1115  | 
if self._last_entry_index is not None:  | 
|
1116  | 
                # mini-bisect here.
 | 
|
1117  | 
entry_index = self._last_entry_index + 1  | 
|
1118  | 
                # A hit is when the key is after the last slot, and before or
 | 
|
1119  | 
                # equal to the next slot.
 | 
|
| 
2921.1.2
by Robert Collins
 Reset the dirstate cache pointer for the entry on lookup of a new block, suggested by John.  | 
1120  | 
if ((entry_index > 0 and block[entry_index - 1][0] < key) and  | 
| 
2921.1.1
by Robert Collins
 Add a cache for dirstate entry lookups.  | 
1121  | 
key <= block[entry_index][0]):  | 
1122  | 
self._last_entry_index = entry_index  | 
|
| 
2921.1.3
by Robert Collins
 Review feedback.  | 
1123  | 
present = (block[entry_index][0] == key)  | 
| 
2921.1.1
by Robert Collins
 Add a cache for dirstate entry lookups.  | 
1124  | 
return entry_index, present  | 
1125  | 
except IndexError:  | 
|
1126  | 
            pass
 | 
|
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
1127  | 
entry_index = bisect.bisect_left(block, (key, []))  | 
| 
2921.1.1
by Robert Collins
 Add a cache for dirstate entry lookups.  | 
1128  | 
present = (entry_index < len_block and  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
1129  | 
block[entry_index][0] == key)  | 
| 
2921.1.1
by Robert Collins
 Add a cache for dirstate entry lookups.  | 
1130  | 
self._last_entry_index = entry_index  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
1131  | 
return entry_index, present  | 
1132  | 
||
| 
1852.13.6
by Robert Collins
 start hooking in the prototype dirstate serialiser.  | 
1133  | 
    @staticmethod
 | 
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1134  | 
def from_tree(tree, dir_state_filename):  | 
| 
1852.13.10
by Robert Collins
 Use just the tree api to generate dirstate information.  | 
1135  | 
"""Create a dirstate from a bzr Tree.  | 
| 
1852.13.6
by Robert Collins
 start hooking in the prototype dirstate serialiser.  | 
1136  | 
|
1137  | 
        :param tree: The tree which should provide parent information and
 | 
|
1138  | 
            inventory ids.
 | 
|
| 
2255.5.1
by John Arbash Meinel
 Update the dirstate tests to lock and unlock properly.  | 
1139  | 
        :return: a DirState object which is currently locked for writing.
 | 
1140  | 
            (it was locked by DirState.initialize)
 | 
|
| 
1852.13.6
by Robert Collins
 start hooking in the prototype dirstate serialiser.  | 
1141  | 
        """
 | 
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
1142  | 
result = DirState.initialize(dir_state_filename)  | 
| 
2255.5.1
by John Arbash Meinel
 Update the dirstate tests to lock and unlock properly.  | 
1143  | 
try:  | 
1144  | 
tree.lock_read()  | 
|
1145  | 
try:  | 
|
1146  | 
parent_ids = tree.get_parent_ids()  | 
|
1147  | 
num_parents = len(parent_ids)  | 
|
1148  | 
parent_trees = []  | 
|
1149  | 
for parent_id in parent_ids:  | 
|
1150  | 
parent_tree = tree.branch.repository.revision_tree(parent_id)  | 
|
1151  | 
parent_trees.append((parent_id, parent_tree))  | 
|
1152  | 
parent_tree.lock_read()  | 
|
1153  | 
result.set_parent_trees(parent_trees, [])  | 
|
1154  | 
result.set_state_from_inventory(tree.inventory)  | 
|
1155  | 
finally:  | 
|
1156  | 
for revid, parent_tree in parent_trees:  | 
|
1157  | 
parent_tree.unlock()  | 
|
1158  | 
tree.unlock()  | 
|
1159  | 
except:  | 
|
1160  | 
            # The caller won't have a chance to unlock this, so make sure we
 | 
|
1161  | 
            # cleanup ourselves
 | 
|
1162  | 
result.unlock()  | 
|
1163  | 
            raise
 | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1164  | 
return result  | 
1165  | 
||
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1166  | 
def update_basis_by_delta(self, delta, new_revid):  | 
1167  | 
"""Update the parents of this tree after a commit.  | 
|
1168  | 
||
1169  | 
        This gives the tree one parent, with revision id new_revid. The
 | 
|
1170  | 
        inventory delta is applied to the current basis tree to generate the
 | 
|
1171  | 
        inventory for the parent new_revid, and all other parent trees are
 | 
|
1172  | 
        discarded.
 | 
|
1173  | 
||
1174  | 
        Note that an exception during the operation of this method will leave
 | 
|
1175  | 
        the dirstate in a corrupt state where it should not be saved.
 | 
|
1176  | 
||
1177  | 
        Finally, we expect all changes to be synchronising the basis tree with
 | 
|
1178  | 
        the working tree.
 | 
|
1179  | 
||
1180  | 
        :param new_revid: The new revision id for the trees parent.
 | 
|
1181  | 
        :param delta: An inventory delta (see apply_inventory_delta) describing
 | 
|
1182  | 
            the changes from the current left most parent revision to new_revid.
 | 
|
1183  | 
        """
 | 
|
1184  | 
self._read_dirblocks_if_needed()  | 
|
1185  | 
self._discard_merge_parents()  | 
|
1186  | 
if self._ghosts != []:  | 
|
1187  | 
raise NotImplementedError(self.update_basis_by_delta)  | 
|
1188  | 
if len(self._parents) == 0:  | 
|
1189  | 
            # setup a blank tree, the most simple way.
 | 
|
1190  | 
empty_parent = DirState.NULL_PARENT_DETAILS  | 
|
1191  | 
for entry in self._iter_entries():  | 
|
1192  | 
entry[1].append(empty_parent)  | 
|
1193  | 
self._parents.append(new_revid)  | 
|
1194  | 
||
1195  | 
self._parents[0] = new_revid  | 
|
1196  | 
||
1197  | 
delta = sorted(delta, reverse=True)  | 
|
1198  | 
adds = []  | 
|
1199  | 
changes = []  | 
|
1200  | 
deletes = []  | 
|
1201  | 
        # The paths this function accepts are unicode and must be encoded as we
 | 
|
1202  | 
        # go.
 | 
|
1203  | 
encode = cache_utf8.encode  | 
|
1204  | 
inv_to_entry = self._inv_entry_to_details  | 
|
1205  | 
        # delta is now (deletes, changes), (adds) in reverse lexographical
 | 
|
1206  | 
        # order.
 | 
|
1207  | 
        # deletes in reverse lexographic order are safe to process in situ.
 | 
|
1208  | 
        # renames are not, as a rename from any path could go to a path
 | 
|
1209  | 
        # lexographically lower, so we transform renames into delete, add pairs,
 | 
|
1210  | 
        # expanding them recursively as needed.
 | 
|
1211  | 
        # At the same time, to reduce interface friction we convert the input
 | 
|
1212  | 
        # inventory entries to dirstate.
 | 
|
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
1213  | 
root_only = ('', '')  | 
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1214  | 
for old_path, new_path, file_id, inv_entry in delta:  | 
1215  | 
if old_path is None:  | 
|
1216  | 
adds.append((None, encode(new_path), file_id,  | 
|
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
1217  | 
inv_to_entry(inv_entry), True))  | 
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1218  | 
elif new_path is None:  | 
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
1219  | 
deletes.append((encode(old_path), None, file_id, None, True))  | 
1220  | 
elif (old_path, new_path) != root_only:  | 
|
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1221  | 
                # Renames:
 | 
1222  | 
                # Because renames must preserve their children we must have
 | 
|
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
1223  | 
                # processed all relocations and removes before hand. The sort
 | 
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1224  | 
                # order ensures we've examined the child paths, but we also
 | 
1225  | 
                # have to execute the removals, or the split to an add/delete
 | 
|
1226  | 
                # pair will result in the deleted item being reinserted, or
 | 
|
1227  | 
                # renamed items being reinserted twice - and possibly at the
 | 
|
1228  | 
                # wrong place. Splitting into a delete/add pair also simplifies
 | 
|
1229  | 
                # the handling of entries with ('f', ...), ('r' ...) because
 | 
|
1230  | 
                # the target of the 'r' is old_path here, and we add that to
 | 
|
1231  | 
                # deletes, meaning that the add handler does not need to check
 | 
|
1232  | 
                # for 'r' items on every pass.
 | 
|
1233  | 
self._update_basis_apply_deletes(deletes)  | 
|
1234  | 
deletes = []  | 
|
1235  | 
new_path_utf8 = encode(new_path)  | 
|
1236  | 
                # Split into an add/delete pair recursively.
 | 
|
1237  | 
adds.append((None, new_path_utf8, file_id,  | 
|
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
1238  | 
inv_to_entry(inv_entry), False))  | 
1239  | 
                # Expunge deletes that we've seen so that deleted/renamed
 | 
|
1240  | 
                # children of a rename directory are handled correctly.
 | 
|
1241  | 
new_deletes = reversed(list(self._iter_child_entries(1,  | 
|
1242  | 
encode(old_path))))  | 
|
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1243  | 
                # Remove the current contents of the tree at orig_path, and
 | 
1244  | 
                # reinsert at the correct new path.
 | 
|
1245  | 
for entry in new_deletes:  | 
|
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
1246  | 
if entry[0][0]:  | 
1247  | 
source_path = entry[0][0] + '/' + entry[0][1]  | 
|
1248  | 
else:  | 
|
1249  | 
source_path = entry[0][1]  | 
|
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1250  | 
target_path = new_path_utf8 + source_path[len(old_path):]  | 
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
1251  | 
adds.append((None, target_path, entry[0][2], entry[1][1], False))  | 
1252  | 
deletes.append(  | 
|
1253  | 
(source_path, target_path, entry[0][2], None, False))  | 
|
1254  | 
deletes.append(  | 
|
1255  | 
(encode(old_path), new_path, file_id, None, False))  | 
|
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1256  | 
else:  | 
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
1257  | 
                # changes to just the root should not require remove/insertion
 | 
1258  | 
                # of everything.
 | 
|
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1259  | 
changes.append((encode(old_path), encode(new_path), file_id,  | 
1260  | 
inv_to_entry(inv_entry)))  | 
|
1261  | 
||
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
1262  | 
        # Finish expunging deletes/first half of renames.
 | 
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1263  | 
self._update_basis_apply_deletes(deletes)  | 
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
1264  | 
        # Reinstate second half of renames and new paths.
 | 
1265  | 
self._update_basis_apply_adds(adds)  | 
|
1266  | 
        # Apply in-situ changes.
 | 
|
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1267  | 
self._update_basis_apply_changes(changes)  | 
1268  | 
||
1269  | 
self._dirblock_state = DirState.IN_MEMORY_MODIFIED  | 
|
1270  | 
self._header_state = DirState.IN_MEMORY_MODIFIED  | 
|
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
1271  | 
self._id_index = None  | 
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1272  | 
        return
 | 
1273  | 
||
1274  | 
def _update_basis_apply_adds(self, adds):  | 
|
1275  | 
"""Apply a sequence of adds to tree 1 during update_basis_by_delta.  | 
|
1276  | 
||
1277  | 
        They may be adds, or renames that have been split into add/delete
 | 
|
1278  | 
        pairs.
 | 
|
1279  | 
||
1280  | 
        :param adds: A sequence of adds. Each add is a tuple:
 | 
|
| 
2929.2.3
by Robert Collins
 Review feedback.  | 
1281  | 
            (None, new_path_utf8, file_id, (entry_details), real_add). real_add
 | 
1282  | 
            is False when the add is the second half of a remove-and-reinsert
 | 
|
1283  | 
            pair created to handle renames and deletes.
 | 
|
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1284  | 
        """
 | 
1285  | 
        # Adds are accumulated partly from renames, so can be in any input
 | 
|
1286  | 
        # order - sort it.
 | 
|
1287  | 
adds.sort()  | 
|
1288  | 
        # adds is now in lexographic order, which places all parents before
 | 
|
1289  | 
        # their children, so we can process it linearly.
 | 
|
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
1290  | 
absent = 'ar'  | 
1291  | 
for old_path, new_path, file_id, new_details, real_add in adds:  | 
|
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1292  | 
assert old_path is None  | 
1293  | 
            # the entry for this file_id must be in tree 0.
 | 
|
1294  | 
entry = self._get_entry(0, file_id, new_path)  | 
|
1295  | 
if entry[0][2] != file_id:  | 
|
1296  | 
raise errors.BzrError('dirstate: cannot apply delta, working'  | 
|
1297  | 
' tree does not contain new entry %r %r' %  | 
|
1298  | 
(new_path, file_id))  | 
|
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
1299  | 
if real_add and entry[1][1][0] not in absent:  | 
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1300  | 
raise errors.BzrError('dirstate: inconsistent delta, with '  | 
1301  | 
'tree 0. %r %r' % (new_path, file_id))  | 
|
1302  | 
            # We don't need to update the target of an 'r' because the handling
 | 
|
1303  | 
            # of renames turns all 'r' situations into a delete at the original
 | 
|
1304  | 
            # location.
 | 
|
1305  | 
entry[1][1] = new_details  | 
|
1306  | 
||
1307  | 
def _update_basis_apply_changes(self, changes):  | 
|
1308  | 
"""Apply a sequence of changes to tree 1 during update_basis_by_delta.  | 
|
1309  | 
||
1310  | 
        :param adds: A sequence of changes. Each change is a tuple:
 | 
|
1311  | 
            (path_utf8, path_utf8, file_id, (entry_details))
 | 
|
1312  | 
        """
 | 
|
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
1313  | 
absent = 'ar'  | 
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1314  | 
for old_path, new_path, file_id, new_details in changes:  | 
1315  | 
assert old_path == new_path  | 
|
1316  | 
            # the entry for this file_id must be in tree 0.
 | 
|
1317  | 
entry = self._get_entry(0, file_id, new_path)  | 
|
1318  | 
if entry[0][2] != file_id:  | 
|
1319  | 
raise errors.BzrError('dirstate: cannot apply delta, working'  | 
|
1320  | 
' tree does not contain new entry %r %r' %  | 
|
1321  | 
(new_path, file_id))  | 
|
1322  | 
if (entry[1][0][0] in absent or  | 
|
1323  | 
entry[1][1][0] in absent):  | 
|
1324  | 
raise errors.BzrError('dirstate: inconsistent delta, with '  | 
|
1325  | 
'tree 0. %r %r' % (new_path, file_id))  | 
|
1326  | 
entry[1][1] = new_details  | 
|
1327  | 
||
1328  | 
def _update_basis_apply_deletes(self, deletes):  | 
|
1329  | 
"""Apply a sequence of deletes to tree 1 during update_basis_by_delta.  | 
|
1330  | 
||
1331  | 
        They may be deletes, or renames that have been split into add/delete
 | 
|
1332  | 
        pairs.
 | 
|
1333  | 
||
| 
2929.2.3
by Robert Collins
 Review feedback.  | 
1334  | 
        :param deletes: A sequence of deletes. Each delete is a tuple:
 | 
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
1335  | 
            (old_path_utf8, new_path_utf8, file_id, None, real_delete).
 | 
1336  | 
            real_delete is True when the desired outcome is an actual deletion
 | 
|
1337  | 
            rather than the rename handling logic temporarily deleting a path
 | 
|
1338  | 
            during the replacement of a parent.
 | 
|
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1339  | 
        """
 | 
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
1340  | 
null = DirState.NULL_PARENT_DETAILS  | 
1341  | 
for old_path, new_path, file_id, _, real_delete in deletes:  | 
|
1342  | 
if real_delete:  | 
|
1343  | 
assert new_path is None  | 
|
1344  | 
else:  | 
|
1345  | 
assert new_path is not None  | 
|
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1346  | 
            # the entry for this file_id must be in tree 1.
 | 
1347  | 
dirname, basename = osutils.split(old_path)  | 
|
1348  | 
block_index, entry_index, dir_present, file_present = \  | 
|
1349  | 
self._get_block_entry_index(dirname, basename, 1)  | 
|
1350  | 
if not file_present:  | 
|
1351  | 
raise errors.BzrError('dirstate: cannot apply delta, basis'  | 
|
1352  | 
' tree does not contain new entry %r %r' %  | 
|
1353  | 
(old_path, file_id))  | 
|
1354  | 
entry = self._dirblocks[block_index][1][entry_index]  | 
|
1355  | 
if entry[0][2] != file_id:  | 
|
1356  | 
raise errors.BzrError('mismatched file_id in tree 1 %r %r' %  | 
|
1357  | 
(old_path, file_id))  | 
|
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
1358  | 
if real_delete:  | 
1359  | 
if entry[1][0][0] != 'a':  | 
|
1360  | 
raise errors.BzrError('dirstate: inconsistent delta, with '  | 
|
1361  | 
'tree 0. %r %r' % (old_path, file_id))  | 
|
1362  | 
del self._dirblocks[block_index][1][entry_index]  | 
|
1363  | 
else:  | 
|
1364  | 
if entry[1][0][0] == 'a':  | 
|
1365  | 
raise errors.BzrError('dirstate: inconsistent delta, with '  | 
|
1366  | 
'tree 0. %r %r' % (old_path, file_id))  | 
|
1367  | 
elif entry[1][0][0] == 'r':  | 
|
1368  | 
                    # implement the rename
 | 
|
1369  | 
del self._dirblocks[block_index][1][entry_index]  | 
|
1370  | 
else:  | 
|
1371  | 
                    # it is being resurrected here, so blank it out temporarily.
 | 
|
1372  | 
self._dirblocks[block_index][1][entry_index][1][1] = null  | 
|
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1373  | 
|
| 
2485.3.3
by John Arbash Meinel
 Avoid extra work in inner 'DirState.update_entry' code.  | 
1374  | 
def update_entry(self, entry, abspath, stat_value,  | 
1375  | 
_stat_to_minikind=_stat_to_minikind,  | 
|
1376  | 
_pack_stat=pack_stat):  | 
|
| 
2255.10.3
by John Arbash Meinel
 (broken) Change get_sha1_for_entry into update_entry  | 
1377  | 
"""Update the entry based on what is actually on disk.  | 
| 
2255.10.1
by John Arbash Meinel
 Update WorkingTree4 so that it doesn't use a HashCache,  | 
1378  | 
|
1379  | 
        :param entry: This is the dirblock entry for the file in question.
 | 
|
1380  | 
        :param abspath: The path on disk for this file.
 | 
|
1381  | 
        :param stat_value: (optional) if we already have done a stat on the
 | 
|
1382  | 
            file, re-use it.
 | 
|
| 
2255.10.3
by John Arbash Meinel
 (broken) Change get_sha1_for_entry into update_entry  | 
1383  | 
        :return: The sha1 hexdigest of the file (40 bytes) or link target of a
 | 
1384  | 
                symlink.
 | 
|
| 
2255.10.1
by John Arbash Meinel
 Update WorkingTree4 so that it doesn't use a HashCache,  | 
1385  | 
        """
 | 
| 
2255.10.3
by John Arbash Meinel
 (broken) Change get_sha1_for_entry into update_entry  | 
1386  | 
try:  | 
| 
2485.3.3
by John Arbash Meinel
 Avoid extra work in inner 'DirState.update_entry' code.  | 
1387  | 
minikind = _stat_to_minikind[stat_value.st_mode & 0170000]  | 
1388  | 
except KeyError:  | 
|
1389  | 
            # Unhandled kind
 | 
|
| 
2255.10.2
by John Arbash Meinel
 Update to dirstate locking.  | 
1390  | 
return None  | 
| 
2485.3.3
by John Arbash Meinel
 Avoid extra work in inner 'DirState.update_entry' code.  | 
1391  | 
packed_stat = _pack_stat(stat_value)  | 
| 
2255.10.3
by John Arbash Meinel
 (broken) Change get_sha1_for_entry into update_entry  | 
1392  | 
(saved_minikind, saved_link_or_sha1, saved_file_size,  | 
1393  | 
saved_executable, saved_packed_stat) = entry[1][0]  | 
|
1394  | 
||
1395  | 
if (minikind == saved_minikind  | 
|
| 
2485.3.1
by John Arbash Meinel
 Fix DirState handling of dir records.  | 
1396  | 
and packed_stat == saved_packed_stat):  | 
| 
2485.3.11
by John Arbash Meinel
 Correct DirState.update_entry to check when caching the sha1  | 
1397  | 
            # The stat hasn't changed since we saved, so we can re-use the
 | 
1398  | 
            # saved sha hash.
 | 
|
| 
2255.10.5
by John Arbash Meinel
 Fix a small bug when we have a symlink that does not need to be re-read.  | 
1399  | 
if minikind == 'd':  | 
| 
2255.10.3
by John Arbash Meinel
 (broken) Change get_sha1_for_entry into update_entry  | 
1400  | 
return None  | 
1401  | 
||
| 
2485.3.1
by John Arbash Meinel
 Fix DirState handling of dir records.  | 
1402  | 
            # size should also be in packed_stat
 | 
| 
2485.3.3
by John Arbash Meinel
 Avoid extra work in inner 'DirState.update_entry' code.  | 
1403  | 
if saved_file_size == stat_value.st_size:  | 
| 
2485.3.11
by John Arbash Meinel
 Correct DirState.update_entry to check when caching the sha1  | 
1404  | 
return saved_link_or_sha1  | 
| 
2255.10.3
by John Arbash Meinel
 (broken) Change get_sha1_for_entry into update_entry  | 
1405  | 
|
| 
2255.10.1
by John Arbash Meinel
 Update WorkingTree4 so that it doesn't use a HashCache,  | 
1406  | 
        # If we have gotten this far, that means that we need to actually
 | 
| 
2255.10.3
by John Arbash Meinel
 (broken) Change get_sha1_for_entry into update_entry  | 
1407  | 
        # process this entry.
 | 
1408  | 
link_or_sha1 = None  | 
|
1409  | 
if minikind == 'f':  | 
|
| 
2872.3.1
by Martin Pool
 Add -Dhashcache option; clean up dirstate sha1 code  | 
1410  | 
link_or_sha1 = self._sha1_file(abspath)  | 
| 
2255.10.3
by John Arbash Meinel
 (broken) Change get_sha1_for_entry into update_entry  | 
1411  | 
executable = self._is_executable(stat_value.st_mode,  | 
1412  | 
saved_executable)  | 
|
| 
2485.3.11
by John Arbash Meinel
 Correct DirState.update_entry to check when caching the sha1  | 
1413  | 
if self._cutoff_time is None:  | 
1414  | 
self._sha_cutoff_time()  | 
|
1415  | 
if (stat_value.st_mtime < self._cutoff_time  | 
|
1416  | 
and stat_value.st_ctime < self._cutoff_time):  | 
|
1417  | 
entry[1][0] = ('f', link_or_sha1, stat_value.st_size,  | 
|
1418  | 
executable, packed_stat)  | 
|
1419  | 
else:  | 
|
1420  | 
entry[1][0] = ('f', '', stat_value.st_size,  | 
|
1421  | 
executable, DirState.NULLSTAT)  | 
|
| 
2255.10.3
by John Arbash Meinel
 (broken) Change get_sha1_for_entry into update_entry  | 
1422  | 
elif minikind == 'd':  | 
1423  | 
link_or_sha1 = None  | 
|
1424  | 
entry[1][0] = ('d', '', 0, False, packed_stat)  | 
|
1425  | 
if saved_minikind != 'd':  | 
|
1426  | 
                # This changed from something into a directory. Make sure we
 | 
|
1427  | 
                # have a directory block for it. This doesn't happen very
 | 
|
1428  | 
                # often, so this doesn't have to be super fast.
 | 
|
1429  | 
block_index, entry_index, dir_present, file_present = \  | 
|
1430  | 
self._get_block_entry_index(entry[0][0], entry[0][1], 0)  | 
|
1431  | 
self._ensure_block(block_index, entry_index,  | 
|
1432  | 
osutils.pathjoin(entry[0][0], entry[0][1]))  | 
|
1433  | 
elif minikind == 'l':  | 
|
1434  | 
link_or_sha1 = self._read_link(abspath, saved_link_or_sha1)  | 
|
| 
2485.3.14
by John Arbash Meinel
 Update the code so that symlinks aren't cached at incorrect times  | 
1435  | 
if self._cutoff_time is None:  | 
1436  | 
self._sha_cutoff_time()  | 
|
1437  | 
if (stat_value.st_mtime < self._cutoff_time  | 
|
1438  | 
and stat_value.st_ctime < self._cutoff_time):  | 
|
1439  | 
entry[1][0] = ('l', link_or_sha1, stat_value.st_size,  | 
|
1440  | 
False, packed_stat)  | 
|
1441  | 
else:  | 
|
1442  | 
entry[1][0] = ('l', '', stat_value.st_size,  | 
|
1443  | 
False, DirState.NULLSTAT)  | 
|
| 
2255.10.1
by John Arbash Meinel
 Update WorkingTree4 so that it doesn't use a HashCache,  | 
1444  | 
self._dirblock_state = DirState.IN_MEMORY_MODIFIED  | 
| 
2255.10.3
by John Arbash Meinel
 (broken) Change get_sha1_for_entry into update_entry  | 
1445  | 
return link_or_sha1  | 
| 
2255.10.1
by John Arbash Meinel
 Update WorkingTree4 so that it doesn't use a HashCache,  | 
1446  | 
|
1447  | 
def _sha_cutoff_time(self):  | 
|
1448  | 
"""Return cutoff time.  | 
|
1449  | 
||
1450  | 
        Files modified more recently than this time are at risk of being
 | 
|
1451  | 
        undetectably modified and so can't be cached.
 | 
|
1452  | 
        """
 | 
|
| 
2255.10.6
by John Arbash Meinel
 Save approx 30-60ms (5-10%) on a LP tree by not calling time.time() for every entry.  | 
1453  | 
        # Cache the cutoff time as long as we hold a lock.
 | 
1454  | 
        # time.time() isn't super expensive (approx 3.38us), but
 | 
|
1455  | 
        # when you call it 50,000 times it adds up.
 | 
|
1456  | 
        # For comparison, os.lstat() costs 7.2us if it is hot.
 | 
|
1457  | 
self._cutoff_time = int(time.time()) - 3  | 
|
1458  | 
return self._cutoff_time  | 
|
| 
2255.10.1
by John Arbash Meinel
 Update WorkingTree4 so that it doesn't use a HashCache,  | 
1459  | 
|
| 
2255.10.3
by John Arbash Meinel
 (broken) Change get_sha1_for_entry into update_entry  | 
1460  | 
def _lstat(self, abspath, entry):  | 
1461  | 
"""Return the os.lstat value for this path."""  | 
|
1462  | 
return os.lstat(abspath)  | 
|
1463  | 
||
| 
2872.3.1
by Martin Pool
 Add -Dhashcache option; clean up dirstate sha1 code  | 
1464  | 
def _sha1_file_and_mutter(self, abspath):  | 
1465  | 
        # when -Dhashcache is turned on, this is monkey-patched in to log
 | 
|
1466  | 
        # file reads
 | 
|
1467  | 
trace.mutter("dirstate sha1 " + abspath)  | 
|
1468  | 
return osutils.sha_file_by_name(abspath)  | 
|
| 
2255.10.1
by John Arbash Meinel
 Update WorkingTree4 so that it doesn't use a HashCache,  | 
1469  | 
|
| 
2255.10.3
by John Arbash Meinel
 (broken) Change get_sha1_for_entry into update_entry  | 
1470  | 
def _is_executable(self, mode, old_executable):  | 
1471  | 
"""Is this file executable?"""  | 
|
1472  | 
return bool(S_IEXEC & mode)  | 
|
1473  | 
||
| 
2255.10.7
by John Arbash Meinel
 Some updates to how we handle the executable bit. In preparation for supporting Win32  | 
1474  | 
def _is_executable_win32(self, mode, old_executable):  | 
1475  | 
"""On win32 the executable bit is stored in the dirstate."""  | 
|
1476  | 
return old_executable  | 
|
1477  | 
||
1478  | 
if sys.platform == 'win32':  | 
|
1479  | 
_is_executable = _is_executable_win32  | 
|
1480  | 
||
| 
2255.10.3
by John Arbash Meinel
 (broken) Change get_sha1_for_entry into update_entry  | 
1481  | 
def _read_link(self, abspath, old_link):  | 
1482  | 
"""Read the target of a symlink"""  | 
|
1483  | 
        # TODO: jam 200700301 On Win32, this could just return the value
 | 
|
| 
2255.10.7
by John Arbash Meinel
 Some updates to how we handle the executable bit. In preparation for supporting Win32  | 
1484  | 
        #       already in memory. However, this really needs to be done at a
 | 
1485  | 
        #       higher level, because there either won't be anything on disk,
 | 
|
1486  | 
        #       or the thing on disk will be a file.
 | 
|
| 
2255.10.3
by John Arbash Meinel
 (broken) Change get_sha1_for_entry into update_entry  | 
1487  | 
return os.readlink(abspath)  | 
1488  | 
||
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1489  | 
def get_ghosts(self):  | 
1490  | 
"""Return a list of the parent tree revision ids that are ghosts."""  | 
|
1491  | 
self._read_header_if_needed()  | 
|
1492  | 
return self._ghosts  | 
|
1493  | 
||
| 
1852.13.15
by Robert Collins
 Ensure Format4 working trees start with a dirstate.  | 
1494  | 
def get_lines(self):  | 
1495  | 
"""Serialise the entire dirstate to a sequence of lines."""  | 
|
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1496  | 
if (self._header_state == DirState.IN_MEMORY_UNMODIFIED and  | 
1497  | 
self._dirblock_state == DirState.IN_MEMORY_UNMODIFIED):  | 
|
1498  | 
            # read whats on disk.
 | 
|
1499  | 
self._state_file.seek(0)  | 
|
1500  | 
return self._state_file.readlines()  | 
|
| 
1852.13.19
by Robert Collins
 Get DirState objects roundtripping an add of a ghost tree.  | 
1501  | 
lines = []  | 
1502  | 
lines.append(self._get_parents_line(self.get_parent_ids()))  | 
|
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1503  | 
lines.append(self._get_ghosts_line(self._ghosts))  | 
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
1504  | 
        # append the root line which is special cased
 | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1505  | 
lines.extend(map(self._entry_to_line, self._iter_entries()))  | 
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1506  | 
return self._get_output_lines(lines)  | 
| 
1852.13.15
by Robert Collins
 Ensure Format4 working trees start with a dirstate.  | 
1507  | 
|
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1508  | 
def _get_ghosts_line(self, ghost_ids):  | 
1509  | 
"""Create a line for the state file for ghost information."""  | 
|
| 
2255.2.84
by John Arbash Meinel
 Remove now-unecessary encode/decode calls for revision ids.  | 
1510  | 
return '\0'.join([str(len(ghost_ids))] + ghost_ids)  | 
1511  | 
||
| 
1852.13.15
by Robert Collins
 Ensure Format4 working trees start with a dirstate.  | 
1512  | 
def _get_parents_line(self, parent_ids):  | 
1513  | 
"""Create a line for the state file for parents information."""  | 
|
| 
2255.2.84
by John Arbash Meinel
 Remove now-unecessary encode/decode calls for revision ids.  | 
1514  | 
return '\0'.join([str(len(parent_ids))] + parent_ids)  | 
1515  | 
||
| 
2255.3.1
by John Arbash Meinel
 Rewrite the inner parsing loop, needs performance testing.  | 
1516  | 
def _get_fields_to_entry(self):  | 
1517  | 
"""Get a function which converts entry fields into a entry record.  | 
|
1518  | 
||
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
1519  | 
        This handles size and executable, as well as parent records.
 | 
| 
2255.3.1
by John Arbash Meinel
 Rewrite the inner parsing loop, needs performance testing.  | 
1520  | 
|
1521  | 
        :return: A function which takes a list of fields, and returns an
 | 
|
1522  | 
            appropriate record for storing in memory.
 | 
|
1523  | 
        """
 | 
|
1524  | 
        # This is intentionally unrolled for performance
 | 
|
1525  | 
num_present_parents = self._num_present_parents()  | 
|
1526  | 
if num_present_parents == 0:  | 
|
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
1527  | 
def fields_to_entry_0_parents(fields, _int=int):  | 
| 
2255.2.108
by John Arbash Meinel
 tuple(list[:3]) noticablely slower than (list[0], list[1], list[2])  | 
1528  | 
path_name_file_id_key = (fields[0], fields[1], fields[2])  | 
| 
2255.3.1
by John Arbash Meinel
 Rewrite the inner parsing loop, needs performance testing.  | 
1529  | 
return (path_name_file_id_key, [  | 
1530  | 
( # Current tree  | 
|
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
1531  | 
fields[3], # minikind  | 
| 
2255.3.1
by John Arbash Meinel
 Rewrite the inner parsing loop, needs performance testing.  | 
1532  | 
fields[4], # fingerprint  | 
1533  | 
_int(fields[5]), # size  | 
|
1534  | 
fields[6] == 'y', # executable  | 
|
1535  | 
fields[7], # packed_stat or revision_id  | 
|
1536  | 
                    )])
 | 
|
1537  | 
return fields_to_entry_0_parents  | 
|
1538  | 
elif num_present_parents == 1:  | 
|
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
1539  | 
def fields_to_entry_1_parent(fields, _int=int):  | 
| 
2255.2.108
by John Arbash Meinel
 tuple(list[:3]) noticablely slower than (list[0], list[1], list[2])  | 
1540  | 
path_name_file_id_key = (fields[0], fields[1], fields[2])  | 
| 
2255.3.1
by John Arbash Meinel
 Rewrite the inner parsing loop, needs performance testing.  | 
1541  | 
return (path_name_file_id_key, [  | 
1542  | 
( # Current tree  | 
|
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
1543  | 
fields[3], # minikind  | 
| 
2255.3.1
by John Arbash Meinel
 Rewrite the inner parsing loop, needs performance testing.  | 
1544  | 
fields[4], # fingerprint  | 
1545  | 
_int(fields[5]), # size  | 
|
1546  | 
fields[6] == 'y', # executable  | 
|
1547  | 
fields[7], # packed_stat or revision_id  | 
|
1548  | 
                    ),
 | 
|
1549  | 
( # Parent 1  | 
|
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
1550  | 
fields[8], # minikind  | 
| 
2255.3.1
by John Arbash Meinel
 Rewrite the inner parsing loop, needs performance testing.  | 
1551  | 
fields[9], # fingerprint  | 
1552  | 
_int(fields[10]), # size  | 
|
1553  | 
fields[11] == 'y', # executable  | 
|
1554  | 
fields[12], # packed_stat or revision_id  | 
|
1555  | 
                    ),
 | 
|
1556  | 
                    ])
 | 
|
1557  | 
return fields_to_entry_1_parent  | 
|
1558  | 
elif num_present_parents == 2:  | 
|
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
1559  | 
def fields_to_entry_2_parents(fields, _int=int):  | 
| 
2255.2.108
by John Arbash Meinel
 tuple(list[:3]) noticablely slower than (list[0], list[1], list[2])  | 
1560  | 
path_name_file_id_key = (fields[0], fields[1], fields[2])  | 
| 
2255.3.1
by John Arbash Meinel
 Rewrite the inner parsing loop, needs performance testing.  | 
1561  | 
return (path_name_file_id_key, [  | 
1562  | 
( # Current tree  | 
|
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
1563  | 
fields[3], # minikind  | 
| 
2255.3.1
by John Arbash Meinel
 Rewrite the inner parsing loop, needs performance testing.  | 
1564  | 
fields[4], # fingerprint  | 
1565  | 
_int(fields[5]), # size  | 
|
1566  | 
fields[6] == 'y', # executable  | 
|
1567  | 
fields[7], # packed_stat or revision_id  | 
|
1568  | 
                    ),
 | 
|
1569  | 
( # Parent 1  | 
|
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
1570  | 
fields[8], # minikind  | 
| 
2255.3.1
by John Arbash Meinel
 Rewrite the inner parsing loop, needs performance testing.  | 
1571  | 
fields[9], # fingerprint  | 
1572  | 
_int(fields[10]), # size  | 
|
1573  | 
fields[11] == 'y', # executable  | 
|
1574  | 
fields[12], # packed_stat or revision_id  | 
|
1575  | 
                    ),
 | 
|
1576  | 
( # Parent 2  | 
|
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
1577  | 
fields[13], # minikind  | 
| 
2255.3.1
by John Arbash Meinel
 Rewrite the inner parsing loop, needs performance testing.  | 
1578  | 
fields[14], # fingerprint  | 
1579  | 
_int(fields[15]), # size  | 
|
1580  | 
fields[16] == 'y', # executable  | 
|
1581  | 
fields[17], # packed_stat or revision_id  | 
|
1582  | 
                    ),
 | 
|
1583  | 
                    ])
 | 
|
1584  | 
return fields_to_entry_2_parents  | 
|
1585  | 
else:  | 
|
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
1586  | 
def fields_to_entry_n_parents(fields, _int=int):  | 
| 
2255.2.108
by John Arbash Meinel
 tuple(list[:3]) noticablely slower than (list[0], list[1], list[2])  | 
1587  | 
path_name_file_id_key = (fields[0], fields[1], fields[2])  | 
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
1588  | 
trees = [(fields[cur], # minikind  | 
| 
2255.3.1
by John Arbash Meinel
 Rewrite the inner parsing loop, needs performance testing.  | 
1589  | 
fields[cur+1], # fingerprint  | 
1590  | 
_int(fields[cur+2]), # size  | 
|
1591  | 
fields[cur+3] == 'y', # executable  | 
|
1592  | 
fields[cur+4], # stat or revision_id  | 
|
1593  | 
) for cur in xrange(3, len(fields)-1, 5)]  | 
|
1594  | 
return path_name_file_id_key, trees  | 
|
1595  | 
return fields_to_entry_n_parents  | 
|
1596  | 
||
| 
1852.13.15
by Robert Collins
 Ensure Format4 working trees start with a dirstate.  | 
1597  | 
def get_parent_ids(self):  | 
1598  | 
"""Return a list of the parent tree ids for the directory state."""  | 
|
| 
1852.13.19
by Robert Collins
 Get DirState objects roundtripping an add of a ghost tree.  | 
1599  | 
self._read_header_if_needed()  | 
| 
2255.2.41
by Robert Collins
 Fix Dirstate.get_parent_ids to return a copy of the ids, not a list whose mutation will break us.  | 
1600  | 
return list(self._parents)  | 
| 
1852.13.15
by Robert Collins
 Ensure Format4 working trees start with a dirstate.  | 
1601  | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1602  | 
def _get_block_entry_index(self, dirname, basename, tree_index):  | 
| 
2255.2.66
by John Arbash Meinel
 Move _get_row and _get_block_row_index into Dirstate itself.  | 
1603  | 
"""Get the coordinates for a path in the state structure.  | 
1604  | 
||
1605  | 
        :param dirname: The utf8 dirname to lookup.
 | 
|
1606  | 
        :param basename: The utf8 basename to lookup.
 | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1607  | 
        :param tree_index: The index of the tree for which this lookup should
 | 
1608  | 
            be attempted.
 | 
|
| 
2255.2.66
by John Arbash Meinel
 Move _get_row and _get_block_row_index into Dirstate itself.  | 
1609  | 
        :return: A tuple describing where the path is located, or should be
 | 
1610  | 
            inserted. The tuple contains four fields: the block index, the row
 | 
|
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
1611  | 
            index, the directory is present (boolean), the entire path is
 | 
1612  | 
            present (boolean).  There is no guarantee that either
 | 
|
| 
2255.2.66
by John Arbash Meinel
 Move _get_row and _get_block_row_index into Dirstate itself.  | 
1613  | 
            coordinate is currently reachable unless the found field for it is
 | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1614  | 
            True. For instance, a directory not present in the searched tree
 | 
1615  | 
            may be returned with a value one greater than the current highest
 | 
|
1616  | 
            block offset. The directory present field will always be True when
 | 
|
1617  | 
            the path present field is True. The directory present field does
 | 
|
1618  | 
            NOT indicate that the directory is present in the searched tree,
 | 
|
1619  | 
            rather it indicates that there are at least some files in some
 | 
|
1620  | 
            tree present there.
 | 
|
| 
2255.2.66
by John Arbash Meinel
 Move _get_row and _get_block_row_index into Dirstate itself.  | 
1621  | 
        """
 | 
1622  | 
self._read_dirblocks_if_needed()  | 
|
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
1623  | 
key = dirname, basename, ''  | 
1624  | 
block_index, present = self._find_block_index_from_key(key)  | 
|
1625  | 
if not present:  | 
|
| 
2255.2.66
by John Arbash Meinel
 Move _get_row and _get_block_row_index into Dirstate itself.  | 
1626  | 
            # no such directory - return the dir index and 0 for the row.
 | 
1627  | 
return block_index, 0, False, False  | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1628  | 
block = self._dirblocks[block_index][1] # access the entries only  | 
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
1629  | 
entry_index, present = self._find_entry_index(key, block)  | 
| 
2921.1.1
by Robert Collins
 Add a cache for dirstate entry lookups.  | 
1630  | 
        # linear search through entries at this path to find the one
 | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1631  | 
        # requested.
 | 
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
1632  | 
while entry_index < len(block) and block[entry_index][0][1] == basename:  | 
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
1633  | 
if block[entry_index][1][tree_index][0] not in 'ar':  | 
1634  | 
                # neither absent or relocated
 | 
|
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
1635  | 
return block_index, entry_index, True, True  | 
1636  | 
entry_index += 1  | 
|
1637  | 
return block_index, entry_index, True, False  | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1638  | 
|
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
1639  | 
def _get_entry(self, tree_index, fileid_utf8=None, path_utf8=None):  | 
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
1640  | 
"""Get the dirstate entry for path in tree tree_index.  | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1641  | 
|
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
1642  | 
        If either file_id or path is supplied, it is used as the key to lookup.
 | 
1643  | 
        If both are supplied, the fastest lookup is used, and an error is
 | 
|
1644  | 
        raised if they do not both point at the same row.
 | 
|
| 
2255.7.13
by John Arbash Meinel
 find an edge case in our _get_entry logic and fix it.  | 
1645  | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1646  | 
        :param tree_index: The index of the tree we wish to locate this path
 | 
1647  | 
            in. If the path is present in that tree, the entry containing its
 | 
|
1648  | 
            details is returned, otherwise (None, None) is returned
 | 
|
| 
2255.7.93
by Martin Pool
 Add support for tree-references in dirstate  | 
1649  | 
            0 is the working tree, higher indexes are successive parent
 | 
1650  | 
            trees.
 | 
|
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
1651  | 
        :param fileid_utf8: A utf8 file_id to look up.
 | 
1652  | 
        :param path_utf8: An utf8 path to be looked up.
 | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1653  | 
        :return: The dirstate entry tuple for path, or (None, None)
 | 
1654  | 
        """
 | 
|
| 
2255.2.94
by Robert Collins
 DirState: handle id lookup redirects correctly.  | 
1655  | 
self._read_dirblocks_if_needed()  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
1656  | 
if path_utf8 is not None:  | 
| 
2921.1.1
by Robert Collins
 Add a cache for dirstate entry lookups.  | 
1657  | 
assert path_utf8.__class__ == str, ('path_utf8 is not a str: %s %s'  | 
1658  | 
% (type(path_utf8), path_utf8))  | 
|
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
1659  | 
            # path lookups are faster
 | 
| 
2255.2.146
by John Arbash Meinel
 Implement move_directory by factoring out move_one  | 
1660  | 
dirname, basename = osutils.split(path_utf8)  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
1661  | 
block_index, entry_index, dir_present, file_present = \  | 
1662  | 
self._get_block_entry_index(dirname, basename, tree_index)  | 
|
1663  | 
if not file_present:  | 
|
1664  | 
return None, None  | 
|
1665  | 
entry = self._dirblocks[block_index][1][entry_index]  | 
|
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
1666  | 
assert entry[0][2] and entry[1][tree_index][0] not in ('a', 'r'), 'unversioned entry?!?!'  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
1667  | 
if fileid_utf8:  | 
1668  | 
if entry[0][2] != fileid_utf8:  | 
|
| 
2255.2.144
by John Arbash Meinel
 Simplify update_minimal a bit more, by making id_index a  | 
1669  | 
raise errors.BzrError('integrity error ? : mismatching'  | 
1670  | 
' tree_index, file_id and path')  | 
|
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
1671  | 
return entry  | 
1672  | 
else:  | 
|
| 
2255.7.13
by John Arbash Meinel
 find an edge case in our _get_entry logic and fix it.  | 
1673  | 
assert fileid_utf8 is not None  | 
| 
2255.2.147
by John Arbash Meinel
 Move fast id => path lookups down into DirState  | 
1674  | 
possible_keys = self._get_id_index().get(fileid_utf8, None)  | 
1675  | 
if not possible_keys:  | 
|
1676  | 
return None, None  | 
|
1677  | 
for key in possible_keys:  | 
|
| 
2255.7.76
by Robert Collins
 Fix _get_entry, which got broken at some point, this fixes tests now, so it should not be breakable in future.  | 
1678  | 
block_index, present = \  | 
1679  | 
self._find_block_index_from_key(key)  | 
|
1680  | 
                # strange, probably indicates an out of date
 | 
|
1681  | 
                # id index - for now, allow this.
 | 
|
1682  | 
if not present:  | 
|
1683  | 
                    continue
 | 
|
1684  | 
                # WARNING: DO not change this code to use _get_block_entry_index
 | 
|
1685  | 
                # as that function is not suitable: it does not use the key
 | 
|
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
1686  | 
                # to lookup, and thus the wrong coordinates are returned.
 | 
| 
2255.7.76
by Robert Collins
 Fix _get_entry, which got broken at some point, this fixes tests now, so it should not be breakable in future.  | 
1687  | 
block = self._dirblocks[block_index][1]  | 
1688  | 
entry_index, present = self._find_entry_index(key, block)  | 
|
1689  | 
if present:  | 
|
| 
2255.2.147
by John Arbash Meinel
 Move fast id => path lookups down into DirState  | 
1690  | 
entry = self._dirblocks[block_index][1][entry_index]  | 
| 
2255.2.172
by Martin Pool
 Recognize 't' (tree-reference) minikind in DirState._get_entry  | 
1691  | 
if entry[1][tree_index][0] in 'fdlt':  | 
| 
2255.7.76
by Robert Collins
 Fix _get_entry, which got broken at some point, this fixes tests now, so it should not be breakable in future.  | 
1692  | 
                        # this is the result we are looking for: the  
 | 
1693  | 
                        # real home of this file_id in this tree.
 | 
|
1694  | 
return entry  | 
|
1695  | 
if entry[1][tree_index][0] == 'a':  | 
|
1696  | 
                        # there is no home for this entry in this tree
 | 
|
1697  | 
return None, None  | 
|
| 
2255.2.172
by Martin Pool
 Recognize 't' (tree-reference) minikind in DirState._get_entry  | 
1698  | 
assert entry[1][tree_index][0] == 'r', \  | 
1699  | 
"entry %r has invalid minikind %r for tree %r" \  | 
|
1700  | 
% (entry,  | 
|
1701  | 
entry[1][tree_index][0],  | 
|
1702  | 
tree_index)  | 
|
| 
2255.7.76
by Robert Collins
 Fix _get_entry, which got broken at some point, this fixes tests now, so it should not be breakable in future.  | 
1703  | 
real_path = entry[1][tree_index][1]  | 
1704  | 
return self._get_entry(tree_index, fileid_utf8=fileid_utf8,  | 
|
1705  | 
path_utf8=real_path)  | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1706  | 
return None, None  | 
| 
2255.2.66
by John Arbash Meinel
 Move _get_row and _get_block_row_index into Dirstate itself.  | 
1707  | 
|
| 
2255.10.1
by John Arbash Meinel
 Update WorkingTree4 so that it doesn't use a HashCache,  | 
1708  | 
    @classmethod
 | 
1709  | 
def initialize(cls, path):  | 
|
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
1710  | 
"""Create a new dirstate on path.  | 
1711  | 
||
1712  | 
        The new dirstate will be an empty tree - that is it has no parents,
 | 
|
1713  | 
        and only a root node - which has id ROOT_ID.
 | 
|
| 
2255.2.84
by John Arbash Meinel
 Remove now-unecessary encode/decode calls for revision ids.  | 
1714  | 
|
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
1715  | 
        :param path: The name of the file for the dirstate.
 | 
| 
2425.5.1
by Martin Pool
 doc Dirstate.initialize  | 
1716  | 
        :return: A write-locked DirState object.
 | 
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
1717  | 
        """
 | 
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1718  | 
        # This constructs a new DirState object on a path, sets the _state_file
 | 
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
1719  | 
        # to a new empty file for that path. It then calls _set_data() with our
 | 
1720  | 
        # stock empty dirstate information - a root with ROOT_ID, no children,
 | 
|
1721  | 
        # and no parents. Finally it calls save() to ensure that this data will
 | 
|
1722  | 
        # persist.
 | 
|
| 
2255.10.1
by John Arbash Meinel
 Update WorkingTree4 so that it doesn't use a HashCache,  | 
1723  | 
result = cls(path)  | 
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
1724  | 
        # root dir and root dir contents with no children.
 | 
1725  | 
empty_tree_dirblocks = [('', []), ('', [])]  | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1726  | 
        # a new root directory, with a NULLSTAT.
 | 
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
1727  | 
empty_tree_dirblocks[0][1].append(  | 
| 
2255.8.4
by John Arbash Meinel
 Rather than using split hunks, implement a bisect_dirblocks  | 
1728  | 
(('', '', inventory.ROOT_ID), [  | 
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
1729  | 
('d', '', 0, False, DirState.NULLSTAT),  | 
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
1730  | 
            ]))
 | 
| 
2255.4.2
by James Westby
 (broken) Add the locking methods.  | 
1731  | 
result.lock_write()  | 
| 
1852.13.15
by Robert Collins
 Ensure Format4 working trees start with a dirstate.  | 
1732  | 
try:  | 
| 
2255.4.2
by James Westby
 (broken) Add the locking methods.  | 
1733  | 
result._set_data([], empty_tree_dirblocks)  | 
| 
1852.13.19
by Robert Collins
 Get DirState objects roundtripping an add of a ghost tree.  | 
1734  | 
result.save()  | 
1735  | 
except:  | 
|
| 
2255.4.2
by James Westby
 (broken) Add the locking methods.  | 
1736  | 
result.unlock()  | 
| 
1852.13.19
by Robert Collins
 Get DirState objects roundtripping an add of a ghost tree.  | 
1737  | 
            raise
 | 
| 
1852.13.15
by Robert Collins
 Ensure Format4 working trees start with a dirstate.  | 
1738  | 
return result  | 
1739  | 
||
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
1740  | 
def _inv_entry_to_details(self, inv_entry):  | 
1741  | 
"""Convert an inventory entry (from a revision tree) to state details.  | 
|
1742  | 
||
1743  | 
        :param inv_entry: An inventory entry whose sha1 and link targets can be
 | 
|
1744  | 
            relied upon, and which has a revision set.
 | 
|
1745  | 
        :return: A details tuple - the details for a single tree at a path +
 | 
|
1746  | 
            id.
 | 
|
1747  | 
        """
 | 
|
1748  | 
kind = inv_entry.kind  | 
|
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
1749  | 
minikind = DirState._kind_to_minikind[kind]  | 
| 
2255.2.107
by John Arbash Meinel
 (working), fix dirstate to use utf8 file ids.  | 
1750  | 
tree_data = inv_entry.revision  | 
| 
2825.7.1
by Robert Collins
 * Partial commits are now approximately 40% faster by walking over the  | 
1751  | 
assert tree_data, 'empty revision for the inv_entry %s.' % \  | 
1752  | 
inv_entry.file_id  | 
|
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
1753  | 
if kind == 'directory':  | 
1754  | 
fingerprint = ''  | 
|
1755  | 
size = 0  | 
|
1756  | 
executable = False  | 
|
1757  | 
elif kind == 'symlink':  | 
|
1758  | 
fingerprint = inv_entry.symlink_target or ''  | 
|
1759  | 
size = 0  | 
|
1760  | 
executable = False  | 
|
1761  | 
elif kind == 'file':  | 
|
1762  | 
fingerprint = inv_entry.text_sha1 or ''  | 
|
1763  | 
size = inv_entry.text_size or 0  | 
|
1764  | 
executable = inv_entry.executable  | 
|
| 
2255.2.158
by Martin Pool
 Most of the integration of dirstate and subtree  | 
1765  | 
elif kind == 'tree-reference':  | 
1766  | 
fingerprint = inv_entry.reference_revision or ''  | 
|
1767  | 
size = 0  | 
|
1768  | 
executable = False  | 
|
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
1769  | 
else:  | 
| 
2255.2.158
by Martin Pool
 Most of the integration of dirstate and subtree  | 
1770  | 
raise Exception("can't pack %s" % inv_entry)  | 
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
1771  | 
return (minikind, fingerprint, size, executable, tree_data)  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
1772  | 
|
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1773  | 
def _iter_child_entries(self, tree_index, path_utf8):  | 
1774  | 
"""Iterate over all the entries that are children of path_utf.  | 
|
1775  | 
||
1776  | 
        This only returns entries that are present (not in 'a', 'r') in 
 | 
|
1777  | 
        tree_index. tree_index data is not refreshed, so if tree 0 is used,
 | 
|
1778  | 
        results may differ from that obtained if paths were statted to
 | 
|
1779  | 
        determine what ones were directories.
 | 
|
1780  | 
||
1781  | 
        Asking for the children of a non-directory will return an empty
 | 
|
1782  | 
        iterator.
 | 
|
1783  | 
        """
 | 
|
1784  | 
pending_dirs = []  | 
|
1785  | 
next_pending_dirs = [path_utf8]  | 
|
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
1786  | 
absent = 'ar'  | 
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1787  | 
while next_pending_dirs:  | 
1788  | 
pending_dirs = next_pending_dirs  | 
|
1789  | 
next_pending_dirs = []  | 
|
1790  | 
for path in pending_dirs:  | 
|
1791  | 
block_index, present = self._find_block_index_from_key(  | 
|
1792  | 
(path, '', ''))  | 
|
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
1793  | 
if block_index == 0:  | 
1794  | 
block_index = 1  | 
|
1795  | 
if len(self._dirblocks) == 1:  | 
|
1796  | 
                        # asked for the children of the root with no other
 | 
|
1797  | 
                        # contents.
 | 
|
1798  | 
                        return
 | 
|
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1799  | 
if not present:  | 
1800  | 
                    # children of a non-directory asked for.
 | 
|
1801  | 
                    continue
 | 
|
1802  | 
block = self._dirblocks[block_index]  | 
|
1803  | 
for entry in block[1]:  | 
|
1804  | 
kind = entry[1][tree_index][0]  | 
|
1805  | 
if kind not in absent:  | 
|
1806  | 
yield entry  | 
|
1807  | 
if kind == 'd':  | 
|
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
1808  | 
if entry[0][0]:  | 
1809  | 
path = entry[0][0] + '/' + entry[0][1]  | 
|
1810  | 
else:  | 
|
1811  | 
path = entry[0][1]  | 
|
1812  | 
next_pending_dirs.append(path)  | 
|
| 
2929.2.1
by Robert Collins
 * Commit updates the state of the working tree via a delta rather than  | 
1813  | 
|
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
1814  | 
def _iter_entries(self):  | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1815  | 
"""Iterate over all the entries in the dirstate.  | 
1816  | 
||
1817  | 
        Each yelt item is an entry in the standard format described in the
 | 
|
1818  | 
        docstring of bzrlib.dirstate.
 | 
|
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1819  | 
        """
 | 
1820  | 
self._read_dirblocks_if_needed()  | 
|
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
1821  | 
for directory in self._dirblocks:  | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1822  | 
for entry in directory[1]:  | 
1823  | 
yield entry  | 
|
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1824  | 
|
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
1825  | 
def _get_id_index(self):  | 
1826  | 
"""Get an id index of self._dirblocks."""  | 
|
| 
2255.2.144
by John Arbash Meinel
 Simplify update_minimal a bit more, by making id_index a  | 
1827  | 
if self._id_index is None:  | 
1828  | 
id_index = {}  | 
|
1829  | 
for key, tree_details in self._iter_entries():  | 
|
1830  | 
id_index.setdefault(key[2], set()).add(key)  | 
|
1831  | 
self._id_index = id_index  | 
|
1832  | 
return self._id_index  | 
|
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
1833  | 
|
| 
1852.13.15
by Robert Collins
 Ensure Format4 working trees start with a dirstate.  | 
1834  | 
def _get_output_lines(self, lines):  | 
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
1835  | 
"""Format lines for final output.  | 
| 
2255.2.84
by John Arbash Meinel
 Remove now-unecessary encode/decode calls for revision ids.  | 
1836  | 
|
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
1837  | 
        :param lines: A sequence of lines containing the parents list and the
 | 
| 
1852.13.15
by Robert Collins
 Ensure Format4 working trees start with a dirstate.  | 
1838  | 
            path lines.
 | 
1839  | 
        """
 | 
|
| 
2255.8.6
by John Arbash Meinel
 Because the disk format (sorting) has now changed  | 
1840  | 
output_lines = [DirState.HEADER_FORMAT_3]  | 
| 
1852.13.6
by Robert Collins
 start hooking in the prototype dirstate serialiser.  | 
1841  | 
lines.append('') # a final newline  | 
1842  | 
inventory_text = '\0\n\0'.join(lines)  | 
|
| 
2255.2.239
by Robert Collins
 Change from adler to crc checksums, as adler32 in python is not stable from 32 to 64 bit systems.  | 
1843  | 
output_lines.append('crc32: %s\n' % (zlib.crc32(inventory_text),))  | 
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1844  | 
        # -3, 1 for num parents, 1 for ghosts, 1 for final newline
 | 
1845  | 
num_entries = len(lines)-3  | 
|
| 
1852.13.6
by Robert Collins
 start hooking in the prototype dirstate serialiser.  | 
1846  | 
output_lines.append('num_entries: %s\n' % (num_entries,))  | 
1847  | 
output_lines.append(inventory_text)  | 
|
| 
1852.13.15
by Robert Collins
 Ensure Format4 working trees start with a dirstate.  | 
1848  | 
return output_lines  | 
| 
1852.13.6
by Robert Collins
 start hooking in the prototype dirstate serialiser.  | 
1849  | 
|
| 
2255.2.36
by Robert Collins
 Fix Dirstate unversioning of entries which are in a parent.  | 
1850  | 
def _make_deleted_row(self, fileid_utf8, parents):  | 
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
1851  | 
"""Return a deleted row for fileid_utf8."""  | 
| 
2255.2.36
by Robert Collins
 Fix Dirstate unversioning of entries which are in a parent.  | 
1852  | 
return ('/', 'RECYCLED.BIN', 'file', fileid_utf8, 0, DirState.NULLSTAT,  | 
1853  | 
''), parents  | 
|
1854  | 
||
| 
2255.3.1
by John Arbash Meinel
 Rewrite the inner parsing loop, needs performance testing.  | 
1855  | 
def _num_present_parents(self):  | 
1856  | 
"""The number of parent entries in each record row."""  | 
|
1857  | 
return len(self._parents) - len(self._ghosts)  | 
|
1858  | 
||
| 
1852.13.15
by Robert Collins
 Ensure Format4 working trees start with a dirstate.  | 
1859  | 
    @staticmethod
 | 
1860  | 
def on_file(path):  | 
|
| 
2255.5.1
by John Arbash Meinel
 Update the dirstate tests to lock and unlock properly.  | 
1861  | 
"""Construct a DirState on the file at path path.  | 
1862  | 
||
1863  | 
        :return: An unlocked DirState object, associated with the given path.
 | 
|
1864  | 
        """
 | 
|
| 
2255.4.1
by James Westby
 Store the filename of the dirstate in an attribute.  | 
1865  | 
result = DirState(path)  | 
| 
1852.13.6
by Robert Collins
 start hooking in the prototype dirstate serialiser.  | 
1866  | 
return result  | 
1867  | 
||
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1868  | 
def _read_dirblocks_if_needed(self):  | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1869  | 
"""Read in all the dirblocks from the file if they are not in memory.  | 
1870  | 
        
 | 
|
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
1871  | 
        This populates self._dirblocks, and sets self._dirblock_state to
 | 
1872  | 
        IN_MEMORY_UNMODIFIED. It is not currently ready for incremental block
 | 
|
1873  | 
        loading.
 | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1874  | 
        """
 | 
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1875  | 
self._read_header_if_needed()  | 
1876  | 
if self._dirblock_state == DirState.NOT_IN_MEMORY:  | 
|
| 
2474.1.1
by John Arbash Meinel
 Create a Pyrex extension for reading the dirstate file.  | 
1877  | 
_read_dirblocks(self)  | 
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1878  | 
|
| 
1852.13.15
by Robert Collins
 Ensure Format4 working trees start with a dirstate.  | 
1879  | 
def _read_header(self):  | 
1880  | 
"""This reads in the metadata header, and the parent ids.  | 
|
1881  | 
||
1882  | 
        After reading in, the file should be positioned at the null
 | 
|
1883  | 
        just before the start of the first record in the file.
 | 
|
1884  | 
||
| 
2255.2.239
by Robert Collins
 Change from adler to crc checksums, as adler32 in python is not stable from 32 to 64 bit systems.  | 
1885  | 
        :return: (expected crc checksum, number of entries, parent list)
 | 
| 
1852.13.15
by Robert Collins
 Ensure Format4 working trees start with a dirstate.  | 
1886  | 
        """
 | 
1887  | 
self._read_prelude()  | 
|
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1888  | 
parent_line = self._state_file.readline()  | 
| 
1852.13.15
by Robert Collins
 Ensure Format4 working trees start with a dirstate.  | 
1889  | 
info = parent_line.split('\0')  | 
1890  | 
num_parents = int(info[0])  | 
|
1891  | 
assert num_parents == len(info)-2, 'incorrect parent info line'  | 
|
| 
2255.2.84
by John Arbash Meinel
 Remove now-unecessary encode/decode calls for revision ids.  | 
1892  | 
self._parents = info[1:-1]  | 
| 
1852.13.15
by Robert Collins
 Ensure Format4 working trees start with a dirstate.  | 
1893  | 
|
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1894  | 
ghost_line = self._state_file.readline()  | 
1895  | 
info = ghost_line.split('\0')  | 
|
1896  | 
num_ghosts = int(info[1])  | 
|
1897  | 
assert num_ghosts == len(info)-3, 'incorrect ghost info line'  | 
|
| 
2255.2.84
by John Arbash Meinel
 Remove now-unecessary encode/decode calls for revision ids.  | 
1898  | 
self._ghosts = info[2:-1]  | 
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1899  | 
self._header_state = DirState.IN_MEMORY_UNMODIFIED  | 
| 
2255.3.2
by John Arbash Meinel
 (broken) some basic work on adding bisect functionality to dirstate.  | 
1900  | 
self._end_of_header = self._state_file.tell()  | 
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1901  | 
|
| 
1852.13.19
by Robert Collins
 Get DirState objects roundtripping an add of a ghost tree.  | 
1902  | 
def _read_header_if_needed(self):  | 
1903  | 
"""Read the header of the dirstate file if needed."""  | 
|
| 
2255.4.2
by James Westby
 (broken) Add the locking methods.  | 
1904  | 
        # inline this as it will be called a lot
 | 
1905  | 
if not self._lock_token:  | 
|
1906  | 
raise errors.ObjectNotLocked(self)  | 
|
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1907  | 
if self._header_state == DirState.NOT_IN_MEMORY:  | 
| 
1852.13.19
by Robert Collins
 Get DirState objects roundtripping an add of a ghost tree.  | 
1908  | 
self._read_header()  | 
1909  | 
||
| 
1852.13.15
by Robert Collins
 Ensure Format4 working trees start with a dirstate.  | 
1910  | 
def _read_prelude(self):  | 
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
1911  | 
"""Read in the prelude header of the dirstate file.  | 
| 
1852.13.15
by Robert Collins
 Ensure Format4 working trees start with a dirstate.  | 
1912  | 
|
| 
2255.2.239
by Robert Collins
 Change from adler to crc checksums, as adler32 in python is not stable from 32 to 64 bit systems.  | 
1913  | 
        This only reads in the stuff that is not connected to the crc
 | 
| 
1852.13.15
by Robert Collins
 Ensure Format4 working trees start with a dirstate.  | 
1914  | 
        checksum. The position will be correct to read in the rest of
 | 
1915  | 
        the file and check the checksum after this point.
 | 
|
1916  | 
        The next entry in the file should be the number of parents,
 | 
|
1917  | 
        and their ids. Followed by a newline.
 | 
|
1918  | 
        """
 | 
|
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1919  | 
header = self._state_file.readline()  | 
| 
2255.8.6
by John Arbash Meinel
 Because the disk format (sorting) has now changed  | 
1920  | 
assert header == DirState.HEADER_FORMAT_3, \  | 
| 
1852.13.15
by Robert Collins
 Ensure Format4 working trees start with a dirstate.  | 
1921  | 
'invalid header line: %r' % (header,)  | 
| 
2255.2.239
by Robert Collins
 Change from adler to crc checksums, as adler32 in python is not stable from 32 to 64 bit systems.  | 
1922  | 
crc_line = self._state_file.readline()  | 
1923  | 
assert crc_line.startswith('crc32: '), 'missing crc32 checksum'  | 
|
1924  | 
self.crc_expected = int(crc_line[len('crc32: '):-1])  | 
|
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1925  | 
num_entries_line = self._state_file.readline()  | 
| 
1852.13.15
by Robert Collins
 Ensure Format4 working trees start with a dirstate.  | 
1926  | 
assert num_entries_line.startswith('num_entries: '), 'missing num_entries line'  | 
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1927  | 
self._num_entries = int(num_entries_line[len('num_entries: '):-1])  | 
| 
2255.10.2
by John Arbash Meinel
 Update to dirstate locking.  | 
1928  | 
|
| 
2929.1.1
by Robert Collins
 Use a dict to access stat cache information from dirstate.  | 
1929  | 
def sha1_from_stat(self, path, stat_result, _pack_stat=pack_stat):  | 
1930  | 
"""Find a sha1 given a stat lookup."""  | 
|
1931  | 
return self._get_packed_stat_index().get(_pack_stat(stat_result), None)  | 
|
1932  | 
||
1933  | 
def _get_packed_stat_index(self):  | 
|
1934  | 
"""Get a packed_stat index of self._dirblocks."""  | 
|
1935  | 
if self._packed_stat_index is None:  | 
|
1936  | 
index = {}  | 
|
1937  | 
for key, tree_details in self._iter_entries():  | 
|
1938  | 
if tree_details[0][0] == 'f':  | 
|
| 
2929.1.2
by Robert Collins
 Review feedback.  | 
1939  | 
index[tree_details[0][4]] = tree_details[0][1]  | 
| 
2929.1.1
by Robert Collins
 Use a dict to access stat cache information from dirstate.  | 
1940  | 
self._packed_stat_index = index  | 
1941  | 
return self._packed_stat_index  | 
|
1942  | 
||
| 
1852.13.19
by Robert Collins
 Get DirState objects roundtripping an add of a ghost tree.  | 
1943  | 
def save(self):  | 
| 
2255.2.32
by Robert Collins
 Make test_clear_merge_conflicts pass for dirstate. This involved working  | 
1944  | 
"""Save any pending changes created during this session.  | 
| 
2255.10.2
by John Arbash Meinel
 Update to dirstate locking.  | 
1945  | 
|
| 
2255.2.32
by Robert Collins
 Make test_clear_merge_conflicts pass for dirstate. This involved working  | 
1946  | 
        We reuse the existing file, because that prevents race conditions with
 | 
| 
2255.10.2
by John Arbash Meinel
 Update to dirstate locking.  | 
1947  | 
        file creation, and use oslocks on it to prevent concurrent modification
 | 
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
1948  | 
        and reads - because dirstate's incremental data aggregation is not
 | 
| 
2255.10.2
by John Arbash Meinel
 Update to dirstate locking.  | 
1949  | 
        compatible with reading a modified file, and replacing a file in use by
 | 
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
1950  | 
        another process is impossible on Windows.
 | 
| 
2255.2.32
by Robert Collins
 Make test_clear_merge_conflicts pass for dirstate. This involved working  | 
1951  | 
|
1952  | 
        A dirstate in read only mode should be smart enough though to validate
 | 
|
1953  | 
        that the file has not changed, and otherwise discard its cache and
 | 
|
1954  | 
        start over, to allow for fine grained read lock duration, so 'status'
 | 
|
1955  | 
        wont block 'commit' - for example.
 | 
|
1956  | 
        """
 | 
|
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1957  | 
if (self._header_state == DirState.IN_MEMORY_MODIFIED or  | 
1958  | 
self._dirblock_state == DirState.IN_MEMORY_MODIFIED):  | 
|
| 
2255.10.2
by John Arbash Meinel
 Update to dirstate locking.  | 
1959  | 
|
| 
2353.4.7
by John Arbash Meinel
 Change the temporary_write_lock api, so that it always returns a lock object,  | 
1960  | 
grabbed_write_lock = False  | 
| 
2353.4.5
by John Arbash Meinel
 Update DirState to use the new 'temporary_write_lock', and add tests that it works.  | 
1961  | 
if self._lock_state != 'w':  | 
| 
2353.4.7
by John Arbash Meinel
 Change the temporary_write_lock api, so that it always returns a lock object,  | 
1962  | 
grabbed_write_lock, new_lock = self._lock_token.temporary_write_lock()  | 
1963  | 
                # Switch over to the new lock, as the old one may be closed.
 | 
|
1964  | 
                # TODO: jam 20070315 We should validate the disk file has
 | 
|
1965  | 
                #       not changed contents. Since temporary_write_lock may
 | 
|
1966  | 
                #       not be an atomic operation.
 | 
|
1967  | 
self._lock_token = new_lock  | 
|
1968  | 
self._state_file = new_lock.f  | 
|
1969  | 
if not grabbed_write_lock:  | 
|
1970  | 
                    # We couldn't grab a write lock, so we switch back to a read one
 | 
|
| 
2255.10.2
by John Arbash Meinel
 Update to dirstate locking.  | 
1971  | 
                    return
 | 
1972  | 
try:  | 
|
| 
2353.4.5
by John Arbash Meinel
 Update DirState to use the new 'temporary_write_lock', and add tests that it works.  | 
1973  | 
self._state_file.seek(0)  | 
1974  | 
self._state_file.writelines(self.get_lines())  | 
|
1975  | 
self._state_file.truncate()  | 
|
1976  | 
self._state_file.flush()  | 
|
| 
2255.10.2
by John Arbash Meinel
 Update to dirstate locking.  | 
1977  | 
self._header_state = DirState.IN_MEMORY_UNMODIFIED  | 
1978  | 
self._dirblock_state = DirState.IN_MEMORY_UNMODIFIED  | 
|
1979  | 
finally:  | 
|
| 
2353.4.7
by John Arbash Meinel
 Change the temporary_write_lock api, so that it always returns a lock object,  | 
1980  | 
if grabbed_write_lock:  | 
| 
2353.4.8
by John Arbash Meinel
 Use the right lock object.  | 
1981  | 
self._lock_token = self._lock_token.restore_read_lock()  | 
| 
2353.4.5
by John Arbash Meinel
 Update DirState to use the new 'temporary_write_lock', and add tests that it works.  | 
1982  | 
self._state_file = self._lock_token.f  | 
1983  | 
                    # TODO: jam 20070315 We should validate the disk file has
 | 
|
1984  | 
                    #       not changed contents. Since restore_read_lock may
 | 
|
1985  | 
                    #       not be an atomic operation.
 | 
|
| 
1852.13.6
by Robert Collins
 start hooking in the prototype dirstate serialiser.  | 
1986  | 
|
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
1987  | 
def _set_data(self, parent_ids, dirblocks):  | 
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1988  | 
"""Set the full dirstate data in memory.  | 
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
1989  | 
|
1990  | 
        This is an internal function used to completely replace the objects
 | 
|
1991  | 
        in memory state. It puts the dirstate into state 'full-dirty'.
 | 
|
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1992  | 
|
1993  | 
        :param parent_ids: A list of parent tree revision ids.
 | 
|
1994  | 
        :param dirblocks: A list containing one tuple for each directory in the
 | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
1995  | 
            tree. Each tuple contains the directory path and a list of entries 
 | 
1996  | 
            found in that directory.
 | 
|
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
1997  | 
        """
 | 
1998  | 
        # our memory copy is now authoritative.
 | 
|
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
1999  | 
self._dirblocks = dirblocks  | 
2000  | 
self._header_state = DirState.IN_MEMORY_MODIFIED  | 
|
2001  | 
self._dirblock_state = DirState.IN_MEMORY_MODIFIED  | 
|
2002  | 
self._parents = list(parent_ids)  | 
|
| 
2255.2.147
by John Arbash Meinel
 Move fast id => path lookups down into DirState  | 
2003  | 
self._id_index = None  | 
| 
2929.1.1
by Robert Collins
 Use a dict to access stat cache information from dirstate.  | 
2004  | 
self._packed_stat_index = None  | 
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
2005  | 
|
| 
2255.2.4
by Robert Collins
 Snapshot dirstate development  | 
2006  | 
def set_path_id(self, path, new_id):  | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
2007  | 
"""Change the id of path to new_id in the current working tree.  | 
| 
2255.2.4
by Robert Collins
 Snapshot dirstate development  | 
2008  | 
|
2009  | 
        :param path: The path inside the tree to set - '' is the root, 'foo'
 | 
|
2010  | 
            is the path foo in the root.
 | 
|
| 
2255.2.107
by John Arbash Meinel
 (working), fix dirstate to use utf8 file ids.  | 
2011  | 
        :param new_id: The new id to assign to the path. This must be a utf8
 | 
2012  | 
            file id (not unicode, and not None).
 | 
|
| 
2255.2.4
by Robert Collins
 Snapshot dirstate development  | 
2013  | 
        """
 | 
| 
2255.2.236
by Martin Pool
 Review cleanups: mostly updating or removing todo comments.  | 
2014  | 
assert new_id.__class__ == str, \  | 
2015  | 
"path_id %r is not a plain string" % (new_id,)  | 
|
| 
2255.2.37
by Robert Collins
 Get TestExecutable.test_06_pull working on DirState: fix cloning and the set_last_revision api on WorkingTree4.  | 
2016  | 
self._read_dirblocks_if_needed()  | 
| 
2255.2.75
by Robert Collins
 Correct generation of revisiontree inventories to handle out of order parents.  | 
2017  | 
if len(path):  | 
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
2018  | 
            # TODO: logic not written
 | 
| 
2255.2.75
by Robert Collins
 Correct generation of revisiontree inventories to handle out of order parents.  | 
2019  | 
raise NotImplementedError(self.set_path_id)  | 
2020  | 
        # TODO: check new id is unique
 | 
|
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
2021  | 
entry = self._get_entry(0, path_utf8=path)  | 
| 
2255.7.14
by John Arbash Meinel
 Make set_root_id() a no-op if the id doesn't change,  | 
2022  | 
if entry[0][2] == new_id:  | 
2023  | 
            # Nothing to change.
 | 
|
2024  | 
            return
 | 
|
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
2025  | 
        # mark the old path absent, and insert a new root path
 | 
2026  | 
self._make_absent(entry)  | 
|
| 
2255.2.142
by John Arbash Meinel
 Simplify the update_minimal api a little bit, and document the parameters.  | 
2027  | 
self.update_minimal(('', '', new_id), 'd',  | 
| 
2255.2.144
by John Arbash Meinel
 Simplify update_minimal a bit more, by making id_index a  | 
2028  | 
path_utf8='', packed_stat=entry[1][0][4])  | 
| 
2255.2.15
by Robert Collins
 Dirstate - truncate state file fixing bug in saving a smaller file, get more tree_implementation tests passing.  | 
2029  | 
self._dirblock_state = DirState.IN_MEMORY_MODIFIED  | 
| 
2255.2.147
by John Arbash Meinel
 Move fast id => path lookups down into DirState  | 
2030  | 
if self._id_index is not None:  | 
2031  | 
self._id_index.setdefault(new_id, set()).add(entry[0])  | 
|
| 
2255.2.4
by Robert Collins
 Snapshot dirstate development  | 
2032  | 
|
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
2033  | 
def set_parent_trees(self, trees, ghosts):  | 
2034  | 
"""Set the parent trees for the dirstate.  | 
|
2035  | 
||
2036  | 
        :param trees: A list of revision_id, tree tuples. tree must be provided
 | 
|
2037  | 
            even if the revision_id refers to a ghost: supply an empty tree in 
 | 
|
2038  | 
            this case.
 | 
|
2039  | 
        :param ghosts: A list of the revision_ids that are ghosts at the time
 | 
|
2040  | 
            of setting.
 | 
|
2041  | 
        """ 
 | 
|
| 
2255.2.4
by Robert Collins
 Snapshot dirstate development  | 
2042  | 
        # TODO: generate a list of parent indexes to preserve to save 
 | 
2043  | 
        # processing specific parent trees. In the common case one tree will
 | 
|
2044  | 
        # be preserved - the left most parent.
 | 
|
2045  | 
        # TODO: if the parent tree is a dirstate, we might want to walk them
 | 
|
2046  | 
        # all by path in parallel for 'optimal' common-case performance.
 | 
|
2047  | 
        # generate new root row.
 | 
|
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
2048  | 
self._read_dirblocks_if_needed()  | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
2049  | 
        # TODO future sketch: Examine the existing parents to generate a change
 | 
2050  | 
        # map and then walk the new parent trees only, mapping them into the
 | 
|
2051  | 
        # dirstate. Walk the dirstate at the same time to remove unreferenced
 | 
|
2052  | 
        # entries.
 | 
|
2053  | 
        # for now: 
 | 
|
2054  | 
        # sketch: loop over all entries in the dirstate, cherry picking 
 | 
|
2055  | 
        # entries from the parent trees, if they are not ghost trees.
 | 
|
| 
2255.2.4
by Robert Collins
 Snapshot dirstate development  | 
2056  | 
        # after we finish walking the dirstate, all entries not in the dirstate
 | 
2057  | 
        # are deletes, so we want to append them to the end as per the design
 | 
|
2058  | 
        # discussions. So do a set difference on ids with the parents to
 | 
|
2059  | 
        # get deletes, and add them to the end.
 | 
|
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2060  | 
        # During the update process we need to answer the following questions:
 | 
2061  | 
        # - find other keys containing a fileid in order to create cross-path
 | 
|
2062  | 
        #   links. We dont't trivially use the inventory from other trees
 | 
|
2063  | 
        #   because this leads to either double touching, or to accessing
 | 
|
2064  | 
        #   missing keys,
 | 
|
2065  | 
        # - find other keys containing a path 
 | 
|
2066  | 
        # We accumulate each entry via this dictionary, including the root 
 | 
|
2067  | 
by_path = {}  | 
|
2068  | 
id_index = {}  | 
|
2069  | 
        # we could do parallel iterators, but because file id data may be
 | 
|
2070  | 
        # scattered throughout, we dont save on index overhead: we have to look
 | 
|
2071  | 
        # at everything anyway. We can probably save cycles by reusing parent
 | 
|
2072  | 
        # data and doing an incremental update when adding an additional
 | 
|
2073  | 
        # parent, but for now the common cases are adding a new parent (merge),
 | 
|
2074  | 
        # and replacing completely (commit), and commit is more common: so
 | 
|
2075  | 
        # optimise merge later.
 | 
|
2076  | 
||
2077  | 
        # ---- start generation of full tree mapping data
 | 
|
2078  | 
        # what trees should we use?
 | 
|
| 
2255.2.4
by Robert Collins
 Snapshot dirstate development  | 
2079  | 
parent_trees = [tree for rev_id, tree in trees if rev_id not in ghosts]  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2080  | 
        # how many trees do we end up with 
 | 
2081  | 
parent_count = len(parent_trees)  | 
|
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
2082  | 
|
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2083  | 
        # one: the current tree
 | 
2084  | 
for entry in self._iter_entries():  | 
|
2085  | 
            # skip entries not in the current tree
 | 
|
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
2086  | 
if entry[1][0][0] in 'ar': # absent, relocated  | 
| 
2255.2.85
by Robert Collins
 [BROKEN] Partial conversion to new dirstate structure, please continue on the tests matching dirstate from here.  | 
2087  | 
                continue
 | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2088  | 
by_path[entry[0]] = [entry[1][0]] + \  | 
2089  | 
[DirState.NULL_PARENT_DETAILS] * parent_count  | 
|
2090  | 
id_index[entry[0][2]] = set([entry[0]])  | 
|
2091  | 
||
2092  | 
        # now the parent trees:
 | 
|
2093  | 
for tree_index, tree in enumerate(parent_trees):  | 
|
2094  | 
            # the index is off by one, adjust it.
 | 
|
2095  | 
tree_index = tree_index + 1  | 
|
2096  | 
            # when we add new locations for a fileid we need these ranges for
 | 
|
2097  | 
            # any fileid in this tree as we set the by_path[id] to:
 | 
|
2098  | 
            # already_processed_tree_details + new_details + new_location_suffix
 | 
|
2099  | 
            # the suffix is from tree_index+1:parent_count+1.
 | 
|
2100  | 
new_location_suffix = [DirState.NULL_PARENT_DETAILS] * (parent_count - tree_index)  | 
|
2101  | 
            # now stitch in all the entries from this tree
 | 
|
2102  | 
for path, entry in tree.inventory.iter_entries_by_dir():  | 
|
2103  | 
                # here we process each trees details for each item in the tree.
 | 
|
2104  | 
                # we first update any existing entries for the id at other paths,
 | 
|
2105  | 
                # then we either create or update the entry for the id at the
 | 
|
2106  | 
                # right path, and finally we add (if needed) a mapping from
 | 
|
2107  | 
                # file_id to this path. We do it in this order to allow us to
 | 
|
2108  | 
                # avoid checking all known paths for the id when generating a
 | 
|
2109  | 
                # new entry at this path: by adding the id->path mapping last,
 | 
|
2110  | 
                # all the mappings are valid and have correct relocation
 | 
|
2111  | 
                # records where needed. 
 | 
|
| 
2255.2.107
by John Arbash Meinel
 (working), fix dirstate to use utf8 file ids.  | 
2112  | 
file_id = entry.file_id  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2113  | 
path_utf8 = path.encode('utf8')  | 
| 
2255.2.146
by John Arbash Meinel
 Implement move_directory by factoring out move_one  | 
2114  | 
dirname, basename = osutils.split(path_utf8)  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2115  | 
new_entry_key = (dirname, basename, file_id)  | 
2116  | 
                # tree index consistency: All other paths for this id in this tree
 | 
|
2117  | 
                # index must point to the correct path.
 | 
|
2118  | 
for entry_key in id_index.setdefault(file_id, set()):  | 
|
2119  | 
                    # TODO:PROFILING: It might be faster to just update
 | 
|
2120  | 
                    # rather than checking if we need to, and then overwrite
 | 
|
2121  | 
                    # the one we are located at.
 | 
|
2122  | 
if entry_key != new_entry_key:  | 
|
2123  | 
                        # this file id is at a different path in one of the
 | 
|
2124  | 
                        # other trees, so put absent pointers there
 | 
|
2125  | 
                        # This is the vertical axis in the matrix, all pointing
 | 
|
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
2126  | 
                        # to the real path.
 | 
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
2127  | 
by_path[entry_key][tree_index] = ('r', path_utf8, 0, False, '')  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2128  | 
                # by path consistency: Insert into an existing path record (trivial), or 
 | 
2129  | 
                # add a new one with relocation pointers for the other tree indexes.
 | 
|
2130  | 
if new_entry_key in id_index[file_id]:  | 
|
2131  | 
                    # there is already an entry where this data belongs, just insert it.
 | 
|
2132  | 
by_path[new_entry_key][tree_index] = \  | 
|
2133  | 
self._inv_entry_to_details(entry)  | 
|
2134  | 
else:  | 
|
2135  | 
                    # add relocated entries to the horizontal axis - this row
 | 
|
2136  | 
                    # mapping from path,id. We need to look up the correct path
 | 
|
2137  | 
                    # for the indexes from 0 to tree_index -1
 | 
|
2138  | 
new_details = []  | 
|
2139  | 
for lookup_index in xrange(tree_index):  | 
|
2140  | 
                        # boundary case: this is the first occurence of file_id
 | 
|
2141  | 
                        # so there are no id_indexs, possibly take this out of
 | 
|
2142  | 
                        # the loop?
 | 
|
2143  | 
if not len(id_index[file_id]):  | 
|
2144  | 
new_details.append(DirState.NULL_PARENT_DETAILS)  | 
|
2145  | 
else:  | 
|
2146  | 
                            # grab any one entry, use it to find the right path.
 | 
|
2147  | 
                            # TODO: optimise this to reduce memory use in highly 
 | 
|
2148  | 
                            # fragmented situations by reusing the relocation
 | 
|
2149  | 
                            # records.
 | 
|
2150  | 
a_key = iter(id_index[file_id]).next()  | 
|
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
2151  | 
if by_path[a_key][lookup_index][0] in ('r', 'a'):  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2152  | 
                                # its a pointer or missing statement, use it as is.
 | 
2153  | 
new_details.append(by_path[a_key][lookup_index])  | 
|
2154  | 
else:  | 
|
2155  | 
                                # we have the right key, make a pointer to it.
 | 
|
2156  | 
real_path = ('/'.join(a_key[0:2])).strip('/')  | 
|
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
2157  | 
new_details.append(('r', real_path, 0, False, ''))  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2158  | 
new_details.append(self._inv_entry_to_details(entry))  | 
2159  | 
new_details.extend(new_location_suffix)  | 
|
2160  | 
by_path[new_entry_key] = new_details  | 
|
2161  | 
id_index[file_id].add(new_entry_key)  | 
|
2162  | 
        # --- end generation of full tree mappings
 | 
|
| 
2255.2.9
by Robert Collins
 Dirstate: Fix setting of parent trees to record data about entries not in  | 
2163  | 
|
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2164  | 
        # sort and output all the entries
 | 
| 
2255.7.94
by Martin Pool
 Fix dirstate sorting bug and refine the _validate() assertions:  | 
2165  | 
new_entries = self._sort_entries(by_path.items())  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2166  | 
self._entries_to_current_state(new_entries)  | 
| 
1852.13.24
by Robert Collins
 Get back to the broken-pending-revision-tree-from-dirstate state of development, changing dirstate from_tree to use _set_data rather than generating lines itself.  | 
2167  | 
self._parents = [rev_id for rev_id, tree in trees]  | 
2168  | 
self._ghosts = list(ghosts)  | 
|
2169  | 
self._header_state = DirState.IN_MEMORY_MODIFIED  | 
|
2170  | 
self._dirblock_state = DirState.IN_MEMORY_MODIFIED  | 
|
| 
2255.2.144
by John Arbash Meinel
 Simplify update_minimal a bit more, by making id_index a  | 
2171  | 
self._id_index = id_index  | 
| 
2255.7.94
by Martin Pool
 Fix dirstate sorting bug and refine the _validate() assertions:  | 
2172  | 
|
2173  | 
def _sort_entries(self, entry_list):  | 
|
2174  | 
"""Given a list of entries, sort them into the right order.  | 
|
2175  | 
||
2176  | 
        This is done when constructing a new dirstate from trees - normally we
 | 
|
2177  | 
        try to keep everything in sorted blocks all the time, but sometimes
 | 
|
2178  | 
        it's easier to sort after the fact.
 | 
|
2179  | 
        """
 | 
|
2180  | 
def _key(entry):  | 
|
2181  | 
            # sort by: directory parts, file name, file id
 | 
|
2182  | 
return entry[0][0].split('/'), entry[0][1], entry[0][2]  | 
|
2183  | 
return sorted(entry_list, key=_key)  | 
|
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
2184  | 
|
| 
2255.2.16
by Robert Collins
 Implement WorkingTreeFormat4._write_inventory for better compatability with existing code, letting more test_test_trees pass, now up to test_tree_with_subdirs_and_all_content_types.  | 
2185  | 
def set_state_from_inventory(self, new_inv):  | 
2186  | 
"""Set new_inv as the current state.  | 
|
2187  | 
||
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2188  | 
        This API is called by tree transform, and will usually occur with
 | 
2189  | 
        existing parent trees.
 | 
|
2190  | 
||
| 
2255.2.16
by Robert Collins
 Implement WorkingTreeFormat4._write_inventory for better compatability with existing code, letting more test_test_trees pass, now up to test_tree_with_subdirs_and_all_content_types.  | 
2191  | 
        :param new_inv: The inventory object to set current state from.
 | 
2192  | 
        """
 | 
|
| 
2872.4.2
by Martin Pool
 Treat set_state_from_inventory as evil, and del dead variables rather than just setting to null  | 
2193  | 
if 'evil' in debug.debug_flags:  | 
2194  | 
trace.mutter_callsite(1,  | 
|
2195  | 
"set_state_from_inventory called; please mutate the tree instead")  | 
|
| 
2255.2.16
by Robert Collins
 Implement WorkingTreeFormat4._write_inventory for better compatability with existing code, letting more test_test_trees pass, now up to test_tree_with_subdirs_and_all_content_types.  | 
2196  | 
self._read_dirblocks_if_needed()  | 
2197  | 
        # sketch:
 | 
|
| 
2872.4.11
by Martin Pool
 Review documentation cleanups  | 
2198  | 
        # Two iterators: current data and new data, both in dirblock order. 
 | 
2199  | 
        # We zip them together, which tells about entries that are new in the
 | 
|
2200  | 
        # inventory, or removed in the inventory, or present in both and
 | 
|
2201  | 
        # possibly changed.  
 | 
|
2202  | 
        #
 | 
|
2203  | 
        # You might think we could just synthesize a new dirstate directly
 | 
|
2204  | 
        # since we're processing it in the right order.  However, we need to
 | 
|
2205  | 
        # also consider there may be any number of parent trees and relocation
 | 
|
2206  | 
        # pointers, and we don't want to duplicate that here.
 | 
|
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2207  | 
new_iterator = new_inv.iter_entries_by_dir()  | 
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
2208  | 
        # we will be modifying the dirstate, so we need a stable iterator. In
 | 
2209  | 
        # future we might write one, for now we just clone the state into a
 | 
|
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
2210  | 
        # list - which is a shallow copy.
 | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2211  | 
old_iterator = iter(list(self._iter_entries()))  | 
2212  | 
        # both must have roots so this is safe:
 | 
|
2213  | 
current_new = new_iterator.next()  | 
|
2214  | 
current_old = old_iterator.next()  | 
|
2215  | 
def advance(iterator):  | 
|
| 
2255.2.16
by Robert Collins
 Implement WorkingTreeFormat4._write_inventory for better compatability with existing code, letting more test_test_trees pass, now up to test_tree_with_subdirs_and_all_content_types.  | 
2216  | 
try:  | 
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
2217  | 
return iterator.next()  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2218  | 
except StopIteration:  | 
2219  | 
return None  | 
|
2220  | 
while current_new or current_old:  | 
|
2221  | 
            # skip entries in old that are not really there
 | 
|
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
2222  | 
if current_old and current_old[1][0][0] in 'ar':  | 
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
2223  | 
                # relocated or absent
 | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2224  | 
current_old = advance(old_iterator)  | 
| 
2255.2.16
by Robert Collins
 Implement WorkingTreeFormat4._write_inventory for better compatability with existing code, letting more test_test_trees pass, now up to test_tree_with_subdirs_and_all_content_types.  | 
2225  | 
                continue
 | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2226  | 
if current_new:  | 
2227  | 
                # convert new into dirblock style
 | 
|
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
2228  | 
new_path_utf8 = current_new[0].encode('utf8')  | 
| 
2255.2.146
by John Arbash Meinel
 Implement move_directory by factoring out move_one  | 
2229  | 
new_dirname, new_basename = osutils.split(new_path_utf8)  | 
| 
2255.2.107
by John Arbash Meinel
 (working), fix dirstate to use utf8 file ids.  | 
2230  | 
new_id = current_new[1].file_id  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2231  | 
new_entry_key = (new_dirname, new_basename, new_id)  | 
| 
2255.2.142
by John Arbash Meinel
 Simplify the update_minimal api a little bit, and document the parameters.  | 
2232  | 
current_new_minikind = \  | 
2233  | 
DirState._kind_to_minikind[current_new[1].kind]  | 
|
| 
2255.2.195
by Robert Collins
 Fix set_reference_revision on dirstate format trees.  | 
2234  | 
if current_new_minikind == 't':  | 
| 
2645.2.1
by Wouter van Heyst
 The DirState fingerprint for tree-references should be an empty string instead of None  | 
2235  | 
fingerprint = current_new[1].reference_revision or ''  | 
| 
2255.2.195
by Robert Collins
 Fix set_reference_revision on dirstate format trees.  | 
2236  | 
else:  | 
| 
2872.4.7
by Martin Pool
 More cleanups of dirstate work  | 
2237  | 
                    # We normally only insert or remove records, or update
 | 
2238  | 
                    # them when it has significantly changed.  Then we want to
 | 
|
2239  | 
                    # erase its fingerprint.  Unaffected records should
 | 
|
2240  | 
                    # normally not be updated at all.
 | 
|
| 
2255.2.195
by Robert Collins
 Fix set_reference_revision on dirstate format trees.  | 
2241  | 
fingerprint = ''  | 
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
2242  | 
else:  | 
2243  | 
                # for safety disable variables
 | 
|
| 
2872.4.7
by Martin Pool
 More cleanups of dirstate work  | 
2244  | 
new_path_utf8 = new_dirname = new_basename = new_id = \  | 
| 
2872.4.9
by Martin Pool
 Use cmp_by_dirs in set_state_from_inventory rather than hardcoding the equivalent  | 
2245  | 
new_entry_key = None  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2246  | 
            # 5 cases, we dont have a value that is strictly greater than everything, so
 | 
2247  | 
            # we make both end conditions explicit
 | 
|
| 
2872.4.11
by Martin Pool
 Review documentation cleanups  | 
2248  | 
if not current_old:  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2249  | 
                # old is finished: insert current_new into the state.
 | 
| 
2255.2.142
by John Arbash Meinel
 Simplify the update_minimal api a little bit, and document the parameters.  | 
2250  | 
self.update_minimal(new_entry_key, current_new_minikind,  | 
2251  | 
executable=current_new[1].executable,  | 
|
| 
2255.2.195
by Robert Collins
 Fix set_reference_revision on dirstate format trees.  | 
2252  | 
path_utf8=new_path_utf8, fingerprint=fingerprint)  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2253  | 
current_new = advance(new_iterator)  | 
| 
2872.4.11
by Martin Pool
 Review documentation cleanups  | 
2254  | 
elif not current_new:  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2255  | 
                # new is finished
 | 
| 
2255.2.144
by John Arbash Meinel
 Simplify update_minimal a bit more, by making id_index a  | 
2256  | 
self._make_absent(current_old)  | 
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
2257  | 
current_old = advance(old_iterator)  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2258  | 
elif new_entry_key == current_old[0]:  | 
2259  | 
                # same -  common case
 | 
|
| 
2872.4.3
by Martin Pool
 Fix comparison for merge sort in Dirstate.set_state_from_inventory  | 
2260  | 
                # We're looking at the same path and id in both the dirstate
 | 
2261  | 
                # and inventory, so just need to update the fields in the
 | 
|
2262  | 
                # dirstate from the one in the inventory.
 | 
|
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2263  | 
                # TODO: update the record if anything significant has changed.
 | 
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
2264  | 
                # the minimal required trigger is if the execute bit or cached
 | 
2265  | 
                # kind has changed.
 | 
|
2266  | 
if (current_old[1][0][3] != current_new[1].executable or  | 
|
| 
2255.2.142
by John Arbash Meinel
 Simplify the update_minimal api a little bit, and document the parameters.  | 
2267  | 
current_old[1][0][0] != current_new_minikind):  | 
2268  | 
self.update_minimal(current_old[0], current_new_minikind,  | 
|
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
2269  | 
executable=current_new[1].executable,  | 
| 
2255.2.195
by Robert Collins
 Fix set_reference_revision on dirstate format trees.  | 
2270  | 
path_utf8=new_path_utf8, fingerprint=fingerprint)  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2271  | 
                # both sides are dealt with, move on
 | 
2272  | 
current_old = advance(old_iterator)  | 
|
2273  | 
current_new = advance(new_iterator)  | 
|
| 
2872.4.9
by Martin Pool
 Use cmp_by_dirs in set_state_from_inventory rather than hardcoding the equivalent  | 
2274  | 
elif (cmp_by_dirs(new_dirname, current_old[0][0]) < 0  | 
| 
2872.4.3
by Martin Pool
 Fix comparison for merge sort in Dirstate.set_state_from_inventory  | 
2275  | 
or (new_dirname == current_old[0][0]  | 
2276  | 
and new_entry_key[1:] < current_old[0][1:])):  | 
|
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
2277  | 
                # new comes before:
 | 
2278  | 
                # add a entry for this and advance new
 | 
|
| 
2255.2.142
by John Arbash Meinel
 Simplify the update_minimal api a little bit, and document the parameters.  | 
2279  | 
self.update_minimal(new_entry_key, current_new_minikind,  | 
2280  | 
executable=current_new[1].executable,  | 
|
| 
2255.2.195
by Robert Collins
 Fix set_reference_revision on dirstate format trees.  | 
2281  | 
path_utf8=new_path_utf8, fingerprint=fingerprint)  | 
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
2282  | 
current_new = advance(new_iterator)  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2283  | 
else:  | 
| 
2872.4.3
by Martin Pool
 Fix comparison for merge sort in Dirstate.set_state_from_inventory  | 
2284  | 
                # we've advanced past the place where the old key would be,
 | 
2285  | 
                # without seeing it in the new list.  so it must be gone.
 | 
|
| 
2255.2.144
by John Arbash Meinel
 Simplify update_minimal a bit more, by making id_index a  | 
2286  | 
self._make_absent(current_old)  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2287  | 
current_old = advance(old_iterator)  | 
2288  | 
self._dirblock_state = DirState.IN_MEMORY_MODIFIED  | 
|
| 
2255.2.147
by John Arbash Meinel
 Move fast id => path lookups down into DirState  | 
2289  | 
self._id_index = None  | 
| 
2929.1.1
by Robert Collins
 Use a dict to access stat cache information from dirstate.  | 
2290  | 
self._packed_stat_index = None  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2291  | 
|
| 
2255.2.144
by John Arbash Meinel
 Simplify update_minimal a bit more, by making id_index a  | 
2292  | 
def _make_absent(self, current_old):  | 
| 
2255.2.93
by Robert Collins
 Dirstate - update WorkingTree4.unversion to the new layout, other tests still borked.  | 
2293  | 
"""Mark current_old - an entry - as absent for tree 0.  | 
2294  | 
||
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
2295  | 
        :return: True if this was the last details entry for the entry key:
 | 
| 
2255.2.93
by Robert Collins
 Dirstate - update WorkingTree4.unversion to the new layout, other tests still borked.  | 
2296  | 
            that is, if the underlying block has had the entry removed, thus
 | 
| 
2255.2.138
by John Arbash Meinel
 implement several new WorkingTree.move() tests  | 
2297  | 
            shrinking in length.
 | 
| 
2255.2.93
by Robert Collins
 Dirstate - update WorkingTree4.unversion to the new layout, other tests still borked.  | 
2298  | 
        """
 | 
2299  | 
        # build up paths that this id will be left at after the change is made,
 | 
|
2300  | 
        # so we can update their cross references in tree 0
 | 
|
2301  | 
all_remaining_keys = set()  | 
|
| 
2922.2.4
by John Arbash Meinel
 Fix bug #114615 by teaching unversion() to not touch renamed entries.  | 
2302  | 
        # Dont check the working tree, because it's going.
 | 
| 
2255.2.93
by Robert Collins
 Dirstate - update WorkingTree4.unversion to the new layout, other tests still borked.  | 
2303  | 
for details in current_old[1][1:]:  | 
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
2304  | 
if details[0] not in 'ar': # absent, relocated  | 
| 
2255.2.93
by Robert Collins
 Dirstate - update WorkingTree4.unversion to the new layout, other tests still borked.  | 
2305  | 
all_remaining_keys.add(current_old[0])  | 
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
2306  | 
elif details[0] == 'r': # relocated  | 
| 
2255.2.93
by Robert Collins
 Dirstate - update WorkingTree4.unversion to the new layout, other tests still borked.  | 
2307  | 
                # record the key for the real path.
 | 
| 
2255.2.146
by John Arbash Meinel
 Implement move_directory by factoring out move_one  | 
2308  | 
all_remaining_keys.add(tuple(osutils.split(details[1])) + (current_old[0][2],))  | 
| 
2255.2.93
by Robert Collins
 Dirstate - update WorkingTree4.unversion to the new layout, other tests still borked.  | 
2309  | 
            # absent rows are not present at any path.
 | 
2310  | 
last_reference = current_old[0] not in all_remaining_keys  | 
|
2311  | 
if last_reference:  | 
|
2312  | 
            # the current row consists entire of the current item (being marked
 | 
|
2313  | 
            # absent), and relocated or absent entries for the other trees:
 | 
|
2314  | 
            # Remove it, its meaningless.
 | 
|
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
2315  | 
block = self._find_block(current_old[0])  | 
2316  | 
entry_index, present = self._find_entry_index(current_old[0], block[1])  | 
|
| 
2255.8.4
by John Arbash Meinel
 Rather than using split hunks, implement a bisect_dirblocks  | 
2317  | 
assert present, 'could not find entry for %s' % (current_old,)  | 
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
2318  | 
block[1].pop(entry_index)  | 
| 
2255.2.93
by Robert Collins
 Dirstate - update WorkingTree4.unversion to the new layout, other tests still borked.  | 
2319  | 
            # if we have an id_index in use, remove this key from it for this id.
 | 
| 
2255.2.144
by John Arbash Meinel
 Simplify update_minimal a bit more, by making id_index a  | 
2320  | 
if self._id_index is not None:  | 
2321  | 
self._id_index[current_old[0][2]].remove(current_old[0])  | 
|
| 
2255.2.93
by Robert Collins
 Dirstate - update WorkingTree4.unversion to the new layout, other tests still borked.  | 
2322  | 
        # update all remaining keys for this id to record it as absent. The
 | 
| 
2922.2.2
by John Arbash Meinel
 If THIS is considered renamed, _make_absent needs to remove the renamed target.  | 
2323  | 
        # existing details may either be the record we are marking as deleted
 | 
| 
2255.2.93
by Robert Collins
 Dirstate - update WorkingTree4.unversion to the new layout, other tests still borked.  | 
2324  | 
        # (if there were other trees with the id present at this path), or may
 | 
2325  | 
        # be relocations.
 | 
|
2326  | 
for update_key in all_remaining_keys:  | 
|
2327  | 
update_block_index, present = \  | 
|
2328  | 
self._find_block_index_from_key(update_key)  | 
|
| 
2255.8.4
by John Arbash Meinel
 Rather than using split hunks, implement a bisect_dirblocks  | 
2329  | 
assert present, 'could not find block for %s' % (update_key,)  | 
| 
2255.2.93
by Robert Collins
 Dirstate - update WorkingTree4.unversion to the new layout, other tests still borked.  | 
2330  | 
update_entry_index, present = \  | 
2331  | 
self._find_entry_index(update_key, self._dirblocks[update_block_index][1])  | 
|
| 
2255.8.4
by John Arbash Meinel
 Rather than using split hunks, implement a bisect_dirblocks  | 
2332  | 
assert present, 'could not find entry for %s' % (update_key,)  | 
| 
2255.2.93
by Robert Collins
 Dirstate - update WorkingTree4.unversion to the new layout, other tests still borked.  | 
2333  | 
update_tree_details = self._dirblocks[update_block_index][1][update_entry_index][1]  | 
| 
2922.2.4
by John Arbash Meinel
 Fix bug #114615 by teaching unversion() to not touch renamed entries.  | 
2334  | 
            # it must not be absent at the moment
 | 
2335  | 
assert update_tree_details[0][0] != 'a' # absent  | 
|
| 
2255.2.93
by Robert Collins
 Dirstate - update WorkingTree4.unversion to the new layout, other tests still borked.  | 
2336  | 
update_tree_details[0] = DirState.NULL_PARENT_DETAILS  | 
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
2337  | 
self._dirblock_state = DirState.IN_MEMORY_MODIFIED  | 
| 
2255.2.93
by Robert Collins
 Dirstate - update WorkingTree4.unversion to the new layout, other tests still borked.  | 
2338  | 
return last_reference  | 
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
2339  | 
|
| 
2255.2.142
by John Arbash Meinel
 Simplify the update_minimal api a little bit, and document the parameters.  | 
2340  | 
def update_minimal(self, key, minikind, executable=False, fingerprint='',  | 
| 
2255.2.144
by John Arbash Meinel
 Simplify update_minimal a bit more, by making id_index a  | 
2341  | 
packed_stat=None, size=0, path_utf8=None):  | 
| 
2255.2.142
by John Arbash Meinel
 Simplify the update_minimal api a little bit, and document the parameters.  | 
2342  | 
"""Update an entry to the state in tree 0.  | 
2343  | 
||
2344  | 
        This will either create a new entry at 'key' or update an existing one.
 | 
|
2345  | 
        It also makes sure that any other records which might mention this are
 | 
|
2346  | 
        updated as well.
 | 
|
2347  | 
||
2348  | 
        :param key: (dir, name, file_id) for the new entry
 | 
|
2349  | 
        :param minikind: The type for the entry ('f' == 'file', 'd' ==
 | 
|
2350  | 
                'directory'), etc.
 | 
|
2351  | 
        :param executable: Should the executable bit be set?
 | 
|
| 
2872.4.7
by Martin Pool
 More cleanups of dirstate work  | 
2352  | 
        :param fingerprint: Simple fingerprint for new entry: sha1 for files, 
 | 
2353  | 
            referenced revision id for subtrees, etc.
 | 
|
| 
2872.4.3
by Martin Pool
 Fix comparison for merge sort in Dirstate.set_state_from_inventory  | 
2354  | 
        :param packed_stat: Packed stat value for new entry.
 | 
| 
2255.2.142
by John Arbash Meinel
 Simplify the update_minimal api a little bit, and document the parameters.  | 
2355  | 
        :param size: Size information for new entry
 | 
2356  | 
        :param path_utf8: key[0] + '/' + key[1], just passed in to avoid doing
 | 
|
2357  | 
                extra computation.
 | 
|
| 
2872.4.3
by Martin Pool
 Fix comparison for merge sort in Dirstate.set_state_from_inventory  | 
2358  | 
|
2359  | 
        If packed_stat and fingerprint are not given, they're invalidated in
 | 
|
2360  | 
        the entry.
 | 
|
| 
2255.2.142
by John Arbash Meinel
 Simplify the update_minimal api a little bit, and document the parameters.  | 
2361  | 
        """
 | 
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
2362  | 
block = self._find_block(key)[1]  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2363  | 
if packed_stat is None:  | 
2364  | 
packed_stat = DirState.NULLSTAT  | 
|
| 
2872.4.5
by Martin Pool
 doc  | 
2365  | 
        # XXX: Some callers pass '' as the packed_stat, and it seems to be
 | 
2366  | 
        # sometimes present in the dirstate - this seems oddly inconsistent.
 | 
|
2367  | 
        # mbp 20071008
 | 
|
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2368  | 
entry_index, present = self._find_entry_index(key, block)  | 
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
2369  | 
new_details = (minikind, fingerprint, size, executable, packed_stat)  | 
| 
2255.2.144
by John Arbash Meinel
 Simplify update_minimal a bit more, by making id_index a  | 
2370  | 
id_index = self._get_id_index()  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2371  | 
if not present:  | 
2372  | 
            # new entry, synthesis cross reference here,
 | 
|
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
2373  | 
existing_keys = id_index.setdefault(key[2], set())  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2374  | 
if not existing_keys:  | 
2375  | 
                # not currently in the state, simplest case
 | 
|
2376  | 
new_entry = key, [new_details] + self._empty_parent_info()  | 
|
2377  | 
else:  | 
|
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
2378  | 
                # present at one or more existing other paths.
 | 
2379  | 
                # grab one of them and use it to generate parent
 | 
|
2380  | 
                # relocation/absent entries.
 | 
|
2381  | 
new_entry = key, [new_details]  | 
|
2382  | 
for other_key in existing_keys:  | 
|
2383  | 
                    # change the record at other to be a pointer to this new
 | 
|
2384  | 
                    # record. The loop looks similar to the change to
 | 
|
2385  | 
                    # relocations when updating an existing record but its not:
 | 
|
2386  | 
                    # the test for existing kinds is different: this can be
 | 
|
2387  | 
                    # factored out to a helper though.
 | 
|
2388  | 
other_block_index, present = self._find_block_index_from_key(other_key)  | 
|
| 
2255.8.4
by John Arbash Meinel
 Rather than using split hunks, implement a bisect_dirblocks  | 
2389  | 
assert present, 'could not find block for %s' % (other_key,)  | 
2390  | 
other_entry_index, present = self._find_entry_index(other_key,  | 
|
2391  | 
self._dirblocks[other_block_index][1])  | 
|
2392  | 
assert present, 'could not find entry for %s' % (other_key,)  | 
|
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
2393  | 
assert path_utf8 is not None  | 
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
2394  | 
self._dirblocks[other_block_index][1][other_entry_index][1][0] = \  | 
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
2395  | 
('r', path_utf8, 0, False, '')  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2396  | 
|
| 
2255.2.142
by John Arbash Meinel
 Simplify the update_minimal api a little bit, and document the parameters.  | 
2397  | 
num_present_parents = self._num_present_parents()  | 
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
2398  | 
for lookup_index in xrange(1, num_present_parents + 1):  | 
2399  | 
                    # grab any one entry, use it to find the right path.
 | 
|
2400  | 
                    # TODO: optimise this to reduce memory use in highly 
 | 
|
2401  | 
                    # fragmented situations by reusing the relocation
 | 
|
2402  | 
                    # records.
 | 
|
2403  | 
update_block_index, present = \  | 
|
2404  | 
self._find_block_index_from_key(other_key)  | 
|
| 
2255.8.4
by John Arbash Meinel
 Rather than using split hunks, implement a bisect_dirblocks  | 
2405  | 
assert present, 'could not find block for %s' % (other_key,)  | 
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
2406  | 
update_entry_index, present = \  | 
2407  | 
self._find_entry_index(other_key, self._dirblocks[update_block_index][1])  | 
|
| 
2255.8.4
by John Arbash Meinel
 Rather than using split hunks, implement a bisect_dirblocks  | 
2408  | 
assert present, 'could not find entry for %s' % (other_key,)  | 
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
2409  | 
update_details = self._dirblocks[update_block_index][1][update_entry_index][1][lookup_index]  | 
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
2410  | 
if update_details[0] in 'ar': # relocated, absent  | 
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
2411  | 
                        # its a pointer or absent in lookup_index's tree, use
 | 
2412  | 
                        # it as is.
 | 
|
2413  | 
new_entry[1].append(update_details)  | 
|
2414  | 
else:  | 
|
2415  | 
                        # we have the right key, make a pointer to it.
 | 
|
| 
2255.2.146
by John Arbash Meinel
 Implement move_directory by factoring out move_one  | 
2416  | 
pointer_path = osutils.pathjoin(*other_key[0:2])  | 
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
2417  | 
new_entry[1].append(('r', pointer_path, 0, False, ''))  | 
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2418  | 
block.insert(entry_index, new_entry)  | 
2419  | 
existing_keys.add(key)  | 
|
2420  | 
else:  | 
|
2421  | 
            # Does the new state matter? 
 | 
|
2422  | 
block[entry_index][1][0] = new_details  | 
|
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
2423  | 
            # parents cannot be affected by what we do.
 | 
2424  | 
            # other occurences of this id can be found 
 | 
|
2425  | 
            # from the id index.
 | 
|
2426  | 
            # ---
 | 
|
2427  | 
            # tree index consistency: All other paths for this id in this tree
 | 
|
2428  | 
            # index must point to the correct path. We have to loop here because
 | 
|
2429  | 
            # we may have passed entries in the state with this file id already
 | 
|
2430  | 
            # that were absent - where parent entries are - and they need to be
 | 
|
2431  | 
            # converted to relocated.
 | 
|
2432  | 
assert path_utf8 is not None  | 
|
2433  | 
for entry_key in id_index.setdefault(key[2], set()):  | 
|
2434  | 
                # TODO:PROFILING: It might be faster to just update
 | 
|
2435  | 
                # rather than checking if we need to, and then overwrite
 | 
|
2436  | 
                # the one we are located at.
 | 
|
2437  | 
if entry_key != key:  | 
|
2438  | 
                    # this file id is at a different path in one of the
 | 
|
2439  | 
                    # other trees, so put absent pointers there
 | 
|
2440  | 
                    # This is the vertical axis in the matrix, all pointing
 | 
|
2441  | 
                    # to the real path.
 | 
|
2442  | 
block_index, present = self._find_block_index_from_key(entry_key)  | 
|
2443  | 
assert present  | 
|
2444  | 
entry_index, present = self._find_entry_index(entry_key, self._dirblocks[block_index][1])  | 
|
2445  | 
assert present  | 
|
2446  | 
self._dirblocks[block_index][1][entry_index][1][0] = \  | 
|
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
2447  | 
('r', path_utf8, 0, False, '')  | 
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
2448  | 
        # add a containing dirblock if needed.
 | 
| 
2255.2.113
by John Arbash Meinel
 545ms, 600ms: Switch memory model from storing kind to using minikind  | 
2449  | 
if new_details[0] == 'd':  | 
| 
2255.2.146
by John Arbash Meinel
 Implement move_directory by factoring out move_one  | 
2450  | 
subdir_key = (osutils.pathjoin(*key[0:2]), '', '')  | 
| 
2255.2.96
by Robert Collins
 Restore dirstate to all tests passing condition.  | 
2451  | 
block_index, present = self._find_block_index_from_key(subdir_key)  | 
2452  | 
if not present:  | 
|
2453  | 
self._dirblocks.insert(block_index, (subdir_key[0], []))  | 
|
| 
2255.2.88
by Robert Collins
 Significant steps back to operation.  | 
2454  | 
|
| 
2255.2.87
by Robert Collins
 core dirstate tests passing with new structure.  | 
2455  | 
self._dirblock_state = DirState.IN_MEMORY_MODIFIED  | 
2456  | 
||
| 
2255.2.168
by Martin Pool
 merge robert, debugging  | 
2457  | 
def _validate(self):  | 
2458  | 
"""Check that invariants on the dirblock are correct.  | 
|
2459  | 
||
2460  | 
        This can be useful in debugging; it shouldn't be necessary in 
 | 
|
2461  | 
        normal code.
 | 
|
| 
2323.6.13
by Martin Pool
 Fix some tests that need to lock dirstate before validating  | 
2462  | 
|
2463  | 
        This must be called with a lock held.
 | 
|
| 
2255.2.168
by Martin Pool
 merge robert, debugging  | 
2464  | 
        """
 | 
| 
2323.5.12
by Martin Pool
 doc  | 
2465  | 
        # NOTE: This must always raise AssertionError not just assert,
 | 
2466  | 
        # otherwise it may not behave properly under python -O
 | 
|
2467  | 
        #
 | 
|
| 
2323.5.7
by Martin Pool
 Better DirState._validate and tests for it.  | 
2468  | 
        # TODO: All entries must have some content that's not 'a' or 'r',
 | 
2469  | 
        # otherwise it could just be removed.
 | 
|
2470  | 
        #
 | 
|
2471  | 
        # TODO: All relocations must point directly to a real entry.
 | 
|
2472  | 
        #
 | 
|
2473  | 
        # TODO: No repeated keys.
 | 
|
2474  | 
        #
 | 
|
2475  | 
        # -- mbp 20070325
 | 
|
| 
2255.2.168
by Martin Pool
 merge robert, debugging  | 
2476  | 
from pprint import pformat  | 
| 
2323.5.7
by Martin Pool
 Better DirState._validate and tests for it.  | 
2477  | 
self._read_dirblocks_if_needed()  | 
| 
2255.2.168
by Martin Pool
 merge robert, debugging  | 
2478  | 
if len(self._dirblocks) > 0:  | 
| 
2323.5.10
by Martin Pool
 DirState._validate must raise AssertionError rather than using assert  | 
2479  | 
if not self._dirblocks[0][0] == '':  | 
2480  | 
raise AssertionError(  | 
|
| 
2255.2.168
by Martin Pool
 merge robert, debugging  | 
2481  | 
"dirblocks don't start with root block:\n" + \  | 
| 
2323.5.10
by Martin Pool
 DirState._validate must raise AssertionError rather than using assert  | 
2482  | 
pformat(dirblocks))  | 
| 
2255.2.168
by Martin Pool
 merge robert, debugging  | 
2483  | 
if len(self._dirblocks) > 1:  | 
| 
2323.5.10
by Martin Pool
 DirState._validate must raise AssertionError rather than using assert  | 
2484  | 
if not self._dirblocks[1][0] == '':  | 
2485  | 
raise AssertionError(  | 
|
| 
2255.2.168
by Martin Pool
 merge robert, debugging  | 
2486  | 
"dirblocks missing root directory:\n" + \  | 
| 
2323.5.10
by Martin Pool
 DirState._validate must raise AssertionError rather than using assert  | 
2487  | 
pformat(dirblocks))  | 
| 
2255.7.94
by Martin Pool
 Fix dirstate sorting bug and refine the _validate() assertions:  | 
2488  | 
        # the dirblocks are sorted by their path components, name, and dir id
 | 
2489  | 
dir_names = [d[0].split('/')  | 
|
2490  | 
for d in self._dirblocks[1:]]  | 
|
2491  | 
if dir_names != sorted(dir_names):  | 
|
2492  | 
raise AssertionError(  | 
|
2493  | 
"dir names are not in sorted order:\n" + \  | 
|
2494  | 
pformat(self._dirblocks) + \  | 
|
2495  | 
"\nkeys:\n" +  | 
|
2496  | 
pformat(dir_names))  | 
|
| 
2255.2.168
by Martin Pool
 merge robert, debugging  | 
2497  | 
for dirblock in self._dirblocks:  | 
| 
2255.7.94
by Martin Pool
 Fix dirstate sorting bug and refine the _validate() assertions:  | 
2498  | 
            # within each dirblock, the entries are sorted by filename and
 | 
| 
2323.5.12
by Martin Pool
 doc  | 
2499  | 
            # then by id.
 | 
| 
2323.5.6
by Martin Pool
 Add some tests and better messages for DirState._validate  | 
2500  | 
for entry in dirblock[1]:  | 
| 
2323.5.10
by Martin Pool
 DirState._validate must raise AssertionError rather than using assert  | 
2501  | 
if dirblock[0] != entry[0][0]:  | 
2502  | 
raise AssertionError(  | 
|
2503  | 
"entry key for %r"  | 
|
2504  | 
"doesn't match directory name in\n%r" %  | 
|
2505  | 
(entry, pformat(dirblock)))  | 
|
2506  | 
if dirblock[1] != sorted(dirblock[1]):  | 
|
2507  | 
raise AssertionError(  | 
|
2508  | 
"dirblock for %r is not sorted:\n%s" % \  | 
|
2509  | 
(dirblock[0], pformat(dirblock)))  | 
|
| 
2255.2.16
by Robert Collins
 Implement WorkingTreeFormat4._write_inventory for better compatability with existing code, letting more test_test_trees pass, now up to test_tree_with_subdirs_and_all_content_types.  | 
2510  | 
|
| 
2438.1.2
by John Arbash Meinel
 Add a check that all entries have a valid parent entry.  | 
2511  | 
def check_valid_parent():  | 
2512  | 
"""Check that the current entry has a valid parent.  | 
|
2513  | 
||
2514  | 
            This makes sure that the parent has a record,
 | 
|
2515  | 
            and that the parent isn't marked as "absent" in the
 | 
|
2516  | 
            current tree. (It is invalid to have a non-absent file in an absent
 | 
|
2517  | 
            directory.)
 | 
|
2518  | 
            """
 | 
|
2519  | 
if entry[0][0:2] == ('', ''):  | 
|
2520  | 
                # There should be no parent for the root row
 | 
|
2521  | 
                return
 | 
|
2522  | 
parent_entry = self._get_entry(tree_index, path_utf8=entry[0][0])  | 
|
2523  | 
if parent_entry == (None, None):  | 
|
2524  | 
raise AssertionError(  | 
|
2525  | 
"no parent entry for: %s in tree %s"  | 
|
2526  | 
% (this_path, tree_index))  | 
|
| 
2438.1.15
by John Arbash Meinel
 Remove a superfluous 'else' (recommended by Martin)  | 
2527  | 
if parent_entry[1][tree_index][0] != 'd':  | 
2528  | 
raise AssertionError(  | 
|
2529  | 
"Parent entry for %s is not marked as a valid"  | 
|
2530  | 
" directory. %s" % (this_path, parent_entry,))  | 
|
| 
2438.1.2
by John Arbash Meinel
 Add a check that all entries have a valid parent entry.  | 
2531  | 
|
| 
2323.5.6
by Martin Pool
 Add some tests and better messages for DirState._validate  | 
2532  | 
        # For each file id, for each tree: either
 | 
2533  | 
        # the file id is not present at all; all rows with that id in the
 | 
|
2534  | 
        # key have it marked as 'absent'
 | 
|
2535  | 
        # OR the file id is present under exactly one name; any other entries 
 | 
|
2536  | 
        # that mention that id point to the correct name.
 | 
|
2537  | 
        #
 | 
|
2538  | 
        # We check this with a dict per tree pointing either to the present
 | 
|
2539  | 
        # name, or None if absent.
 | 
|
| 
2323.5.7
by Martin Pool
 Better DirState._validate and tests for it.  | 
2540  | 
tree_count = self._num_present_parents() + 1  | 
2541  | 
id_path_maps = [dict() for i in range(tree_count)]  | 
|
| 
2371.2.1
by John Arbash Meinel
 Update DirState._validate() to detect rename errors.  | 
2542  | 
        # Make sure that all renamed entries point to the correct location.
 | 
2543  | 
for entry in self._iter_entries():  | 
|
| 
2323.5.6
by Martin Pool
 Add some tests and better messages for DirState._validate  | 
2544  | 
file_id = entry[0][2]  | 
| 
2323.5.7
by Martin Pool
 Better DirState._validate and tests for it.  | 
2545  | 
this_path = osutils.pathjoin(entry[0][0], entry[0][1])  | 
| 
2323.5.10
by Martin Pool
 DirState._validate must raise AssertionError rather than using assert  | 
2546  | 
if len(entry[1]) != tree_count:  | 
2547  | 
raise AssertionError(  | 
|
| 
2323.5.7
by Martin Pool
 Better DirState._validate and tests for it.  | 
2548  | 
"wrong number of entry details for row\n%s" \  | 
2549  | 
",\nexpected %d" % \  | 
|
| 
2323.5.10
by Martin Pool
 DirState._validate must raise AssertionError rather than using assert  | 
2550  | 
(pformat(entry), tree_count))  | 
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
2551  | 
absent_positions = 0  | 
| 
2371.2.1
by John Arbash Meinel
 Update DirState._validate() to detect rename errors.  | 
2552  | 
for tree_index, tree_state in enumerate(entry[1]):  | 
| 
2323.5.7
by Martin Pool
 Better DirState._validate and tests for it.  | 
2553  | 
this_tree_map = id_path_maps[tree_index]  | 
2554  | 
minikind = tree_state[0]  | 
|
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
2555  | 
if minikind in 'ar':  | 
2556  | 
absent_positions += 1  | 
|
| 
2323.5.7
by Martin Pool
 Better DirState._validate and tests for it.  | 
2557  | 
                # have we seen this id before in this column?
 | 
2558  | 
if file_id in this_tree_map:  | 
|
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
2559  | 
previous_path, previous_loc = this_tree_map[file_id]  | 
| 
2323.5.7
by Martin Pool
 Better DirState._validate and tests for it.  | 
2560  | 
                    # any later mention of this file must be consistent with
 | 
2561  | 
                    # what was said before
 | 
|
2562  | 
if minikind == 'a':  | 
|
| 
2323.5.10
by Martin Pool
 DirState._validate must raise AssertionError rather than using assert  | 
2563  | 
if previous_path is not None:  | 
2564  | 
raise AssertionError(  | 
|
| 
2323.5.7
by Martin Pool
 Better DirState._validate and tests for it.  | 
2565  | 
"file %s is absent in row %r but also present " \  | 
2566  | 
"at %r"% \  | 
|
| 
2323.5.10
by Martin Pool
 DirState._validate must raise AssertionError rather than using assert  | 
2567  | 
(file_id, entry, previous_path))  | 
| 
2323.5.7
by Martin Pool
 Better DirState._validate and tests for it.  | 
2568  | 
elif minikind == 'r':  | 
2569  | 
target_location = tree_state[1]  | 
|
| 
2323.5.10
by Martin Pool
 DirState._validate must raise AssertionError rather than using assert  | 
2570  | 
if previous_path != target_location:  | 
2571  | 
raise AssertionError(  | 
|
| 
2323.5.7
by Martin Pool
 Better DirState._validate and tests for it.  | 
2572  | 
"file %s relocation in row %r but also at %r" \  | 
| 
2323.5.10
by Martin Pool
 DirState._validate must raise AssertionError rather than using assert  | 
2573  | 
% (file_id, entry, previous_path))  | 
| 
2323.5.7
by Martin Pool
 Better DirState._validate and tests for it.  | 
2574  | 
else:  | 
2575  | 
                        # a file, directory, etc - may have been previously
 | 
|
2576  | 
                        # pointed to by a relocation, which must point here
 | 
|
| 
2323.5.10
by Martin Pool
 DirState._validate must raise AssertionError rather than using assert  | 
2577  | 
if previous_path != this_path:  | 
2578  | 
raise AssertionError(  | 
|
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
2579  | 
"entry %r inconsistent with previous path %r "  | 
2580  | 
"seen at %r" %  | 
|
2581  | 
(entry, previous_path, previous_loc))  | 
|
| 
2438.1.2
by John Arbash Meinel
 Add a check that all entries have a valid parent entry.  | 
2582  | 
check_valid_parent()  | 
| 
2323.5.7
by Martin Pool
 Better DirState._validate and tests for it.  | 
2583  | 
else:  | 
2584  | 
if minikind == 'a':  | 
|
2585  | 
                        # absent; should not occur anywhere else
 | 
|
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
2586  | 
this_tree_map[file_id] = None, this_path  | 
| 
2323.5.7
by Martin Pool
 Better DirState._validate and tests for it.  | 
2587  | 
elif minikind == 'r':  | 
2588  | 
                        # relocation, must occur at expected location 
 | 
|
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
2589  | 
this_tree_map[file_id] = tree_state[1], this_path  | 
| 
2323.5.7
by Martin Pool
 Better DirState._validate and tests for it.  | 
2590  | 
else:  | 
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
2591  | 
this_tree_map[file_id] = this_path, this_path  | 
| 
2438.1.2
by John Arbash Meinel
 Add a check that all entries have a valid parent entry.  | 
2592  | 
check_valid_parent()  | 
| 
2929.2.2
by Robert Collins
 Review feedback on dirstate update_basis_via_delta logic.  | 
2593  | 
if absent_positions == tree_count:  | 
2594  | 
raise AssertionError(  | 
|
2595  | 
"entry %r has no data for any tree." % (entry,))  | 
|
| 
2371.2.1
by John Arbash Meinel
 Update DirState._validate() to detect rename errors.  | 
2596  | 
|
| 
2255.4.2
by James Westby
 (broken) Add the locking methods.  | 
2597  | 
def _wipe_state(self):  | 
2598  | 
"""Forget all state information about the dirstate."""  | 
|
2599  | 
self._header_state = DirState.NOT_IN_MEMORY  | 
|
2600  | 
self._dirblock_state = DirState.NOT_IN_MEMORY  | 
|
2601  | 
self._parents = []  | 
|
2602  | 
self._ghosts = []  | 
|
2603  | 
self._dirblocks = []  | 
|
| 
2255.10.6
by John Arbash Meinel
 Save approx 30-60ms (5-10%) on a LP tree by not calling time.time() for every entry.  | 
2604  | 
self._id_index = None  | 
| 
2929.1.1
by Robert Collins
 Use a dict to access stat cache information from dirstate.  | 
2605  | 
self._packed_stat_index = None  | 
| 
2255.10.6
by John Arbash Meinel
 Save approx 30-60ms (5-10%) on a LP tree by not calling time.time() for every entry.  | 
2606  | 
self._end_of_header = None  | 
2607  | 
self._cutoff_time = None  | 
|
2608  | 
self._split_path_cache = {}  | 
|
| 
2255.4.2
by James Westby
 (broken) Add the locking methods.  | 
2609  | 
|
2610  | 
def lock_read(self):  | 
|
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
2611  | 
"""Acquire a read lock on the dirstate."""  | 
| 
2255.4.2
by James Westby
 (broken) Add the locking methods.  | 
2612  | 
if self._lock_token is not None:  | 
2613  | 
raise errors.LockContention(self._lock_token)  | 
|
| 
2255.10.2
by John Arbash Meinel
 Update to dirstate locking.  | 
2614  | 
        # TODO: jam 20070301 Rather than wiping completely, if the blocks are
 | 
2615  | 
        #       already in memory, we could read just the header and check for
 | 
|
2616  | 
        #       any modification. If not modified, we can just leave things
 | 
|
2617  | 
        #       alone
 | 
|
| 
2255.4.2
by James Westby
 (broken) Add the locking methods.  | 
2618  | 
self._lock_token = lock.ReadLock(self._filename)  | 
| 
2255.10.2
by John Arbash Meinel
 Update to dirstate locking.  | 
2619  | 
self._lock_state = 'r'  | 
| 
2255.5.2
by John Arbash Meinel
 (broken) lock and unlock the DirState object when locking and unlocking the Tree itself  | 
2620  | 
self._state_file = self._lock_token.f  | 
| 
2255.4.2
by James Westby
 (broken) Add the locking methods.  | 
2621  | 
self._wipe_state()  | 
| 
2255.5.1
by John Arbash Meinel
 Update the dirstate tests to lock and unlock properly.  | 
2622  | 
|
| 
2255.4.2
by James Westby
 (broken) Add the locking methods.  | 
2623  | 
def lock_write(self):  | 
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
2624  | 
"""Acquire a write lock on the dirstate."""  | 
| 
2255.4.2
by James Westby
 (broken) Add the locking methods.  | 
2625  | 
if self._lock_token is not None:  | 
2626  | 
raise errors.LockContention(self._lock_token)  | 
|
| 
2255.10.2
by John Arbash Meinel
 Update to dirstate locking.  | 
2627  | 
        # TODO: jam 20070301 Rather than wiping completely, if the blocks are
 | 
2628  | 
        #       already in memory, we could read just the header and check for
 | 
|
2629  | 
        #       any modification. If not modified, we can just leave things
 | 
|
2630  | 
        #       alone
 | 
|
| 
2255.4.2
by James Westby
 (broken) Add the locking methods.  | 
2631  | 
self._lock_token = lock.WriteLock(self._filename)  | 
| 
2255.10.2
by John Arbash Meinel
 Update to dirstate locking.  | 
2632  | 
self._lock_state = 'w'  | 
| 
2255.5.2
by John Arbash Meinel
 (broken) lock and unlock the DirState object when locking and unlocking the Tree itself  | 
2633  | 
self._state_file = self._lock_token.f  | 
| 
2255.4.2
by James Westby
 (broken) Add the locking methods.  | 
2634  | 
self._wipe_state()  | 
2635  | 
||
2636  | 
def unlock(self):  | 
|
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
2637  | 
"""Drop any locks held on the dirstate."""  | 
| 
2255.4.2
by James Westby
 (broken) Add the locking methods.  | 
2638  | 
if self._lock_token is None:  | 
2639  | 
raise errors.LockNotHeld(self)  | 
|
| 
2255.10.2
by John Arbash Meinel
 Update to dirstate locking.  | 
2640  | 
        # TODO: jam 20070301 Rather than wiping completely, if the blocks are
 | 
2641  | 
        #       already in memory, we could read just the header and check for
 | 
|
2642  | 
        #       any modification. If not modified, we can just leave things
 | 
|
2643  | 
        #       alone
 | 
|
| 
2255.5.2
by John Arbash Meinel
 (broken) lock and unlock the DirState object when locking and unlocking the Tree itself  | 
2644  | 
self._state_file = None  | 
| 
2255.10.2
by John Arbash Meinel
 Update to dirstate locking.  | 
2645  | 
self._lock_state = None  | 
| 
2255.4.2
by James Westby
 (broken) Add the locking methods.  | 
2646  | 
self._lock_token.unlock()  | 
2647  | 
self._lock_token = None  | 
|
| 
2255.7.20
by John Arbash Meinel
 update test for format 3, and enable caching of path split while lock is held.  | 
2648  | 
self._split_path_cache = {}  | 
| 
2255.4.2
by James Westby
 (broken) Add the locking methods.  | 
2649  | 
|
2650  | 
def _requires_lock(self):  | 
|
| 
2818.2.1
by Ian Clatworthy
 minor tree & dirstate code cleanups  | 
2651  | 
"""Check that a lock is currently held by someone on the dirstate."""  | 
| 
2255.4.2
by James Westby
 (broken) Add the locking methods.  | 
2652  | 
if not self._lock_token:  | 
2653  | 
raise errors.ObjectNotLocked(self)  | 
|
| 
1852.13.20
by Robert Collins
 Steps toward an object model.  | 
2654  | 
|
| 
2255.8.2
by John Arbash Meinel
 Add a helper function, which allows us to store keys as plain paths,  | 
2655  | 
|
| 
2474.1.1
by John Arbash Meinel
 Create a Pyrex extension for reading the dirstate file.  | 
2656  | 
# Try to load the compiled form if possible
 | 
2657  | 
try:  | 
|
| 
2474.1.57
by John Arbash Meinel
 Move code around to refactor according to our pyrex extension design.  | 
2658  | 
from bzrlib._dirstate_helpers_c import (  | 
2659  | 
_read_dirblocks_c as _read_dirblocks,  | 
|
2660  | 
bisect_dirblock_c as bisect_dirblock,  | 
|
| 
2474.1.66
by John Arbash Meinel
 Some restructuring.  | 
2661  | 
_bisect_path_left_c as _bisect_path_left,  | 
2662  | 
_bisect_path_right_c as _bisect_path_right,  | 
|
| 
2474.1.57
by John Arbash Meinel
 Move code around to refactor according to our pyrex extension design.  | 
2663  | 
cmp_by_dirs_c as cmp_by_dirs,  | 
| 
2474.1.21
by John Arbash Meinel
 Cleanup the multiple testing.  | 
2664  | 
        )
 | 
| 
2474.1.1
by John Arbash Meinel
 Create a Pyrex extension for reading the dirstate file.  | 
2665  | 
except ImportError:  | 
| 
2474.1.57
by John Arbash Meinel
 Move code around to refactor according to our pyrex extension design.  | 
2666  | 
from bzrlib._dirstate_helpers_py import (  | 
2667  | 
_read_dirblocks_py as _read_dirblocks,  | 
|
2668  | 
bisect_dirblock_py as bisect_dirblock,  | 
|
| 
2474.1.66
by John Arbash Meinel
 Some restructuring.  | 
2669  | 
_bisect_path_left_py as _bisect_path_left,  | 
2670  | 
_bisect_path_right_py as _bisect_path_right,  | 
|
| 
2474.1.57
by John Arbash Meinel
 Move code around to refactor according to our pyrex extension design.  | 
2671  | 
cmp_by_dirs_py as cmp_by_dirs,  | 
2672  | 
        )
 |