summaryrefslogtreecommitdiff
path: root/sys/lib/python/mercurial/dirstate.py
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2021-06-14 00:00:37 +0000
committerOri Bernstein <ori@eigenstate.org>2021-06-14 00:00:37 +0000
commita73a964e51247ed169d322c725a3a18859f109a3 (patch)
tree3f752d117274d444bda44e85609aeac1acf313f3 /sys/lib/python/mercurial/dirstate.py
parente64efe273fcb921a61bf27d33b230c4e64fcd425 (diff)
python, hg: tow outside the environment.
they've served us well, and can ride off into the sunset.
Diffstat (limited to 'sys/lib/python/mercurial/dirstate.py')
-rw-r--r--sys/lib/python/mercurial/dirstate.py601
1 files changed, 0 insertions, 601 deletions
diff --git a/sys/lib/python/mercurial/dirstate.py b/sys/lib/python/mercurial/dirstate.py
deleted file mode 100644
index c10e3a6c7..000000000
--- a/sys/lib/python/mercurial/dirstate.py
+++ /dev/null
@@ -1,601 +0,0 @@
-# dirstate.py - working directory tracking for mercurial
-#
-# Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
-#
-# This software may be used and distributed according to the terms of the
-# GNU General Public License version 2, incorporated herein by reference.
-
-from node import nullid
-from i18n import _
-import util, ignore, osutil, parsers
-import struct, os, stat, errno
-import cStringIO, sys
-
-_unknown = ('?', 0, 0, 0)
-_format = ">cllll"
-propertycache = util.propertycache
-
-def _finddirs(path):
- pos = path.rfind('/')
- while pos != -1:
- yield path[:pos]
- pos = path.rfind('/', 0, pos)
-
-def _incdirs(dirs, path):
- for base in _finddirs(path):
- if base in dirs:
- dirs[base] += 1
- return
- dirs[base] = 1
-
-def _decdirs(dirs, path):
- for base in _finddirs(path):
- if dirs[base] > 1:
- dirs[base] -= 1
- return
- del dirs[base]
-
-class dirstate(object):
-
- def __init__(self, opener, ui, root):
- self._opener = opener
- self._root = root
- self._rootdir = os.path.join(root, '')
- self._dirty = False
- self._dirtypl = False
- self._ui = ui
-
- @propertycache
- def _map(self):
- self._read()
- return self._map
-
- @propertycache
- def _copymap(self):
- self._read()
- return self._copymap
-
- @propertycache
- def _foldmap(self):
- f = {}
- for name in self._map:
- f[os.path.normcase(name)] = name
- return f
-
- @propertycache
- def _branch(self):
- try:
- return self._opener("branch").read().strip() or "default"
- except IOError:
- return "default"
-
- @propertycache
- def _pl(self):
- try:
- st = self._opener("dirstate").read(40)
- l = len(st)
- if l == 40:
- return st[:20], st[20:40]
- elif l > 0 and l < 40:
- raise util.Abort(_('working directory state appears damaged!'))
- except IOError, err:
- if err.errno != errno.ENOENT: raise
- return [nullid, nullid]
-
- @propertycache
- def _dirs(self):
- dirs = {}
- for f,s in self._map.iteritems():
- if s[0] != 'r':
- _incdirs(dirs, f)
- return dirs
-
- @propertycache
- def _ignore(self):
- files = [self._join('.hgignore')]
- for name, path in self._ui.configitems("ui"):
- if name == 'ignore' or name.startswith('ignore.'):
- files.append(os.path.expanduser(path))
- return ignore.ignore(self._root, files, self._ui.warn)
-
- @propertycache
- def _slash(self):
- return self._ui.configbool('ui', 'slash') and os.sep != '/'
-
- @propertycache
- def _checklink(self):
- return util.checklink(self._root)
-
- @propertycache
- def _checkexec(self):
- return util.checkexec(self._root)
-
- @propertycache
- def _checkcase(self):
- return not util.checkcase(self._join('.hg'))
-
- def _join(self, f):
- # much faster than os.path.join()
- # it's safe because f is always a relative path
- return self._rootdir + f
-
- def flagfunc(self, fallback):
- if self._checklink:
- if self._checkexec:
- def f(x):
- p = self._join(x)
- if os.path.islink(p):
- return 'l'
- if util.is_exec(p):
- return 'x'
- return ''
- return f
- def f(x):
- if os.path.islink(self._join(x)):
- return 'l'
- if 'x' in fallback(x):
- return 'x'
- return ''
- return f
- if self._checkexec:
- def f(x):
- if 'l' in fallback(x):
- return 'l'
- if util.is_exec(self._join(x)):
- return 'x'
- return ''
- return f
- return fallback
-
- def getcwd(self):
- cwd = os.getcwd()
- if cwd == self._root: return ''
- # self._root ends with a path separator if self._root is '/' or 'C:\'
- rootsep = self._root
- if not util.endswithsep(rootsep):
- rootsep += os.sep
- if cwd.startswith(rootsep):
- return cwd[len(rootsep):]
- else:
- # we're outside the repo. return an absolute path.
- return cwd
-
- def pathto(self, f, cwd=None):
- if cwd is None:
- cwd = self.getcwd()
- path = util.pathto(self._root, cwd, f)
- if self._slash:
- return util.normpath(path)
- return path
-
- def __getitem__(self, key):
- ''' current states:
- n normal
- m needs merging
- r marked for removal
- a marked for addition
- ? not tracked'''
- return self._map.get(key, ("?",))[0]
-
- def __contains__(self, key):
- return key in self._map
-
- def __iter__(self):
- for x in sorted(self._map):
- yield x
-
- def parents(self):
- return self._pl
-
- def branch(self):
- return self._branch
-
- def setparents(self, p1, p2=nullid):
- self._dirty = self._dirtypl = True
- self._pl = p1, p2
-
- def setbranch(self, branch):
- self._branch = branch
- self._opener("branch", "w").write(branch + '\n')
-
- def _read(self):
- self._map = {}
- self._copymap = {}
- try:
- st = self._opener("dirstate").read()
- except IOError, err:
- if err.errno != errno.ENOENT: raise
- return
- if not st:
- return
-
- p = parsers.parse_dirstate(self._map, self._copymap, st)
- if not self._dirtypl:
- self._pl = p
-
- def invalidate(self):
- for a in "_map _copymap _foldmap _branch _pl _dirs _ignore".split():
- if a in self.__dict__:
- delattr(self, a)
- self._dirty = False
-
- def copy(self, source, dest):
- """Mark dest as a copy of source. Unmark dest if source is None.
- """
- if source == dest:
- return
- self._dirty = True
- if source is not None:
- self._copymap[dest] = source
- elif dest in self._copymap:
- del self._copymap[dest]
-
- def copied(self, file):
- return self._copymap.get(file, None)
-
- def copies(self):
- return self._copymap
-
- def _droppath(self, f):
- if self[f] not in "?r" and "_dirs" in self.__dict__:
- _decdirs(self._dirs, f)
-
- def _addpath(self, f, check=False):
- oldstate = self[f]
- if check or oldstate == "r":
- if '\r' in f or '\n' in f:
- raise util.Abort(
- _("'\\n' and '\\r' disallowed in filenames: %r") % f)
- if f in self._dirs:
- raise util.Abort(_('directory %r already in dirstate') % f)
- # shadows
- for d in _finddirs(f):
- if d in self._dirs:
- break
- if d in self._map and self[d] != 'r':
- raise util.Abort(
- _('file %r in dirstate clashes with %r') % (d, f))
- if oldstate in "?r" and "_dirs" in self.__dict__:
- _incdirs(self._dirs, f)
-
- def normal(self, f):
- 'mark a file normal and clean'
- self._dirty = True
- self._addpath(f)
- s = os.lstat(self._join(f))
- self._map[f] = ('n', s.st_mode, s.st_size, int(s.st_mtime))
- if f in self._copymap:
- del self._copymap[f]
-
- def normallookup(self, f):
- 'mark a file normal, but possibly dirty'
- if self._pl[1] != nullid and f in self._map:
- # if there is a merge going on and the file was either
- # in state 'm' or dirty before being removed, restore that state.
- entry = self._map[f]
- if entry[0] == 'r' and entry[2] in (-1, -2):
- source = self._copymap.get(f)
- if entry[2] == -1:
- self.merge(f)
- elif entry[2] == -2:
- self.normaldirty(f)
- if source:
- self.copy(source, f)
- return
- if entry[0] == 'm' or entry[0] == 'n' and entry[2] == -2:
- return
- self._dirty = True
- self._addpath(f)
- self._map[f] = ('n', 0, -1, -1)
- if f in self._copymap:
- del self._copymap[f]
-
- def normaldirty(self, f):
- 'mark a file normal, but dirty'
- self._dirty = True
- self._addpath(f)
- self._map[f] = ('n', 0, -2, -1)
- if f in self._copymap:
- del self._copymap[f]
-
- def add(self, f):
- 'mark a file added'
- self._dirty = True
- self._addpath(f, True)
- self._map[f] = ('a', 0, -1, -1)
- if f in self._copymap:
- del self._copymap[f]
-
- def remove(self, f):
- 'mark a file removed'
- self._dirty = True
- self._droppath(f)
- size = 0
- if self._pl[1] != nullid and f in self._map:
- entry = self._map[f]
- if entry[0] == 'm':
- size = -1
- elif entry[0] == 'n' and entry[2] == -2:
- size = -2
- self._map[f] = ('r', 0, size, 0)
- if size == 0 and f in self._copymap:
- del self._copymap[f]
-
- def merge(self, f):
- 'mark a file merged'
- self._dirty = True
- s = os.lstat(self._join(f))
- self._addpath(f)
- self._map[f] = ('m', s.st_mode, s.st_size, int(s.st_mtime))
- if f in self._copymap:
- del self._copymap[f]
-
- def forget(self, f):
- 'forget a file'
- self._dirty = True
- try:
- self._droppath(f)
- del self._map[f]
- except KeyError:
- self._ui.warn(_("not in dirstate: %s\n") % f)
-
- def _normalize(self, path, knownpath):
- norm_path = os.path.normcase(path)
- fold_path = self._foldmap.get(norm_path, None)
- if fold_path is None:
- if knownpath or not os.path.exists(os.path.join(self._root, path)):
- fold_path = path
- else:
- fold_path = self._foldmap.setdefault(norm_path,
- util.fspath(path, self._root))
- return fold_path
-
- def clear(self):
- self._map = {}
- if "_dirs" in self.__dict__:
- delattr(self, "_dirs");
- self._copymap = {}
- self._pl = [nullid, nullid]
- self._dirty = True
-
- def rebuild(self, parent, files):
- self.clear()
- for f in files:
- if 'x' in files.flags(f):
- self._map[f] = ('n', 0777, -1, 0)
- else:
- self._map[f] = ('n', 0666, -1, 0)
- self._pl = (parent, nullid)
- self._dirty = True
-
- def write(self):
- if not self._dirty:
- return
- st = self._opener("dirstate", "w", atomictemp=True)
-
- try:
- gran = int(self._ui.config('dirstate', 'granularity', 1))
- except ValueError:
- gran = 1
- limit = sys.maxint
- if gran > 0:
- limit = util.fstat(st).st_mtime - gran
-
- cs = cStringIO.StringIO()
- copymap = self._copymap
- pack = struct.pack
- write = cs.write
- write("".join(self._pl))
- for f, e in self._map.iteritems():
- if f in copymap:
- f = "%s\0%s" % (f, copymap[f])
- if e[3] > limit and e[0] == 'n':
- e = (e[0], 0, -1, -1)
- e = pack(_format, e[0], e[1], e[2], e[3], len(f))
- write(e)
- write(f)
- st.write(cs.getvalue())
- st.rename()
- self._dirty = self._dirtypl = False
-
- def _dirignore(self, f):
- if f == '.':
- return False
- if self._ignore(f):
- return True
- for p in _finddirs(f):
- if self._ignore(p):
- return True
- return False
-
- def walk(self, match, unknown, ignored):
- '''
- walk recursively through the directory tree, finding all files
- matched by the match function
-
- results are yielded in a tuple (filename, stat), where stat
- and st is the stat result if the file was found in the directory.
- '''
-
- def fwarn(f, msg):
- self._ui.warn('%s: %s\n' % (self.pathto(f), msg))
- return False
-
- def badtype(mode):
- kind = _('unknown')
- if stat.S_ISCHR(mode): kind = _('character device')
- elif stat.S_ISBLK(mode): kind = _('block device')
- elif stat.S_ISFIFO(mode): kind = _('fifo')
- elif stat.S_ISSOCK(mode): kind = _('socket')
- elif stat.S_ISDIR(mode): kind = _('directory')
- return _('unsupported file type (type is %s)') % kind
-
- ignore = self._ignore
- dirignore = self._dirignore
- if ignored:
- ignore = util.never
- dirignore = util.never
- elif not unknown:
- # if unknown and ignored are False, skip step 2
- ignore = util.always
- dirignore = util.always
-
- matchfn = match.matchfn
- badfn = match.bad
- dmap = self._map
- normpath = util.normpath
- listdir = osutil.listdir
- lstat = os.lstat
- getkind = stat.S_IFMT
- dirkind = stat.S_IFDIR
- regkind = stat.S_IFREG
- lnkkind = stat.S_IFLNK
- join = self._join
- work = []
- wadd = work.append
-
- if self._checkcase:
- normalize = self._normalize
- else:
- normalize = lambda x, y: x
-
- exact = skipstep3 = False
- if matchfn == match.exact: # match.exact
- exact = True
- dirignore = util.always # skip step 2
- elif match.files() and not match.anypats(): # match.match, no patterns
- skipstep3 = True
-
- files = set(match.files())
- if not files or '.' in files:
- files = ['']
- results = {'.hg': None}
-
- # step 1: find all explicit files
- for ff in sorted(files):
- nf = normalize(normpath(ff), False)
- if nf in results:
- continue
-
- try:
- st = lstat(join(nf))
- kind = getkind(st.st_mode)
- if kind == dirkind:
- skipstep3 = False
- if nf in dmap:
- #file deleted on disk but still in dirstate
- results[nf] = None
- match.dir(nf)
- if not dirignore(nf):
- wadd(nf)
- elif kind == regkind or kind == lnkkind:
- results[nf] = st
- else:
- badfn(ff, badtype(kind))
- if nf in dmap:
- results[nf] = None
- except OSError, inst:
- if nf in dmap: # does it exactly match a file?
- results[nf] = None
- else: # does it match a directory?
- prefix = nf + "/"
- for fn in dmap:
- if fn.startswith(prefix):
- match.dir(nf)
- skipstep3 = False
- break
- else:
- badfn(ff, inst.strerror)
-
- # step 2: visit subdirectories
- while work:
- nd = work.pop()
- skip = None
- if nd == '.':
- nd = ''
- else:
- skip = '.hg'
- try:
- entries = listdir(join(nd), stat=True, skip=skip)
- except OSError, inst:
- if inst.errno == errno.EACCES:
- fwarn(nd, inst.strerror)
- continue
- raise
- for f, kind, st in entries:
- nf = normalize(nd and (nd + "/" + f) or f, True)
- if nf not in results:
- if kind == dirkind:
- if not ignore(nf):
- match.dir(nf)
- wadd(nf)
- if nf in dmap and matchfn(nf):
- results[nf] = None
- elif kind == regkind or kind == lnkkind:
- if nf in dmap:
- if matchfn(nf):
- results[nf] = st
- elif matchfn(nf) and not ignore(nf):
- results[nf] = st
- elif nf in dmap and matchfn(nf):
- results[nf] = None
-
- # step 3: report unseen items in the dmap hash
- if not skipstep3 and not exact:
- visit = sorted([f for f in dmap if f not in results and matchfn(f)])
- for nf, st in zip(visit, util.statfiles([join(i) for i in visit])):
- if not st is None and not getkind(st.st_mode) in (regkind, lnkkind):
- st = None
- results[nf] = st
-
- del results['.hg']
- return results
-
- def status(self, match, ignored, clean, unknown):
- listignored, listclean, listunknown = ignored, clean, unknown
- lookup, modified, added, unknown, ignored = [], [], [], [], []
- removed, deleted, clean = [], [], []
-
- dmap = self._map
- ladd = lookup.append
- madd = modified.append
- aadd = added.append
- uadd = unknown.append
- iadd = ignored.append
- radd = removed.append
- dadd = deleted.append
- cadd = clean.append
-
- for fn, st in self.walk(match, listunknown, listignored).iteritems():
- if fn not in dmap:
- if (listignored or match.exact(fn)) and self._dirignore(fn):
- if listignored:
- iadd(fn)
- elif listunknown:
- uadd(fn)
- continue
-
- state, mode, size, time = dmap[fn]
-
- if not st and state in "nma":
- dadd(fn)
- elif state == 'n':
- if (size >= 0 and
- (size != st.st_size
- or ((mode ^ st.st_mode) & 0100 and self._checkexec))
- or size == -2
- or fn in self._copymap):
- madd(fn)
- elif time != int(st.st_mtime):
- ladd(fn)
- elif listclean:
- cadd(fn)
- elif state == 'm':
- madd(fn)
- elif state == 'a':
- aadd(fn)
- elif state == 'r':
- radd(fn)
-
- return (lookup, modified, added, removed, deleted, unknown, ignored,
- clean)