mercurial/chgserver.py
author Jun Wu <quark@fb.com>
Fri, 16 Dec 2016 14:48:37 +0000
changeset 30644 2bb8c53be961
parent 30643 dfb19aed409e
child 30645 a3f335d1247c
permissions -rw-r--r--
chgserver: override runcommand Next patches will customize chgserver's runcommand. So let's override it. The docstring is temporarily missing and will be filled later.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     1
# chgserver.py - command server extension for cHg
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     2
#
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     3
# Copyright 2011 Yuya Nishihara <yuya@tcha.org>
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     4
#
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms of the
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     6
# GNU General Public License version 2 or any later version.
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     7
30513
ff7df4bb75de chgserver: make it a core module and drop extension flags
Yuya Nishihara <yuya@tcha.org>
parents: 30512
diff changeset
     8
"""command server extension for cHg
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     9
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    10
'S' channel (read/write)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    11
    propagate ui.system() request to client
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    12
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    13
'attachio' command
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    14
    attach client's stdio passed by sendmsg()
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    15
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    16
'chdir' command
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    17
    change current directory
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    18
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    19
'getpager' command
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    20
    checks if pager is enabled and which pager should be executed
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    21
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    22
'setenv' command
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    23
    replace os.environ completely
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    24
28325
9fec3cb8d128 chgserver: update docs
Jun Wu <quark@fb.com>
parents: 28277
diff changeset
    25
'setumask' command
9fec3cb8d128 chgserver: update docs
Jun Wu <quark@fb.com>
parents: 28277
diff changeset
    26
    set umask
9fec3cb8d128 chgserver: update docs
Jun Wu <quark@fb.com>
parents: 28277
diff changeset
    27
28350
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
    28
'validate' command
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
    29
    reload the config and check if the server is up to date
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
    30
28325
9fec3cb8d128 chgserver: update docs
Jun Wu <quark@fb.com>
parents: 28277
diff changeset
    31
Config
9fec3cb8d128 chgserver: update docs
Jun Wu <quark@fb.com>
parents: 28277
diff changeset
    32
------
9fec3cb8d128 chgserver: update docs
Jun Wu <quark@fb.com>
parents: 28277
diff changeset
    33
9fec3cb8d128 chgserver: update docs
Jun Wu <quark@fb.com>
parents: 28277
diff changeset
    34
::
9fec3cb8d128 chgserver: update docs
Jun Wu <quark@fb.com>
parents: 28277
diff changeset
    35
9fec3cb8d128 chgserver: update docs
Jun Wu <quark@fb.com>
parents: 28277
diff changeset
    36
  [chgserver]
9fec3cb8d128 chgserver: update docs
Jun Wu <quark@fb.com>
parents: 28277
diff changeset
    37
  idletimeout = 3600 # seconds, after which an idle server will exit
28326
ea400a4f32e6 chgserver: mangle server address to include confighash
Jun Wu <quark@fb.com>
parents: 28325
diff changeset
    38
  skiphash = False   # whether to skip config or env change checks
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    39
"""
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    40
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    41
from __future__ import absolute_import
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    42
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    43
import errno
29341
0d83ad967bf8 cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
Augie Fackler <raf@durin42.com>
parents: 29101
diff changeset
    44
import hashlib
28276
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
    45
import inspect
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    46
import os
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    47
import re
29428
247ea0dfdb94 chgserver: do not ignore SIGPIPE if pager is used
Jun Wu <quark@fb.com>
parents: 29341
diff changeset
    48
import signal
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    49
import struct
28276
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
    50
import sys
28223
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
    51
import time
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    52
30513
ff7df4bb75de chgserver: make it a core module and drop extension flags
Yuya Nishihara <yuya@tcha.org>
parents: 30512
diff changeset
    53
from .i18n import _
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    54
30513
ff7df4bb75de chgserver: make it a core module and drop extension flags
Yuya Nishihara <yuya@tcha.org>
parents: 30512
diff changeset
    55
