mercurial/chgserver.py
author Kyle Lippincott <spectral@google.com>
Mon, 05 Aug 2019 13:31:12 -0700
changeset 42732 cdf0e9523de1
parent 42530 49998d5ba66a
child 42828 0cbe17335857
permissions -rw-r--r--
branchmap: explicitly warm+write all subsets of the branchmap caches 'full' claims it will warm all of the caches that are known about, but this was not the case - it did not actually warm the branchmap caches for subsets that we haven't requested, or for subsets that are still considered "valid". By explicitly writing them to disk, we can force the subsets for ex: "served" to be written ("immutable" and "base"), making it cheaper to calculate "served" the next time it needs to be updated. Differential Revision: https://phab.mercurial-scm.org/D6710
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
30522
ff7df4bb75de chgserver: make it a core module and drop extension flags
Yuya Nishihara <yuya@tcha.org>
parents: 30521
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
'setenv' command
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    20
    replace os.environ completely
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    21
40109
e5fbdc3659fc chgserver: add "setumask2" command which uses correct message frame
Yuya Nishihara <yuya@tcha.org>
parents: 39845
diff changeset
    22
'setumask' command (DEPRECATED)
e5fbdc3659fc chgserver: add "setumask2" command which uses correct message frame
Yuya Nishihara <yuya@tcha.org>
parents: 39845
diff changeset
    23
'setumask2' command
28325
9fec3cb8d128 chgserver: update docs
Jun Wu <quark@fb.com>
parents: 28277
diff changeset
    24
    set umask
9fec3cb8d128 chgserver: update docs
Jun Wu <quark@fb.com>
parents: 28277
diff changeset
    25
28350
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
    26
'validate' command
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
    27
    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
    28
28325
9fec3cb8d128 chgserver: update docs
Jun Wu <quark@fb.com>
parents: 28277
diff changeset
    29
Config
9fec3cb8d128 chgserver: update docs
Jun Wu <quark@fb.com>
parents: 28277
diff changeset
    30
------
9fec3cb8d128 chgserver: update docs
Jun Wu <quark@fb.com>
parents: 28277
diff changeset
    31
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
  [chgserver]
31010
cb899ee133d8 chgserver: move comments in config example
Jun Wu <quark@fb.com>
parents: 30944
diff changeset
    35
  # how long (in seconds) should an idle chg server exit
cb899ee133d8 chgserver: move comments in config example
Jun Wu <quark@fb.com>
parents: 30944
diff changeset
    36
  idletimeout = 3600
cb899ee133d8 chgserver: move comments in config example
Jun Wu <quark@fb.com>
parents: 30944
diff changeset
    37
cb899ee133d8 chgserver: move comments in config example
Jun Wu <quark@fb.com>
parents: 30944
diff changeset
    38
  # whether to skip config or env change checks
cb899ee133d8 chgserver: move comments in config example
Jun Wu <quark@fb.com>
parents: 30944
diff changeset
    39
  skiphash = False
27792
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
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    42
from __future__ import absolute_import
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    43
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
32276
c8b9943c07eb commandserver: move "listen" responsibility from service to handler
Jun Wu <quark@fb.com>
parents: 32248
diff changeset
    48
import socket
36789
ffa3026d4196 cleanup: use stat_result[stat.ST_MTIME] instead of stat_result.st_mtime
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
    49
import stat
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    50
import struct
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
30522
ff7df4bb75de chgserver: make it a core module and drop extension flags
Yuya Nishihara <yuya@tcha.org>
parents: 30521
diff changeset
    53
from .i18n import _
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    54
30522
ff7df4bb75de chgserver: make it a core module and drop extension flags
Yuya Nishihara <yuya@tcha.org>
parents: 30521
diff changeset
    55
