|
@@
-1,609
+1,624
b''
|
|
1
|
"""
|
|
1
|
"""
|
|
2
|
dirstate.py - working directory tracking for mercurial
|
|
2
|
dirstate.py - working directory tracking for mercurial
|
|
3
|
|
|
3
|
|
|
4
|
Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
|
|
4
|
Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
|
|
5
|
|
|
5
|
|
|
6
|
This software may be used and distributed according to the terms
|
|
6
|
This software may be used and distributed according to the terms
|
|
7
|
of the GNU General Public License, incorporated herein by reference.
|
|
7
|
of the GNU General Public License, incorporated herein by reference.
|
|
8
|
"""
|
|
8
|
"""
|
|
9
|
|
|
9
|
|
|
10
|
from node import nullid
|
|
10
|
from node import nullid
|
|
11
|
from i18n import _
|
|
11
|
from i18n import _
|
|
12
|
import struct, os, bisect, stat, strutil, util, errno, ignore
|
|
12
|
import struct, os, bisect, stat, strutil, util, errno, ignore
|
|
13
|
import cStringIO, osutil
|
|
13
|
import cStringIO, osutil
|
|
14
|
|
|
14
|
|
|
15
|
_unknown = ('?', 0, 0, 0)
|
|
15
|
_unknown = ('?', 0, 0, 0)
|
|
16
|
_format = ">cllll"
|
|
16
|
_format = ">cllll"
|
|
17
|
|
|
17
|
|
|
18
|
class dirstate(object):
|
|
18
|
class dirstate(object):
|
|
19
|
|
|
19
|
|
|
20
|
def __init__(self, opener, ui, root):
|
|
20
|
def __init__(self, opener, ui, root):
|
|
21
|
self._opener = opener
|
|
21
|
self._opener = opener
|
|
22
|
self._root = root
|
|
22
|
self._root = root
|
|
23
|
self._dirty = False
|
|
23
|
self._dirty = False
|
|
24
|
self._dirtypl = False
|
|
24
|
self._dirtypl = False
|
|
25
|
self._ui = ui
|
|
25
|
self._ui = ui
|
|
26
|
|
|
26
|
|
|
27
|
def __getattr__(self, name):
|
|
27
|
def __getattr__(self, name):
|
|
28
|
if name == '_map':
|
|
28
|
if name == '_map':
|
|
29
|
self._read()
|
|
29
|
self._read()
|
|
30
|
return self._map
|
|
30
|
return self._map
|
|
31
|
elif name == '_copymap':
|
|
31
|
elif name == '_copymap':
|
|
32
|
self._read()
|
|
32
|
self._read()
|
|
33
|
return self._copymap
|
|
33
|
return self._copymap
|
|
34
|
elif name == '_branch':
|
|
34
|
elif name == '_branch':
|
|
35
|
try:
|
|
35
|
try:
|
|
36
|
self._branch = (self._opener("branch").read().strip()
|
|
36
|
self._branch = (self._opener("branch").read().strip()
|
|
37
|
or "default")
|
|
37
|
or "default")
|
|
38
|
except IOError:
|
|
38
|
except IOError:
|
|
39
|
self._branch = "default"
|
|
39
|
self._branch = "default"
|
|
40
|
return self._branch
|
|
40
|
return self._branch
|
|
41
|
elif name == '_pl':
|
|
41
|
elif name == '_pl':
|
|
42
|
self._pl = [nullid, nullid]
|
|
42
|
self._pl = [nullid, nullid]
|
|
43
|
try:
|
|
43
|
try:
|
|
44
|
st = self._opener("dirstate").read(40)
|
|
44
|
st = self._opener("dirstate").read(40)
|
|
45
|
if len(st) == 40:
|
|
45
|
if len(st) == 40:
|
|
46
|
self._pl = st[:20], st[20:40]
|
|
46
|
self._pl = st[:20], st[20:40]
|
|
47
|
except IOError, err:
|
|
47
|
except IOError, err:
|
|
48
|
if err.errno != errno.ENOENT: raise
|
|
48
|
if err.errno != errno.ENOENT: raise
|
|
49
|
return self._pl
|
|
49
|
return self._pl
|
|
50
|
elif name == '_dirs':
|
|
50
|
elif name == '_dirs':
|
|
51
|
self._dirs = {}
|
|
51
|
self._dirs = {}
|
|
52
|
for f in self._map:
|
|
52
|
for f in self._map:
|
|
53
|
if self[f] != 'r':
|
|
53
|
if self[f] != 'r':
|
|
54
|
self._incpath(f)
|
|
54
|
self._incpath(f)
|
|
55
|
return self._dirs
|
|
55
|
return self._dirs
|
|
56
|
elif name == '_ignore':
|
|
56
|
elif name == '_ignore':
|
|
57
|
files = [self._join('.hgignore')]
|
|
57
|
files = [self._join('.hgignore')]
|
|
58
|
for name, path in self._ui.configitems("ui"):
|
|
58
|
for name, path in self._ui.configitems("ui"):
|
|
59
|
if name == 'ignore' or name.startswith('ignore.'):
|
|
59
|
if name == 'ignore' or name.startswith('ignore.'):
|
|
60
|
files.append(os.path.expanduser(path))
|
|
60
|
files.append(os.path.expanduser(path))
|
|
61
|
self._ignore = ignore.ignore(self._root, files, self._ui.warn)
|
|
61
|
self._ignore = ignore.ignore(self._root, files, self._ui.warn)
|
|
62
|
return self._ignore
|
|
62
|
return self._ignore
|
|
63
|
elif name == '_slash':
|
|
63
|
elif name == '_slash':
|
|
64
|
self._slash = self._ui.configbool('ui', 'slash') and os.sep != '/'
|
|
64
|
self._slash = self._ui.configbool('ui', 'slash') and os.sep != '/'
|
|
65
|
return self._slash
|
|
65
|
return self._slash
|
|
66
|
elif name == '_checkexec':
|
|
66
|
elif name == '_checkexec':
|
|
67
|
self._checkexec = util.checkexec(self._root)
|
|
67
|
self._checkexec = util.checkexec(self._root)
|
|
68
|
return self._checkexec
|
|
68
|
return self._checkexec
|
|
69
|
else:
|
|
69
|
else:
|
|
70
|
raise AttributeError, name
|
|
70
|
raise AttributeError, name
|
|
71
|
|
|
71
|
|
|
72
|
def _join(self, f):
|
|
72
|
def _join(self, f):
|
|
73
|
return os.path.join(self._root, f)
|
|
73
|
return os.path.join(self._root, f)
|
|
74
|
|
|
74
|
|
|
75
|
def getcwd(self):
|
|
75
|
def getcwd(self):
|
|
76
|
cwd = os.getcwd()
|
|
76
|
cwd = os.getcwd()
|
|
77
|
if cwd == self._root: return ''
|
|
77
|
if cwd == self._root: return ''
|
|
78
|
# self._root ends with a path separator if self._root is '/' or 'C:\'
|
|
78
|
# self._root ends with a path separator if self._root is '/' or 'C:\'
|
|
79
|
rootsep = self._root
|
|
79
|
rootsep = self._root
|
|
80
|
if not util.endswithsep(rootsep):
|
|
80
|
if not util.endswithsep(rootsep):
|
|
81
|
rootsep += os.sep
|
|
81
|
rootsep += os.sep
|
|
82
|
if cwd.startswith(rootsep):
|
|
82
|
if cwd.startswith(rootsep):
|
|
83
|
return cwd[len(rootsep):]
|
|
83
|
return cwd[len(rootsep):]
|
|
84
|
else:
|
|
84
|
else:
|
|
85
|
# we're outside the repo. return an absolute path.
|
|
85
|
# we're outside the repo. return an absolute path.
|
|
86
|
return cwd
|
|
86
|
return cwd
|
|
87
|
|
|
87
|
|
|
88
|
def pathto(self, f, cwd=None):
|
|
88
|
def pathto(self, f, cwd=None):
|
|
89
|
if cwd is None:
|
|
89
|
if cwd is None:
|
|
90
|
cwd = self.getcwd()
|
|
90
|
cwd = self.getcwd()
|
|
91
|
path = util.pathto(self._root, cwd, f)
|
|
91
|
path = util.pathto(self._root, cwd, f)
|
|
92
|
if self._slash:
|
|
92
|
if self._slash:
|
|
93
|
return util.normpath(path)
|
|
93
|
return util.normpath(path)
|
|
94
|
return path
|
|
94
|
return path
|
|
95
|
|
|
95
|
|
|
96
|
def __getitem__(self, key):
|
|
96
|
def __getitem__(self, key):
|
|
97
|
''' current states:
|
|
97
|
''' current states:
|
|
98
|
n normal
|
|
98
|
n normal
|
|
99
|
m needs merging
|
|
99
|
m needs merging
|
|
100
|
r marked for removal
|
|
100
|
r marked for removal
|
|
101
|
a marked for addition
|
|
101
|
a marked for addition
|
|
102
|
? not tracked'''
|
|
102
|
? not tracked'''
|
|
103
|
return self._map.get(key, ("?",))[0]
|
|
103
|
return self._map.get(key, ("?",))[0]
|
|
104
|
|
|
104
|
|
|
105
|
def __contains__(self, key):
|
|
105
|
def __contains__(self, key):
|
|
106
|
return key in self._map
|
|
106
|
return key in self._map
|
|
107
|
|
|
107
|
|
|
108
|
def __iter__(self):
|
|
108
|
def __iter__(self):
|
|
109
|
a = self._map.keys()
|
|
109
|
a = self._map.keys()
|
|
110
|
a.sort()
|
|
110
|
a.sort()
|
|
111
|
for x in a:
|
|
111
|
for x in a:
|
|
112
|
yield x
|
|
112
|
yield x
|
|
113
|
|
|
113
|
|
|
114
|
def parents(self):
|
|
114
|
def parents(self):
|
|
115
|
return self._pl
|
|
115
|
return self._pl
|
|
116
|
|
|
116
|
|
|
117
|
def branch(self):
|
|
117
|
def branch(self):
|
|
118
|
return self._branch
|
|
118
|
return self._branch
|
|
119
|
|
|
119
|
|
|
120
|
def setparents(self, p1, p2=nullid):
|
|
120
|
def setparents(self, p1, p2=nullid):
|
|
121
|
self._dirty = self._dirtypl = True
|
|
121
|
self._dirty = self._dirtypl = True
|
|
122
|
self._pl = p1, p2
|
|
122
|
self._pl = p1, p2
|
|
123
|
|
|
123
|
|
|
124
|
def setbranch(self, branch):
|
|
124
|
def setbranch(self, branch):
|
|
125
|
self._branch = branch
|
|
125
|
self._branch = branch
|
|
126
|
self._opener("branch", "w").write(branch + '\n')
|
|
126
|
self._opener("branch", "w").write(branch + '\n')
|
|
127
|
|
|
127
|
|
|
128
|
def _read(self):
|
|
128
|
def _read(self):
|
|
129
|
self._map = {}
|
|
129
|
self._map = {}
|
|
130
|
self._copymap = {}
|
|
130
|
self._copymap = {}
|
|
131
|
if not self._dirtypl:
|
|
131
|
if not self._dirtypl:
|
|
132
|
self._pl = [nullid, nullid]
|
|
132
|
self._pl = [nullid, nullid]
|
|
133
|
try:
|
|
133
|
try:
|
|
134
|
st = self._opener("dirstate").read()
|
|
134
|
st = self._opener("dirstate").read()
|
|
135
|
except IOError, err:
|
|
135
|
except IOError, err:
|
|
136
|
if err.errno != errno.ENOENT: raise
|
|
136
|
if err.errno != errno.ENOENT: raise
|
|
137
|
return
|
|
137
|
return
|
|
138
|
if not st:
|
|
138
|
if not st:
|
|
139
|
return
|
|
139
|
return
|
|
140
|
|
|
140
|
|
|
141
|
if not self._dirtypl:
|
|
141
|
if not self._dirtypl:
|
|
142
|
self._pl = [st[:20], st[20: 40]]
|
|
142
|
self._pl = [st[:20], st[20: 40]]
|
|
143
|
|
|
143
|
|
|
144
|
# deref fields so they will be local in loop
|
|
144
|
# deref fields so they will be local in loop
|
|
145
|
dmap = self._map
|
|
145
|
dmap = self._map
|
|
146
|
copymap = self._copymap
|
|
146
|
copymap = self._copymap
|
|
147
|
unpack = struct.unpack
|
|
147
|
unpack = struct.unpack
|
|
148
|
e_size = struct.calcsize(_format)
|
|
148
|
e_size = struct.calcsize(_format)
|
|
149
|
pos1 = 40
|
|
149
|
pos1 = 40
|
|
150
|
l = len(st)
|
|
150
|
l = len(st)
|
|
151
|
|
|
151
|
|
|
152
|
# the inner loop
|
|
152
|
# the inner loop
|
|
153
|
while pos1 < l:
|
|
153
|
while pos1 < l:
|
|
154
|
pos2 = pos1 + e_size
|
|
154
|
pos2 = pos1 + e_size
|
|
155
|
e = unpack(">cllll", st[pos1:pos2]) # a literal here is faster
|
|
155
|
e = unpack(">cllll", st[pos1:pos2]) # a literal here is faster
|
|
156
|
pos1 = pos2 + e[4]
|
|
156
|
pos1 = pos2 + e[4]
|
|
157
|
f = st[pos2:pos1]
|
|
157
|
f = st[pos2:pos1]
|
|
158
|
if '\0' in f:
|
|
158
|
if '\0' in f:
|
|
159
|
f, c = f.split('\0')
|
|
159
|
f, c = f.split('\0')
|
|
160
|
copymap[f] = c
|
|
160
|
copymap[f] = c
|
|
161
|
dmap[f] = e # we hold onto e[4] because making a subtuple is slow
|
|
161
|
dmap[f] = e # we hold onto e[4] because making a subtuple is slow
|
|
162
|
|
|
162
|
|
|
163
|
def invalidate(self):
|
|
163
|
def invalidate(self):
|
|
164
|
for a in "_map _copymap _branch _pl _dirs _ignore".split():
|
|
164
|
for a in "_map _copymap _branch _pl _dirs _ignore".split():
|
|
165
|
if a in self.__dict__:
|
|
165
|
if a in self.__dict__:
|
|
166
|
delattr(self, a)
|
|
166
|
delattr(self, a)
|
|
167
|
self._dirty = False
|
|
167
|
self._dirty = False
|
|
168
|
|
|
168
|
|
|
169
|
def copy(self, source, dest):
|
|
169
|
def copy(self, source, dest):
|
|
170
|
self._dirty = True
|
|
170
|
self._dirty = True
|
|
171
|
self._copymap[dest] = source
|
|
171
|
self._copymap[dest] = source
|
|
172
|
|
|
172
|
|
|
173
|
def copied(self, file):
|
|
173
|
def copied(self, file):
|
|
174
|
return self._copymap.get(file, None)
|
|
174
|
return self._copymap.get(file, None)
|
|
175
|
|
|
175
|
|
|
176
|
def copies(self):
|
|
176
|
def copies(self):
|
|
177
|
return self._copymap
|
|
177
|
return self._copymap
|
|
178
|
|
|
178
|
|
|
179
|
def _incpath(self, path):
|
|
179
|
def _incpath(self, path):
|
|
180
|
c = path.rfind('/')
|
|
180
|
c = path.rfind('/')
|
|
181
|
if c >= 0:
|
|
181
|
if c >= 0:
|
|
182
|
dirs = self._dirs
|
|
182
|
dirs = self._dirs
|
|
183
|
base = path[:c]
|
|
183
|
base = path[:c]
|
|
184
|
if base not in dirs:
|
|
184
|
if base not in dirs:
|
|
185
|
self._incpath(base)
|
|
185
|
self._incpath(base)
|
|
186
|
dirs[base] = 1
|
|
186
|
dirs[base] = 1
|
|
187
|
else:
|
|
187
|
else:
|
|
188
|
dirs[base] += 1
|
|
188
|
dirs[base] += 1
|
|
189
|
|
|
189
|
|
|
190
|
def _decpath(self, path):
|
|
190
|
def _decpath(self, path):
|
|
191
|
c = path.rfind('/')
|
|
191
|
c = path.rfind('/')
|
|
192
|
if c >= 0:
|
|
192
|
if c >= 0:
|
|
193
|
base = path[:c]
|
|
193
|
base = path[:c]
|
|
194
|
dirs = self._dirs
|
|
194
|
dirs = self._dirs
|
|
195
|
if dirs[base] == 1:
|
|
195
|
if dirs[base] == 1:
|
|
196
|
del dirs[base]
|
|
196
|
del dirs[base]
|
|
197
|
self._decpath(base)
|
|
197
|
self._decpath(base)
|
|
198
|
else:
|
|
198
|
else:
|
|
199
|
dirs[base] -= 1
|
|
199
|
dirs[base] -= 1
|
|
200
|
|
|
200
|
|
|
201
|
def _incpathcheck(self, f):
|
|
201
|
def _incpathcheck(self, f):
|
|
202
|
if '\r' in f or '\n' in f:
|
|
202
|
if '\r' in f or '\n' in f:
|
|
203
|
raise util.Abort(_("'\\n' and '\\r' disallowed in filenames: %r")
|
|
203
|
raise util.Abort(_("'\\n' and '\\r' disallowed in filenames: %r")
|
|
204
|
% f)
|
|
204
|
% f)
|
|
205
|
# shadows
|
|
205
|
# shadows
|
|
206
|
if f in self._dirs:
|
|
206
|
if f in self._dirs:
|
|
207
|
raise util.Abort(_('directory %r already in dirstate') % f)
|
|
207
|
raise util.Abort(_('directory %r already in dirstate') % f)
|
|
208
|
for c in strutil.rfindall(f, '/'):
|
|
208
|
for c in strutil.rfindall(f, '/'):
|
|
209
|
d = f[:c]
|
|
209
|
d = f[:c]
|
|
210
|
if d in self._dirs:
|
|
210
|
if d in self._dirs:
|
|
211
|
break
|
|
211
|
break
|
|
212
|
if d in self._map and self[d] != 'r':
|
|
212
|
if d in self._map and self[d] != 'r':
|
|
213
|
raise util.Abort(_('file %r in dirstate clashes with %r') %
|
|
213
|
raise util.Abort(_('file %r in dirstate clashes with %r') %
|
|
214
|
(d, f))
|
|
214
|
(d, f))
|
|
215
|
self._incpath(f)
|
|
215
|
self._incpath(f)
|
|
216
|
|
|
216
|
|
|
217
|
def _changepath(self, f, newstate, relaxed=False):
|
|
217
|
def _changepath(self, f, newstate, relaxed=False):
|
|
218
|
# handle upcoming path changes
|
|
218
|
# handle upcoming path changes
|
|
219
|
oldstate = self[f]
|
|
219
|
oldstate = self[f]
|
|
220
|
if oldstate not in "?r" and newstate in "?r":
|
|
220
|
if oldstate not in "?r" and newstate in "?r":
|
|
221
|
if "_dirs" in self.__dict__:
|
|
221
|
if "_dirs" in self.__dict__:
|
|
222
|
self._decpath(f)
|
|
222
|
self._decpath(f)
|
|
223
|
return
|
|
223
|
return
|
|
224
|
if oldstate in "?r" and newstate not in "?r":
|
|
224
|
if oldstate in "?r" and newstate not in "?r":
|
|
225
|
if relaxed and oldstate == '?':
|
|
225
|
if relaxed and oldstate == '?':
|
|
226
|
# XXX
|
|
226
|
# XXX
|
|
227
|
# in relaxed mode we assume the caller knows
|
|
227
|
# in relaxed mode we assume the caller knows
|
|
228
|
# what it is doing, workaround for updating
|
|
228
|
# what it is doing, workaround for updating
|
|
229
|
# dir-to-file revisions
|
|
229
|
# dir-to-file revisions
|
|
230
|
if "_dirs" in self.__dict__:
|
|
230
|
if "_dirs" in self.__dict__:
|
|
231
|
self._incpath(f)
|
|
231
|
self._incpath(f)
|
|
232
|
return
|
|
232
|
return
|
|
233
|
self._incpathcheck(f)
|
|
233
|
self._incpathcheck(f)
|
|
234
|
return
|
|
234
|
return
|
|
235
|
|
|
235
|
|
|
236
|
def normal(self, f):
|
|
236
|
def normal(self, f):
|
|
237
|
'mark a file normal and clean'
|
|
237
|
'mark a file normal and clean'
|
|
238
|
self._dirty = True
|
|
238
|
self._dirty = True
|
|
239
|
self._changepath(f, 'n', True)
|
|
239
|
self._changepath(f, 'n', True)
|
|
240
|
s = os.lstat(self._join(f))
|
|
240
|
s = os.lstat(self._join(f))
|
|
241
|
self._map[f] = ('n', s.st_mode, s.st_size, s.st_mtime, 0)
|
|
241
|
self._map[f] = ('n', s.st_mode, s.st_size, s.st_mtime, 0)
|
|
242
|
if f in self._copymap:
|
|
242
|
if f in self._copymap:
|
|
243
|
del self._copymap[f]
|
|
243
|
del self._copymap[f]
|
|
244
|
|
|
244
|
|
|
245
|
def normallookup(self, f):
|
|
245
|
def normallookup(self, f):
|
|
246
|
'mark a file normal, but possibly dirty'
|
|
246
|
'mark a file normal, but possibly dirty'
|
|
|
|
|
247
|
if self._pl[1] != nullid and f in self._map:
|
|
|
|
|
248
|
# if there is a merge going on and the file was either
|
|
|
|
|
249
|
# in state 'm' or dirty before being removed, restore that state.
|
|
|
|
|
250
|
entry = self._map[f]
|
|
|
|
|
251
|
if entry[0] == 'r' and entry[2] in (-1, -2):
|
|
|
|
|
252
|
source = self._copymap.get(f)
|
|
|
|
|
253
|
if entry[2] == -1:
|
|
|
|
|
254
|
self.merge(f)
|
|
|
|
|
255
|
elif entry[2] == -2:
|
|
|
|
|
256
|
self.normaldirty(f)
|
|
|
|
|
257
|
if source:
|
|
|
|
|
258
|
self.copy(source, f)
|
|
|
|
|
259
|
return
|
|
|
|
|
260
|
if entry[0] == 'm' or entry[0] == 'n' and entry[2] == -2:
|
|
|
|
|
261
|
return
|
|
247
|
self._dirty = True
|
|
262
|
self._dirty = True
|
|
248
|
self._changepath(f, 'n', True)
|
|
263
|
self._changepath(f, 'n', True)
|
|
249
|
self._map[f] = ('n', 0, -1, -1, 0)
|
|
264
|
self._map[f] = ('n', 0, -1, -1, 0)
|
|
250
|
if f in self._copymap:
|
|
265
|
if f in self._copymap:
|
|
251
|
del self._copymap[f]
|
|
266
|
del self._copymap[f]
|
|
252
|
|
|
267
|
|
|
253
|
def normaldirty(self, f):
|
|
268
|
def normaldirty(self, f):
|
|
254
|
'mark a file normal, but dirty'
|
|
269
|
'mark a file normal, but dirty'
|
|
255
|
self._dirty = True
|
|
270
|
self._dirty = True
|
|
256
|
self._changepath(f, 'n', True)
|
|
271
|
self._changepath(f, 'n', True)
|
|
257
|
self._map[f] = ('n', 0, -2, -1, 0)
|
|
272
|
self._map[f] = ('n', 0, -2, -1, 0)
|
|
258
|
if f in self._copymap:
|
|
273
|
if f in self._copymap:
|
|
259
|
del self._copymap[f]
|
|
274
|
del self._copymap[f]
|
|
260
|
|
|
275
|
|
|
261
|
def add(self, f):
|
|
276
|
def add(self, f):
|
|
262
|
'mark a file added'
|
|
277
|
'mark a file added'
|
|
263
|
self._dirty = True
|
|
278
|
self._dirty = True
|
|
264
|
self._changepath(f, 'a')
|
|
279
|
self._changepath(f, 'a')
|
|
265
|
self._map[f] = ('a', 0, -1, -1, 0)
|
|
280
|
self._map[f] = ('a', 0, -1, -1, 0)
|
|
266
|
if f in self._copymap:
|
|
281
|
if f in self._copymap:
|
|
267
|
del self._copymap[f]
|
|
282
|
del self._copymap[f]
|
|
268
|
|
|
283
|
|
|
269
|
def remove(self, f):
|
|
284
|
def remove(self, f):
|
|
270
|
'mark a file removed'
|
|
285
|
'mark a file removed'
|
|
271
|
self._dirty = True
|
|
286
|
self._dirty = True
|
|
272
|
self._changepath(f, 'r')
|
|
287
|
self._changepath(f, 'r')
|
|
273
|
size = 0
|
|
288
|
size = 0
|
|
274
|
if self._pl[1] != nullid and f in self._map:
|
|
289
|
if self._pl[1] != nullid and f in self._map:
|
|
275
|
entry = self._map[f]
|
|
290
|
entry = self._map[f]
|
|
276
|
if entry[0] == 'm':
|
|
291
|
if entry[0] == 'm':
|
|
277
|
size = -1
|
|
292
|
size = -1
|
|
278
|
elif entry[0] == 'n' and entry[2] == -2:
|
|
293
|
elif entry[0] == 'n' and entry[2] == -2:
|
|
279
|
size = -2
|
|
294
|
size = -2
|
|
280
|
self._map[f] = ('r', 0, size, 0, 0)
|
|
295
|
self._map[f] = ('r', 0, size, 0, 0)
|
|
281
|
if size == 0 and f in self._copymap:
|
|
296
|
if size == 0 and f in self._copymap:
|
|
282
|
del self._copymap[f]
|
|
297
|
del self._copymap[f]
|
|
283
|
|
|
298
|
|
|
284
|
def merge(self, f):
|
|
299
|
def merge(self, f):
|
|
285
|
'mark a file merged'
|
|
300
|
'mark a file merged'
|
|
286
|
self._dirty = True
|
|
301
|
self._dirty = True
|
|
287
|
s = os.lstat(self._join(f))
|
|
302
|
s = os.lstat(self._join(f))
|
|
288
|
self._changepath(f, 'm', True)
|
|
303
|
self._changepath(f, 'm', True)
|
|
289
|
self._map[f] = ('m', s.st_mode, s.st_size, s.st_mtime, 0)
|
|
304
|
self._map[f] = ('m', s.st_mode, s.st_size, s.st_mtime, 0)
|
|
290
|
if f in self._copymap:
|
|
305
|
if f in self._copymap:
|
|
291
|
del self._copymap[f]
|
|
306
|
del self._copymap[f]
|
|
292
|
|
|
307
|
|
|
293
|
def forget(self, f):
|
|
308
|
def forget(self, f):
|
|
294
|
'forget a file'
|
|
309
|
'forget a file'
|
|
295
|
self._dirty = True
|
|
310
|
self._dirty = True
|
|
296
|
try:
|
|
311
|
try:
|
|
297
|
self._changepath(f, '?')
|
|
312
|
self._changepath(f, '?')
|
|
298
|
del self._map[f]
|
|
313
|
del self._map[f]
|
|
299
|
except KeyError:
|
|
314
|
except KeyError:
|
|
300
|
self._ui.warn(_("not in dirstate: %s\n") % f)
|
|
315
|
self._ui.warn(_("not in dirstate: %s\n") % f)
|
|
301
|
|
|
316
|
|
|
302
|
def clear(self):
|
|
317
|
def clear(self):
|
|
303
|
self._map = {}
|
|
318
|
self._map = {}
|
|
304
|
if "_dirs" in self.__dict__:
|
|
319
|
if "_dirs" in self.__dict__:
|
|
305
|
delattr(self, "_dirs");
|
|
320
|
delattr(self, "_dirs");
|
|
306
|
self._copymap = {}
|
|
321
|
self._copymap = {}
|
|
307
|
self._pl = [nullid, nullid]
|
|
322
|
self._pl = [nullid, nullid]
|
|
308
|
self._dirty = True
|
|
323
|
self._dirty = True
|
|
309
|
|
|
324
|
|
|
310
|
def rebuild(self, parent, files):
|
|
325
|
def rebuild(self, parent, files):
|
|
311
|
self.clear()
|
|
326
|
self.clear()
|
|
312
|
for f in files:
|
|
327
|
for f in files:
|
|
313
|
if files.execf(f):
|
|
328
|
if files.execf(f):
|
|
314
|
self._map[f] = ('n', 0777, -1, 0, 0)
|
|
329
|
self._map[f] = ('n', 0777, -1, 0, 0)
|
|
315
|
else:
|
|
330
|
else:
|
|
316
|
self._map[f] = ('n', 0666, -1, 0, 0)
|
|
331
|
self._map[f] = ('n', 0666, -1, 0, 0)
|
|
317
|
self._pl = (parent, nullid)
|
|
332
|
self._pl = (parent, nullid)
|
|
318
|
self._dirty = True
|
|
333
|
self._dirty = True
|
|
319
|
|
|
334
|
|
|
320
|
def write(self):
|
|
335
|
def write(self):
|
|
321
|
if not self._dirty:
|
|
336
|
if not self._dirty:
|
|
322
|
return
|
|
337
|
return
|
|
323
|
cs = cStringIO.StringIO()
|
|
338
|
cs = cStringIO.StringIO()
|
|
324
|
copymap = self._copymap
|
|
339
|
copymap = self._copymap
|
|
325
|
pack = struct.pack
|
|
340
|
pack = struct.pack
|
|
326
|
write = cs.write
|
|
341
|
write = cs.write
|
|
327
|
write("".join(self._pl))
|
|
342
|
write("".join(self._pl))
|
|
328
|
for f, e in self._map.iteritems():
|
|
343
|
for f, e in self._map.iteritems():
|
|
329
|
if f in copymap:
|
|
344
|
if f in copymap:
|
|
330
|
f = "%s\0%s" % (f, copymap[f])
|
|
345
|
f = "%s\0%s" % (f, copymap[f])
|
|
331
|
e = pack(_format, e[0], e[1], e[2], e[3], len(f))
|
|
346
|
e = pack(_format, e[0], e[1], e[2], e[3], len(f))
|
|
332
|
write(e)
|
|
347
|
write(e)
|
|
333
|
write(f)
|
|
348
|
write(f)
|
|
334
|
st = self._opener("dirstate", "w", atomictemp=True)
|
|
349
|
st = self._opener("dirstate", "w", atomictemp=True)
|
|
335
|
st.write(cs.getvalue())
|
|
350
|
st.write(cs.getvalue())
|
|
336
|
st.rename()
|
|
351
|
st.rename()
|
|
337
|
self._dirty = self._dirtypl = False
|
|
352
|
self._dirty = self._dirtypl = False
|
|
338
|
|
|
353
|
|
|
339
|
def _filter(self, files):
|
|
354
|
def _filter(self, files):
|
|
340
|
ret = {}
|
|
355
|
ret = {}
|
|
341
|
unknown = []
|
|
356
|
unknown = []
|
|
342
|
|
|
357
|
|
|
343
|
for x in files:
|
|
358
|
for x in files:
|
|
344
|
if x == '.':
|
|
359
|
if x == '.':
|
|
345
|
return self._map.copy()
|
|
360
|
return self._map.copy()
|
|
346
|
if x not in self._map:
|
|
361
|
if x not in self._map:
|
|
347
|
unknown.append(x)
|
|
362
|
unknown.append(x)
|
|
348
|
else:
|
|
363
|
else:
|
|
349
|
ret[x] = self._map[x]
|
|
364
|
ret[x] = self._map[x]
|
|
350
|
|
|
365
|
|
|
351
|
if not unknown:
|
|
366
|
if not unknown:
|
|
352
|
return ret
|
|
367
|
return ret
|
|
353
|
|
|
368
|
|
|
354
|
b = self._map.keys()
|
|
369
|
b = self._map.keys()
|
|
355
|
b.sort()
|
|
370
|
b.sort()
|
|
356
|
blen = len(b)
|
|
371
|
blen = len(b)
|
|
357
|
|
|
372
|
|
|
358
|
for x in unknown:
|
|
373
|
for x in unknown:
|
|
359
|
bs = bisect.bisect(b, "%s%s" % (x, '/'))
|
|
374
|
bs = bisect.bisect(b, "%s%s" % (x, '/'))
|
|
360
|
while bs < blen:
|
|
375
|
while bs < blen:
|
|
361
|
s = b[bs]
|
|
376
|
s = b[bs]
|
|
362
|
if len(s) > len(x) and s.startswith(x):
|
|
377
|
if len(s) > len(x) and s.startswith(x):
|
|
363
|
ret[s] = self._map[s]
|
|
378
|
ret[s] = self._map[s]
|
|
364
|
else:
|
|
379
|
else:
|
|
365
|
break
|
|
380
|
break
|
|
366
|
bs += 1
|
|
381
|
bs += 1
|
|
367
|
return ret
|
|
382
|
return ret
|
|
368
|
|
|
383
|
|
|
369
|
def _supported(self, f, mode, verbose=False):
|
|
384
|
def _supported(self, f, mode, verbose=False):
|
|
370
|
if stat.S_ISREG(mode) or stat.S_ISLNK(mode):
|
|
385
|
if stat.S_ISREG(mode) or stat.S_ISLNK(mode):
|
|
371
|
return True
|
|
386
|
return True
|
|
372
|
if verbose:
|
|
387
|
if verbose:
|
|
373
|
kind = 'unknown'
|
|
388
|
kind = 'unknown'
|
|
374
|
if stat.S_ISCHR(mode): kind = _('character device')
|
|
389
|
if stat.S_ISCHR(mode): kind = _('character device')
|
|
375
|
elif stat.S_ISBLK(mode): kind = _('block device')
|
|
390
|
elif stat.S_ISBLK(mode): kind = _('block device')
|
|
376
|
elif stat.S_ISFIFO(mode): kind = _('fifo')
|
|
391
|
elif stat.S_ISFIFO(mode): kind = _('fifo')
|
|
377
|
elif stat.S_ISSOCK(mode): kind = _('socket')
|
|
392
|
elif stat.S_ISSOCK(mode): kind = _('socket')
|
|
378
|
elif stat.S_ISDIR(mode): kind = _('directory')
|
|
393
|
elif stat.S_ISDIR(mode): kind = _('directory')
|
|
379
|
self._ui.warn(_('%s: unsupported file type (type is %s)\n')
|
|
394
|
self._ui.warn(_('%s: unsupported file type (type is %s)\n')
|
|
380
|
% (self.pathto(f), kind))
|
|
395
|
% (self.pathto(f), kind))
|
|
381
|
return False
|
|
396
|
return False
|
|
382
|
|
|
397
|
|
|
383
|
def _dirignore(self, f):
|
|
398
|
def _dirignore(self, f):
|
|
384
|
if self._ignore(f):
|
|
399
|
if self._ignore(f):
|
|
385
|
return True
|
|
400
|
return True
|
|
386
|
for c in strutil.findall(f, '/'):
|
|
401
|
for c in strutil.findall(f, '/'):
|
|
387
|
if self._ignore(f[:c]):
|
|
402
|
if self._ignore(f[:c]):
|
|
388
|
return True
|
|
403
|
return True
|
|
389
|
return False
|
|
404
|
return False
|
|
390
|
|
|
405
|
|
|
391
|
def walk(self, files=None, match=util.always, badmatch=None):
|
|
406
|
def walk(self, files=None, match=util.always, badmatch=None):
|
|
392
|
# filter out the stat
|
|
407
|
# filter out the stat
|
|
393
|
for src, f, st in self.statwalk(files, match, badmatch=badmatch):
|
|
408
|
for src, f, st in self.statwalk(files, match, badmatch=badmatch):
|
|
394
|
yield src, f
|
|
409
|
yield src, f
|
|
395
|
|
|
410
|
|
|
396
|
def statwalk(self, files=None, match=util.always, unknown=True,
|
|
411
|
def statwalk(self, files=None, match=util.always, unknown=True,
|
|
397
|
ignored=False, badmatch=None, directories=False):
|
|
412
|
ignored=False, badmatch=None, directories=False):
|
|
398
|
'''
|
|
413
|
'''
|
|
399
|
walk recursively through the directory tree, finding all files
|
|
414
|
walk recursively through the directory tree, finding all files
|
|
400
|
matched by the match function
|
|
415
|
matched by the match function
|
|
401
|
|
|
416
|
|
|
402
|
results are yielded in a tuple (src, filename, st), where src
|
|
417
|
results are yielded in a tuple (src, filename, st), where src
|
|
403
|
is one of:
|
|
418
|
is one of:
|
|
404
|
'f' the file was found in the directory tree
|
|
419
|
'f' the file was found in the directory tree
|
|
405
|
'd' the file is a directory of the tree
|
|
420
|
'd' the file is a directory of the tree
|
|
406
|
'm' the file was only in the dirstate and not in the tree
|
|
421
|
'm' the file was only in the dirstate and not in the tree
|
|
407
|
'b' file was not found and matched badmatch
|
|
422
|
'b' file was not found and matched badmatch
|
|
408
|
|
|
423
|
|
|
409
|
and st is the stat result if the file was found in the directory.
|
|
424
|
and st is the stat result if the file was found in the directory.
|
|
410
|
'''
|
|
425
|
'''
|
|
411
|
|
|
426
|
|
|
412
|
# walk all files by default
|
|
427
|
# walk all files by default
|
|
413
|
if not files:
|
|
428
|
if not files:
|
|
414
|
files = ['.']
|
|
429
|
files = ['.']
|
|
415
|
dc = self._map.copy()
|
|
430
|
dc = self._map.copy()
|
|
416
|
else:
|
|
431
|
else:
|
|
417
|
files = util.unique(files)
|
|
432
|
files = util.unique(files)
|
|
418
|
dc = self._filter(files)
|
|
433
|
dc = self._filter(files)
|
|
419
|
|
|
434
|
|
|
420
|
def imatch(file_):
|
|
435
|
def imatch(file_):
|
|
421
|
if file_ not in dc and self._ignore(file_):
|
|
436
|
if file_ not in dc and self._ignore(file_):
|
|
422
|
return False
|
|
437
|
return False
|
|
423
|
return match(file_)
|
|
438
|
return match(file_)
|
|
424
|
|
|
439
|
|
|
425
|
# TODO: don't walk unknown directories if unknown and ignored are False
|
|
440
|
# TODO: don't walk unknown directories if unknown and ignored are False
|
|
426
|
ignore = self._ignore
|
|
441
|
ignore = self._ignore
|
|
427
|
dirignore = self._dirignore
|
|
442
|
dirignore = self._dirignore
|
|
428
|
if ignored:
|
|
443
|
if ignored:
|
|
429
|
imatch = match
|
|
444
|
imatch = match
|
|
430
|
ignore = util.never
|
|
445
|
ignore = util.never
|
|
431
|
dirignore = util.never
|
|
446
|
dirignore = util.never
|
|
432
|
|
|
447
|
|
|
433
|
# self._root may end with a path separator when self._root == '/'
|
|
448
|
# self._root may end with a path separator when self._root == '/'
|
|
434
|
common_prefix_len = len(self._root)
|
|
449
|
common_prefix_len = len(self._root)
|
|
435
|
if not util.endswithsep(self._root):
|
|
450
|
if not util.endswithsep(self._root):
|
|
436
|
common_prefix_len += 1
|
|
451
|
common_prefix_len += 1
|
|
437
|
|
|
452
|
|
|
438
|
normpath = util.normpath
|
|
453
|
normpath = util.normpath
|
|
439
|
listdir = osutil.listdir
|
|
454
|
listdir = osutil.listdir
|
|
440
|
lstat = os.lstat
|
|
455
|
lstat = os.lstat
|
|
441
|
bisect_left = bisect.bisect_left
|
|
456
|
bisect_left = bisect.bisect_left
|
|
442
|
isdir = os.path.isdir
|
|
457
|
isdir = os.path.isdir
|
|
443
|
pconvert = util.pconvert
|
|
458
|
pconvert = util.pconvert
|
|
444
|
join = os.path.join
|
|
459
|
join = os.path.join
|
|
445
|
s_isdir = stat.S_ISDIR
|
|
460
|
s_isdir = stat.S_ISDIR
|
|
446
|
supported = self._supported
|
|
461
|
supported = self._supported
|
|
447
|
_join = self._join
|
|
462
|
_join = self._join
|
|
448
|
known = {'.hg': 1}
|
|
463
|
known = {'.hg': 1}
|
|
449
|
|
|
464
|
|
|
450
|
# recursion free walker, faster than os.walk.
|
|
465
|
# recursion free walker, faster than os.walk.
|
|
451
|
def findfiles(s):
|
|
466
|
def findfiles(s):
|
|
452
|
work = [s]
|
|
467
|
work = [s]
|
|
453
|
wadd = work.append
|
|
468
|
wadd = work.append
|
|
454
|
found = []
|
|
469
|
found = []
|
|
455
|
add = found.append
|
|
470
|
add = found.append
|
|
456
|
if directories:
|
|
471
|
if directories:
|
|
457
|
add((normpath(s[common_prefix_len:]), 'd', lstat(s)))
|
|
472
|
add((normpath(s[common_prefix_len:]), 'd', lstat(s)))
|
|
458
|
while work:
|
|
473
|
while work:
|
|
459
|
top = work.pop()
|
|
474
|
top = work.pop()
|
|
460
|
entries = listdir(top, stat=True)
|
|
475
|
entries = listdir(top, stat=True)
|
|
461
|
# nd is the top of the repository dir tree
|
|
476
|
# nd is the top of the repository dir tree
|
|
462
|
nd = normpath(top[common_prefix_len:])
|
|
477
|
nd = normpath(top[common_prefix_len:])
|
|
463
|
if nd == '.':
|
|
478
|
if nd == '.':
|
|
464
|
nd = ''
|
|
479
|
nd = ''
|
|
465
|
else:
|
|
480
|
else:
|
|
466
|
# do not recurse into a repo contained in this
|
|
481
|
# do not recurse into a repo contained in this
|
|
467
|
# one. use bisect to find .hg directory so speed
|
|
482
|
# one. use bisect to find .hg directory so speed
|
|
468
|
# is good on big directory.
|
|
483
|
# is good on big directory.
|
|
469
|
names = [e[0] for e in entries]
|
|
484
|
names = [e[0] for e in entries]
|
|
470
|
hg = bisect_left(names, '.hg')
|
|
485
|
hg = bisect_left(names, '.hg')
|
|
471
|
if hg < len(names) and names[hg] == '.hg':
|
|
486
|
if hg < len(names) and names[hg] == '.hg':
|
|
472
|
if isdir(join(top, '.hg')):
|
|
487
|
if isdir(join(top, '.hg')):
|
|
473
|
continue
|
|
488
|
continue
|
|
474
|
for f, kind, st in entries:
|
|
489
|
for f, kind, st in entries:
|
|
475
|
np = pconvert(join(nd, f))
|
|
490
|
np = pconvert(join(nd, f))
|
|
476
|
if np in known:
|
|
491
|
if np in known:
|
|
477
|
continue
|
|
492
|
continue
|
|
478
|
known[np] = 1
|
|
493
|
known[np] = 1
|
|
479
|
p = join(top, f)
|
|
494
|
p = join(top, f)
|
|
480
|
# don't trip over symlinks
|
|
495
|
# don't trip over symlinks
|
|
481
|
if kind == stat.S_IFDIR:
|
|
496
|
if kind == stat.S_IFDIR:
|
|
482
|
if not ignore(np):
|
|
497
|
if not ignore(np):
|
|
483
|
wadd(p)
|
|
498
|
wadd(p)
|
|
484
|
if directories:
|
|
499
|
if directories:
|
|
485
|
add((np, 'd', st))
|
|
500
|
add((np, 'd', st))
|
|
486
|
if np in dc and match(np):
|
|
501
|
if np in dc and match(np):
|
|
487
|
add((np, 'm', st))
|
|
502
|
add((np, 'm', st))
|
|
488
|
elif imatch(np):
|
|
503
|
elif imatch(np):
|
|
489
|
if supported(np, st.st_mode):
|
|
504
|
if supported(np, st.st_mode):
|
|
490
|
add((np, 'f', st))
|
|
505
|
add((np, 'f', st))
|
|
491
|
elif np in dc:
|
|
506
|
elif np in dc:
|
|
492
|
add((np, 'm', st))
|
|
507
|
add((np, 'm', st))
|
|
493
|
found.sort()
|
|
508
|
found.sort()
|
|
494
|
return found
|
|
509
|
return found
|
|
495
|
|
|
510
|
|
|
496
|
# step one, find all files that match our criteria
|
|
511
|
# step one, find all files that match our criteria
|
|
497
|
files.sort()
|
|
512
|
files.sort()
|
|
498
|
for ff in files:
|
|
513
|
for ff in files:
|
|
499
|
nf = normpath(ff)
|
|
514
|
nf = normpath(ff)
|
|
500
|
f = _join(ff)
|
|
515
|
f = _join(ff)
|
|
501
|
try:
|
|
516
|
try:
|
|
502
|
st = lstat(f)
|
|
517
|
st = lstat(f)
|
|
503
|
except OSError, inst:
|
|
518
|
except OSError, inst:
|
|
504
|
found = False
|
|
519
|
found = False
|
|
505
|
for fn in dc:
|
|
520
|
for fn in dc:
|
|
506
|
if nf == fn or (fn.startswith(nf) and fn[len(nf)] == '/'):
|
|
521
|
if nf == fn or (fn.startswith(nf) and fn[len(nf)] == '/'):
|
|
507
|
found = True
|
|
522
|
found = True
|
|
508
|
break
|
|
523
|
break
|
|
509
|
if not found:
|
|
524
|
if not found:
|
|
510
|
if inst.errno != errno.ENOENT or not badmatch:
|
|
525
|
if inst.errno != errno.ENOENT or not badmatch:
|
|
511
|
self._ui.warn('%s: %s\n' %
|
|
526
|
self._ui.warn('%s: %s\n' %
|
|
512
|
(self.pathto(ff), inst.strerror))
|
|
527
|
(self.pathto(ff), inst.strerror))
|
|
513
|
elif badmatch and badmatch(ff) and imatch(nf):
|
|
528
|
elif badmatch and badmatch(ff) and imatch(nf):
|
|
514
|
yield 'b', ff, None
|
|
529
|
yield 'b', ff, None
|
|
515
|
continue
|
|
530
|
continue
|
|
516
|
if s_isdir(st.st_mode):
|
|
531
|
if s_isdir(st.st_mode):
|
|
517
|
if not dirignore(nf):
|
|
532
|
if not dirignore(nf):
|
|
518
|
for f, src, st in findfiles(f):
|
|
533
|
for f, src, st in findfiles(f):
|
|
519
|
yield src, f, st
|
|
534
|
yield src, f, st
|
|
520
|
else:
|
|
535
|
else:
|
|
521
|
if nf in known:
|
|
536
|
if nf in known:
|
|
522
|
continue
|
|
537
|
continue
|
|
523
|
known[nf] = 1
|
|
538
|
known[nf] = 1
|
|
524
|
if match(nf):
|
|
539
|
if match(nf):
|
|
525
|
if supported(ff, st.st_mode, verbose=True):
|
|
540
|
if supported(ff, st.st_mode, verbose=True):
|
|
526
|
yield 'f', nf, st
|
|
541
|
yield 'f', nf, st
|
|
527
|
elif ff in dc:
|
|
542
|
elif ff in dc:
|
|
528
|
yield 'm', nf, st
|
|
543
|
yield 'm', nf, st
|
|
529
|
|
|
544
|
|
|
530
|
# step two run through anything left in the dc hash and yield
|
|
545
|
# step two run through anything left in the dc hash and yield
|
|
531
|
# if we haven't already seen it
|
|
546
|
# if we haven't already seen it
|
|
532
|
ks = dc.keys()
|
|
547
|
ks = dc.keys()
|
|
533
|
ks.sort()
|
|
548
|
ks.sort()
|
|
534
|
for k in ks:
|
|
549
|
for k in ks:
|
|
535
|
if k in known:
|
|
550
|
if k in known:
|
|
536
|
continue
|
|
551
|
continue
|
|
537
|
known[k] = 1
|
|
552
|
known[k] = 1
|
|
538
|
if imatch(k):
|
|
553
|
if imatch(k):
|
|
539
|
yield 'm', k, None
|
|
554
|
yield 'm', k, None
|
|
540
|
|
|
555
|
|
|
541
|
def status(self, files, match, list_ignored, list_clean, list_unknown=True):
|
|
556
|
def status(self, files, match, list_ignored, list_clean, list_unknown=True):
|
|
542
|
lookup, modified, added, unknown, ignored = [], [], [], [], []
|
|
557
|
lookup, modified, added, unknown, ignored = [], [], [], [], []
|
|
543
|
removed, deleted, clean = [], [], []
|
|
558
|
removed, deleted, clean = [], [], []
|
|
544
|
|
|
559
|
|
|
545
|
files = files or []
|
|
560
|
files = files or []
|
|
546
|
_join = self._join
|
|
561
|
_join = self._join
|
|
547
|
lstat = os.lstat
|
|
562
|
lstat = os.lstat
|
|
548
|
cmap = self._copymap
|
|
563
|
cmap = self._copymap
|
|
549
|
dmap = self._map
|
|
564
|
dmap = self._map
|
|
550
|
ladd = lookup.append
|
|
565
|
ladd = lookup.append
|
|
551
|
madd = modified.append
|
|
566
|
madd = modified.append
|
|
552
|
aadd = added.append
|
|
567
|
aadd = added.append
|
|
553
|
uadd = unknown.append
|
|
568
|
uadd = unknown.append
|
|
554
|
iadd = ignored.append
|
|
569
|
iadd = ignored.append
|
|
555
|
radd = removed.append
|
|
570
|
radd = removed.append
|
|
556
|
dadd = deleted.append
|
|
571
|
dadd = deleted.append
|
|
557
|
cadd = clean.append
|
|
572
|
cadd = clean.append
|
|
558
|
|
|
573
|
|
|
559
|
for src, fn, st in self.statwalk(files, match, unknown=list_unknown,
|
|
574
|
for src, fn, st in self.statwalk(files, match, unknown=list_unknown,
|
|
560
|
ignored=list_ignored):
|
|
575
|
ignored=list_ignored):
|
|
561
|
if fn in dmap:
|
|
576
|
if fn in dmap:
|
|
562
|
type_, mode, size, time, foo = dmap[fn]
|
|
577
|
type_, mode, size, time, foo = dmap[fn]
|
|
563
|
else:
|
|
578
|
else:
|
|
564
|
if (list_ignored or fn in files) and self._dirignore(fn):
|
|
579
|
if (list_ignored or fn in files) and self._dirignore(fn):
|
|
565
|
if list_ignored:
|
|
580
|
if list_ignored:
|
|
566
|
iadd(fn)
|
|
581
|
iadd(fn)
|
|
567
|
elif list_unknown:
|
|
582
|
elif list_unknown:
|
|
568
|
uadd(fn)
|
|
583
|
uadd(fn)
|
|
569
|
continue
|
|
584
|
continue
|
|
570
|
if src == 'm':
|
|
585
|
if src == 'm':
|
|
571
|
nonexistent = True
|
|
586
|
nonexistent = True
|
|
572
|
if not st:
|
|
587
|
if not st:
|
|
573
|
try:
|
|
588
|
try:
|
|
574
|
st = lstat(_join(fn))
|
|
589
|
st = lstat(_join(fn))
|
|
575
|
except OSError, inst:
|
|
590
|
except OSError, inst:
|
|
576
|
if inst.errno not in (errno.ENOENT, errno.ENOTDIR):
|
|
591
|
if inst.errno not in (errno.ENOENT, errno.ENOTDIR):
|
|
577
|
raise
|
|
592
|
raise
|
|
578
|
st = None
|
|
593
|
st = None
|
|
579
|
# We need to re-check that it is a valid file
|
|
594
|
# We need to re-check that it is a valid file
|
|
580
|
if st and self._supported(fn, st.st_mode):
|
|
595
|
if st and self._supported(fn, st.st_mode):
|
|
581
|
nonexistent = False
|
|
596
|
nonexistent = False
|
|
582
|
# XXX: what to do with file no longer present in the fs
|
|
597
|
# XXX: what to do with file no longer present in the fs
|
|
583
|
# who are not removed in the dirstate ?
|
|
598
|
# who are not removed in the dirstate ?
|
|
584
|
if nonexistent and type_ in "nma":
|
|
599
|
if nonexistent and type_ in "nma":
|
|
585
|
dadd(fn)
|
|
600
|
dadd(fn)
|
|
586
|
continue
|
|
601
|
continue
|
|
587
|
# check the common case first
|
|
602
|
# check the common case first
|
|
588
|
if type_ == 'n':
|
|
603
|
if type_ == 'n':
|
|
589
|
if not st:
|
|
604
|
if not st:
|
|
590
|
st = lstat(_join(fn))
|
|
605
|
st = lstat(_join(fn))
|
|
591
|
if (size >= 0 and
|
|
606
|
if (size >= 0 and
|
|
592
|
(size != st.st_size
|
|
607
|
(size != st.st_size
|
|
593
|
or ((mode ^ st.st_mode) & 0100 and self._checkexec))
|
|
608
|
or ((mode ^ st.st_mode) & 0100 and self._checkexec))
|
|
594
|
or size == -2
|
|
609
|
or size == -2
|
|
595
|
or fn in self._copymap):
|
|
610
|
or fn in self._copymap):
|
|
596
|
madd(fn)
|
|
611
|
madd(fn)
|
|
597
|
elif time != int(st.st_mtime):
|
|
612
|
elif time != int(st.st_mtime):
|
|
598
|
ladd(fn)
|
|
613
|
ladd(fn)
|
|
599
|
elif list_clean:
|
|
614
|
elif list_clean:
|
|
600
|
cadd(fn)
|
|
615
|
cadd(fn)
|
|
601
|
elif type_ == 'm':
|
|
616
|
elif type_ == 'm':
|
|
602
|
madd(fn)
|
|
617
|
madd(fn)
|
|
603
|
elif type_ == 'a':
|
|
618
|
elif type_ == 'a':
|
|
604
|
aadd(fn)
|
|
619
|
aadd(fn)
|
|
605
|
elif type_ == 'r':
|
|
620
|
elif type_ == 'r':
|
|
606
|
radd(fn)
|
|
621
|
radd(fn)
|
|
607
|
|
|
622
|
|
|
608
|
return (lookup, modified, added, removed, deleted, unknown, ignored,
|
|
623
|
return (lookup, modified, added, removed, deleted, unknown, ignored,
|
|
609
|
clean)
|
|
624
|
clean)
|