##// END OF EJS Templates
git: skeleton of a new extension to _directly_ operate on git repos...
git: skeleton of a new extension to _directly_ operate on git repos This is based in part of work I did years ago in hgit, but it's mostly new code since I'm using pygit2 instead of dulwich and the hg storage interfaces have improved. Some cleanup of old hgit code by Pulkit, which I greatly appreciate. test-git-interop.t does not cover a whole lot of cases, but it passes. It includes status, diff, making a new commit, and `hg annotate` working on the git repository. This is _not_ (yet) production quality code: this is an experiment. Known technical debt lurking in this implementation: * Writing bookmarks just totally ignores transactions. * The way progress is threaded down into the gitstore is awful. * Ideally we'd find a way to incrementally reindex DAGs. I'm not sure how to do that efficiently, so we might need a "known only fast-forwards" mode on the DAG indexer for use on `hg commit` and friends. * We don't even _try_ to do anything reasonable for `hg pull` or `hg push`. * Mercurial need an interface for the changelog type. Tests currently require git 2.24 as far as I'm aware: `git status` has some changed output that I didn't try and handle in a compatible way. This patch has produced some interesting cleanups, most recently on the manifest type. I expect continuing down this road will produce other meritorious cleanups throughout our code. Differential Revision: https://phab.mercurial-scm.org/D6734

File last commit:

