##// END OF EJS Templates
Merge with main...
Patrick Mezard -
r6812:fdf5980b merge default
parent child Browse files
Show More
@@ -104,7 +104,8 b' def catcommit(ui, repo, n, prefix, ctx=N'
104 ctx = repo[n]
104 ctx = repo[n]
105 ui.write("tree %s\n" % short(ctx.changeset()[0])) # use ctx.node() instead ??
105 ui.write("tree %s\n" % short(ctx.changeset()[0])) # use ctx.node() instead ??
106 for p in ctx.parents():
106 for p in ctx.parents():
107 ui.write("parent %s\n" % short(p.node()))
107 ui.write("parent %s\n" % p)
108
108 date = ctx.date()
109 date = ctx.date()
109 description = ctx.description().replace("\0", "")
110 description = ctx.description().replace("\0", "")
110 lines = description.splitlines()
111 lines = description.splitlines()
@@ -472,13 +472,9 b' class workingctx(changectx):'
472 self._date = util.parsedate(date)
472 self._date = util.parsedate(date)
473 else:
473 else:
474 self._date = util.makedate()
474 self._date = util.makedate()
475 if user:
475 self._user = user
476 self._user = user
477 else:
478 self._user = self._repo.ui.username()
479 if parents:
476 if parents:
480 p1, p2 = parents
477 self._parents = [changectx(self._repo, p) for p in parents]
481 self._parents = [changectx(self._repo, p) for p in (p1, p2)]
482 if changes:
478 if changes:
483 self._status = list(changes)
479 self._status = list(changes)
484
480
@@ -501,6 +497,9 b' class workingctx(changectx):'
501 def __nonzero__(self):
497 def __nonzero__(self):
502 return True
498 return True
503
499
500 def __contains__(self, key):
501 return self._dirstate[f] not in "?r"
502
504 def __getattr__(self, name):
503 def __getattr__(self, name):
505 if name == '_status':
504 if name == '_status':
506 self._status = self._repo.status(unknown=True)
505 self._status = self._repo.status(unknown=True)
@@ -541,7 +540,7 b' class workingctx(changectx):'
541
540
542 def manifest(self): return self._manifest
541 def manifest(self): return self._manifest
543
542
544 def user(self): return self._user
543 def user(self): return self._user or self._repo.ui.username()
545 def date(self): return self._date
544 def date(self): return self._date
546 def description(self): return self._text
545 def description(self): return self._text
547 def files(self):
546 def files(self):
@@ -701,7 +700,7 b' class memctx(object):'
701 self._node = None
700 self._node = None
702 self._text = text
701 self._text = text
703 self._date = date and util.parsedate(date) or util.makedate()
702 self._date = date and util.parsedate(date) or util.makedate()
704 self._user = user or self._repo.ui.username()
703 self._user = user
705 parents = [(p or nullid) for p in parents]
704 parents = [(p or nullid) for p in parents]
706 p1, p2 = parents
705 p1, p2 = parents
707 self._parents = [changectx(self._repo, p) for p in (p1, p2)]
706 self._parents = [changectx(self._repo, p) for p in (p1, p2)]
@@ -724,7 +723,7 b' class memctx(object):'
724 def __nonzero__(self):
723 def __nonzero__(self):
725 return True
724 return True
726
725
727 def user(self): return self._user
726 def user(self): return self._user or self._repo.ui.username()
728 def date(self): return self._date
727 def date(self): return self._date
729 def description(self): return self._text
728 def description(self): return self._text
730 def files(self): return self.modified()
729 def files(self): return self.modified()
@@ -9,12 +9,20 b' of the GNU General Public License, incor'
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, util, errno, ignore
13 import cStringIO, osutil, sys
13 import cStringIO, osutil, sys
14
14
15 _unknown = ('?', 0, 0, 0)
15 _unknown = ('?', 0, 0, 0)
16 _format = ">cllll"
16 _format = ">cllll"
17
17
18 def _finddirs(path):
19 pos = len(path)
20 while 1:
21 pos = path.rfind('/', 0, pos)
22 if pos == -1:
23 break
24 yield path[:pos]
25
18 class dirstate(object):
26 class dirstate(object):
19
27
20 def __init__(self, opener, ui, root):
28 def __init__(self, opener, ui, root):
@@ -55,10 +63,12 b' class dirstate(object):'
55 if err.errno != errno.ENOENT: raise
63 if err.errno != errno.ENOENT: raise
56 return self._pl
64 return self._pl
57 elif name == '_dirs':
65 elif name == '_dirs':
58 self._dirs = {}
66 dirs = {}
59 for f in self._map:
67 for f,s in self._map.items():
60 if self[f] != 'r':
68 if s[0] != 'r':
61 self._incpath(f)
69 for base in _finddirs(f):
70 dirs[base] = dirs.get(base, 0) + 1
71 self._dirs = dirs
62 return self._dirs
72 return self._dirs
63 elif name == '_ignore':
73 elif name == '_ignore':
64 files = [self._join('.hgignore')]
74 files = [self._join('.hgignore')]
@@ -223,67 +233,39 b' class dirstate(object):'
223 def copies(self):
233 def copies(self):
224 return self._copymap
234 return self._copymap
225
235
226 def _incpath(self, path):
236 def _droppath(self, f):
227 c = path.rfind('/')
237 if self[f] not in "?r" and "_dirs" in self.__dict__:
228 if c >= 0:
229 dirs = self._dirs
238 dirs = self._dirs
230 base = path[:c]
239 for base in _finddirs(f):
231 if base not in dirs:
240 if dirs[base] == 1:
232 self._incpath(base)
241 del dirs[base]
233 dirs[base] = 1
242 else:
234 else:
243 dirs[base] -= 1
235 dirs[base] += 1
236
237 def _decpath(self, path):
238 c = path.rfind('/')
239 if c >= 0:
240 base = path[:c]
241 dirs = self._dirs
242 if dirs[base] == 1:
243 del dirs[base]
244 self._decpath(base)
245 else:
246 dirs[base] -= 1
247
244
248 def _incpathcheck(self, f):
245 def _addpath(self, f, check=False):
249 if '\r' in f or '\n' in f:
250 raise util.Abort(_("'\\n' and '\\r' disallowed in filenames: %r")
251 % f)
252 # shadows
253 if f in self._dirs:
254 raise util.Abort(_('directory %r already in dirstate') % f)
255 for c in strutil.rfindall(f, '/'):
256 d = f[:c]
257 if d in self._dirs:
258 break
259 if d in self._map and self[d] != 'r':
260 raise util.Abort(_('file %r in dirstate clashes with %r') %
261 (d, f))
262 self._incpath(f)
263
264 def _changepath(self, f, newstate, relaxed=False):
265 # handle upcoming path changes
266 oldstate = self[f]
246 oldstate = self[f]
267 if oldstate not in "?r" and newstate in "?r":
247 if check or oldstate == "r":
268 if "_dirs" in self.__dict__:
248 if '\r' in f or '\n' in f:
269 self._decpath(f)
249 raise util.Abort(
270 return
250 _("'\\n' and '\\r' disallowed in filenames: %r") % f)
271 if oldstate in "?r" and newstate not in "?r":
251 if f in self._dirs:
272 if relaxed and oldstate == '?':
252 raise util.Abort(_('directory %r already in dirstate') % f)
273 # XXX
253 # shadows
274 # in relaxed mode we assume the caller knows
254 for d in _finddirs(f):
275 # what it is doing, workaround for updating
255 if d in self._dirs:
276 # dir-to-file revisions
256 break
277 if "_dirs" in self.__dict__:
257 if d in self._map and self[d] != 'r':
278 self._incpath(f)
258 raise util.Abort(
279 return
259 _('file %r in dirstate clashes with %r') % (d, f))
280 self._incpathcheck(f)
260 if oldstate in "?r" and "_dirs" in self.__dict__:
281 return
261 dirs = self._dirs
262 for base in _finddirs(f):
263 dirs[base] = dirs.get(base, 0) + 1
282
264
283 def normal(self, f):
265 def normal(self, f):
284 'mark a file normal and clean'
266 'mark a file normal and clean'
285 self._dirty = True
267 self._dirty = True
286 self._changepath(f, 'n', True)
268 self._addpath(f)
287 s = os.lstat(self._join(f))
269 s = os.lstat(self._join(f))
288 self._map[f] = ('n', s.st_mode, s.st_size, s.st_mtime, 0)
270 self._map[f] = ('n', s.st_mode, s.st_size, s.st_mtime, 0)
289 if f in self._copymap:
271 if f in self._copymap:
@@ -307,7 +289,7 b' class dirstate(object):'
307 if entry[0] == 'm' or entry[0] == 'n' and entry[2] == -2:
289 if entry[0] == 'm' or entry[0] == 'n' and entry[2] == -2:
308 return
290 return
309 self._dirty = True
291 self._dirty = True
310 self._changepath(f, 'n', True)
292 self._addpath(f)
311 self._map[f] = ('n', 0, -1, -1, 0)
293 self._map[f] = ('n', 0, -1, -1, 0)
312 if f in self._copymap:
294 if f in self._copymap:
313 del self._copymap[f]
295 del self._copymap[f]
@@ -315,7 +297,7 b' class dirstate(object):'
315 def normaldirty(self, f):
297 def normaldirty(self, f):
316 'mark a file normal, but dirty'
298 'mark a file normal, but dirty'
317 self._dirty = True
299 self._dirty = True
318 self._changepath(f, 'n', True)
300 self._addpath(f)
319 self._map[f] = ('n', 0, -2, -1, 0)
301 self._map[f] = ('n', 0, -2, -1, 0)
320 if f in self._copymap:
302 if f in self._copymap:
321 del self._copymap[f]
303 del self._copymap[f]
@@ -323,7 +305,7 b' class dirstate(object):'
323 def add(self, f):
305 def add(self, f):
324 'mark a file added'
306 'mark a file added'
325 self._dirty = True
307 self._dirty = True
326 self._changepath(f, 'a')
308 self._addpath(f, True)
327 self._map[f] = ('a', 0, -1, -1, 0)
309 self._map[f] = ('a', 0, -1, -1, 0)
328 if f in self._copymap:
310 if f in self._copymap:
329 del self._copymap[f]
311 del self._copymap[f]
@@ -331,7 +313,7 b' class dirstate(object):'
331 def remove(self, f):
313 def remove(self, f):
332 'mark a file removed'
314 'mark a file removed'
333 self._dirty = True
315 self._dirty = True
334 self._changepath(f, 'r')
316 self._droppath(f)
335 size = 0
317 size = 0
336 if self._pl[1] != nullid and f in self._map:
318 if self._pl[1] != nullid and f in self._map:
337 entry = self._map[f]
319 entry = self._map[f]
@@ -347,7 +329,7 b' class dirstate(object):'
347 'mark a file merged'
329 'mark a file merged'
348 self._dirty = True
330 self._dirty = True
349 s = os.lstat(self._join(f))
331 s = os.lstat(self._join(f))
350 self._changepath(f, 'm', True)
332 self._addpath(f)
351 self._map[f] = ('m', s.st_mode, s.st_size, s.st_mtime, 0)
333 self._map[f] = ('m', s.st_mode, s.st_size, s.st_mtime, 0)
352 if f in self._copymap:
334 if f in self._copymap:
353 del self._copymap[f]
335 del self._copymap[f]
@@ -356,7 +338,7 b' class dirstate(object):'
356 'forget a file'
338 'forget a file'
357 self._dirty = True
339 self._dirty = True
358 try:
340 try:
359 self._changepath(f, '?')
341 self._droppath(f)
360 del self._map[f]
342 del self._map[f]
361 except KeyError:
343 except KeyError:
362 self._ui.warn(_("not in dirstate: %s\n") % f)
344 self._ui.warn(_("not in dirstate: %s\n") % f)
@@ -467,8 +449,8 b' class dirstate(object):'
467 return False
449 return False
468 if self._ignore(f):
450 if self._ignore(f):
469 return True
451 return True
470 for c in strutil.findall(f, '/'):
452 for p in _finddirs(f):
471 if self._ignore(f[:c]):
453 if self._ignore(p):
472 return True
454 return True
473 return False
455 return False
474
456
@@ -606,7 +588,7 b' class dirstate(object):'
606 known[nn] = 1
588 known[nn] = 1
607 if match(nf):
589 if match(nf):
608 if supported(ff, st.st_mode, verbose=True):
590 if supported(ff, st.st_mode, verbose=True):
609 yield 'f', self.normalize(nf), st
591 yield 'f', nn, st
610 elif ff in dc:
592 elif ff in dc:
611 yield 'm', nf, st
593 yield 'm', nf, st
612
594
@@ -21,7 +21,7 b' helptable = ('
21 "13:18" (today assumed)
21 "13:18" (today assumed)
22 "3:39" (3:39AM assumed)
22 "3:39" (3:39AM assumed)
23 "3:39pm" (15:39)
23 "3:39pm" (15:39)
24 "2006-12-6 13:18:29" (ISO 8601 format)
24 "2006-12-06 13:18:29" (ISO 8601 format)
25 "2006-12-6 13:18"
25 "2006-12-6 13:18"
26 "2006-12-6"
26 "2006-12-6"
27 "12-6"
27 "12-6"
@@ -943,7 +943,7 b' class localrepository(repo.repository):'
943 '''
943 '''
944 return self[node].walk(match)
944 return self[node].walk(match)
945
945
946 def status(self, node1=None, node2=None, match=None,
946 def status(self, node1='.', node2=None, match=None,
947 ignored=False, clean=False, unknown=False):
947 ignored=False, clean=False, unknown=False):
948 """return status of files between two nodes or node and working directory
948 """return status of files between two nodes or node and working directory
949
949
@@ -951,111 +951,84 b' class localrepository(repo.repository):'
951 If node2 is None, compare node1 with working directory.
951 If node2 is None, compare node1 with working directory.
952 """
952 """
953
953
954 def fcmp(fn, getnode):
954 def mfmatches(ctx):
955 t1 = self.wread(fn)
955 mf = ctx.manifest().copy()
956 return self.file(fn).cmp(getnode(fn), t1)
957
958 def mfmatches(node):
959 change = self.changelog.read(node)
960 mf = self.manifest.read(change[0]).copy()
961 for fn in mf.keys():
956 for fn in mf.keys():
962 if not match(fn):
957 if not match(fn):
963 del mf[fn]
958 del mf[fn]
964 return mf
959 return mf
965
960
966 if not match:
961 ctx1 = self[node1]
967 match = match_.always(self.root, self.getcwd())
962 ctx2 = self[node2]
968
963 working = ctx2 == self[None]
964 parentworking = working and ctx1 == self['.']
965 match = match or match_.always(self.root, self.getcwd())
969 listignored, listclean, listunknown = ignored, clean, unknown
966 listignored, listclean, listunknown = ignored, clean, unknown
970 modified, added, removed, deleted, unknown = [], [], [], [], []
971 ignored, clean = [], []
972
967
973 compareworking = False
968 if working: # we need to scan the working dir
974 if not node1 or (not node2 and node1 == self.dirstate.parents()[0]):
969 s = self.dirstate.status(match, listignored, listclean, listunknown)
975 compareworking = True
970 cmp, modified, added, removed, deleted, unknown, ignored, clean = s
976
977 if not compareworking:
978 # read the manifest from node1 before the manifest from node2,
979 # so that we'll hit the manifest cache if we're going through
980 # all the revisions in parent->child order.
981 mf1 = mfmatches(node1)
982
971
983 # are we comparing the working directory?
972 # check for any possibly clean files
984 if not node2:
973 if parentworking and cmp:
985 (lookup, modified, added, removed, deleted, unknown,
974 fixup = []
986 ignored, clean) = self.dirstate.status(match, listignored,
975 # do a full compare of any files that might have changed
987 listclean, listunknown)
976 for f in cmp:
988 # are we comparing working dir against its parent?
977 if (f not in ctx1 or ctx2.flags(f) != ctx1.flags(f)
989 if compareworking:
978 or ctx1[f].cmp(ctx2[f].data())):
990 if lookup:
979 modified.append(f)
991 fixup = []
980 else:
992 # do a full compare of any files that might have changed
981 fixup.append(f)
993 ctx = self['.']
982
994 ff = self.dirstate.flagfunc(ctx.flags)
983 modified.sort()
995 for f in lookup:
984 if listclean:
996 if (f not in ctx or ff(f) != ctx.flags(f)
985 clean = util.sort(clean + fixup)
997 or ctx[f].cmp(self.wread(f))):
998 modified.append(f)
999 else:
1000 fixup.append(f)
1001 if listclean:
1002 clean.append(f)
1003
986
1004 # update dirstate for files that are actually clean
987 # update dirstate for files that are actually clean
1005 if fixup:
988 if fixup:
1006 wlock = None
989 wlock = None
990 try:
1007 try:
991 try:
1008 try:
992 wlock = self.wlock(False)
1009 wlock = self.wlock(False)
993 for f in fixup:
1010 except lock.LockException:
994 self.dirstate.normal(f)
1011 pass
995 except lock.LockException:
1012 if wlock:
996 pass
1013 for f in fixup:
997 finally:
1014 self.dirstate.normal(f)
998 del wlock
1015 finally:
999
1016 del wlock
1000 if not parentworking:
1017 else:
1001 mf1 = mfmatches(ctx1)
1002 if working:
1018 # we are comparing working dir against non-parent
1003 # we are comparing working dir against non-parent
1019 # generate a pseudo-manifest for the working dir
1004 # generate a pseudo-manifest for the working dir
1020 # XXX: create it in dirstate.py ?
1005 mf2 = mfmatches(self['.'])
1021 mf2 = mfmatches(self.dirstate.parents()[0])
1006 mf2.flags = ctx2.flags # delay flag lookup
1022 ff = self.dirstate.flagfunc(mf2.flags)
1007 for f in cmp + modified + added:
1023 for f in lookup + modified + added:
1008 mf2[f] = None
1024 mf2[f] = ""
1025 mf2.set(f, ff(f))
1026 for f in removed:
1009 for f in removed:
1027 if f in mf2:
1010 if f in mf2:
1028 del mf2[f]
1011 del mf2[f]
1029
1012 else:
1030 else:
1013 # we are comparing two revisions
1031 # we are comparing two revisions
1014 deleted, unknown, ignored = [], [], []
1032 mf2 = mfmatches(node2)
1015 mf2 = mfmatches(ctx2)
1033
1016
1034 if not compareworking:
1035 # flush lists from dirstate before comparing manifests
1036 modified, added, clean = [], [], []
1017 modified, added, clean = [], [], []
1037
1038 # make sure to sort the files so we talk to the disk in a
1039 # reasonable order
1040 getnode = lambda fn: mf1.get(fn, nullid)
1041 for fn in util.sort(mf2):
1018 for fn in util.sort(mf2):
1042 if fn in mf1:
1019 if fn in mf1:
1043 if (mf1.flags(fn) != mf2.flags(fn) or
1020 if ((mf1[fn] != mf2[fn] and
1044 (mf1[fn] != mf2[fn] and
1021 (mf2[fn] or ctx1[fn].cmp(ctx2[fn].data())))
1045 (mf2[fn] != "" or fcmp(fn, getnode)))):
1022 or mf1.flags(fn) != mf2.flags(fn)):
1046 modified.append(fn)
1023 modified.append(fn)
1047 elif listclean:
1024 elif listclean:
1048 clean.append(fn)
1025 clean.append(fn)
1049 del mf1[fn]
1026 del mf1[fn]
1050 else:
1027 else:
1051 added.append(fn)
1028 added.append(fn)
1052
1029 removed = util.sort(mf1.keys())
1053 removed = mf1.keys()
1054
1030
1055 # sort and return results:
1031 return modified, added, removed, deleted, unknown, ignored, clean
1056 for l in modified, added, removed, deleted, unknown, ignored, clean:
1057 l.sort()
1058 return (modified, added, removed, deleted, unknown, ignored, clean)
1059
1032
1060 def add(self, list):
1033 def add(self, list):
1061 wlock = self.wlock()
1034 wlock = self.wlock()
General Comments 0
You need to be logged in to leave comments. Login now