--- a/contrib/undumprevlog Wed Apr 20 23:30:07 2011 +0200
+++ b/contrib/undumprevlog Wed Apr 20 19:54:57 2011 +0200
@@ -4,12 +4,12 @@
# $ undumprevlog < repo.dump
import sys
-from mercurial import revlog, node, util, transaction
+from mercurial import revlog, node, scmutil, util, transaction
for fp in (sys.stdin, sys.stdout, sys.stderr):
util.set_binary(fp)
-opener = util.opener('.', False)
+opener = scmutil.opener('.', False)
tr = transaction.transaction(sys.stderr.write, opener, "undump.journal")
while 1:
l = sys.stdin.readline()
--- a/hgext/convert/subversion.py Wed Apr 20 23:30:07 2011 +0200
+++ b/hgext/convert/subversion.py Wed Apr 20 19:54:57 2011 +0200
@@ -10,7 +10,7 @@
import urllib
import urllib2
-from mercurial import strutil, util, encoding
+from mercurial import strutil, scmutil, util, encoding
from mercurial.i18n import _
# Subversion stuff. Works best with very recent Python SVN bindings
@@ -998,8 +998,8 @@
self.run0('checkout', path, wcpath)
self.wc = wcpath
- self.opener = util.opener(self.wc)
- self.wopener = util.opener(self.wc)
+ self.opener = scmutil.opener(self.wc)
+ self.wopener = scmutil.opener(self.wc)
self.childmap = mapfile(ui, self.join('hg-childmap'))
self.is_exec = util.checkexec(self.wc) and util.is_exec or None
--- a/hgext/extdiff.py Wed Apr 20 23:30:07 2011 +0200
+++ b/hgext/extdiff.py Wed Apr 20 19:54:57 2011 +0200
@@ -61,7 +61,7 @@
from mercurial.i18n import _
from mercurial.node import short, nullid
-from mercurial import cmdutil, util, commands, encoding
+from mercurial import cmdutil, scmutil, util, commands, encoding
import os, shlex, shutil, tempfile, re
def snapshot(ui, repo, files, node, tmproot):
@@ -81,7 +81,7 @@
else:
ui.note(_('making snapshot of %d files from working directory\n') %
(len(files)))
- wopener = util.opener(base)
+ wopener = scmutil.opener(base)
fns_and_mtime = []
ctx = repo[node]
for fn in files:
--- a/hgext/mq.py Wed Apr 20 23:30:07 2011 +0200
+++ b/hgext/mq.py Wed Apr 20 19:54:57 2011 +0200
@@ -45,7 +45,7 @@
from mercurial.i18n import _
from mercurial.node import bin, hex, short, nullid, nullrev
from mercurial.lock import release
-from mercurial import commands, cmdutil, hg, patch, util
+from mercurial import commands, cmdutil, hg, patch, scmutil, util
from mercurial import repair, extensions, url, error
import os, sys, re, errno, shutil
@@ -259,7 +259,7 @@
except IOError:
curpath = os.path.join(path, 'patches')
self.path = patchdir or curpath
- self.opener = util.opener(self.path)
+ self.opener = scmutil.opener(self.path)
self.ui = ui
self.applied_dirty = 0
self.series_dirty = 0
--- a/hgext/transplant.py Wed Apr 20 23:30:07 2011 +0200
+++ b/hgext/transplant.py Wed Apr 20 19:54:57 2011 +0200
@@ -16,7 +16,7 @@
from mercurial.i18n import _
import os, tempfile
from mercurial import bundlerepo, cmdutil, hg, merge, match
-from mercurial import patch, revlog, util, error
+from mercurial import patch, revlog, scmutil, util, error
from mercurial import revset, templatekw
class transplantentry(object):
@@ -31,7 +31,7 @@
self.opener = opener
if not opener:
- self.opener = util.opener(self.path)
+ self.opener = scmutil.opener(self.path)
self.transplants = {}
self.dirty = False
self.read()
@@ -74,7 +74,7 @@
def __init__(self, ui, repo):
self.ui = ui
self.path = repo.join('transplant')
- self.opener = util.opener(self.path)
+ self.opener = scmutil.opener(self.path)
self.transplants = transplants(self.path, 'transplants',
opener=self.opener)
--- a/mercurial/archival.py Wed Apr 20 23:30:07 2011 +0200
+++ b/mercurial/archival.py Wed Apr 20 19:54:57 2011 +0200
@@ -8,7 +8,7 @@
from i18n import _
from node import hex
import cmdutil
-import util, encoding
+import scmutil, util, encoding
import cStringIO, os, tarfile, time, zipfile
import zlib, gzip
@@ -187,7 +187,7 @@
def __init__(self, name, mtime):
self.basedir = name
- self.opener = util.opener(self.basedir)
+ self.opener = scmutil.opener(self.basedir)
def addfile(self, name, mode, islink, data):
if islink:
--- a/mercurial/commands.py Wed Apr 20 23:30:07 2011 +0200
+++ b/mercurial/commands.py Wed Apr 20 19:54:57 2011 +0200
@@ -9,7 +9,7 @@
from lock import release
from i18n import _, gettext
import os, re, sys, difflib, time, tempfile
-import hg, util, revlog, extensions, copies, error, bookmarks
+import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
import patch, help, mdiff, url, encoding, templatekw, discovery
import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
import merge as mergemod
@@ -975,7 +975,7 @@
"""find the ancestor revision of two revisions in a given index"""
if len(args) == 3:
index, rev1, rev2 = args
- r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
+ r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
lookup = r.lookup
elif len(args) == 2:
if not repo:
@@ -1393,7 +1393,7 @@
spaces = opts.get('spaces')
dots = opts.get('dots')
if file_:
- rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
+ rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
revs = set((int(r) for r in revs))
def events():
for r in rlog:
@@ -1443,7 +1443,8 @@
if len(filelog):
r = filelog
if not r:
- r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
+ r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False),
+ file_[:-2] + ".i")
try:
ui.write(r.revision(r.lookup(rev)))
except KeyError:
@@ -1482,7 +1483,7 @@
raise util.Abort(_("unknown format %d") % format)
if not r:
- r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
+ r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
if format == 0:
ui.write(" rev offset length base linkrev"
@@ -1515,7 +1516,7 @@
if len(filelog):
r = filelog
if not r:
- r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
+ r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
ui.write("digraph G {\n")
for i in r:
node = r.node(i)
--- a/mercurial/localrepo.py Wed Apr 20 23:30:07 2011 +0200
+++ b/mercurial/localrepo.py Wed Apr 20 19:54:57 2011 +0200
@@ -10,7 +10,7 @@
import repo, changegroup, subrepo, discovery, pushkey
import changelog, dirstate, filelog, manifest, context, bookmarks
import lock, transaction, store, encoding
-import util, extensions, hook, error
+import scmutil, util, extensions, hook, error
import match as matchmod
import merge as mergemod
import tags as tagsmod
@@ -32,8 +32,8 @@
self.path = os.path.join(self.root, ".hg")
self.origroot = path
self.auditor = util.path_auditor(self.root, self._checknested)
- self.opener = util.opener(self.path)
- self.wopener = util.opener(self.root)
+ self.opener = scmutil.opener(self.path)
+ self.wopener = scmutil.opener(self.root)
self.baseui = baseui
self.ui = baseui.copy()
@@ -90,7 +90,7 @@
if inst.errno != errno.ENOENT:
raise
- self.store = store.store(requirements, self.sharedpath, util.opener)
+ self.store = store.store(requirements, self.sharedpath, scmutil.opener)
self.spath = self.store.path
self.sopener = self.store.opener
self.sjoin = self.store.join
--- a/mercurial/patch.py Wed Apr 20 23:30:07 2011 +0200
+++ b/mercurial/patch.py Wed Apr 20 19:54:57 2011 +0200
@@ -11,7 +11,7 @@
from i18n import _
from node import hex, nullid, short
-import base85, mdiff, util, diffhelpers, copies, encoding
+import base85, mdiff, scmutil, util, diffhelpers, copies, encoding
gitre = re.compile('diff --git a/(.*) b/(.*)')
@@ -1111,7 +1111,7 @@
err = 0
current_file = None
cwd = os.getcwd()
- opener = util.opener(cwd)
+ opener = scmutil.opener(cwd)
for state, values in iterhunks(ui, fp):
if state == 'hunk':
--- a/mercurial/scmutil.py Wed Apr 20 23:30:07 2011 +0200
+++ b/mercurial/scmutil.py Wed Apr 20 19:54:57 2011 +0200
@@ -7,7 +7,7 @@
from i18n import _
import util, error
-import os
+import os, errno
def checkportable(ui, f):
'''Check if filename f is portable and warn or abort depending on config'''
@@ -25,3 +25,98 @@
elif bval is None and lval != 'ignore':
raise error.ConfigError(
_("ui.portablefilenames value is invalid ('%s')") % val)
+
+class opener(object):
+ '''Open files relative to a base directory
+
+ This class is used to hide the details of COW semantics and
+ remote file access from higher level code.
+ '''
+ def __init__(self, base, audit=True):
+ self.base = base
+ if audit:
+ self.auditor = util.path_auditor(base)
+ else:
+ self.auditor = util.always
+ self.createmode = None
+ self._trustnlink = None
+
+ @util.propertycache
+ def _can_symlink(self):
+ return util.checklink(self.base)
+
+ def _fixfilemode(self, name):
+ if self.createmode is None:
+ return
+ os.chmod(name, self.createmode & 0666)
+
+ def __call__(self, path, mode="r", text=False, atomictemp=False):
+ r = util.checkosfilename(path)
+ if r:
+ raise Abort("%s: %r" % (r, path))
+ self.auditor(path)
+ f = os.path.join(self.base, path)
+
+ if not text and "b" not in mode:
+ mode += "b" # for that other OS
+
+ nlink = -1
+ dirname, basename = os.path.split(f)
+ # If basename is empty, then the path is malformed because it points
+ # to a directory. Let the posixfile() call below raise IOError.
+ if basename and mode not in ('r', 'rb'):
+ if atomictemp:
+ if not os.path.isdir(dirname):
+ util.makedirs(dirname, self.createmode)
+ return util.atomictempfile(f, mode, self.createmode)
+ try:
+ if 'w' in mode:
+ util.unlink(f)
+ nlink = 0
+ else:
+ # nlinks() may behave differently for files on Windows
+ # shares if the file is open.
+ fd = util.posixfile(f)
+ nlink = util.nlinks(f)
+ if nlink < 1:
+ nlink = 2 # force mktempcopy (issue1922)
+ fd.close()
+ except (OSError, IOError), e:
+ if e.errno != errno.ENOENT:
+ raise
+ nlink = 0
+ if not os.path.isdir(dirname):
+ util.makedirs(dirname, self.createmode)
+ if nlink > 0:
+ if self._trustnlink is None:
+ self._trustnlink = nlink > 1 or util.checknlink(f)
+ if nlink > 1 or not self._trustnlink:
+ util.rename(util.mktempcopy(f), f)
+ fp = util.posixfile(f, mode)
+ if nlink == 0:
+ self._fixfilemode(f)
+ return fp
+
+ def symlink(self, src, dst):
+ self.auditor(dst)
+ linkname = os.path.join(self.base, dst)
+ try:
+ os.unlink(linkname)
+ except OSError:
+ pass
+
+ dirname = os.path.dirname(linkname)
+ if not os.path.exists(dirname):
+ util.makedirs(dirname, self.createmode)
+
+ if self._can_symlink:
+ try:
+ os.symlink(src, linkname)
+ except OSError, err:
+ raise OSError(err.errno, _('could not symlink to %r: %s') %
+ (src, err.strerror), linkname)
+ else:
+ f = self(dst, "w")
+ f.write(src)
+ f.close()
+ self._fixfilemode(dst)
--- a/mercurial/simplemerge.py Wed Apr 20 23:30:07 2011 +0200
+++ b/mercurial/simplemerge.py Wed Apr 20 19:54:57 2011 +0200
@@ -18,7 +18,7 @@
# s: "i hate that."
from i18n import _
-import util, mdiff
+import scmutil, util, mdiff
import sys, os
class CantReprocessAndShowBase(Exception):
@@ -429,7 +429,7 @@
local = os.path.realpath(local)
if not opts.get('print'):
- opener = util.opener(os.path.dirname(local))
+ opener = scmutil.opener(os.path.dirname(local))
out = opener(os.path.basename(local), "w", atomictemp=True)
else:
out = sys.stdout
--- a/mercurial/util.py Wed Apr 20 23:30:07 2011 +0200
+++ b/mercurial/util.py Wed Apr 20 19:54:57 2011 +0200
@@ -895,101 +895,6 @@
makedirs(parent, mode)
makedirs(name, mode)
-class opener(object):
- """Open files relative to a base directory
-
- This class is used to hide the details of COW semantics and
- remote file access from higher level code.
- """
- def __init__(self, base, audit=True):
- self.base = base
- if audit:
- self.auditor = path_auditor(base)
- else:
- self.auditor = always
- self.createmode = None
- self._trustnlink = None
-
- @propertycache
- def _can_symlink(self):
- return checklink(self.base)
-
- def _fixfilemode(self, name):
- if self.createmode is None:
- return
- os.chmod(name, self.createmode & 0666)
-
- def __call__(self, path, mode="r", text=False, atomictemp=False):
- r = checkosfilename(path)
- if r:
- raise Abort("%s: %r" % (r, path))
- self.auditor(path)
- f = os.path.join(self.base, path)
-
- if not text and "b" not in mode:
- mode += "b" # for that other OS
-
- nlink = -1
- dirname, basename = os.path.split(f)
- # If basename is empty, then the path is malformed because it points
- # to a directory. Let the posixfile() call below raise IOError.
- if basename and mode not in ('r', 'rb'):
- if atomictemp:
- if not os.path.isdir(dirname):
- makedirs(dirname, self.createmode)
- return atomictempfile(f, mode, self.createmode)
- try:
- if 'w' in mode:
- unlink(f)
- nlink = 0
- else:
- # nlinks() may behave differently for files on Windows
- # shares if the file is open.
- fd = posixfile(f)
- nlink = nlinks(f)
- if nlink < 1:
- nlink = 2 # force mktempcopy (issue1922)
- fd.close()
- except (OSError, IOError), e:
- if e.errno != errno.ENOENT:
- raise
- nlink = 0
- if not os.path.isdir(dirname):
- makedirs(dirname, self.createmode)
- if nlink > 0:
- if self._trustnlink is None:
- self._trustnlink = nlink > 1 or checknlink(f)
- if nlink > 1 or not self._trustnlink:
- rename(mktempcopy(f), f)
- fp = posixfile(f, mode)
- if nlink == 0:
- self._fixfilemode(f)
- return fp
-
- def symlink(self, src, dst):
- self.auditor(dst)
- linkname = os.path.join(self.base, dst)
- try:
- os.unlink(linkname)
- except OSError:
- pass
-
- dirname = os.path.dirname(linkname)
- if not os.path.exists(dirname):
- makedirs(dirname, self.createmode)
-
- if self._can_symlink:
- try:
- os.symlink(src, linkname)
- except OSError, err:
- raise OSError(err.errno, _('could not symlink to %r: %s') %
- (src, err.strerror), linkname)
- else:
- f = self(dst, "w")
- f.write(src)
- f.close()
- self._fixfilemode(dst)
-
class chunkbuffer(object):
"""Allow arbitrary sized chunks of data to be efficiently read from an
iterator over chunks of arbitrary size."""
--- a/tests/test-parseindex.t Wed Apr 20 23:30:07 2011 +0200
+++ b/tests/test-parseindex.t Wed Apr 20 19:54:57 2011 +0200
@@ -26,7 +26,7 @@
summary: change foo
$ cat >> test.py << EOF
- > from mercurial import changelog, util
+ > from mercurial import changelog, scmutil
> from mercurial.node import *
>
> class singlebyteread(object):
@@ -42,7 +42,7 @@
> return getattr(self.real, key)
>
> def opener(*args):
- > o = util.opener(*args)
+ > o = scmutil.opener(*args)
> def wrapper(*a):
> f = o(*a)
> return singlebyteread(f)