from . import (
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    56
    commandserver,
30640
a150173da1c1 py3: replace os.environ with encoding.environ (part 2 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30624
diff changeset
    57
    encoding,
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    58
    error,
28276
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
    59
    extensions,
35582
72b91f905065 py3: use node.hex(h.digest()) instead of h.hexdigest()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35233
diff changeset
    60
    node,
30672
10b17ed9b591 py3: replace sys.executable with pycompat.sysexecutable
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30650
diff changeset
    61
    pycompat,
27792
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
37122
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36843
diff changeset
    65
from .utils import (
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36843
diff changeset
    66
    procutil,
41833
bce2356ece68 py3: port things from chgserver.py
Pulkit Goyal <pulkit@yandex-team.ru>
parents: 41821
diff changeset
    67
    stringutil,
37122
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36843
diff changeset
    68
)
d4a2e0d5d042 procutil: bulk-replace util.std* to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36843
diff changeset
    69
28262
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    70
def _hashlist(items):
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    71
    """return sha1 hexdigest for a list"""
41833
bce2356ece68 py3: port things from chgserver.py
Pulkit Goyal <pulkit@yandex-team.ru>
parents: 41821
diff changeset
    72
    return node.hex(hashlib.sha1(stringutil.pprint(items)).digest())
28262
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    73
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    74
# sensitive config sections affecting confighash
28478
e6e183687545 chgserver: include [extdiff] in confighash
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
    75
_configsections = [
29101
57a24a85a2bc chgserver: add [alias] to confighash
Jun Wu <quark@fb.com>
parents: 29088
diff changeset
    76
    'alias',  # affects global state commands.table
34485
37b7581e5737 eol: make [eol] config section sensitive for chg confighash
Jun Wu <quark@fb.com>
parents: 33881
diff changeset
    77
    'eol',    # uses setconfig('eol', ...)
28478
e6e183687545 chgserver: include [extdiff] in confighash
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
    78
    'extdiff',  # uisetup will register new commands
e6e183687545 chgserver: include [extdiff] in confighash
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
    79
    'extensions',
e6e183687545 chgserver: include [extdiff] in confighash
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
    80
]
28262
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    81
34839
110040e715c9 test-show: make it compatible with chg
Jun Wu <quark@fb.com>
parents: 34485
diff changeset
    82
_configsectionitems = [
110040e715c9 test-show: make it compatible with chg
Jun Wu <quark@fb.com>
parents: 34485
diff changeset
    83
    ('commands', 'show.aliasprefix'), # show.py reads it in extsetup
110040e715c9 test-show: make it compatible with chg
Jun Wu <quark@fb.com>
parents: 34485
diff changeset
    84
]
110040e715c9 test-show: make it compatible with chg
Jun Wu <quark@fb.com>
parents: 34485
diff changeset
    85
28262
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    86
# sensitive environment variables affecting confighash
41833
bce2356ece68 py3: port things from chgserver.py
Pulkit Goyal <pulkit@yandex-team.ru>
parents: 41821
diff changeset
    87
_envre = re.compile(br'''\A(?:
28262
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    88
                    CHGHG
32311
6096d27dc119 chgserver: more explicit about sensitive environ variables
Jun Wu <quark@fb.com>
parents: 32277
diff changeset
    89
                    |HG(?:DEMANDIMPORT|EMITWARNINGS|MODULEPOLICY|PROF|RCPATH)?
6096d27dc119 chgserver: more explicit about sensitive environ variables
Jun Wu <quark@fb.com>
parents: 32277
diff changeset
    90
                    |HG(?:ENCODING|PLAIN).*
28262
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    91
                    |LANG(?:UAGE)?
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    92
                    |LC_.*
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    93
                    |LD_.*
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    94
                    |PATH
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    95
                    |PYTHON.*
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    96
                    |TERM(?:INFO)?
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    97
                    |TZ
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    98
                    )\Z''', re.X)
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
    99
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
   100
def _confighash(ui):
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
   101
    """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
   102
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
   103
    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
   104
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
   105
    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
   106
    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
   107
    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
   108
    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
   109
    same time.
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
   110
    """
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
   111
    sectionitems = []
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
   112
    for section in _configsections:
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
   113
        sectionitems.append(ui.configitems(section))
34839
110040e715c9 test-show: make it compatible with chg
Jun Wu <quark@fb.com>
parents: 34485
diff changeset
   114
    for section, item in _configsectionitems:
110040e715c9 test-show: make it compatible with chg
Jun Wu <quark@fb.com>
parents: 34485
diff changeset
   115
        sectionitems.append(ui.config(section, item))
28262
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
   116
    sectionhash = _hashlist(sectionitems)
34887
7bf7544fd6cc chgserver: do not treat HG as sensitive environ when CHGHG is set
Jun Wu <quark@fb.com>
parents: 34839
diff changeset
   117
    # If $CHGHG is set, the change to $HG should not trigger a new chg server
7bf7544fd6cc chgserver: do not treat HG as sensitive environ when CHGHG is set
Jun Wu <quark@fb.com>
parents: 34839
diff changeset
   118
    if 'CHGHG' in encoding.environ:
7bf7544fd6cc chgserver: do not treat HG as sensitive environ when CHGHG is set
Jun Wu <quark@fb.com>
parents: 34839
diff changeset
   119
        ignored = {'HG'}
7bf7544fd6cc chgserver: do not treat HG as sensitive environ when CHGHG is set
Jun Wu <quark@fb.com>
parents: 34839
diff changeset
   120
    else:
7bf7544fd6cc chgserver: do not treat HG as sensitive environ when CHGHG is set
Jun Wu <quark@fb.com>
parents: 34839
diff changeset
   121
        ignored = set()
30640
a150173da1c1 py3: replace os.environ with encoding.environ (part 2 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30624
diff changeset
   122
    envitems = [(k, v) for k, v in encoding.environ.iteritems()
34887
7bf7544fd6cc chgserver: do not treat HG as sensitive environ when CHGHG is set
Jun Wu <quark@fb.com>
parents: 34839
diff changeset
   123
                if _envre.match(k) and k not in ignored]
28262
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
   124
    envhash = _hashlist(sorted(envitems))
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
   125
    return sectionhash[:6] + envhash[:6]
53dc4aada2d9 chgserver: add utilities to calculate confighash
Jun Wu <quark@fb.com>
parents: 28261
diff changeset
   126
28276
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   127
def _getmtimepaths(ui):
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   128
    """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
   129
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   130
    The list will include:
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   131
    - 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
   132
    - mercurial/__version__.py
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   133
    - python binary
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   134
    """
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   135
    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
   136
    try:
30522
ff7df4bb75de chgserver: make it a core module and drop extension flags
Yuya Nishihara <yuya@tcha.org>
parents: 30521
diff changeset
   137
        from . import __version__
28276
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   138
        modules.append(__version__)
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   139
    except ImportError:
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   140
        pass
42530
49998d5ba66a pycompat: make fewer assumptions about sys.executable
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 41833
diff changeset
   141
    files = []
49998d5ba66a pycompat: make fewer assumptions about sys.executable
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 41833
diff changeset
   142
    if pycompat.sysexecutable:
49998d5ba66a pycompat: make fewer assumptions about sys.executable
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 41833
diff changeset
   143
        files.append(pycompat.sysexecutable)
28276
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   144
    for m in modules:
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   145
        try:
41821
78027e7bc544 py3: convert return values of inspect.getabsfile() to bytes
Pulkit Goyal <pulkit@yandex-team.ru>
parents: 41285
diff changeset
   146
            files.append(pycompat.fsencode(inspect.getabsfile(m)))
28276
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   147
        except TypeError:
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   148
            pass
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   149
    return sorted(set(files))
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   150
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   151
def _mtimehash(paths):
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   152
    """return a quick hash for detecting file changes
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   153
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   154
    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
   155
    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
   156
    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
   157
    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
   158
    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
   159
    some carefully crafted situation.
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   160
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   161
    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
   162
    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
   163
71ed5a3ef8a9 chgserver: document why we don't merge mtimehash and confighash
Jun Wu <quark@fb.com>
parents: 29433
diff changeset
   164
    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
   165
    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
   166
    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
   167
    """
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   168
    def trystat(path):
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   169
        try:
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   170
            st = os.stat(path)
36789
ffa3026d4196 cleanup: use stat_result[stat.ST_MTIME] instead of stat_result.st_mtime
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   171
            return (st[stat.ST_MTIME], st.st_size)
28276
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   172
        except OSError:
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   173
            # 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
   174
            pass
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   175
    return _hashlist(map(trystat, paths))[:12]
b4ceadb2c439 chgserver: add utilities to calculate mtimehash
Jun Wu <quark@fb.com>
parents: 28264
diff changeset
   176
28277
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   177
class hashstate(object):
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   178
    """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
   179
    def __init__(self, confighash, mtimehash, mtimepaths):
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   180
        self.confighash = confighash
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   181
        self.mtimehash = mtimehash
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   182
        self.mtimepaths = mtimepaths
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   183
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   184
    @staticmethod
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   185
    def fromui(ui, mtimepaths=None):
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   186
        if mtimepaths is None:
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   187
            mtimepaths = _getmtimepaths(ui)
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   188
        confighash = _confighash(ui)
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   189
        mtimehash = _mtimehash(mtimepaths)
40843
eaabcb689747 commandserver: switch logging facility to ui.log() interface
Yuya Nishihara <yuya@tcha.org>
parents: 40842
diff changeset
   190
        ui.log('cmdserver', 'confighash = %s mtimehash = %s\n',
eaabcb689747 commandserver: switch logging facility to ui.log() interface
Yuya Nishihara <yuya@tcha.org>
parents: 40842
diff changeset
   191
               confighash, mtimehash)
28277
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   192
        return hashstate(confighash, mtimehash, mtimepaths)
cdc6319f6a7d chgserver: add a structure for confighash and mtimehash
Jun Wu <quark@fb.com>
parents: 28276
diff changeset
   193
30740
493935e0327a chgserver: implement chgui._runpager
Jun Wu <quark@fb.com>
parents: 30739
diff changeset
   194
def _newchgui(srcui, csystem, attachio):
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   195
    class chgui(srcui.__class__):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   196
        def __init__(self, src=None):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   197
            super(chgui, self).__init__(src)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   198
            if src:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   199
                self._csystem = getattr(src, '_csystem', csystem)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   200
            else:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   201
                self._csystem = csystem
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   202
31125
3f8f53190d6a chg: deduplicate error handling of ui.system()
Yuya Nishihara <yuya@tcha.org>
parents: 31124
diff changeset
   203
        def _runsystem(self, cmd, environ, cwd, out):
38800
1b9be0b26511 chgserver: update comment describing when to fall back to core _runsystem()
Yuya Nishihara <yuya@tcha.org>
parents: 37123
diff changeset
   204
            # fallback to the original system method if
1b9be0b26511 chgserver: update comment describing when to fall back to core _runsystem()
Yuya Nishihara <yuya@tcha.org>
parents: 37123
diff changeset
   205
            #  a. the output stream is not stdout (e.g. stderr, cStringIO),
41285
cf8677cd7286 ui: proxy protect/restorestdio() calls to update internal flag
Yuya Nishihara <yuya@tcha.org>
parents: 40893
diff changeset
   206
            #  b. or stdout is redirected by protectfinout(),
38800
1b9be0b26511 chgserver: update comment describing when to fall back to core _runsystem()
Yuya Nishihara <yuya@tcha.org>
parents: 37123
diff changeset
   207
            # because the chg client is not aware of these situations and
1b9be0b26511 chgserver: update comment describing when to fall back to core _runsystem()
Yuya Nishihara <yuya@tcha.org>
parents: 37123
diff changeset
   208
            # will behave differently (i.e. write to stdout).
31124
fbce78c58f1e chg: refactor ui.system() to be partly overridden
Yuya Nishihara <yuya@tcha.org>
parents: 31010
diff changeset
   209
            if (out is not self.fout
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
   210
                or not util.safehasattr(self.fout, 'fileno')
38801
23a00bc90a3c chgserver: do not send system() back to client if stdio redirected (issue5992)
Yuya Nishihara <yuya@tcha.org>
parents: 38800
diff changeset
   211
                or self.fout.fileno() != procutil.stdout.fileno()
23a00bc90a3c chgserver: do not send system() back to client if stdio redirected (issue5992)
Yuya Nishihara <yuya@tcha.org>
parents: 38800
diff changeset
   212
                or self._finoutredirected):
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37122
diff changeset
   213
                return procutil.system(cmd, environ=environ, cwd=cwd, out=out)
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   214
            self.flush()
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37122
diff changeset
   215
            return self._csystem(cmd, procutil.shellenviron(environ), cwd)
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   216
31954
e518192d6bac pager: set some environment variables if they're not set
Jun Wu <quark@fb.com>
parents: 31700
diff changeset
   217
        def _runpager(self, cmd, env=None):
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37122
diff changeset
   218
            self._csystem(cmd, procutil.shellenviron(env), type='pager',
30740
493935e0327a chgserver: implement chgui._runpager
Jun Wu <quark@fb.com>
parents: 30739
diff changeset
   219
                          cmdtable={'attachio': attachio})
31695
2d11d278279a ui: defer setting pager related properties until the pager has spawned
Matt Harbison <matt_harbison@yahoo.com>
parents: 31551
diff changeset
   220
            return True
30740
493935e0327a chgserver: implement chgui._runpager
Jun Wu <quark@fb.com>
parents: 30739
diff changeset
   221
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   222
    return chgui(srcui)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   223
40842
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   224
def _loadnewui(srcui, args, cdebug):
30522
ff7df4bb75de chgserver: make it a core module and drop extension flags
Yuya Nishihara <yuya@tcha.org>
parents: 30521
diff changeset
   225
    from . import dispatch  # avoid cycle
30521
cc374292a561 chgserver: delay importing commands and dispatch modules
Yuya Nishihara <yuya@tcha.org>
parents: 30520
diff changeset
   226
30577
cfb227016d01 chgserver: call "load" for new ui objects
Jun Wu <quark@fb.com>
parents: 30522
diff changeset
   227
    newui = srcui.__class__.load()
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   228
    for a in ['fin', 'fout', 'ferr', 'environ']:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   229
        setattr(newui, a, getattr(srcui, a))
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   230
    if util.safehasattr(srcui, '_csystem'):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   231
        newui._csystem = srcui._csystem
28264
3682e201cce6 chgserver: make _renewui load repo and command line configs
Jun Wu <quark@fb.com>
parents: 28262
diff changeset
   232
3682e201cce6 chgserver: make _renewui load repo and command line configs
Jun Wu <quark@fb.com>
parents: 28262
diff changeset
   233
    # command line args
35233
6e6d0a5b88e6 dispatch: replace _earlyreq*() with new fancyopts-based parser
Yuya Nishihara <yuya@tcha.org>
parents: 34996
diff changeset
   234
    options = dispatch._earlyparseopts(newui, args)
34996
c9740b69b9b7 dispatch: add HGPLAIN=+strictflags to restrict early parsing of global options
Yuya Nishihara <yuya@tcha.org>
parents: 34985
diff changeset
   235
    dispatch._parseconfig(newui, options['config'])
28264
3682e201cce6 chgserver: make _renewui load repo and command line configs
Jun Wu <quark@fb.com>
parents: 28262
diff changeset
   236
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   237
    # stolen from tortoisehg.util.copydynamicconfig()
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   238
    for section, name, value in srcui.walkconfig():
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   239
        source = srcui.configsource(section, name)
31700
d73490957d61 chgserver: do not copy configs set by environment variables
Jun Wu <quark@fb.com>
parents: 31695
diff changeset
   240
        if ':' in source or source == '--config' or source.startswith('$'):
d73490957d61 chgserver: do not copy configs set by environment variables
Jun Wu <quark@fb.com>
parents: 31695
diff changeset
   241
            # path:line or command line, or environ
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   242
            continue
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   243
        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
   244
0e7a929754aa chgserver: use global ui instead of repo ui for dispatch.request.ui
Jun Wu <quark@fb.com>
parents: 28586
diff changeset
   245
    # load wd and repo config, copied from dispatch.py
34996
c9740b69b9b7 dispatch: add HGPLAIN=+strictflags to restrict early parsing of global options
Yuya Nishihara <yuya@tcha.org>
parents: 34985
diff changeset
   246
    cwd = options['cwd']
c9740b69b9b7 dispatch: add HGPLAIN=+strictflags to restrict early parsing of global options
Yuya Nishihara <yuya@tcha.org>
parents: 34985
diff changeset
   247
    cwd = cwd and os.path.realpath(cwd) or None
c9740b69b9b7 dispatch: add HGPLAIN=+strictflags to restrict early parsing of global options
Yuya Nishihara <yuya@tcha.org>
parents: 34985
diff changeset
   248
    rpath = options['repository']
28599
0e7a929754aa chgserver: use global ui instead of repo ui for dispatch.request.ui
Jun Wu <quark@fb.com>
parents: 28586
diff changeset
   249
    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
   250
40763
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40111
diff changeset
   251
    extensions.populateui(newui)
40842
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   252
    commandserver.setuplogging(newui, fp=cdebug)
40763
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40111
diff changeset
   253
    if newui is not newlui:
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40111
diff changeset
   254
        extensions.populateui(newlui)
40842
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   255
        commandserver.setuplogging(newlui, fp=cdebug)
40763
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40111
diff changeset
   256
28599
0e7a929754aa chgserver: use global ui instead of repo ui for dispatch.request.ui
Jun Wu <quark@fb.com>
parents: 28586
diff changeset
   257
    return (newui, newlui)
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   258
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   259
class channeledsystem(object):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   260
    """Propagate ui.system() request in the following format:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   261
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   262
    payload length (unsigned int),
30726
dd897eb1699e chg: send type information via S channel (BC)
Jun Wu <quark@fb.com>
parents: 30672
diff changeset
   263
    type, '\0',
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   264
    cmd, '\0',
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   265
    cwd, '\0',
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   266
    envkey, '=', val, '\0',
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   267
    ...
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   268
    envkey, '=', val
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   269
30726
dd897eb1699e chg: send type information via S channel (BC)
Jun Wu <quark@fb.com>
parents: 30672
diff changeset
   270
    if type == 'system', waits for:
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   271
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   272
    exitcode length (unsigned int),
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   273
    exitcode (int)
30739
815e1cefd082 chgserver: make S channel support pager request
Jun Wu <quark@fb.com>
parents: 30737
diff changeset
   274
815e1cefd082 chgserver: make S channel support pager request
Jun Wu <quark@fb.com>
parents: 30737
diff changeset
   275
    if type == 'pager', repetitively waits for a command name ending with '\n'
815e1cefd082 chgserver: make S channel support pager request
Jun Wu <quark@fb.com>
parents: 30737
diff changeset
   276
    and executes it defined by cmdtable, or exits the loop if the command name
815e1cefd082 chgserver: make S channel support pager request
Jun Wu <quark@fb.com>
parents: 30737
diff changeset
   277
    is empty.
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   278
    """
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   279
    def __init__(self, in_, out, channel):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   280
        self.in_ = in_
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   281
        self.out = out
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   282
        self.channel = channel
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   283
30739
815e1cefd082 chgserver: make S channel support pager request
Jun Wu <quark@fb.com>
parents: 30737
diff changeset
   284
    def __call__(self, cmd, environ, cwd=None, type='system', cmdtable=None):
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37122
diff changeset
   285
        args = [type, procutil.quotecommand(cmd), os.path.abspath(cwd or '.')]
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   286
        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
   287
        data = '\0'.join(args)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   288
        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
   289
        self.out.write(data)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   290
        self.out.flush()
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   291
30727
18eb63ec8475 chgserver: check type passed to S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   292
        if type == 'system':
18eb63ec8475 chgserver: check type passed to S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   293
            length = self.in_.read(4)
18eb63ec8475 chgserver: check type passed to S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   294
            length, = struct.unpack('>I', length)
18eb63ec8475 chgserver: check type passed to S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   295
            if length != 4:
18eb63ec8475 chgserver: check type passed to S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   296
                raise error.Abort(_('invalid response'))
18eb63ec8475 chgserver: check type passed to S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   297
            rc, = struct.unpack('>i', self.in_.read(4))
18eb63ec8475 chgserver: check type passed to S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   298
            return rc
30739
815e1cefd082 chgserver: make S channel support pager request
Jun Wu <quark@fb.com>
parents: 30737
diff changeset
   299
        elif type == 'pager':
815e1cefd082 chgserver: make S channel support pager request
Jun Wu <quark@fb.com>
parents: 30737
diff changeset
   300
            while True:
815e1cefd082 chgserver: make S channel support pager request
Jun Wu <quark@fb.com>
parents: 30737
diff changeset
   301
                cmd = self.in_.readline()[:-1]
815e1cefd082 chgserver: make S channel support pager request
Jun Wu <quark@fb.com>
parents: 30737
diff changeset
   302
                if not cmd:
815e1cefd082 chgserver: make S channel support pager request
Jun Wu <quark@fb.com>
parents: 30737
diff changeset
   303
                    break
815e1cefd082 chgserver: make S channel support pager request
Jun Wu <quark@fb.com>
parents: 30737
diff changeset
   304
                if cmdtable and cmd in cmdtable:
815e1cefd082 chgserver: make S channel support pager request
Jun Wu <quark@fb.com>
parents: 30737
diff changeset
   305
                    cmdtable[cmd]()
815e1cefd082 chgserver: make S channel support pager request
Jun Wu <quark@fb.com>
parents: 30737
diff changeset
   306
                else:
815e1cefd082 chgserver: make S channel support pager request
Jun Wu <quark@fb.com>
parents: 30737
diff changeset
   307
                    raise error.Abort(_('unexpected command: %s') % cmd)
30727
18eb63ec8475 chgserver: check type passed to S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   308
        else:
18eb63ec8475 chgserver: check type passed to S channel
Jun Wu <quark@fb.com>
parents: 30726
diff changeset
   309
            raise error.ProgrammingError('invalid S channel type: %s' % type)
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   310
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   311
_iochannels = [
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   312
    # server.ch, ui.fp, mode
36843
5bc7ff103081 py3: use r'' instead of sysstr('') to get around code transformer
Yuya Nishihara <yuya@tcha.org>
parents: 36789
diff changeset
   313
    ('cin', 'fin', r'rb'),
5bc7ff103081 py3: use r'' instead of sysstr('') to get around code transformer
Yuya Nishihara <yuya@tcha.org>
parents: 36789
diff changeset
   314
    ('cout', 'fout', r'wb'),
5bc7ff103081 py3: use r'' instead of sysstr('') to get around code transformer
Yuya Nishihara <yuya@tcha.org>
parents: 36789
diff changeset
   315
    ('cerr', 'ferr', r'wb'),
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   316
]
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   317
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   318
class chgcmdserver(commandserver.server):
40893
e7110f44ee2d commandserver: pass around option to hook repo instance creation
Yuya Nishihara <yuya@tcha.org>
parents: 40846
diff changeset
   319
    def __init__(self, ui, repo, fin, fout, sock, prereposetups,
e7110f44ee2d commandserver: pass around option to hook repo instance creation
Yuya Nishihara <yuya@tcha.org>
parents: 40846
diff changeset
   320
                 hashstate, baseaddress):
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   321
        super(chgcmdserver, self).__init__(
30740
493935e0327a chgserver: implement chgui._runpager
Jun Wu <quark@fb.com>
parents: 30739
diff changeset
   322
            _newchgui(ui, channeledsystem(fin, fout, 'S'), self.attachio),
40893
e7110f44ee2d commandserver: pass around option to hook repo instance creation
Yuya Nishihara <yuya@tcha.org>
parents: 40846
diff changeset
   323
            repo, fin, fout, prereposetups)
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   324
        self.clientsock = sock
39754
a93fe297dfb3 chgserver: add separate flag to remember if stdio fds are replaced
Yuya Nishihara <yuya@tcha.org>
parents: 37123
diff changeset
   325
        self._ioattached = False
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   326
        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
   327
        self.hashstate = hashstate
e00e57d83653 chgserver: pass hashstate and base server address to chgcmdserver
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   328
        self.baseaddress = baseaddress
28350
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   329
        if hashstate is not None:
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   330
            self.capabilities = self.capabilities.copy()
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   331
            self.capabilities['validate'] = chgcmdserver.validate
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   332
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   333
    def cleanup(self):
29512
538d0003c9e0 commandserver: promote .cleanup() hook from chgserver
Yuya Nishihara <yuya@tcha.org>
parents: 29511
diff changeset
   334
        super(chgcmdserver, self).cleanup()
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   335
        # 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
   336
        # handled by dispatch._dispatch()
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   337
        self.ui.flush()
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   338
        self._restoreio()
39754
a93fe297dfb3 chgserver: add separate flag to remember if stdio fds are replaced
Yuya Nishihara <yuya@tcha.org>
parents: 37123
diff changeset
   339
        self._ioattached = False
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 attachio(self):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   342
        """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
   343
        channels except cresult will no longer be used
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   344
        """
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   345
        # 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
   346
        # 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
   347
        self.clientsock.sendall(struct.pack('>cI', 'I', 1))
32248
d74b0cff94a9 osutil: proxy through util (and platform) modules (API)
Yuya Nishihara <yuya@tcha.org>
parents: 31954
diff changeset
   348
        clientfds = util.recvfds(self.clientsock.fileno())
40843
eaabcb689747 commandserver: switch logging facility to ui.log() interface
Yuya Nishihara <yuya@tcha.org>
parents: 40842
diff changeset
   349
        self.ui.log('chgserver', 'received fds: %r\n', clientfds)
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   350
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   351
        ui = self.ui
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   352
        ui.flush()
39754
a93fe297dfb3 chgserver: add separate flag to remember if stdio fds are replaced
Yuya Nishihara <yuya@tcha.org>
parents: 37123
diff changeset
   353
        self._saveio()
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   354
        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
   355
            assert fd > 0
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   356
            fp = getattr(ui, fn)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   357
            os.dup2(fd, fp.fileno())
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   358
            os.close(fd)
39754
a93fe297dfb3 chgserver: add separate flag to remember if stdio fds are replaced
Yuya Nishihara <yuya@tcha.org>
parents: 37123
diff changeset
   359
            if self._ioattached:
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   360
                continue
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   361
            # 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
   362
            # 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
   363
            # 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
   364
            # 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
   365
            if fn == 'ferr':
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   366
                newfp = fp
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   367
            else:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   368
                # 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
   369
                # 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
   370
                if fp.isatty():
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   371
                    bufsize = 1  # line buffered
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   372
                else:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   373
                    bufsize = -1  # system default
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   374
                newfp = os.fdopen(fp.fileno(), mode, bufsize)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   375
                setattr(ui, fn, newfp)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   376
            setattr(self, cn, newfp)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   377
39754
a93fe297dfb3 chgserver: add separate flag to remember if stdio fds are replaced
Yuya Nishihara <yuya@tcha.org>
parents: 37123
diff changeset
   378
        self._ioattached = True
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   379
        self.cresult.write(struct.pack('>i', len(clientfds)))
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   380
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   381
    def _saveio(self):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   382
        if self._oldios:
39754
a93fe297dfb3 chgserver: add separate flag to remember if stdio fds are replaced
Yuya Nishihara <yuya@tcha.org>
parents: 37123
diff changeset
   383
            return
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   384
        ui = self.ui
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   385
        for cn, fn, _mode in _iochannels:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   386
            ch = getattr(self, cn)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   387
            fp = getattr(ui, fn)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   388
            fd = os.dup(fp.fileno())
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   389
            self._oldios.append((ch, fp, fd))
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   390
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   391
    def _restoreio(self):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   392
        ui = self.ui
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   393
        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
   394
            newfp = getattr(ui, fn)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   395
            # 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
   396
            # would be closed when newfp is deleted
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   397
            if newfp is not fp:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   398
                newfp.close()
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   399
            # restore original fd: fp is open again
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   400
            os.dup2(fd, fp.fileno())
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   401
            os.close(fd)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   402
            setattr(self, cn, ch)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   403
            setattr(ui, fn, fp)
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   404
        del self._oldios[:]
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   405
28350
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   406
    def validate(self):
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   407
        """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
   408
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   409
        Read a list of '\0' separated arguments.
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   410
        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
   411
        if the list is empty.
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   412
        An instruction string could be either:
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   413
            - "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
   414
              outdated server.
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   415
            - "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
   416
              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
   417
              "reconnect".
28516
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28514
diff changeset
   418
            - "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
   419
              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
   420
            - "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
   421
              reconnect.
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   422
        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
   423
        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
   424
        the instructions.
28350
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   425
        """
30522
ff7df4bb75de chgserver: make it a core module and drop extension flags
Yuya Nishihara <yuya@tcha.org>
parents: 30521
diff changeset
   426
        from . import dispatch  # avoid cycle
30521
cc374292a561 chgserver: delay importing commands and dispatch modules
Yuya Nishihara <yuya@tcha.org>
parents: 30520
diff changeset
   427
28350
8f9661d1637b chgserver: implement validate command
Jun Wu <quark@fb.com>
parents: 28342
diff changeset
   428
        args = self._readlist()
28516
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28514
diff changeset
   429
        try:
40842
82210d88d814 commandserver: install logger to record server events through canonical API
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   430
            self.ui, lui = _loadnewui(self.ui, args, self.cdebug)
28516
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28514
diff changeset
   431
        except error.ParseError as inst:
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28514
diff changeset
   432
            dispatch._formatparse(self.ui.warn, inst)
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28514
diff changeset
   433
            self.ui.flush()
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28514
diff changeset
   434
            self.cresult.write('exit 255')
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28514
diff changeset
   435
            return
40111
d1338b4e39d0 chgserver: catch Abort while parsing early args to shut down cleanly
Yuya Nishihara <yuya@tcha.org>
parents: 40109
diff changeset
   436
        except error.Abort as inst:
d1338b4e39d0 chgserver: catch Abort while parsing early args to shut down cleanly
Yuya Nishihara <yuya@tcha.org>
parents: 40109
diff changeset
   437
            self.ui.error(_("abort: %s\n") % inst)
d1338b4e39d0 chgserver: catch Abort while parsing early args to shut down cleanly
Yuya Nishihara <yuya@tcha.org>
parents: 40109
diff changeset
   438
            if inst.hint:
d1338b4e39d0 chgserver: catch Abort while parsing early args to shut down cleanly
Yuya Nishihara <yuya@tcha.org>
parents: 40109
diff changeset
   439
                self.ui.error(_("(%s)\n") % inst.hint)
d1338b4e39d0 chgserver: catch Abort while parsing early args to shut down cleanly
Yuya Nishihara <yuya@tcha.org>
parents: 40109
diff changeset
   440
            self.ui.flush()
d1338b4e39d0 chgserver: catch Abort while parsing early args to shut down cleanly
Yuya Nishihara <yuya@tcha.org>
parents: 40109
diff changeset
   441
            self.cresult.write('exit 255')
d1338b4e39d0 chgserver: catch Abort while parsing early args to shut down cleanly
Yuya Nishihara <yuya@tcha.org>
parents: 40109
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)
41833
bce2356ece68 py3: port things from chgserver.py
Pulkit Goyal <pulkit@yandex-team.ru>
parents: 41821
diff changeset
   455
        self.ui.log('chgserver', 'validate: %s\n', stringutil.pprint(insts))
28350
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
40843
eaabcb689747 commandserver: switch logging facility to ui.log() interface
Yuya Nishihara <yuya@tcha.org>
parents: 40842
diff changeset
   467
        self.ui.log('chgserver', 'chdir to %r\n', path)
27792
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):
40109
e5fbdc3659fc chgserver: add "setumask2" command which uses correct message frame
Yuya Nishihara <yuya@tcha.org>
parents: 39845
diff changeset
   471
        """Change umask (DEPRECATED)"""
e5fbdc3659fc chgserver: add "setumask2" command which uses correct message frame
Yuya Nishihara <yuya@tcha.org>
parents: 39845
diff changeset
   472
        # BUG: this does not follow the message frame structure, but kept for
e5fbdc3659fc chgserver: add "setumask2" command which uses correct message frame
Yuya Nishihara <yuya@tcha.org>
parents: 39845
diff changeset
   473
        # backward compatibility with old chg clients for some time
e5fbdc3659fc chgserver: add "setumask2" command which uses correct message frame
Yuya Nishihara <yuya@tcha.org>
parents: 39845
diff changeset
   474
        self._setumask(self._read(4))
e5fbdc3659fc chgserver: add "setumask2" command which uses correct message frame
Yuya Nishihara <yuya@tcha.org>
parents: 39845
diff changeset
   475
e5fbdc3659fc chgserver: add "setumask2" command which uses correct message frame
Yuya Nishihara <yuya@tcha.org>
parents: 39845
diff changeset
   476
    def setumask2(self):
28159
d2d04d1d2f92 chgserver: add setumask method
Jun Wu <quark@fb.com>
parents: 28158
diff changeset
   477
        """Change umask"""
40109
e5fbdc3659fc chgserver: add "setumask2" command which uses correct message frame
Yuya Nishihara <yuya@tcha.org>
parents: 39845
diff changeset
   478
        data = self._readstr()
e5fbdc3659fc chgserver: add "setumask2" command which uses correct message frame
Yuya Nishihara <yuya@tcha.org>
parents: 39845
diff changeset
   479
        if len(data) != 4:
e5fbdc3659fc chgserver: add "setumask2" command which uses correct message frame
Yuya Nishihara <yuya@tcha.org>
parents: 39845
diff changeset
   480
            raise ValueError('invalid mask length in setumask2 request')
e5fbdc3659fc chgserver: add "setumask2" command which uses correct message frame
Yuya Nishihara <yuya@tcha.org>
parents: 39845
diff changeset
   481
        self._setumask(data)
e5fbdc3659fc chgserver: add "setumask2" command which uses correct message frame
Yuya Nishihara <yuya@tcha.org>
parents: 39845
diff changeset
   482
e5fbdc3659fc chgserver: add "setumask2" command which uses correct message frame
Yuya Nishihara <yuya@tcha.org>
parents: 39845
diff changeset
   483
    def _setumask(self, data):
e5fbdc3659fc chgserver: add "setumask2" command which uses correct message frame
Yuya Nishihara <yuya@tcha.org>
parents: 39845
diff changeset
   484
        mask = struct.unpack('>I', data)[0]
40843
eaabcb689747 commandserver: switch logging facility to ui.log() interface
Yuya Nishihara <yuya@tcha.org>
parents: 40842
diff changeset
   485
        self.ui.log('chgserver', 'setumask %r\n', mask)
28159
d2d04d1d2f92 chgserver: add setumask method
Jun Wu <quark@fb.com>
parents: 28158
diff changeset
   486
        os.umask(mask)
d2d04d1d2f92 chgserver: add setumask method
Jun Wu <quark@fb.com>
parents: 28158
diff changeset
   487
30649
2bb8c53be961 chgserver: override runcommand
Jun Wu <quark@fb.com>
parents: 30648
diff changeset
   488
    def runcommand(self):
39755
7cdd47d9ccf8 chgserver: restore pager fds attached within runcommand session
Yuya Nishihara <yuya@tcha.org>
parents: 39754
diff changeset
   489
        # pager may be attached within the runcommand session, which should
7cdd47d9ccf8 chgserver: restore pager fds attached within runcommand session
Yuya Nishihara <yuya@tcha.org>
parents: 39754
diff changeset
   490
        # be detached at the end of the session. otherwise the pager wouldn't
7cdd47d9ccf8 chgserver: restore pager fds attached within runcommand session
Yuya Nishihara <yuya@tcha.org>
parents: 39754
diff changeset
   491
        # receive EOF.
7cdd47d9ccf8 chgserver: restore pager fds attached within runcommand session
Yuya Nishihara <yuya@tcha.org>
parents: 39754
diff changeset
   492
        globaloldios = self._oldios
7cdd47d9ccf8 chgserver: restore pager fds attached within runcommand session
Yuya Nishihara <yuya@tcha.org>
parents: 39754
diff changeset
   493
        self._oldios = []
7cdd47d9ccf8 chgserver: restore pager fds attached within runcommand session
Yuya Nishihara <yuya@tcha.org>
parents: 39754
diff changeset
   494
        try:
7cdd47d9ccf8 chgserver: restore pager fds attached within runcommand session
Yuya Nishihara <yuya@tcha.org>
parents: 39754
diff changeset
   495
            return super(chgcmdserver, self).runcommand()
7cdd47d9ccf8 chgserver: restore pager fds attached within runcommand session
Yuya Nishihara <yuya@tcha.org>
parents: 39754
diff changeset
   496
        finally:
7cdd47d9ccf8 chgserver: restore pager fds attached within runcommand session
Yuya Nishihara <yuya@tcha.org>
parents: 39754
diff changeset
   497
            self._restoreio()
7cdd47d9ccf8 chgserver: restore pager fds attached within runcommand session
Yuya Nishihara <yuya@tcha.org>
parents: 39754
diff changeset
   498
            self._oldios = globaloldios
30649
2bb8c53be961 chgserver: override runcommand
Jun Wu <quark@fb.com>
parents: 30648
diff changeset
   499
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   500
    def setenv(self):
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   501
        """Clear and update os.environ
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   502
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   503
        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
   504
        """
28158
7cc57a531f0c chgserver: use _readlist and _readstr
Jun Wu <quark@fb.com>
parents: 28014
diff changeset
   505
        l = self._readlist()
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   506
        try:
28158
7cc57a531f0c chgserver: use _readlist and _readstr
Jun Wu <quark@fb.com>
parents: 28014
diff changeset
   507
            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
   508
        except ValueError:
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   509
            raise ValueError('unexpected value in setenv request')
40843
eaabcb689747 commandserver: switch logging facility to ui.log() interface
Yuya Nishihara <yuya@tcha.org>
parents: 40842
diff changeset
   510
        self.ui.log('chgserver', 'setenv: %r\n', sorted(newenv.keys()))
30640
a150173da1c1 py3: replace os.environ with encoding.environ (part 2 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30624
diff changeset
   511
        encoding.environ.clear()
a150173da1c1 py3: replace os.environ with encoding.environ (part 2 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30624
diff changeset
   512
        encoding.environ.update(newenv)
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   513
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   514
    capabilities = commandserver.server.capabilities.copy()
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   515
    capabilities.update({'attachio': attachio,
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   516
                         'chdir': chdir,
30649
2bb8c53be961 chgserver: override runcommand
Jun Wu <quark@fb.com>
parents: 30648
diff changeset
   517
                         'runcommand': runcommand,
28159
d2d04d1d2f92 chgserver: add setumask method
Jun Wu <quark@fb.com>
parents: 28158
diff changeset
   518
                         'setenv': setenv,
40109
e5fbdc3659fc chgserver: add "setumask2" command which uses correct message frame
Yuya Nishihara <yuya@tcha.org>
parents: 39845
diff changeset
   519
                         'setumask': setumask,
e5fbdc3659fc chgserver: add "setumask2" command which uses correct message frame
Yuya Nishihara <yuya@tcha.org>
parents: 39845
diff changeset
   520
                         'setumask2': setumask2})
27792
980957333cfa chgserver: import background server extension from cHg
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   521
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37122
diff changeset
   522
    if util.safehasattr(procutil, 'setprocname'):
30750
378686afca52 chgserver: add the setprocname interface
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   523
        def setprocname(self):
378686afca52 chgserver: add the setprocname interface
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   524
            """Change process title"""
378686afca52 chgserver: add the setprocname interface
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   525
            name = self._readstr()
40843
eaabcb689747 commandserver: switch logging facility to ui.log() interface
Yuya Nishihara <yuya@tcha.org>
parents: 40842
diff changeset
   526
            self.ui.log('chgserver', 'setprocname: %r\n', name)
37123
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37122
diff changeset
   527
            procutil.setprocname(name)
30750
378686afca52 chgserver: add the setprocname interface
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   528
        capabilities['setprocname'] = setprocname
378686afca52 chgserver: add the setprocname interface
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   529
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
   530
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
   531
    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
   532
28326
ea400a4f32e6 chgserver: mangle server address to include confighash
Jun Wu <quark@fb.com>
parents: 28325
diff changeset
   533
def _hashaddress(address, hashstr):
30624
88efb4fb1975 chgserver: truncate base address at "." for hash address
Jun Wu <quark@fb.com>
parents: 30623
diff changeset
   534
    # 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: 30623
diff changeset
   535
    # 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: 30623
diff changeset
   536
    # 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: 30623
diff changeset
   537
    dirname, basename = os.path.split(address)
88efb4fb1975 chgserver: truncate base address at "." for hash address
Jun Wu <quark@fb.com>
parents: 30623
diff changeset
   538
    basename = basename.split('.', 1)[0]
88efb4fb1975 chgserver: truncate base address at "." for hash address
Jun Wu <quark@fb.com>
parents: 30623
diff changeset
   539
    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
   540
29547
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   541
class chgunixservicehandler(object):
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   542
    """Set of operations for chg services"""
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   543
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   544
    pollinterval = 1  # [sec]
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
    def __init__(self, ui):
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   547
        self.ui = ui
33499
0407a51b9d8c codemod: register core configitems using a script
Jun Wu <quark@fb.com>
parents: 32311
diff changeset
   548
        self._idletimeout = ui.configint('chgserver', 'idletimeout')
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   549
        self._lastactive = time.time()
29547
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   550
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   551
    def bindsocket(self, sock, address):
29597
581c0c7cb258 chgserver: refactor initialization of real/base addresses
Yuya Nishihara <yuya@tcha.org>
parents: 29596
diff changeset
   552
        self._inithashstate(address)
29545
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   553
        self._checkextensions()
29547
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   554
        self._bind(sock)
29545
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   555
        self._createsymlink()
32277
1ada3d18e7fb commandserver: move printbanner logic to bindsocket
Jun Wu <quark@fb.com>
parents: 32276
diff changeset
   556
        # no "listening at" message should be printed to simulate hg behavior
29545
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   557
29597
581c0c7cb258 chgserver: refactor initialization of real/base addresses
Yuya Nishihara <yuya@tcha.org>
parents: 29596
diff changeset
   558
    def _inithashstate(self, address):
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   559
        self._baseaddress = address
33499
0407a51b9d8c codemod: register core configitems using a script
Jun Wu <quark@fb.com>
parents: 32311
diff changeset
   560
        if self.ui.configbool('chgserver', 'skiphash'):
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   561
            self._hashstate = None
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   562
            self._realaddress = address
29545
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   563
            return
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   564
        self._hashstate = hashstate.fromui(self.ui)
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   565
        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
   566
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   567
    def _checkextensions(self):
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   568
        if not self._hashstate:
29545
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   569
            return
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   570
        if extensions.notloaded():
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   571
            # 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
   572
            # 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
   573
            # 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
   574
            self._hashstate.mtimehash = ''
29545
28aca3fafc2a chgserver: reorder service classes to make future patches readable
Yuya Nishihara <yuya@tcha.org>
parents: 29543
diff changeset
   575
29547
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   576
    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
   577
        # 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
   578
        # check later
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   579
        tempaddress = _tempaddress(self._realaddress)
29547
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   580
        util.bindunixsocket(sock, tempaddress)
29529
02de1dbd4f6e chgserver: narrow scope of chdir() to socket.bind()
Yuya Nishihara <yuya@tcha.org>
parents: 29513
diff changeset
   581
        self._socketstat = os.stat(tempaddress)
32276
c8b9943c07eb commandserver: move "listen" responsibility from service to handler
Jun Wu <quark@fb.com>
parents: 32248
diff changeset
   582
        sock.listen(socket.SOMAXCONN)
29529
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:
36789
ffa3026d4196 cleanup: use stat_result[stat.ST_MTIME] instead of stat_result.st_mtime
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   596
            st = os.stat(self._realaddress)
ffa3026d4196 cleanup: use stat_result[stat.ST_MTIME] instead of stat_result.st_mtime
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   597
            return (st.st_ino == self._socketstat.st_ino and
ffa3026d4196 cleanup: use stat_result[stat.ST_MTIME] instead of stat_result.st_mtime
Augie Fackler <augie@google.com>
parents: 35582
diff changeset
   598
                    st[stat.ST_MTIME] == self._socketstat[stat.ST_MTIME])
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
   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.
31551
82b3ec04b652 chgserver: use tryunlink
Ryan McElroy <rmcelroy@fb.com>
parents: 31125
diff changeset
   609
        util.tryunlink(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
   610
29596
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   611
    def shouldexit(self):
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   612
        if not self._issocketowner():
40846
25e9089c7686 commandserver: turn server debug messages into logs
Yuya Nishihara <yuya@tcha.org>
parents: 40843
diff changeset
   613
            self.ui.log(b'chgserver', b'%s is not owned, exiting.\n',
25e9089c7686 commandserver: turn server debug messages into logs
Yuya Nishihara <yuya@tcha.org>
parents: 40843
diff changeset
   614
                        self._realaddress)
29596
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   615
            return True
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   616
        if time.time() - self._lastactive > self._idletimeout:
40846
25e9089c7686 commandserver: turn server debug messages into logs
Yuya Nishihara <yuya@tcha.org>
parents: 40843
diff changeset
   617
            self.ui.log(b'chgserver', b'being idle too long. exiting.\n')
29596
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   618
            return True
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   619
        return False
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   620
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   621
    def newconnection(self):
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   622
        self._lastactive = time.time()
29596
71c197d82b7e chgserver: reorder functions in chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29595
diff changeset
   623
40893
e7110f44ee2d commandserver: pass around option to hook repo instance creation
Yuya Nishihara <yuya@tcha.org>
parents: 40846
diff changeset
   624
    def createcmdserver(self, repo, conn, fin, fout, prereposetups):
e7110f44ee2d commandserver: pass around option to hook repo instance creation
Yuya Nishihara <yuya@tcha.org>
parents: 40846
diff changeset
   625
        return chgcmdserver(self.ui, repo, fin, fout, conn, prereposetups,
29598
a67398726747 chgserver: rename private functions and variables of chgunixservicehandler
Yuya Nishihara <yuya@tcha.org>
parents: 29597
diff changeset
   626
                            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
   627
29546
a7513390a9db chgserver: extract stub factory of service object
Yuya Nishihara <yuya@tcha.org>
parents: 29545
diff changeset
   628
def chgunixservice(ui, repo, opts):
33881
3cfc9070245f demandimport: disable if chg is being used
Jun Wu <quark@fb.com>
parents: 33499
diff changeset
   629
    # CHGINTERNALMARK is set by chg client. It is an indication of things are
3cfc9070245f demandimport: disable if chg is being used
Jun Wu <quark@fb.com>
parents: 33499
diff changeset
   630
    # started by chg so other code can do things accordingly, like disabling
3cfc9070245f demandimport: disable if chg is being used
Jun Wu <quark@fb.com>
parents: 33499
diff changeset
   631
    # demandimport or detecting chg client started by chg client. When executed
3cfc9070245f demandimport: disable if chg is being used
Jun Wu <quark@fb.com>
parents: 33499
diff changeset
   632
    # here, CHGINTERNALMARK is no longer useful and hence dropped to make
3cfc9070245f demandimport: disable if chg is being used
Jun Wu <quark@fb.com>
parents: 33499
diff changeset
   633
    # environ cleaner.
30640
a150173da1c1 py3: replace os.environ with encoding.environ (part 2 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30624
diff changeset
   634
    if 'CHGINTERNALMARK' in encoding.environ:
a150173da1c1 py3: replace os.environ with encoding.environ (part 2 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30624
diff changeset
   635
        del encoding.environ['CHGINTERNALMARK']
30520
1873563e1ede chgserver: drop CHGINTERNALMARK by chgunixservice()
Yuya Nishihara <yuya@tcha.org>
parents: 30516
diff changeset
   636
29546
a7513390a9db chgserver: extract stub factory of service object
Yuya Nishihara <yuya@tcha.org>
parents: 29545
diff changeset
   637
    if repo:
30342
318a24b52eeb spelling: fixes of non-dictionary words
Mads Kiilerich <madski@unity3d.com>
parents: 29852
diff changeset
   638
        # 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
   639
        ui.setconfig('bundle', 'mainreporoot', '', 'repo')
29547
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   640
    h = chgunixservicehandler(ui)
300318b7d66d chgserver: switch to new forking service
Yuya Nishihara <yuya@tcha.org>
parents: 29546
diff changeset
   641
    return commandserver.unixforkingservice(ui, repo=None, opts=opts, handler=h)