# HG changeset patch # User Matt Mackall # Date 1185051729 18000 # Node ID 6fd953d5faead84491d9e218ef843697a59e7899 # Parent 81078e1772664bc560efa95ae48513a70cb20f14 dirstate: break update into separate functions diff --git a/hgext/convert/hg.py b/hgext/convert/hg.py --- a/hgext/convert/hg.py +++ b/hgext/convert/hg.py @@ -27,7 +27,7 @@ class convert_mercurial(converter_sink): def putfile(self, f, e, data): self.repo.wwrite(f, data, e) if self.repo.dirstate.state(f) == '?': - self.repo.dirstate.update([f], "a") + self.repo.dirstate.add(f) def copyfile(self, source, dest): self.repo.copy(source, dest) diff --git a/hgext/mq.py b/hgext/mq.py --- a/hgext/mq.py +++ b/hgext/mq.py @@ -501,8 +501,10 @@ class queue: merged.append(f) else: removed.append(f) - repo.dirstate.update(repo.dirstate.filterfiles(removed), 'r') - repo.dirstate.update(repo.dirstate.filterfiles(merged), 'm') + for f in removed: + repo.dirstate.remove(f) + for f in merged: + repo.dirstate.merge(f) p1, p2 = repo.dirstate.parents() repo.dirstate.setparents(p1, merge) files = patch.updatedir(self.ui, repo, files, wlock=wlock) @@ -868,7 +870,8 @@ class queue: for f in r: getfile(f, mmap[f]) util.set_exec(repo.wjoin(f), mmap.execf(f)) - repo.dirstate.update(m + r, 'n') + for f in m + r: + repo.dirstate.normal(f) for f in a: try: os.unlink(repo.wjoin(f)) @@ -877,8 +880,7 @@ class queue: raise try: os.removedirs(os.path.dirname(repo.wjoin(f))) except: pass - if a: - repo.dirstate.forget(a) + repo.dirstate.forget(f) repo.dirstate.setparents(qp, revlog.nullid) self.strip(repo, rev, update=False, backup='strip', wlock=wlock) del self.applied[start:end] @@ -1010,7 +1012,7 @@ class queue: if src is None: continue copies.setdefault(src, []).append(dst) - repo.dirstate.update(a, 'a') + repo.dirstate.add(dst) # remember the copies between patchparent and tip # this may be slow, so don't do it if we're not tracking copies if self.diffopts().git: @@ -1027,7 +1029,8 @@ class queue: for src, dsts in copies.iteritems(): for dst in dsts: repo.dirstate.copy(src, dst) - repo.dirstate.update(r, 'r') + for f in r: + repo.dirstate.remove(f) # if the patch excludes a modified file, mark that file with mtime=0 # so status can see it. mm = [] @@ -1035,9 +1038,12 @@ class queue: if not matchfn(m[i]): mm.append(m[i]) del m[i] - repo.dirstate.update(m, 'n') - repo.dirstate.update(mm, 'n', st_mtime=-1, st_size=-1) - repo.dirstate.forget(forget) + for f in m: + repo.dirstate.normal(f) + for f in mm: + repo.dirstate.normaldirty(f) + for f in forget: + repo.dirstate.forget(f) if not msg: if not message: @@ -1066,9 +1072,9 @@ class queue: raise try: os.removedirs(os.path.dirname(f)) except: pass - # forget the file copies in the dirstate - # push should readd the files later on - repo.dirstate.forget(added) + # forget the file copies in the dirstate + # push should readd the files later on + repo.dirstate.forget(a) self.pop(repo, force=True, wlock=wlock) self.push(repo, force=True, wlock=wlock) diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -2415,11 +2415,15 @@ def revert(ui, repo, *pats, **opts): handle(remove, False) if not opts.get('dry_run'): - repo.dirstate.forget(forget[0]) + for f in forget[0]: + repo.dirstate.forget(f) r = hg.revert(repo, node, update.has_key, wlock) - repo.dirstate.update(add[0], 'a') - repo.dirstate.update(undelete[0], 'n') - repo.dirstate.update(remove[0], 'r') + for f in add[0]: + repo.dirstate.add(f) + for f in undelete[0]: + repo.dirstate.normal(f) + for f in remove[0]: + repo.dirstate.remove(f) return r def rollback(ui, repo): diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py --- a/mercurial/dirstate.py +++ b/mercurial/dirstate.py @@ -118,6 +118,11 @@ class dirstate(object): self._opener("branch", "w").write(branch + '\n') def state(self, key): + ''' current states: + n normal + m needs merging + r marked for removal + a marked for addition''' return self._map.get(key, ("?",))[0] def _read(self): @@ -197,41 +202,55 @@ class dirstate(object): raise util.Abort(_('file named %r already in dirstate') % d) self._incpath(f) - def update(self, files, state, **kw): - ''' current states: - n normal - m needs merging - r marked for removal - a marked for addition''' + def normal(self, f): + 'mark a file normal' + self._dirty = True + s = os.lstat(self.wjoin(f)) + self._map[f] = ('n', s.st_mode, s.st_size, s.st_mtime) + if self._copymap.has_key(f): + del self._copymap[f] - if not files: return + def normaldirty(self, f): + 'mark a file normal, but possibly dirty' self._dirty = True - for f in files: - if self._copymap.has_key(f): - del self._copymap[f] + s = os.lstat(self.wjoin(f)) + self._map[f] = ('n', s.st_mode, -1, -1) + if f in self._copymap: + del self._copymap[f] + + def add(self, f): + 'mark a file added' + self._dirty = True + self._incpathcheck(f) + s = os.lstat(self.wjoin(f)) + self._map[f] = ('a', s.st_mode, s.st_size, s.st_mtime) + if f in self._copymap: + del self._copymap[f] - if state == "r": - self._map[f] = ('r', 0, 0, 0) - self._decpath(f) - continue - else: - if state == "a": - self._incpathcheck(f) - s = os.lstat(self.wjoin(f)) - st_size = kw.get('st_size', s.st_size) - st_mtime = kw.get('st_mtime', s.st_mtime) - self._map[f] = (state, s.st_mode, st_size, st_mtime) + def remove(self, f): + 'mark a file removed' + self._dirty = True + self._map[f] = ('r', 0, 0, 0) + self._decpath(f) + if f in self._copymap: + del self._copymap[f] - def forget(self, files): - if not files: return + def merge(self, f): + 'mark a file merged' self._dirty = True - for f in files: - try: - del self._map[f] - self._decpath(f) - except KeyError: - self._ui.warn(_("not in dirstate: %s!\n") % f) - pass + s = os.lstat(self.wjoin(f)) + self._map[f] = ('m', s.st_mode, s.st_size, s.st_mtime) + if f in self._copymap: + del self._copymap[f] + + def forget(self, f): + 'forget a file' + self._dirty = True + try: + del self._map[f] + self._decpath(f) + except KeyError: + self._ui.warn(_("not in dirstate: %s!\n") % f) def rebuild(self, parent, files): self.invalidate() diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -792,8 +792,10 @@ class localrepository(repo.repository): if use_dirstate or update_dirstate: self.dirstate.setparents(n) if use_dirstate: - self.dirstate.update(new, "n") - self.dirstate.forget(removed) + for f in new: + self.dirstate.normal(f) + for f in removed: + self.dirstate.forget(f) self.hook("commit", node=hex(n), parent1=xp1, parent2=xp2) return n @@ -901,7 +903,7 @@ class localrepository(repo.repository): except lock.LockException: pass if wlock: - self.dirstate.update([f], "n") + self.dirstate.normal(f) else: # we are comparing working dir against non-parent # generate a pseudo-manifest for the working dir @@ -971,7 +973,7 @@ class localrepository(repo.repository): elif self.dirstate.state(f) in 'an': self.ui.warn(_("%s already tracked!\n") % f) else: - self.dirstate.update([f], "a") + self.dirstate.add(f) def forget(self, list, wlock=None): if not wlock: @@ -980,7 +982,7 @@ class localrepository(repo.repository): if self.dirstate.state(f) not in 'ai': self.ui.warn(_("%s not added!\n") % f) else: - self.dirstate.forget([f]) + self.dirstate.forget(f) def remove(self, list, unlink=False, wlock=None): if unlink: @@ -996,11 +998,11 @@ class localrepository(repo.repository): if unlink and os.path.exists(self.wjoin(f)): self.ui.warn(_("%s still exists!\n") % f) elif self.dirstate.state(f) == 'a': - self.dirstate.forget([f]) + self.dirstate.forget(f) elif f not in self.dirstate: self.ui.warn(_("%s not tracked!\n") % f) else: - self.dirstate.update([f], "r") + self.dirstate.remove(f) def undelete(self, list, wlock=None): p = self.dirstate.parents()[0] @@ -1014,7 +1016,7 @@ class localrepository(repo.repository): else: t = self.file(f).read(m[f]) self.wwrite(f, t, m.flags(f)) - self.dirstate.update([f], "n") + self.dirstate.normal(f) def copy(self, source, dest, wlock=None): p = self.wjoin(dest) @@ -1027,7 +1029,7 @@ class localrepository(repo.repository): if not wlock: wlock = self.wlock() if self.dirstate.state(dest) == '?': - self.dirstate.update([dest], "a") + self.dirstate.add(dest) self.dirstate.copy(source, dest) def heads(self, start=None): diff --git a/mercurial/merge.py b/mercurial/merge.py --- a/mercurial/merge.py +++ b/mercurial/merge.py @@ -447,25 +447,25 @@ def recordupdates(repo, action, branchme f, m = a[:2] if m == "r": # remove if branchmerge: - repo.dirstate.update([f], 'r') + repo.dirstate.remove(f) else: - repo.dirstate.forget([f]) + repo.dirstate.forget(f) elif m == "f": # forget - repo.dirstate.forget([f]) + repo.dirstate.forget(f) elif m == "g": # get if branchmerge: - repo.dirstate.update([f], 'n', st_mtime=-1) + repo.dirstate.normaldirty(f) else: - repo.dirstate.update([f], 'n') + repo.dirstate.normal(f) elif m == "m": # merge f2, fd, flag, move = a[2:] if branchmerge: # We've done a branch merge, mark this file as merged # so that we properly record the merger later - repo.dirstate.update([fd], 'm') + repo.dirstate.merge(fd) if f != f2: # copy/rename if move: - repo.dirstate.update([f], 'r') + repo.dirstate.remove(f) if f != fd: repo.dirstate.copy(f, fd) else: @@ -476,25 +476,25 @@ def recordupdates(repo, action, branchme # of that file some time in the past. Thus our # merge will appear as a normal local file # modification. - repo.dirstate.update([fd], 'n', st_size=-1, st_mtime=-1) + repo.dirstate.normaldirty(fd) if move: - repo.dirstate.forget([f]) + repo.dirstate.forget(f) elif m == "d": # directory rename f2, fd, flag = a[2:] if not f2 and f not in repo.dirstate: # untracked file moved continue if branchmerge: - repo.dirstate.update([fd], 'a') + repo.dirstate.add(fd) if f: - repo.dirstate.update([f], 'r') + repo.dirstate.remove(f) repo.dirstate.copy(f, fd) if f2: repo.dirstate.copy(f2, fd) else: - repo.dirstate.update([fd], 'n') + repo.dirstate.normal(fd) if f: - repo.dirstate.forget([f]) + repo.dirstate.forget(f) def update(repo, node, branchmerge, force, partial, wlock): """