Skip to content
Snippets Groups Projects
  1. Dec 03, 2015
    • Pierre-Yves David's avatar
      context: use a the nofsauditor when matching file in history (issue4749) · 15c6eb0a
      Pierre-Yves David authored
      Before this change, asking for file from history (eg: 'hg cat -r 42 foo/bar')
      could fail because of the current content of the working copy (eg: current
      "foo" being a symlink). As the working copy state have no influence on the
      content of the history, we can safely skip these checks.
      
      The working copy context class have a different 'match'
      implementation. That implementation still use the repo.auditor will
      still catch symlink traversal.
      
      I've audited all stuff calling "match" and they all go through a ctx
      in a sensible way. The most unclear case was diff which still seemed
      okay. You raised my paranoid level today and I double checked through
      tests. They behave properly.
      
      The odds of someone using the wrong (matching with a changectx for
      operation that will eventually touch the file system) is non-zero
      because you are never sure of what people will do. But I dunno if we
      can fight against that. So I would not commit to "never" for "at this
      level" and "in the future" if someone write especially bad code.
      
      However, as a last defense, the vfs itself is running path auditor in
      all cases outside of .hg/. So I think anything passing the 'matcher'
      for buggy reason would growl at the vfs layer.
      15c6eb0a
    • Pierre-Yves David's avatar
      localrepo: add a second auditor without file system check · dfb836a3
      Pierre-Yves David authored
      Auditors keeps a cache of audited paths. Therefore we cannot use the same
      auditor for working copy and history operation. We create a new one without
      file system check for this purposes.
      dfb836a3
    • Pierre-Yves David's avatar
      pathauditor: add a way to skip file system check · 79a86a95
      Pierre-Yves David authored
      We need to be able to skip it when looking at data within the history.
      Doing them in all cases leads to buggy behavior like issue4749.
      79a86a95
    • Pierre-Yves David's avatar
      pathauditor: move file system specific check in their own function · 6d29ce25
      Pierre-Yves David authored
      This will make it easy to disable that part when not relevant (eg: auditing
      filename for operation in history)
      6d29ce25
  2. Nov 07, 2015
  3. Dec 03, 2015
  4. Dec 04, 2015
    • Gregory Szorc's avatar
      mercurial: support loading modules from zipimporter · 30a20167
      Gregory Szorc authored
      The previous refactor to module importing broke module loading when
      mercurial.* modules were loaded from a zipfile (using a zipimporter).
      This scenario is likely encountered when using py2exe.
      
      Supporting zipimporter and the traditional importer side-by-side
      turns out to be quite a pain. In Python 2.x, the standard, file-based
      import mechanism is partially implemented in C. The sys.meta_path
      and sys.path_hooks hook points exist to allow custom importers in
      Python/userland. zipimport.zipimporter and our "hgimporter" class
      from earlier in this patch series are 2 of these.
      
      In a standard Python installation (no matter if running in py2exe
      or similar or not), zipimport.zipimporter appears to be registered
      in sys.path_hooks. This means that as each sys.path entry is
      consulted, it will ask zipimporter if it supports that path and
      zipimporter will be used if that entry is a zip file. In a
      py2exe environment, sys.path contains an entry with the path to
      the zip file containing the Python standard library along with
      Mercurial's Python files.
      
      The way the importer mechanism works is the first importer that
      declares knowledge of a module (via find_module() returning an
      object) gets to load it. Since our "hgimporter" is registered
      in sys.meta_path and returns an interest in specific mercurial.*
      modules, the zipimporter registered on sys.path_hooks never comes
      into play for these modules. So, we need to be zipimporter aware
      and call into zipimporter to load modules.
      
      This patch teaches "hgimporter" how to call out into zipimporter
      when necessary. We detect the necessity of zipimporter by looking
      at the loader for the "mercurial" module. If it is a zipimporter
      instance, we load via zipimporter.
      
      The behavior of zipimporter is a bit wonky.
      
      You appear to need separate zipimporter instances for each directory
      in the zip file. I'm not sure why this is. I suspect it has
      something to do with the low-level importing mechanism (implemented
      in C) operating on a per-directory basis. PEP-302 makes some
      references to this. I was not able to get a zipimporter to
      import modules outside of its immediate directory no matter how
      I specified the module name. This is why we use separate
      zipimporter instances for the ".zip/mercurial" and
      ".zip/mercurial/pure" locations.
      
      The zipimporter documentation for Python 2.7 explicitly states that
      zipimporter does not import dynamic modules (C extensions). Yet from
      a py2exe distribution on Windows - where the .pyd files are *not*
      in the zip archive - zipimporter imported these dynamic modules
      just fine! I'm not sure if dynamic modules can't be imported from
      *inside* the zip archive or whether zipimporter looks for dynamic
      modules outside the zip archive. All I know is zipimporter does
      manage to import the .pyd files on Windows and this patch makes
      our new importer compatible with py2exe.
      
      In the ideal world, We'd probably reimplement or fall back to parts
      of the built-in import mechanism instead of handling zipimporter
      specially. After all, if we're loading Mercurial modules via
      something that isn't the built-in file-based importer or zipimporter,
      our custom importer will likely fail because it doesn't know how to
      call into it. I'd like to think that we'll never encounter this
      in the wild, but you never know. If we do encounter it, we can
      come up with another solution.
      
      It's worth nothing that Python 3 has moved a lot of the importing
      code from C to Python. Python 3 gives you near total control over
      the import mechanism. So in the very distant future when Mercurial
      drops Python 2 support, it's likely that our custom importer code
      can be refactored to something a bit saner.
      30a20167
  5. Nov 25, 2015
    • Gregory Szorc's avatar
      mercurial: don't load C extensions from PyPy · d308a9ca
      Gregory Szorc authored
      PyPy isn't compatible with Python C extensions.
      
      With this patch, the module load policy is automatically to "Python
      only" when run under PyPy. `hg` and other Python scripts importing
      mercurial.* modules will run from the source checkout or any
      installation when executed with PyPy. This should enable people to
      more easily experiment with PyPy and its potentially significant
      performance benefits over CPython!
      d308a9ca
    • Gregory Szorc's avatar
      mercurial: be more strict about loading dual implemented modules · a40c84de
      Gregory Szorc authored
      With this change in place, we should have slightly stronger guarantees
      about how modules with both Python and C implementations are loaded.
      Before, our module loader's default policy looked under both mercurial/*
      and mercurial/pure/* and imported whatever it found, C or pure. The fact
      it looked in both locations by default was a temporary regression from
      the beginning of this series.
      
      This patch does 2 things:
      
      1) Changes the default module load policy to only load C modules
      2) Verifies that files loaded from mercurial/* are actually C modules
      
      This 2nd behavior change makes our new module loading mechanism
      stricter than from before this series. Before, it was possible to load
      a .py-based module from mercurial/*. This could happen if an old
      installation orphaned a file and then somehow didn't install the C
      version for the new install. We now detect this odd configuration
      and fall back to loading the pure Python module, assuming it is
      allowed. In the case of a busted installation, we fail fast. While
      we could fall back, we explicitly decide not to do this because
      we don't want people accidentally not running the C modules and having
      slow performance as a result.
      a40c84de
  6. Dec 04, 2015
    • Gregory Szorc's avatar
      setup: refactor handling of modules with C/Python implementations · 511a4384
      Gregory Szorc authored
      Previously, .py files under mercurial/pure/ were copied to mercurial/*
      during installation if we were performing a pure Python installation.
      
      Now that the new import hooks and module load policy are in place, this
      hackery from the past is no longer necessary.
      
      With this patch, we stop copying modules from mercurial/pure/* to
      mercurial/*. Instead, we preserve the files at their original
      hierarchy, mirroring the source repository structure.
      
      In addition, we always install the pure modules. Before, we would only
      include the pure modules in the distribution/installation if the
      install-time settings requested a pure Python installation. The upside
      of this change is that CPython and PyPy can run from the same Mercurial
      installation, making packaging and distribution of Mercurial simpler.
      
      The inclusion of pure Python modules in the installation sounds
      risky, as it could lead to inadvertent loading of non-C modules.
      This shouldn't be a problem. The default module load policy is "C
      only" (or at least will be shortly) and the only way to load pure
      modules from an installation is if a) pure installation was requested
      b) the HGMODULELOADPOLICY overrides the requirement for C modules.
      
      The default module load policy as defined in source is a special string
      whose default value from the checkout is equivalent to the "C only"
      policy (again, not exactly the state right now). For pure
      installations, this default policy is not appropriate and will not
      work. This patch adds support for rewriting __init__.py during
      installation to reflect the module load policy that should be in
      place accoding to the installation settings. For default CPython
      installs, the value in the source file will change but there will
      be no functional change. For pure installations, the default policy
      will be set to "py," allowing them to work without having to set
      environment variables.
      511a4384
  7. Nov 25, 2015
  8. Dec 04, 2015
    • Gregory Szorc's avatar
      mercurial: implement import hook for handling C/Python modules · 4374d819
      Gregory Szorc authored
      There are a handful of modules that have both pure Python and C
      extension implementations. Currently, setup.py copies files from
      mercurial/pure/*.py to mercurial/ during the install process if C
      extensions are not available. This way, "import mercurial.X" will
      work whether C extensions are available or not.
      
      This approach has a few drawbacks. First, there aren't run-time checks
      verifying the C extensions are loaded when they should be. This could
      lead to accidental use of the slower pure Python modules. Second, the
      C extensions aren't compatible with PyPy and running Mercurial with
      PyPy requires installing Mercurial - you can't run ./hg from a source
      checkout. This makes developing while running PyPy somewhat difficult.
      
      This patch implements a PEP-302 import hook for finding and loading the
      modules with both C and Python implementations. When a module with dual
      implementations is requested for import, its import is handled by our
      import hook.
      
      The importer has a mechanism that controls what types of modules we
      allow to load. We call this loading behavior the "module load policy."
      There are 3 settings:
      
      * Only load C extensions
      * Only load pure Python
      * Try to load C and fall back to Python
      
      An environment variable allows overriding this policy at run time. This
      is mainly useful for developers and for performing actions against the
      source checkout (such as installing), which require overriding the
      default (strict) policy about requiring C extensions.
      
      The default mode for now is to allow both. This isn't proper and is
      technically backwards incompatible. However, it is necessary to
      implement a sane patch series that doesn't break the world during
      future bisections. The behavior will be corrected in future patch.
      
      We choose the main mercurial/__init__.py module for this code out of
      necessity: in a future world, if the custom module importer isn't
      registered, we'll fail to find/import certain modules when running
      from a pure installation. Without the magical import-time side-effects,
      *any* importer of mercurial.* modules would be required to call a
      function to register our importer. I'm not a fan of import time side
      effects and I initially attempted to do this. However, I was foiled by
      our own test harness, which has numerous `python` invoked scripts that
      "import mercurial" and fail because the importer isn't registered.
      Realizing this problem is probably present in random Python scripts
      that have been written over the years, I decided that sacrificing
      purity for backwards compatibility is necessary. Plus, if you are
      programming Python, "import" should probably "just work."
      
      It's worth noting that now that we have a custom module loader, it
      would be possible to hook up demand module proxies at this level
      instead of replacing __import__. We leave this work for another time,
      if it's even desired.
      
      This patch breaks importing in environments where Mercurial modules
      are loaded from a zip file (such as py2exe distributions). This will
      be addressed in a subsequent patch.
      4374d819
  9. Dec 03, 2015
  10. Dec 02, 2015
    • Augie Fackler's avatar
      changegroup: note during bundle apply if the repo was empty · de3335b4
      Augie Fackler authored
      An upcoming change for exchanging treemanifest data will need to
      update the repository capabilities, which we should only do if the
      repository was empty before we started applying this changegroup. In
      the future we will probably need a strategy for upgrading to
      treemanifest in requires during a pull (I'm assuming at some point
      we'll make it possible to have a flag day to enable treemanifests on
      an existing history.)
      de3335b4
    • timeless's avatar
      histedit: improve missing rule suggestion · 1ec23f3e
      timeless authored
      include actual suggested text
      1ec23f3e
  11. Nov 14, 2015
  12. Nov 25, 2015
  13. Dec 02, 2015
  14. Nov 06, 2015
  15. Dec 01, 2015
    • Katsunori FUJIWARA's avatar
      shelve: execute checkunfinished inside wlock scope · 7df042d0
      Katsunori FUJIWARA authored
      Before this patch, "hg shelve" of shelve extension executes
      'cmdutil.checkunfinished()' before acquisition of wlock.
      
      It may cause unintentional result, if another command runs parallelly
      (see also issue4368).
      
      To avoid this issue, this patch executes 'cmdutil.checkunfinished()'
      inside wlock scope of "hg shelve".
      
      This also fixes issue4957, because now 'cmdutil.checkunfinished()'
      isn't invoked at "hg shelve" with options below:
      
        --cleanup
        --delete
        --list
        --patch
        --stat
      7df042d0
    • Katsunori FUJIWARA's avatar
      shelve: widen wlock scope of shelve for consistency while processing · 6df3ec5b
      Katsunori FUJIWARA authored
      Before this patch, "hg shelve" of shelve extension executes/refers
      below before acquisition of wlock:
      
        - 'repo.dirstate.parents()' via 'repo[None].parents()'
        - 'repo._activebookmark'
      
      It may cause unintentional result, if another command runs parallelly
      (see also issue4368).
      
      This patch widens wlock scope of "hg shelve" of shelve extension for
      consistency while processing.
      6df3ec5b
    • Katsunori FUJIWARA's avatar
      gpg: make sign acquire wlock before processing · 7b4a6157
      Katsunori FUJIWARA authored
      Before this patch, "hg sign" of gpg extension executes/evaluates below
      without acquisition of wlock.
      
        - repo.dirstate.parents()
        - '.hgsigs' not in repo.dirstate
      
      It may cause unintentional result, if another command runs parallelly
      (see also issue4368).
      
      To avoid this issue, this patch makes "hg sign" of gpg extension
      acquire wlock before processing.
      7b4a6157
    • Katsunori FUJIWARA's avatar
      commands: execute checkunfinished and bailifchanged inside wlock scope · 84de71ec
      Katsunori FUJIWARA authored
      Before this patch, "hg import" executes below before acquisition of
      wlock:
      
        - cmdutil.checkunfinished()
        - cmdutil.bailifchanged()
      
      It may cause unintentional result, if another command runs parallelly
      (see also issue4368).
      
      To avoid this issue, this patch executes 'cmdutil.checkunfinished()'
      and 'cmdutil.bailifchanged()' inside wlock scope of "hg import".
      84de71ec
    • Katsunori FUJIWARA's avatar
      commands: widen wlock scope of graft for consitency while processing · 77995317
      Katsunori FUJIWARA authored
      Before this patch, "hg graft" executes below before acquisition of
      wlock.
      
        - cmdutil.checkunfinished()
        - cmdutil.bailifchanged()
        - repo.dirstate.parents() via 'repo["."]'
        - unlinking '.hg/graftstate'
      
      It may cause unintentional result, if another command runs parallelly
      (see also issue4368).
      
      This patch widens wlock scope of "hg graft" for consitency while
      processing.
      77995317
    • Katsunori FUJIWARA's avatar
      commands: make backout acquire locks before processing · c7217f14
      Katsunori FUJIWARA authored
      Before this patch, "hg backout" executes below before acquisition of
      wlock.
      
        - cmdutil.checkunfinished()
        - cmdutil.bailifchanged()
        - repo.dirstate.parents()
      
      It may cause unintentional result, if another command runs parallelly
      (see also issue4368).
      
      In addition to it, "hg backout" refers changelog for purposes below
      without acquisition of store lock (slock), and it may cause
      unintentional result, if store is updated parallelly.
      
        - show and update to the revision by 'repo.changelog.tip()'
      
        - examine for "created new head" by 'repo.branchheads()' and
          'cmdutil.commitstatus()'
      
      To avoid this issue, this patch makes "hg backout" acquire wlock and
      slock before processing.
      c7217f14
    • Katsunori FUJIWARA's avatar
      commands: make commit acquire locks before processing (issue4368) · a01d3d32
      Katsunori FUJIWARA authored
      Before this patch, "hg commit" (process A) executes steps below:
      
        1. get current branch heads via 'repo.branchheads()'
           - cache 'repo.changelog'
        2. invoke 'repo.commit()'
        3. acquire wlock
           - invalidate 'repo.dirstate'
        4. access 'repo.dirstate'
           - re-read '.hg/dirstate'
           - check validity of parent revisions with 'repo.changelog'
        5. invoke 'repo.commitctx()'
        6. acquire store lock (slock)
           - invalidate 'repo.changelog'
        7. do committing
        8. release slock
        9. release wlock
       10. check new branch head (via 'cmdutil.commitstatus()')
      
      If acquisition of wlock at (3) above waits for another "hg commit"
      (process B) or so running parallelly to release wlock, process A
      causes creating orphan revision, because:
      
        - '.hg/dirstate' refers the revision, which is newly added by
          process B, as its parent
      
        - but already cached 'repo.changelog' doesn't contain such revision
      
        - therefore, validating parents of '.hg/dirstate' at (4) above
          replaces such revision with 'nullid'
      
      Then, process A creates "orphan" revision, of which parent is "null"
      revision.
      
      In addition to it, "created new head" may be shown at the end of
      process A unintentionally, if store is updated parallelly, because
      both getting branch heads (1) and checking new branch head (10) are
      executed outside slock scope.
      
      To avoid this issue, this patch makes "hg commit" acquire wlock and
      slock before processing.
      
      This patch resolves the issue between "hg commit" processes, but not
      one between "hg commit" and other commands. Subsequent patches resolve
      the latter.
      
      Even after this patch, there are still corner case problems below:
      
        - filecache may overlook changes of '.hg/dirstate', and it causes
          similar issue (see below for detail)
      
          https://bz.mercurial-scm.org/show_bug.cgi?id=4368#c10
      
        - 3rd party extension may cause similar issue, if it directly uses
          'repo.commit()' without acquisition of wlock and slock
      
          This can be fixed by acquisition of slock at the beginning of
          'repo.commit()', but it seems suitable for "default" branch
      
          In fact, acquisition of slock itself is already introduced at
          "default" branch by 4414d500604f, but acquisition is not at the
          beginning of 'repo.commit()'.
      
      This patch also changes some tests:
      
        - test-fncache.t needs this tricky wrapping, to release (= forced
          failure of) wlock certainly
      
        - order of "hg commit" output is changed by widening scope of locks,
          because some hooks are fired after releasing wlock
      a01d3d32
Loading