from . import (
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    56
    cmdutil,
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    57
    commandserver,
30635
a150173da1c1 py3: replace os.environ with encoding.environ (part 2 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30619
diff changeset
    58
    encoding,
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    59
    error,
28276
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
    60
    extensions,
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    61
    osutil,
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    62
    util,
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    63
)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    64
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    65
_log = commandserver.log
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    66
28262
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    67
def _hashlist(items):
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    68
    """return sha1 hexdigest for a list"""
29341
0d83ad967bf8 cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
Augie Fackler <raf@durin42.com>
parents: 29101
diff changeset
    69
    return hashlib.sha1(str(items)).hexdigest()
28262
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    70
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    71
# sensitive config sections affecting confighash
28478
e6e183687545 chgserver: include [extdiff] in confighash
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
    72
_configsections = [
29101
57a24a85a2bc chgserver: add [alias] to confighash
Jun Wu <quark@fb.com>
parents: 29088
diff changeset
    73
    'alias',  # affects global state commands.table
28478
e6e183687545 chgserver: include [extdiff] in confighash
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
    74
    'extdiff',  # uisetup will register new commands
e6e183687545 chgserver: include [extdiff] in confighash
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
    75
    'extensions',
e6e183687545 chgserver: include [extdiff] in confighash
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
    76
]
28262
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    77
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    78
# sensitive environment variables affecting confighash
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    79
_envre = re.compile(r'''\A(?:
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    80
                    CHGHG
30587
b3643bfc7fcb chg: ignore HG_* in confighash
Jun Wu <quark@fb.com>
parents: 30572
diff changeset
    81
                    |HG(?:[A-Z].*)?
28262
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    82
                    |LANG(?:UAGE)?
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    83
                    |LC_.*
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    84
                    |LD_.*
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    85
                    |PATH
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    86
                    |PYTHON.*
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    87
                    |TERM(?:INFO)?
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    88
                    |TZ
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    89
                    )\Z''', re.X)
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    90
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    91
def _confighash(ui):
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    92
    """return a quick hash for detecting config/env changes
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    93
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    94
    confighash is the hash of sensitive config items and environment variables.
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    95
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    96
    for chgserver, it is designed that once confighash changes, the server is
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    97
    not qualified to serve its client and should redirect the client to a new
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    98
    server. different from mtimehash, confighash change will not mark the
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    99
    server outdated and exit since the user can have different configs at the
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
   100
    same time.
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
   101
    """
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
   102
    sectionitems = []
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
   103
    for section in _configsections:
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
   104
        sectionitems.append(ui.configitems(section))
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
   105
    sectionhash = _hashlist(sectionitems)
30635
a150173da1c1 py3: replace os.environ with encoding.environ (part 2 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30619
diff changeset
   106
    envitems = [(k, v) for k, v in encoding.environ.iteritems()
a150173da1c1 py3: replace os.environ with encoding.environ (part 2 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30619
diff changeset
   107
                if _envre.match(k)]
28262
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
   108
    envhash = _hashlist(sorted(envitems))
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
   109
    return sectionhash[:6] + envhash[:6]
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
   110
28276
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   111
def _getmtimepaths(ui):
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   112
    """get a list of paths that should be checked to detect change
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   113
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   114
    The list will include:
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   115
    - extensions (will not cover all files for complex extensions)
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   116
    - mercurial/__version__.py
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   117
    - python binary
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   118
    """
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   119
    modules = [m for n, m in extensions.extensions(ui)]
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   120
    try:
30513
ff7df4bb75de chgserver: make it a core module and drop extension flags
Yuya Nishihara <yuya@tcha.org>
parents: 30512
diff changeset
   121
        from . import __version__
28276
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   122
        modules.append(__version__)
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   123
    except ImportError:
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   124
        pass
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   125
    files = [sys.executable]
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   126
    for m in modules:
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   127
        try:
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   128
            files.append(inspect.getabsfile(m))
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   129
        except TypeError:
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   130
            pass
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   131
    return sorted(set(files))
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   132
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   133
def _mtimehash(paths):
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   134
    """return a quick hash for detecting file changes
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   135
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   136
    mtimehash calls stat on given paths and calculate a hash based on size and
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   137
    mtime of each file. mtimehash does not read file content because reading is
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   138
    expensive. therefore it's not 100% reliable for detecting content changes.
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   139
    it's possible to return different hashes for same file contents.
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   140
    it's also possible to return a same hash for different file contents for
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   141
    some carefully crafted situation.
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   142
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   143
    for chgserver, it is designed that once mtimehash changes, the server is
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   144
    considered outdated immediately and should no longer provide service.
29462
71ed5a3ef8a9 chgserver: document why we don't merge mtimehash and confighash
Jun Wu <quark@fb.com>
parents: 29433
diff changeset
   145
71ed5a3ef8a9 chgserver: document why we don't merge mtimehash and confighash
Jun Wu <quark@fb.com>
parents: 29433
diff changeset
   146
    mtimehash is not included in confighash because we only know the paths of
71ed5a3ef8a9 chgserver: document why we don't merge mtimehash and confighash
Jun Wu <quark@fb.com>
parents: 29433
diff changeset
   147
    extensions after importing them (there is imp.find_module but that faces
71ed5a3ef8a9 chgserver: document why we don't merge mtimehash and confighash
Jun Wu <quark@fb.com>
parents: 29433
diff changeset
   148
    race conditions). We need to calculate confighash without importing.
28276
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   149
    """
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   150
    def trystat(path):
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   151
        try:
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   152
            st = os.stat(path)
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   153
            return (st.st_mtime, st.st_size)
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   154
        except OSError:
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   155
            # could be ENOENT, EPERM etc. not fatal in any case
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   156
            pass
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   157
    return _hashlist(map(trystat, paths))[:12]
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   158
28277
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   159
class hashstate(object):
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   160
    """a structure storing confighash, mtimehash, paths used for mtimehash"""
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   161
    def __init__(self, confighash, mtimehash, mtimepaths):
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   162
        self.confighash = confighash
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   163
        self.mtimehash = mtimehash
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   164
        self.mtimepaths = mtimepaths
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   165
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   166
    @staticmethod
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   167
    def fromui(ui, mtimepaths=None):
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   168
        if mtimepaths is None:
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   169
            mtimepaths = _getmtimepaths(ui)
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   170
        confighash = _confighash(ui)
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   171
        mtimehash = _mtimehash(mtimepaths)
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   172
        _log('confighash = %s mtimehash = %s\n' % (confighash, mtimehash))
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   173
        return hashstate(confighash, mtimehash, mtimepaths)
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   174
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   175
# copied from hgext/pager.py:uisetup()
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   176
def _setuppagercmd(ui, options, cmd):
30513
ff7df4bb75de chgserver: make it a core module and drop extension flags
Yuya Nishihara <yuya@tcha.org>
parents: 30512
diff changeset
   177
    from . import commands  # avoid cycle
30512
cc374292a561 chgserver: delay importing commands and dispatch modules
Yuya Nishihara <yuya@tcha.org>
parents: 30511
diff changeset
   178
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   179
    if not ui.formatted():
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   180
        return
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   181
30635
a150173da1c1 py3: replace os.environ with encoding.environ (part 2 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30619
diff changeset
   182
    p = ui.config("pager", "pager", encoding.environ.get("PAGER"))
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   183
    usepager = False
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   184
    always = util.parsebool(options['pager'])
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   185
    auto = options['pager'] == 'auto'
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   186
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   187
    if not p:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   188
        pass
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   189
    elif always:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   190
        usepager = True
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   191
    elif not auto:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   192
        usepager = False
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   193
    else:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   194
        attended = ['annotate', 'cat', 'diff', 'export', 'glog', 'log', 'qdiff']
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   195
        attend = ui.configlist('pager', 'attend', attended)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   196
        ignore = ui.configlist('pager', 'ignore')
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   197
        cmds, _ = cmdutil.findcmd(cmd, commands.table)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   198
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   199
        for cmd in cmds:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   200
            var = 'attend-%s' % cmd
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   201
            if ui.config('pager', var):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   202
                usepager = ui.configbool('pager', var)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   203
                break
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   204
            if (cmd in attend or
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   205
                (cmd not in ignore and not attend)):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   206
                usepager = True
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   207
                break
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   208
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   209
    if usepager:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   210
        ui.setconfig('ui', 'formatted', ui.formatted(), 'pager')
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   211
        ui.setconfig('ui', 'interactive', False, 'pager')
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   212
        return p
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   213
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   214
def _newchgui(srcui, csystem):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   215
    class chgui(srcui.__class__):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   216
        def __init__(self, src=None):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   217
            super(chgui, self).__init__(src)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   218
            if src:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   219
                self._csystem = getattr(src, '_csystem', csystem)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   220
            else:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   221
                self._csystem = csystem
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   222
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   223
        def system(self, cmd, environ=None, cwd=None, onerr=None,
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   224
                   errprefix=None):
28586
82cee85d5274 chgserver: use old ui.system if fout is not stdout or needs to be captured
Jun Wu <quark@fb.com>
parents: 28553
diff changeset
   225
            # fallback to the original system method if the output needs to be
82cee85d5274 chgserver: use old ui.system if fout is not stdout or needs to be captured
Jun Wu <quark@fb.com>
parents: 28553
diff changeset
   226
            # captured (to self._buffers), or the output stream is not stdout
82cee85d5274 chgserver: use old ui.system if fout is not stdout or needs to be captured
Jun Wu <quark@fb.com>
parents: 28553
diff changeset
   227
            # (e.g. stderr, cStringIO), because the chg client is not aware of
82cee85d5274 chgserver: use old ui.system if fout is not stdout or needs to be captured
Jun Wu <quark@fb.com>
parents: 28553
diff changeset
   228
            # these situations and will behave differently (write to stdout).
82cee85d5274 chgserver: use old ui.system if fout is not stdout or needs to be captured
Jun Wu <quark@fb.com>
parents: 28553
diff changeset
   229
            if (any(s[1] for s in self._bufferstates)
82cee85d5274 chgserver: use old ui.system if fout is not stdout or needs to be captured
Jun Wu <quark@fb.com>
parents: 28553
diff changeset
   230
                or not util.safehasattr(self.fout, 'fileno')
30473
39d13b8c101d py3: bulk replace sys.stdin/out/err by util's
Yuya Nishihara <yuya@tcha.org>
parents: 30332
diff changeset
   231
                or self.fout.fileno() != util.stdout.fileno()):
28586
82cee85d5274 chgserver: use old ui.system if fout is not stdout or needs to be captured
Jun Wu <quark@fb.com>
parents: 28553
diff changeset
   232
                return super(chgui, self).system(cmd, environ, cwd, onerr,
82cee85d5274 chgserver: use old ui.system if fout is not stdout or needs to be captured
Jun Wu <quark@fb.com>
parents: 28553
diff changeset
   233
                                                 errprefix)
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   234
            # copied from mercurial/util.py:system()
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   235
            self.flush()
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   236
            def py2shell(val):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   237
                if val is None or val is False:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   238
                    return '0'
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   239
                if val is True:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   240
                    return '1'
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   241
                return str(val)
30635
a150173da1c1 py3: replace os.environ with encoding.environ (part 2 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30619
diff changeset
   242
            env = encoding.environ.copy()
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   243
            if environ:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   244
                env.update((k, py2shell(v)) for k, v in environ.iteritems())
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   245
            env['HG'] = util.hgexecutable()
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   246
            rc = self._csystem(cmd, env, cwd)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   247
            if rc and onerr:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   248
                errmsg = '%s %s' % (os.path.basename(cmd.split(None, 1)[0]),
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   249
                                    util.explainexit(rc)[0])
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   250
                if errprefix:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   251
                    errmsg = '%s: %s' % (errprefix, errmsg)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   252
                raise onerr(errmsg)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   253
            return rc
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   254
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   255
    return chgui(srcui)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   256
28602
83127a9fe76e chgserver: drop old hack to recreate ui on HGPLAIN change
Yuya Nishihara <yuya@tcha.org>
parents: 28599
diff changeset
   257
def _loadnewui(srcui, args):
30513
ff7df4bb75de chgserver: make it a core module and drop extension flags
Yuya Nishihara <yuya@tcha.org>
parents: 30512
diff changeset
   258
    from . import dispatch  # avoid cycle
30512
cc374292a561 chgserver: delay importing commands and dispatch modules
Yuya Nishihara <yuya@tcha.org>
parents: 30511
diff changeset
   259
30572
cfb227016d01 chgserver: call "load" for new ui objects
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   260
    newui = srcui.__class__.load()
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   261
    for a in ['fin', 'fout', 'ferr', 'environ']:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   262
        setattr(newui, a, getattr(srcui, a))
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   263
    if util.safehasattr(srcui, '_csystem'):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   264
        newui._csystem = srcui._csystem
28264
3682e201cce6 chgserver: make _renewui load repo and command line configs
Jun Wu <quark@fb.com>
parents: 28262
diff changeset
   265
3682e201cce6 chgserver: make _renewui load repo and command line configs
Jun Wu <quark@fb.com>
parents: 28262
diff changeset
   266
    # command line args
28767
73bfd9a54a5c chgserver: move args copying logic to the correct place
Jun Wu <quark@fb.com>
parents: 28603
diff changeset
   267
    args = args[:]
28264
3682e201cce6 chgserver: make _renewui load repo and command line configs
Jun Wu <quark@fb.com>
parents: 28262
diff changeset
   268
    dispatch._parseconfig(newui, dispatch._earlygetopt(['--config'], args))
3682e201cce6 chgserver: make _renewui load repo and command line configs
Jun Wu <quark@fb.com>
parents: 28262
diff changeset
   269
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   270
    # stolen from tortoisehg.util.copydynamicconfig()
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   271
    for section, name, value in srcui.walkconfig():
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   272
        source = srcui.configsource(section, name)
28264
3682e201cce6 chgserver: make _renewui load repo and command line configs
Jun Wu <quark@fb.com>
parents: 28262
diff changeset
   273
        if ':' in source or source == '--config':
3682e201cce6 chgserver: make _renewui load repo and command line configs
Jun Wu <quark@fb.com>
parents: 28262
diff changeset
   274
            # path:line or command line
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   275
            continue
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   276
        newui.setconfig(section, name, value, source)
28599
0e7a929754aa chgserver: use global ui instead of repo ui for dispatch.request.ui
Jun Wu <quark@fb.com>
parents: 28586
diff changeset
   277
0e7a929754aa chgserver: use global ui instead of repo ui for dispatch.request.ui
Jun Wu <quark@fb.com>
parents: 28586
diff changeset
   278
    # load wd and repo config, copied from dispatch.py
0e7a929754aa chgserver: use global ui instead of repo ui for dispatch.request.ui
Jun Wu <quark@fb.com>
parents: 28586
diff changeset
   279
    cwds = dispatch._earlygetopt(['--cwd'], args)
0e7a929754aa chgserver: use global ui instead of repo ui for dispatch.request.ui
Jun Wu <quark@fb.com>
parents: 28586
diff changeset
   280
    cwd = cwds and os.path.realpath(cwds[-1]) or None
0e7a929754aa chgserver: use global ui instead of repo ui for dispatch.request.ui
Jun Wu <quark@fb.com>
parents: 28586
diff changeset
   281
    rpath = dispatch._earlygetopt(["-R", "--repository", "--repo"], args)
0e7a929754aa chgserver: use global ui instead of repo ui for dispatch.request.ui
Jun Wu <quark@fb.com>
parents: 28586
diff changeset
   282
    path, newlui = dispatch._getlocal(newui, rpath, wd=cwd)
0e7a929754aa chgserver: use global ui instead of repo ui for dispatch.request.ui
Jun Wu <quark@fb.com>
parents: 28586
diff changeset
   283
0e7a929754aa chgserver: use global ui instead of repo ui for dispatch.request.ui
Jun Wu <quark@fb.com>
parents: 28586
diff changeset
   284
    return (newui, newlui)
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   285
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   286
class channeledsystem(object):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   287
    """Propagate ui.system() request in the following format:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   288
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   289
    payload length (unsigned int),
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   290
    cmd, '\0',
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   291
    cwd, '\0',
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   292
    envkey, '=', val, '\0',
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   293
    ...
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   294
    envkey, '=', val
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   295
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   296
    and waits:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   297
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   298
    exitcode length (unsigned int),
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   299
    exitcode (int)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   300
    """
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   301
    def __init__(self, in_, out, channel):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   302
        self.in_ = in_
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   303
        self.out = out
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   304
        self.channel = channel
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   305
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   306
    def __call__(self, cmd, environ, cwd):
28514
0747ef2c4ab2 chgserver: resolve relative path before sending via system channel
Jun Wu <quark@fb.com>
parents: 28511
diff changeset
   307
        args = [util.quotecommand(cmd), os.path.abspath(cwd or '.')]
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   308
        args.extend('%s=%s' % (k, v) for k, v in environ.iteritems())
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   309
        data = '\0'.join(args)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   310
        self.out.write(struct.pack('>cI', self.channel, len(data)))
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   311
        self.out.write(data)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   312
        self.out.flush()
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   313
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   314
        length = self.in_.read(4)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   315
        length, = struct.unpack('>I', length)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   316
        if length != 4:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   317
            raise error.Abort(_('invalid response'))
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   318
        rc, = struct.unpack('>i', self.in_.read(4))
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   319
        return rc
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   320
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   321
_iochannels = [
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   322
    # server.ch, ui.fp, mode
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   323
    ('cin', 'fin', 'rb'),
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   324
    ('cout', 'fout', 'wb'),
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   325
    ('cerr', 'ferr', 'wb'),
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   326
]
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   327
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   328
class chgcmdserver(commandserver.server):
28328
e00e57d83653 chgserver: pass hashstate and base server address to chgcmdserver
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   329
    def __init__(self, ui, repo, fin, fout, sock, hashstate, baseaddress):
30643
dfb19aed409e chgserver: store csystem separately
Jun Wu <quark@fb.com>
parents: 30635
diff changeset
   330
        self._csystem = channeledsystem(fin, fout, 'S')
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   331
        super(chgcmdserver, self).__init__(
30643
dfb19aed409e chgserver: store csystem separately
Jun Wu <quark@fb.com>
parents: 30635
diff changeset
   332
            _newchgui(ui, self._csystem), repo, fin, fout)
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   333
        self.clientsock = sock
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   334
        self._oldios = []  # original (self.ch, ui.fp, fd) before "attachio"
28328
e00e57d83653 chgserver: pass hashstate and base server address to chgcmdserver
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   335
        self.hashstate = hashstate
e00e57d83653 chgserver: pass hashstate and base server address to chgcmdserver
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   336
        self.baseaddress = baseaddress
28350
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   337
        if hashstate is not None:
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   338
            self.capabilities = self.capabilities.copy()
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   339
            self.capabilities['validate'] = chgcmdserver.validate
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   340
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   341
    def cleanup(self):
29512
538d0003c9e0 commandserver: promote .cleanup() hook from chgserver
Yuya Nishihara <yuya@tcha.org>
parents: 29511
diff changeset
   342
        super(chgcmdserver, self).cleanup()
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   343
        # dispatch._runcatch() does not flush outputs if exception is not
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   344
        # handled by dispatch._dispatch()
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   345
        self.ui.flush()
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   346
        self._restoreio()
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   347
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   348
    def attachio(self):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   349
        """Attach to client's stdio passed via unix domain socket; all
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   350
        channels except cresult will no longer be used
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   351
        """
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   352
        # tell client to sendmsg() with 1-byte payload, which makes it
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   353
        # distinctive from "attachio\n" command consumed by client.read()
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   354
        self.clientsock.sendall(struct.pack('>cI', 'I', 1))
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   355
        clientfds = osutil.recvfds(self.clientsock.fileno())
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   356
        _log('received fds: %r\n' % clientfds)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   357
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   358
        ui = self.ui
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   359
        ui.flush()
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   360
        first = self._saveio()
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   361
        for fd, (cn, fn, mode) in zip(clientfds, _iochannels):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   362
            assert fd > 0
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   363
            fp = getattr(ui, fn)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   364
            os.dup2(fd, fp.fileno())
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   365
            os.close(fd)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   366
            if not first:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   367
                continue
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   368
            # reset buffering mode when client is first attached. as we want
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   369
            # to see output immediately on pager, the mode stays unchanged
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   370
            # when client re-attached. ferr is unchanged because it should
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   371
            # be unbuffered no matter if it is a tty or not.
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   372
            if fn == 'ferr':
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   373
                newfp = fp
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   374
            else:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   375
                # make it line buffered explicitly because the default is
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   376
                # decided on first write(), where fout could be a pager.
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   377
                if fp.isatty():
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   378
                    bufsize = 1  # line buffered
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   379
                else:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   380
                    bufsize = -1  # system default
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   381
                newfp = os.fdopen(fp.fileno(), mode, bufsize)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   382
                setattr(ui, fn, newfp)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   383
            setattr(self, cn, newfp)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   384
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   385
        self.cresult.write(struct.pack('>i', len(clientfds)))
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   386
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   387
    def _saveio(self):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   388
        if self._oldios:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   389
            return False
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   390
        ui = self.ui
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   391
        for cn, fn, _mode in _iochannels:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   392
            ch = getattr(self, cn)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   393
            fp = getattr(ui, fn)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   394
            fd = os.dup(fp.fileno())
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   395
            self._oldios.append((ch, fp, fd))
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   396
        return True
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   397
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   398
    def _restoreio(self):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   399
        ui = self.ui
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   400
        for (ch, fp, fd), (cn, fn, _mode) in zip(self._oldios, _iochannels):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   401
            newfp = getattr(ui, fn)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   402
            # close newfp while it's associated with client; otherwise it
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   403
            # would be closed when newfp is deleted
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   404
            if newfp is not fp:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   405
                newfp.close()
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   406
            # restore original fd: fp is open again
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   407
            os.dup2(fd, fp.fileno())
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   408
            os.close(fd)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   409
            setattr(self, cn, ch)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   410
            setattr(ui, fn, fp)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   411
        del self._oldios[:]
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   412
28350
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   413
    def validate(self):
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   414
        """Reload the config and check if the server is up to date
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   415
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   416
        Read a list of '\0' separated arguments.
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   417
        Write a non-empty list of '\0' separated instruction strings or '\0'
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   418
        if the list is empty.
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   419
        An instruction string could be either:
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   420
            - "unlink $path", the client should unlink the path to stop the
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   421
              outdated server.
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   422
            - "redirect $path", the client should attempt to connect to $path
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   423
              first. If it does not work, start a new server. It implies
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   424
              "reconnect".
28516
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28514
diff changeset
   425
            - "exit $n", the client should exit directly with code n.
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28514
diff changeset
   426
              This may happen if we cannot parse the config.
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   427
            - "reconnect", the client should close the connection and
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   428
              reconnect.
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   429
        If neither "reconnect" nor "redirect" is included in the instruction
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   430
        list, the client can continue with this server after completing all
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   431
        the instructions.
28350
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   432
        """
30513
ff7df4bb75de chgserver: make it a core module and drop extension flags
Yuya Nishihara <yuya@tcha.org>
parents: 30512
diff changeset
   433
        from . import dispatch  # avoid cycle
30512
cc374292a561 chgserver: delay importing commands and dispatch modules
Yuya Nishihara <yuya@tcha.org>
parents: 30511
diff changeset
   434
28350
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   435
        args = self._readlist()
28516
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28514
diff changeset
   436
        try:
28599
0e7a929754aa chgserver: use global ui instead of repo ui for dispatch.request.ui
Jun Wu <quark@fb.com>
parents: 28586
diff changeset
   437
            self.ui, lui = _loadnewui(self.ui, args)
28516
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28514
diff changeset
   438
        except error.ParseError as inst:
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28514
diff changeset
   439
            dispatch._formatparse(self.ui.warn, inst)
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28514
diff changeset
   440
            self.ui.flush()
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28514
diff changeset
   441
            self.cresult.write('exit 255')
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28514
diff changeset
   442
            return
28599
0e7a929754aa chgserver: use global ui instead of repo ui for dispatch.request.ui
Jun Wu <quark@fb.com>
parents: 28586
diff changeset
   443
        newhash = hashstate.fromui(lui, self.hashstate.mtimepaths)
28350
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   444
        insts = []
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   445
        if newhash.mtimehash != self.hashstate.mtimehash:
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   446
            addr = _hashaddress(self.baseaddress, self.hashstate.confighash)
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   447
            insts.append('unlink %s' % addr)
28536
a979f5b03320 chgserver: invalidate the server if extensions fail to load
Jun Wu <quark@fb.com>
parents: 28535
diff changeset
   448
            # mtimehash is empty if one or more extensions fail to load.
a979f5b03320 chgserver: invalidate the server if extensions fail to load
Jun Wu <quark@fb.com>
parents: 28535
diff changeset
   449
            # to be compatible with hg, still serve the client this time.
a979f5b03320 chgserver: invalidate the server if extensions fail to load
Jun Wu <quark@fb.com>
parents: 28535
diff changeset
   450
            if self.hashstate.mtimehash:
a979f5b03320 chgserver: invalidate the server if extensions fail to load
Jun Wu <quark@fb.com>
parents: 28535
diff changeset
   451
                insts.append('reconnect')
28350
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   452
        if newhash.confighash != self.hashstate.confighash:
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   453
            addr = _hashaddress(self.baseaddress, newhash.confighash)
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   454
            insts.append('redirect %s' % addr)
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   455
        _log('validate: %s\n' % insts)
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   456
        self.cresult.write('\0'.join(insts) or '\0')
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   457
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   458
    def chdir(self):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   459
        """Change current directory
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   460
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   461
        Note that the behavior of --cwd option is bit different from this.
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   462
        It does not affect --config parameter.
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   463
        """
28158
7cc57a531f0c chgserver: use _readlist and _readstr
Jun Wu <quark@fb.com>
parents: 28014
diff changeset
   464
        path = self._readstr()
7cc57a531f0c chgserver: use _readlist and _readstr
Jun Wu <quark@fb.com>
parents: 28014
diff changeset
   465
        if not path:
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   466
            return
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   467
        _log('chdir to %r\n' % path)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   468
        os.chdir(path)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   469
28159
d2d04d1d2f92 chgserver: add setumask method
Jun Wu <quark@fb.com>
parents: 28158
diff changeset
   470
    def setumask(self):
d2d04d1d2f92 chgserver: add setumask method
Jun Wu <quark@fb.com>
parents: 28158
diff changeset
   471
        """Change umask"""
d2d04d1d2f92 chgserver: add setumask method
Jun Wu <quark@fb.com>
parents: 28158
diff changeset
   472
        mask = struct.unpack('>I', self._read(4))[0]
d2d04d1d2f92 chgserver: add setumask method
Jun Wu <quark@fb.com>
parents: 28158
diff changeset
   473
        _log('setumask %r\n' % mask)
d2d04d1d2f92 chgserver: add setumask method
Jun Wu <quark@fb.com>
parents: 28158
diff changeset
   474
        os.umask(mask)
d2d04d1d2f92 chgserver: add setumask method
Jun Wu <quark@fb.com>
parents: 28158
diff changeset
   475
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   476
    def getpager(self):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   477
        """Read cmdargs and write pager command to r-channel if enabled
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   478
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   479
        If pager isn't enabled, this writes '\0' because channeledoutput
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   480
        does not allow to write empty data.
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   481
        """
30513
ff7df4bb75de chgserver: make it a core module and drop extension flags
Yuya Nishihara <yuya@tcha.org>
parents: 30512
diff changeset
   482
        from . import dispatch  # avoid cycle
30512
cc374292a561 chgserver: delay importing commands and dispatch modules
Yuya Nishihara <yuya@tcha.org>
parents: 30511
diff changeset
   483
28158
7cc57a531f0c chgserver: use _readlist and _readstr
Jun Wu <quark@fb.com>
parents: 28014
diff changeset
   484
        args = self._readlist()
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   485
        try:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   486
            cmd, _func, args, options, _cmdoptions = dispatch._parse(self.ui,
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   487
                                                                     args)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   488
        except (error.Abort, error.AmbiguousCommand, error.CommandError,
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   489
                error.UnknownCommand):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   490
            cmd = None
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   491
            options = {}
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   492
        if not cmd or 'pager' not in options:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   493
            self.cresult.write('\0')
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   494
            return
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   495
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   496
        pagercmd = _setuppagercmd(self.ui, options, cmd)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   497
        if pagercmd:
29428
247ea0dfdb94 chgserver: do not ignore SIGPIPE if pager is used
Jun Wu <quark@fb.com>
parents: 29341
diff changeset
   498
            # Python's SIGPIPE is SIG_IGN by default. change to SIG_DFL so
247ea0dfdb94 chgserver: do not ignore SIGPIPE if pager is used
Jun Wu <quark@fb.com>
parents: 29341
diff changeset
   499
            # we can exit if the pipe to the pager is closed
247ea0dfdb94 chgserver: do not ignore SIGPIPE if pager is used
Jun Wu <quark@fb.com>
parents: 29341
diff changeset
   500
            if util.safehasattr(signal, 'SIGPIPE') and \
247ea0dfdb94 chgserver: do not ignore SIGPIPE if pager is used
Jun Wu <quark@fb.com>
parents: 29341
diff changeset
   501
                    signal.getsignal(signal.SIGPIPE) == signal.SIG_IGN:
247ea0dfdb94 chgserver: do not ignore SIGPIPE if pager is used
Jun Wu <quark@fb.com>
parents: 29341
diff changeset
   502
                signal.signal(signal.SIGPIPE, signal.SIG_DFL)
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   503
            self.cresult.write(pagercmd)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   504
        else:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   505
            self.cresult.write('\0')
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   506
30644
2bb8c53be961 chgserver: override runcommand
Jun Wu <quark@fb.com>
parents: 30643
diff changeset
   507
    def runcommand(self):
2bb8c53be961 chgserver: override runcommand
Jun Wu <quark@fb.com>
parents: 30643
diff changeset
   508
        return super(chgcmdserver, self).runcommand()
2bb8c53be961 chgserver: override runcommand
Jun Wu <quark@fb.com>
parents: 30643
diff changeset
   509
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   510
    def setenv(self):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   511
        """Clear and update os.environ
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   512
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   513
        Note that not all variables can make an effect on the running process.
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   514
        """
28158
7cc57a531f0c chgserver: use _readlist and _readstr
Jun Wu <quark@fb.com>
parents: 28014
diff changeset
   515
        l = self._readlist()
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   516
        try:
28158
7cc57a531f0c chgserver: use _readlist and _readstr
Jun Wu <quark@fb.com>
parents: 28014
diff changeset
   517
            newenv = dict(s.split('=', 1) for s in l)
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   518
        except ValueError:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   519
            raise ValueError('unexpected value in setenv request')
28602
83127a9fe76e chgserver: drop old hack to recreate ui on HGPLAIN change
Yuya Nishihara <yuya@tcha.org>
parents: 28599
diff changeset
   520
        _log('setenv: %r\n' % sorted(newenv.keys()))
30635
a150173da1c1 py3: replace os.environ with encoding.environ (part 2 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30619
diff changeset
   521
        encoding.environ.clear()
a150173da1c1 py3: replace os.environ with encoding.environ (part 2 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30619
diff changeset
   522
        encoding.environ.update(newenv)
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   523
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   524
    capabilities = commandserver.server.capabilities.copy()
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   525
    capabilities.update({'attachio': attachio,
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   526
                         'chdir': chdir,
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   527
                         'getpager': getpager,
30644
2bb8c53be961 chgserver: override runcommand
Jun Wu <quark@fb.com>
parents: 30643
diff changeset
   528
                         'runcommand': runcommand,
28159
d2d04d1d2f92 chgserver: add setumask method
Jun Wu <quark@fb.com>
parents: 28158
diff changeset
   529
                         'setenv': setenv,
d2d04d1d2f92 chgserver: add setumask method
Jun Wu <quark@fb.com>
parents: 28158
diff changeset
   530
                         'setumask': setumask})
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   531
28223
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   532
def _tempaddress(address):
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   533
    return '%s.%d.tmp' % (address, os.getpid())
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   534
28326
ea400a4f32e6 chgserver: mangle server address to include confighash
Jun Wu <quark@fb.com>
parents: 28325
diff changeset
   535
def _hashaddress(address, hashstr):
30619
88efb4fb1975 chgserver: truncate base address at "." for hash address
Jun Wu <quark@fb.com>
parents: 30618
diff changeset
   536
    # if the basename of address contains '.', use only the left part. this
88efb4fb1975 chgserver: truncate base address at "." for hash address
Jun Wu <quark@fb.com>
parents: 30618
diff changeset
   537
    # makes it possible for the client to pass 'server.tmp$PID' and follow by
88efb4fb1975 chgserver: truncate base address at "." for hash address
Jun Wu <quark@fb.com>
parents: 30618
diff changeset
   538
    # an atomic rename to avoid locking when spawning new servers.
88efb4fb1975 chgserver: truncate base address at "." for hash address
Jun Wu <quark@fb.com>
parents: 30618
diff changeset
   539
    dirname, basename = os.path.split(address)
88efb4fb1975 chgserver: truncate base address at "." for hash address
Jun Wu <quark@fb.com>
parents: 30618
diff changeset
   540
    basename = basename.split('.', 1)[0]
88efb4fb1975 chgserver: truncate base address at "." for hash address
Jun Wu <quark@fb.com>
parents: 30618
diff changeset
   541
    return '%s-%s' % (os.path.join(dirname, basename), hashstr)
28326
ea400a4f32e6 chgserver: mangle server address to include confighash
Jun Wu <quark@fb.com>
parents: 28325
diff changeset
   542
29547
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   543
class chgunixservicehandler(object):
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   544
    """Set of operations for chg services"""
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   545
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   546
    pollinterval = 1  # [sec]
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   547
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   548
    def __init__(self, ui):
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   549
        self.ui = ui
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   550
        self._idletimeout = ui.configint('chgserver', 'idletimeout', 3600)
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   551
        self._lastactive = time.time()
29547
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   552
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   553
    def bindsocket(self, sock, address):
29597
581c0c7cb258 chgserver: refactor initialization of real/base addresses
Yuya Nishihara <yuya@tcha.org>
parents: 29596
diff changeset
   554
        self._inithashstate(address)
29545
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   555
        self._checkextensions()
29547
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   556
        self._bind(sock)
29545
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   557
        self._createsymlink()
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   558
29597
581c0c7cb258 chgserver: refactor initialization of real/base addresses
Yuya Nishihara <yuya@tcha.org>
parents: 29596
diff changeset
   559
    def _inithashstate(self, address):
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   560
        self._baseaddress = address
29545
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   561
        if self.ui.configbool('chgserver', 'skiphash', False):
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   562
            self._hashstate = None
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   563
            self._realaddress = address
29545
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   564
            return
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   565
        self._hashstate = hashstate.fromui(self.ui)
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   566
        self._realaddress = _hashaddress(address, self._hashstate.confighash)
29545
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   567
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   568
    def _checkextensions(self):
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   569
        if not self._hashstate:
29545
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   570
            return
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   571
        if extensions.notloaded():
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   572
            # one or more extensions failed to load. mtimehash becomes
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   573
            # meaningless because we do not know the paths of those extensions.
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   574
            # set mtimehash to an illegal hash value to invalidate the server.
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   575
            self._hashstate.mtimehash = ''
29545
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   576
29547
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   577
    def _bind(self, sock):
28223
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   578
        # use a unique temp address so we can stat the file and do ownership
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   579
        # check later
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   580
        tempaddress = _tempaddress(self._realaddress)
29547
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   581
        util.bindunixsocket(sock, tempaddress)
29529
02de1dbd4f6e chgserver: narrow scope of chdir() to socket.bind()
Yuya Nishihara <yuya@tcha.org>
parents: 29513
diff changeset
   582
        self._socketstat = os.stat(tempaddress)
02de1dbd4f6e chgserver: narrow scope of chdir() to socket.bind()
Yuya Nishihara <yuya@tcha.org>
parents: 29513
diff changeset
   583
        # rename will replace the old socket file if exists atomically. the
02de1dbd4f6e chgserver: narrow scope of chdir() to socket.bind()
Yuya Nishihara <yuya@tcha.org>
parents: 29513
diff changeset
   584
        # old server will detect ownership change and exit.
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   585
        util.rename(tempaddress, self._realaddress)
28223
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   586
29596
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   587
    def _createsymlink(self):
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   588
        if self._baseaddress == self._realaddress:
29596
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   589
            return
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   590
        tempaddress = _tempaddress(self._baseaddress)
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   591
        os.symlink(os.path.basename(self._realaddress), tempaddress)
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   592
        util.rename(tempaddress, self._baseaddress)
29596
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   593
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   594
    def _issocketowner(self):
28223
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   595
        try:
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   596
            stat = os.stat(self._realaddress)
28223
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   597
            return (stat.st_ino == self._socketstat.st_ino and
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   598
                    stat.st_mtime == self._socketstat.st_mtime)
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   599
        except OSError:
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   600
            return False
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   601
29547
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   602
    def unlinksocket(self, address):
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   603
        if not self._issocketowner():
28223
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   604
            return
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   605
        # it is possible to have a race condition here that we may
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   606
        # remove another server's socket file. but that's okay
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   607
        # since that server will detect and exit automatically and
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   608
        # the client will start a new server on demand.
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   609
        try:
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   610
            os.unlink(self._realaddress)
28223
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   611
        except OSError as exc:
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   612
            if exc.errno != errno.ENOENT:
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   613
                raise
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   614
29596
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   615
    def printbanner(self, address):
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   616
        # no "listening at" message should be printed to simulate hg behavior
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   617
        pass
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   618
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   619
    def shouldexit(self):
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   620
        if not self._issocketowner():
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   621
            self.ui.debug('%s is not owned, exiting.\n' % self._realaddress)
29596
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   622
            return True
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   623
        if time.time() - self._lastactive > self._idletimeout:
29596
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   624
            self.ui.debug('being idle too long. exiting.\n')
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   625
            return True
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   626
        return False
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   627
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   628
    def newconnection(self):
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   629
        self._lastactive = time.time()
29596
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   630
29547
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   631
    def createcmdserver(self, repo, conn, fin, fout):
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   632
        return chgcmdserver(self.ui, repo, fin, fout, conn,
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   633
                            self._hashstate, self._baseaddress)
28223
0a853dc9b306 chgserver: auto exit after being idle for too long or lose the socket file
Jun Wu <quark@fb.com>
parents: 28159
diff changeset
   634
29546
a7513390a9db chgserver: extract stub factory of service object
Yuya Nishihara <yuya@tcha.org>
parents: 29545
diff changeset
   635
def chgunixservice(ui, repo, opts):
30511
1873563e1ede chgserver: drop CHGINTERNALMARK by chgunixservice()
Yuya Nishihara <yuya@tcha.org>
parents: 30507
diff changeset
   636
    # CHGINTERNALMARK is temporarily set by chg client to detect if chg will
1873563e1ede chgserver: drop CHGINTERNALMARK by chgunixservice()
Yuya Nishihara <yuya@tcha.org>
parents: 30507
diff changeset
   637
    # start another chg. drop it to avoid possible side effects.
30635
a150173da1c1 py3: replace os.environ with encoding.environ (part 2 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30619
diff changeset
   638
    if 'CHGINTERNALMARK' in encoding.environ:
a150173da1c1 py3: replace os.environ with encoding.environ (part 2 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30619
diff changeset
   639
        del encoding.environ['CHGINTERNALMARK']
30511
1873563e1ede chgserver: drop CHGINTERNALMARK by chgunixservice()
Yuya Nishihara <yuya@tcha.org>
parents: 30507
diff changeset
   640
29546
a7513390a9db chgserver: extract stub factory of service object
Yuya Nishihara <yuya@tcha.org>
parents: 29545
diff changeset
   641
    if repo:
30332
318a24b52eeb spelling: fixes of non-dictionary words
Mads Kiilerich <madski@unity3d.com>
parents: 29841
diff changeset
   642
        # one chgserver can serve multiple repos. drop repo information
29546
a7513390a9db chgserver: extract stub factory of service object
Yuya Nishihara <yuya@tcha.org>
parents: 29545
diff changeset
   643
        ui.setconfig('bundle', 'mainreporoot', '', 'repo')
29547
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   644
    h = chgunixservicehandler(ui)
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   645
    return commandserver.unixforkingservice(ui, repo=None, opts=opts, handler=h)