diff --git a/hgext/gpg.py b/hgext/gpg.py --- a/hgext/gpg.py +++ b/hgext/gpg.py @@ -247,7 +247,7 @@ def sign(ui, repo, *revs, **opts): repo.wfile(".hgsigs", "ab").write(sigmessage) if '.hgsigs' not in repo.dirstate: - repo.add([".hgsigs"]) + repo[None].add([".hgsigs"]) if opts["no_commit"]: return diff --git a/hgext/keyword.py b/hgext/keyword.py --- a/hgext/keyword.py +++ b/hgext/keyword.py @@ -358,7 +358,7 @@ def demo(ui, repo, *args, **opts): demoitems('keywordmaps', kwmaps.iteritems()) keywords = '$' + '$\n$'.join(sorted(kwmaps.keys())) + '$\n' repo.wopener(fn, 'w').write(keywords) - repo.add([fn]) + repo[None].add([fn]) ui.note(_('\nkeywords written to %s:\n') % fn) ui.note(keywords) repo.dirstate.setbranch('demobranch') diff --git a/hgext/mq.py b/hgext/mq.py --- a/hgext/mq.py +++ b/hgext/mq.py @@ -705,7 +705,7 @@ class queue(object): if not keep: r = self.qrepo() if r: - r.remove(patches, True) + r[None].remove(patches, True) else: for p in patches: os.unlink(self.join(p)) @@ -874,7 +874,7 @@ class queue(object): wlock = None r = self.qrepo() if r: - r.add([patchfn]) + r[None].add([patchfn]) except: repo.rollback() raise @@ -1713,7 +1713,7 @@ class queue(object): self.series_dirty = 1 qrepo = self.qrepo() if qrepo: - qrepo.add(added) + qrepo[None].add(added) def delete(ui, repo, *patches, **opts): """remove patches from queue @@ -1832,7 +1832,7 @@ def qinit(ui, repo, create): fp.close() if not os.path.exists(r.wjoin('series')): r.wopener('series', 'w').close() - r.add(['.hgignore', 'series']) + r[None].add(['.hgignore', 'series']) commands.add(ui, r) return 0 @@ -2308,6 +2308,7 @@ def rename(ui, repo, patch, name=None, * util.rename(q.join(patch), absdest) r = q.qrepo() if r: + wctx = r[None] wlock = r.wlock() try: if r.dirstate[patch] == 'a': @@ -2315,9 +2316,9 @@ def rename(ui, repo, patch, name=None, * r.dirstate.add(name) else: if r.dirstate[name] == 'r': - r.undelete([name]) - r.copy(patch, name) - r.remove([patch], False) + wctx.undelete([name]) + wctx.copy(patch, name) + wctx.remove([patch], False) finally: wlock.release() diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -311,12 +311,13 @@ def addremove(repo, pats=[], opts={}, dr copies[new] = old if not dry_run: + wctx = repo[None] wlock = repo.wlock() try: - repo.remove(deleted) - repo.add(unknown) + wctx.remove(deleted) + wctx.add(unknown) for new, old in copies.iteritems(): - repo.copy(old, new) + wctx.copy(old, new) finally: wlock.release() @@ -329,6 +330,7 @@ def copy(ui, repo, pats, opts, rename=Fa targets = {} after = opts.get("after") dryrun = opts.get("dry_run") + wctx = repo[None] def walkpat(pat): srcs = [] @@ -421,12 +423,12 @@ def copy(ui, repo, pats, opts, rename=Fa "data will be stored for %s.\n") % (repo.pathto(origsrc, cwd), reltarget)) if repo.dirstate[abstarget] in '?r' and not dryrun: - repo.add([abstarget]) + wctx.add([abstarget]) elif not dryrun: - repo.copy(origsrc, abstarget) + wctx.copy(origsrc, abstarget) if rename and not dryrun: - repo.remove([abssrc], not after) + wctx.remove([abssrc], not after) # pat: ossep # dest ossep diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -56,7 +56,7 @@ def add(ui, repo, *pats, **opts): if ui.verbose or not exact: ui.status(_('adding %s\n') % m.rel(f)) if not opts.get('dry_run'): - bad += [f for f in repo.add(names) if f in m.files()] + bad += [f for f in repo[None].add(names) if f in m.files()] return bad and 1 or 0 def addremove(ui, repo, *pats, **opts): @@ -1314,7 +1314,7 @@ def forget(ui, repo, *pats, **opts): if ui.verbose or not m.exact(f): ui.status(_('removing %s\n') % m.rel(f)) - repo.remove(forget, unlink=False) + repo[None].remove(forget, unlink=False) return errs def grep(ui, repo, pattern, *pats, **opts): @@ -2669,8 +2669,8 @@ def remove(ui, repo, *pats, **opts): if ui.verbose or not m.exact(f): ui.status(_('removing %s\n') % m.rel(f)) - repo.forget(forget) - repo.remove(remove, unlink=not after) + repo[None].forget(forget) + repo[None].remove(remove, unlink=not after) return ret def rename(ui, repo, *pats, **opts): diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -8,7 +8,7 @@ from node import nullid, nullrev, short, hex from i18n import _ import ancestor, bdiff, error, util, subrepo, patch -import os, errno +import os, errno, stat propertycache = util.propertycache @@ -761,6 +761,103 @@ class workingctx(changectx): self.modified() or self.added() or self.removed() or (missing and self.deleted())) + def add(self, list): + wlock = self._repo.wlock() + ui, ds = self._repo.ui, self._repo.dirstate + try: + rejected = [] + for f in list: + p = self._repo.wjoin(f) + try: + st = os.lstat(p) + except: + ui.warn(_("%s does not exist!\n") % f) + rejected.append(f) + continue + if st.st_size > 10000000: + ui.warn(_("%s: up to %d MB of RAM may be required " + "to manage this file\n" + "(use 'hg revert %s' to cancel the " + "pending addition)\n") + % (f, 3 * st.st_size // 1000000, f)) + if not (stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode)): + ui.warn(_("%s not added: only files and symlinks " + "supported currently\n") % f) + rejected.append(p) + elif ds[f] in 'amn': + ui.warn(_("%s already tracked!\n") % f) + elif ds[f] == 'r': + ds.normallookup(f) + else: + ds.add(f) + return rejected + finally: + wlock.release() + + def forget(self, list): + wlock = self._repo.wlock() + try: + for f in list: + if self._repo.dirstate[f] != 'a': + self._repo.ui.warn(_("%s not added!\n") % f) + else: + self._repo.dirstate.forget(f) + finally: + wlock.release() + + def remove(self, list, unlink=False): + if unlink: + for f in list: + try: + util.unlink(self._repo.wjoin(f)) + except OSError, inst: + if inst.errno != errno.ENOENT: + raise + wlock = self._repo.wlock() + try: + for f in list: + if unlink and os.path.exists(self._repo.wjoin(f)): + self._repo.ui.warn(_("%s still exists!\n") % f) + elif self._repo.dirstate[f] == 'a': + self._repo.dirstate.forget(f) + elif f not in self._repo.dirstate: + self._repo.ui.warn(_("%s not tracked!\n") % f) + else: + self._repo.dirstate.remove(f) + finally: + wlock.release() + + def undelete(self, list): + pctxs = self.parents() + wlock = self._repo.wlock() + try: + for f in list: + if self._repo.dirstate[f] != 'r': + self._repo.ui.warn(_("%s not removed!\n") % f) + else: + fctx = f in pctxs[0] and pctxs[0] or pctxs[1] + t = fctx.data() + self._repo.wwrite(f, t, fctx.flags()) + self._repo.dirstate.normal(f) + finally: + wlock.release() + + def copy(self, source, dest): + p = self._repo.wjoin(dest) + if not (os.path.exists(p) or os.path.islink(p)): + self._repo.ui.warn(_("%s does not exist!\n") % dest) + elif not (os.path.isfile(p) or os.path.islink(p)): + self._repo.ui.warn(_("copy failed: %s is not a file or a " + "symbolic link\n") % dest) + else: + wlock = self._repo.wlock() + try: + if self._repo.dirstate[dest] in '?r': + self._repo.dirstate.add(dest) + self._repo.dirstate.copy(source, dest) + finally: + wlock.release() + class workingfilectx(filectx): """A workingfilectx object makes access to data related to a particular file in the working directory convenient.""" diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -16,7 +16,7 @@ import merge as mergemod import tags as tagsmod import url as urlmod from lock import release -import weakref, stat, errno, os, time, inspect +import weakref, errno, os, time, inspect propertycache = util.propertycache class localrepository(repo.repository): @@ -210,7 +210,7 @@ class localrepository(repo.repository): writetags(fp, names, encoding.fromlocal, prevtags) if '.hgtags' not in self.dirstate: - self.add(['.hgtags']) + self[None].add(['.hgtags']) m = matchmod.exact(self.root, '', ['.hgtags']) tagnode = self.commit(message, user, date, extra=extra, match=m) @@ -1112,103 +1112,6 @@ class localrepository(repo.repository): [l.sort() for l in r] return r - def add(self, list): - wlock = self.wlock() - try: - rejected = [] - for f in list: - p = self.wjoin(f) - try: - st = os.lstat(p) - except: - self.ui.warn(_("%s does not exist!\n") % f) - rejected.append(f) - continue - if st.st_size > 10000000: - self.ui.warn(_("%s: up to %d MB of RAM may be required " - "to manage this file\n" - "(use 'hg revert %s' to cancel the " - "pending addition)\n") - % (f, 3 * st.st_size // 1000000, f)) - if not (stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode)): - self.ui.warn(_("%s not added: only files and symlinks " - "supported currently\n") % f) - rejected.append(p) - elif self.dirstate[f] in 'amn': - self.ui.warn(_("%s already tracked!\n") % f) - elif self.dirstate[f] == 'r': - self.dirstate.normallookup(f) - else: - self.dirstate.add(f) - return rejected - finally: - wlock.release() - - def forget(self, list): - wlock = self.wlock() - try: - for f in list: - if self.dirstate[f] != 'a': - self.ui.warn(_("%s not added!\n") % f) - else: - self.dirstate.forget(f) - finally: - wlock.release() - - def remove(self, list, unlink=False): - if unlink: - for f in list: - try: - util.unlink(self.wjoin(f)) - except OSError, inst: - if inst.errno != errno.ENOENT: - raise - wlock = self.wlock() - try: - for f in list: - if unlink and os.path.exists(self.wjoin(f)): - self.ui.warn(_("%s still exists!\n") % f) - elif self.dirstate[f] == 'a': - self.dirstate.forget(f) - elif f not in self.dirstate: - self.ui.warn(_("%s not tracked!\n") % f) - else: - self.dirstate.remove(f) - finally: - wlock.release() - - def undelete(self, list): - manifests = [self.manifest.read(self.changelog.read(p)[0]) - for p in self.dirstate.parents() if p != nullid] - wlock = self.wlock() - try: - for f in list: - if self.dirstate[f] != 'r': - self.ui.warn(_("%s not removed!\n") % f) - else: - m = f in manifests[0] and manifests[0] or manifests[1] - t = self.file(f).read(m[f]) - self.wwrite(f, t, m.flags(f)) - self.dirstate.normal(f) - finally: - wlock.release() - - def copy(self, source, dest): - p = self.wjoin(dest) - if not (os.path.exists(p) or os.path.islink(p)): - self.ui.warn(_("%s does not exist!\n") % dest) - elif not (os.path.isfile(p) or os.path.islink(p)): - self.ui.warn(_("copy failed: %s is not a file or a " - "symbolic link\n") % dest) - else: - wlock = self.wlock() - try: - if self.dirstate[dest] in '?r': - self.dirstate.add(dest) - self.dirstate.copy(source, dest) - finally: - wlock.release() - def heads(self, start=None): heads = self.changelog.heads(start) # sort the output in rev descending order diff --git a/mercurial/patch.py b/mercurial/patch.py --- a/mercurial/patch.py +++ b/mercurial/patch.py @@ -1226,10 +1226,13 @@ def updatedir(ui, repo, patches, similar copies.append((gp.oldpath, gp.path)) elif gp.op == 'DELETE': removes.add(gp.path) + + wctx = repo[None] for src, dst in copies: - repo.copy(src, dst) + wctx.copy(src, dst) if (not similarity) and removes: - repo.remove(sorted(removes), True) + wctx.remove(sorted(removes), True) + for f in patches: gp = patches[f] if gp and gp.mode: diff --git a/tests/test-context.py b/tests/test-context.py --- a/tests/test-context.py +++ b/tests/test-context.py @@ -13,7 +13,7 @@ f.close() os.utime('foo', (1000, 1000)) # add+commit 'foo' -repo.add(['foo']) +repo[None].add(['foo']) repo.commit(text='commit1', date="0 0") print "workingfilectx.date =", repo[None]['foo'].date() diff --git a/tests/test-revlog-ancestry.py b/tests/test-revlog-ancestry.py --- a/tests/test-revlog-ancestry.py +++ b/tests/test-revlog-ancestry.py @@ -13,7 +13,7 @@ def addcommit(name, time): f = open(name, 'w') f.write('%s\n' % name) f.close() - repo.add([name]) + repo[None].add([name]) commit(name, time) def update(rev):