r43710:8a9e53b9 stable
r44961:ad718271 default
Show More
state.py
150 lines | 4.7 KiB | text/x-python | PythonLexer
Martijn Pieters
fsmonitor: new experimental extension...
r28433 # state.py - fsmonitor persistent state
#
# Copyright 2013-2016 Facebook, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import
import errno
import os
import socket
import struct
Yuya Nishihara
py3: move up symbol imports to enforce import-checker rules...
r29205 from mercurial.i18n import _
Siddharth Agarwal
fsmonitor: don't write out state if identity has changed (issue5581)...
r32816 from mercurial import (
Gregory Szorc
fsmonitor: normalize hostname to bytes...
r43710 encoding,
Siddharth Agarwal
fsmonitor: don't write out state if identity has changed (issue5581)...
r32816 pathutil,
util,
)
Martijn Pieters
fsmonitor: new experimental extension...
r28433
_version = 4
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _versionformat = b">I"
Martijn Pieters
fsmonitor: new experimental extension...
r28433
Augie Fackler
formatting: blacken the codebase...
r43346
Martijn Pieters
fsmonitor: new experimental extension...
r28433 class state(object):
def __init__(self, repo):
Durham Goode
fsmonitor: remove use of repo.opener...
r31215 self._vfs = repo.vfs
Martijn Pieters
fsmonitor: new experimental extension...
r28433 self._ui = repo.ui
self._rootdir = pathutil.normasprefix(repo.root)
self._lastclock = None
Siddharth Agarwal
fsmonitor: don't write out state if identity has changed (issue5581)...
r32816 self._identity = util.filestat(None)
Martijn Pieters
fsmonitor: new experimental extension...
r28433
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.mode = self._ui.config(b'fsmonitor', b'mode')
Martijn Pieters
fsmonitor: new experimental extension...
r28433 self.walk_on_invalidate = self._ui.configbool(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'fsmonitor', b'walk_on_invalidate'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.timeout = float(self._ui.config(b'fsmonitor', b'timeout'))
Martijn Pieters
fsmonitor: new experimental extension...
r28433
def get(self):
try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 file = self._vfs(b'fsmonitor.state', b'rb')
Martijn Pieters
fsmonitor: new experimental extension...
r28433 except IOError as inst:
Siddharth Agarwal
fsmonitor: don't write out state if identity has changed (issue5581)...
r32816 self._identity = util.filestat(None)
Martijn Pieters
fsmonitor: new experimental extension...
r28433 if inst.errno != errno.ENOENT:
raise
return None, None, None
Siddharth Agarwal
fsmonitor: don't write out state if identity has changed (issue5581)...
r32816 self._identity = util.filestat.fromfp(file)
Martijn Pieters
fsmonitor: new experimental extension...
r28433 versionbytes = file.read(4)
if len(versionbytes) < 4:
self._ui.log(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'fsmonitor',
b'fsmonitor: state file only has %d bytes, '
b'nuking state\n' % len(versionbytes),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martijn Pieters
fsmonitor: new experimental extension...
r28433 self.invalidate()
return None, None, None
try:
diskversion = struct.unpack(_versionformat, versionbytes)[0]
if diskversion != _version:
# different version, nuke state and start over
self._ui.log(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'fsmonitor',
b'fsmonitor: version switch from %d to '
b'%d, nuking state\n' % (diskversion, _version),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martijn Pieters
fsmonitor: new experimental extension...
r28433 self.invalidate()
return None, None, None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 state = file.read().split(b'\0')
Martijn Pieters
fsmonitor: new experimental extension...
r28433 # state = hostname\0clock\0ignorehash\0 + list of files, each
# followed by a \0
Simon Farnsworth
fsmonitor: be robust in the face of bad state...
r30539 if len(state) < 3:
self._ui.log(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'fsmonitor',
b'fsmonitor: state file truncated (expected '
b'3 chunks, found %d), nuking state\n',
Augie Fackler
formatting: blacken the codebase...
r43346 len(state),
)
Simon Farnsworth
fsmonitor: be robust in the face of bad state...
r30539 self.invalidate()
return None, None, None
Martijn Pieters
fsmonitor: new experimental extension...
r28433 diskhostname = state[0]
Gregory Szorc
fsmonitor: normalize hostname to bytes...
r43710 hostname = encoding.strtolocal(socket.gethostname())
Martijn Pieters
fsmonitor: new experimental extension...
r28433 if diskhostname != hostname:
# file got moved to a different host
Augie Fackler
formatting: blacken the codebase...
r43346 self._ui.log(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'fsmonitor',
b'fsmonitor: stored hostname "%s" '
b'different from current "%s", nuking state\n'
Augie Fackler
formatting: blacken the codebase...
r43346 % (diskhostname, hostname),
)
Martijn Pieters
fsmonitor: new experimental extension...
r28433 self.invalidate()
return None, None, None
clock = state[1]
ignorehash = state[2]
# discard the value after the last \0
notefiles = state[3:-1]
finally:
file.close()
return clock, ignorehash, notefiles
def set(self, clock, ignorehash, notefiles):
if clock is None:
self.invalidate()
return
Siddharth Agarwal
fsmonitor: don't write out state if identity has changed (issue5581)...
r32816 # Read the identity from the file on disk rather than from the open file
# pointer below, because the latter is actually a brand new file.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 identity = util.filestat.frompath(self._vfs.join(b'fsmonitor.state'))
Siddharth Agarwal
fsmonitor: don't write out state if identity has changed (issue5581)...
r32816 if identity != self._identity:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._ui.debug(
b'skip updating fsmonitor.state: identity mismatch\n'
)
Siddharth Agarwal
fsmonitor: don't write out state if identity has changed (issue5581)...
r32816 return
Martijn Pieters
fsmonitor: new experimental extension...
r28433 try:
Augie Fackler
formatting: blacken the codebase...
r43346 file = self._vfs(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'fsmonitor.state', b'wb', atomictemp=True, checkambig=True
Augie Fackler
formatting: blacken the codebase...
r43346 )
Martijn Pieters
fsmonitor: new experimental extension...
r28433 except (IOError, OSError):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._ui.warn(_(b"warning: unable to write out fsmonitor state\n"))
Martijn Pieters
fsmonitor: new experimental extension...
r28433 return
Simon Farnsworth
fsmonitor: be robust in the face of bad state...
r30539 with file:
Martijn Pieters
fsmonitor: new experimental extension...
r28433 file.write(struct.pack(_versionformat, _version))
Gregory Szorc
fsmonitor: normalize hostname to bytes...
r43710 file.write(encoding.strtolocal(socket.gethostname()) + b'\0')
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 file.write(clock + b'\0')
file.write(ignorehash + b'\0')
Martijn Pieters
fsmonitor: new experimental extension...
r28433 if notefiles:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 file.write(b'\0'.join(notefiles))
file.write(b'\0')
Martijn Pieters
fsmonitor: new experimental extension...
r28433
def invalidate(self):
try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 os.unlink(os.path.join(self._rootdir, b'.hg', b'fsmonitor.state'))
Martijn Pieters
fsmonitor: new experimental extension...
r28433 except OSError as inst:
if inst.errno != errno.ENOENT:
raise
Siddharth Agarwal
fsmonitor: don't write out state if identity has changed (issue5581)...
r32816 self._identity = util.filestat(None)
Martijn Pieters
fsmonitor: new experimental extension...
r28433
def setlastclock(self, clock):
self._lastclock = clock
def getlastclock(self):
return self._lastclock