[PATCH 6 of 6] scmutil.filecache: support watching over multiple files
Augie Fackler
raf at durin42.com
Sun Nov 17 16:19:34 CST 2013
On Sat, Nov 16, 2013 at 03:21:12PM -0800, Siddharth Agarwal wrote:
> # HG changeset patch
> # User Siddharth Agarwal <sid0 at fb.com>
> # Date 1384637379 28800
> # Sat Nov 16 13:29:39 2013 -0800
> # Node ID c3b07326434223e8957ea6e332d80f4cf5caa84a
> # Parent c31031f519a1410a7ab92a0a0b8c263cf1e92161
> scmutil.filecache: support watching over multiple files
Queueing these.
>
> diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
> --- a/mercurial/scmutil.py
> +++ b/mercurial/scmutil.py
> @@ -924,23 +924,26 @@
> entry.refresh()
>
> class filecache(object):
> - '''A property like decorator that tracks a file under .hg/ for updates.
> + '''A property like decorator that tracks files under .hg/ for updates.
>
> Records stat info when called in _filecache.
>
> - On subsequent calls, compares old stat info with new info, and recreates
> - the object when needed, updating the new stat info in _filecache.
> + On subsequent calls, compares old stat info with new info, and recreates the
> + object when any of the files changes, updating the new stat info in
> + _filecache.
>
> Mercurial either atomic renames or appends for files under .hg,
> so to ensure the cache is reliable we need the filesystem to be able
> to tell us if a file has been replaced. If it can't, we fallback to
> recreating the object on every call (essentially the same behaviour as
> - propertycache).'''
> - def __init__(self, path):
> - self.path = path
> + propertycache).
> +
> + '''
> + def __init__(self, *paths):
> + self.paths = paths
>
> def join(self, obj, fname):
> - """Used to compute the runtime path of the cached file.
> + """Used to compute the runtime path of a cached file.
>
> Users should subclass filecache and provide their own version of this
> function to call the appropriate join function on 'obj' (an instance
> @@ -965,11 +968,11 @@
> if entry.changed():
> entry.obj = self.func(obj)
> else:
> - path = self.join(obj, self.path)
> + paths = [self.join(obj, path) for path in self.paths]
>
> # We stat -before- creating the object so our cache doesn't lie if
> # a writer modified between the time we read and stat
> - entry = filecachesubentry(path, True)
> + entry = filecacheentry(paths, True)
> entry.obj = self.func(obj)
>
> obj._filecache[self.name] = entry
> @@ -981,7 +984,8 @@
> if self.name not in obj._filecache:
> # we add an entry for the missing value because X in __dict__
> # implies X in _filecache
> - ce = filecachesubentry(self.join(obj, self.path), False)
> + paths = [self.join(obj, path) for path in self.paths]
> + ce = filecacheentry(paths, False)
> obj._filecache[self.name] = ce
> else:
> ce = obj._filecache[self.name]
> diff --git a/tests/test-filecache.py b/tests/test-filecache.py
> --- a/tests/test-filecache.py
> +++ b/tests/test-filecache.py
> @@ -18,7 +18,7 @@
> def sjoin(self, p):
> return p
>
> - @filecache('x')
> + @filecache('x', 'y')
> def cached(self):
> print 'creating'
> return 'string from function'
> @@ -31,12 +31,12 @@
> pass
>
> def basic(repo):
> - print "* file doesn't exist"
> + print "* neither file exists"
> # calls function
> repo.cached
>
> repo.invalidate()
> - print "* file still doesn't exist"
> + print "* neither file still exists"
> # uses cache
> repo.cached
>
> @@ -57,7 +57,7 @@
> repo.cached
>
> repo.invalidate()
> - print "* nothing changed with file x"
> + print "* nothing changed with either file"
> # stats file again, reuses object
> repo.cached
>
> @@ -72,6 +72,41 @@
> print "* file x changed inode"
> repo.cached
>
> + # create empty file y
> + f = open('y', 'w')
> + f.close()
> + repo.invalidate()
> + print "* empty file y created"
> + # should recreate the object
> + repo.cached
> +
> + f = open('y', 'w')
> + f.write('A')
> + f.close()
> + repo.invalidate()
> + print "* file y changed size"
> + # should recreate the object
> + repo.cached
> +
> + f = scmutil.opener('.')('y', 'w', atomictemp=True)
> + f.write('B')
> + f.close()
> +
> + repo.invalidate()
> + print "* file y changed inode"
> + repo.cached
> +
> + f = scmutil.opener('.')('x', 'w', atomictemp=True)
> + f.write('c')
> + f.close()
> + f = scmutil.opener('.')('y', 'w', atomictemp=True)
> + f.write('C')
> + f.close()
> +
> + repo.invalidate()
> + print "* both files changed inode"
> + repo.cached
> +
> def fakeuncacheable():
> def wrapcacheable(orig, *args, **kwargs):
> return False
> @@ -83,10 +118,11 @@
> origcacheable = extensions.wrapfunction(util.cachestat, 'cacheable',
> wrapcacheable)
>
> - try:
> - os.remove('x')
> - except OSError:
> - pass
> + for fn in ['x', 'y']:
> + try:
> + os.remove(fn)
> + except OSError:
> + pass
>
> basic(fakerepo())
>
> @@ -110,9 +146,10 @@
>
> def setbeforeget(repo):
> os.remove('x')
> + os.remove('y')
> repo.cached = 'string set externally'
> repo.invalidate()
> - print "* file x doesn't exist"
> + print "* neither file exists"
> print repo.cached
> repo.invalidate()
> f = open('x', 'w')
> @@ -121,6 +158,18 @@
> print "* file x created"
> print repo.cached
>
> + repo.cached = 'string 2 set externally'
> + repo.invalidate()
> + print "* string set externally again"
> + print repo.cached
> +
> + repo.invalidate()
> + f = open('y', 'w')
> + f.write('b')
> + f.close()
> + print "* file y created"
> + print repo.cached
> +
> print 'basic:'
> print
> basic(fakerepo())
> diff --git a/tests/test-filecache.py.out b/tests/test-filecache.py.out
> --- a/tests/test-filecache.py.out
> +++ b/tests/test-filecache.py.out
> @@ -1,30 +1,46 @@
> basic:
>
> -* file doesn't exist
> +* neither file exists
> creating
> -* file still doesn't exist
> +* neither file still exists
> * empty file x created
> creating
> * file x changed size
> creating
> -* nothing changed with file x
> +* nothing changed with either file
> * file x changed inode
> creating
> +* empty file y created
> +creating
> +* file y changed size
> +creating
> +* file y changed inode
> +creating
> +* both files changed inode
> +creating
>
> fakeuncacheable:
>
> -* file doesn't exist
> +* neither file exists
> creating
> -* file still doesn't exist
> +* neither file still exists
> creating
> * empty file x created
> creating
> * file x changed size
> creating
> -* nothing changed with file x
> +* nothing changed with either file
> creating
> * file x changed inode
> creating
> +* empty file y created
> +creating
> +* file y changed size
> +creating
> +* file y changed inode
> +creating
> +* both files changed inode
> +creating
> repository tip rolled back to revision -1 (undo commit)
> working directory now based on revision -1
> repository tip rolled back to revision -1 (undo commit)
> @@ -32,8 +48,13 @@
>
> setbeforeget:
>
> -* file x doesn't exist
> +* neither file exists
> string set externally
> * file x created
> creating
> string from function
> +* string set externally again
> +string 2 set externally
> +* file y created
> +creating
> +string from function
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
More information about the Mercurial-devel
mailing list