hgext/factotum.py
author Gregory Szorc <gregory.szorc@gmail.com>
Sun, 20 Apr 2014 14:04:37 -0700
changeset 21440 ece127734db1
parent 21228 be561a622100
child 23393 c834c0194dbb
permissions -rw-r--r--
run-tests: don't print progress from Test when in unittest mode unittest does its own printing of progress indicators as part of TestResult. So, there is no need to print them when running in unittest mode. This will fix the double output of progress indicators that had been occurring in unittest mode.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
16383
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
     1
# factotum.py - Plan 9 factotum integration for Mercurial
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
     2
#
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
     3
# Copyright (C) 2012 Steven Stallion <sstallion@gmail.com>
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
     4
#
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
     5
# This program is free software; you can redistribute it and/or modify it
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
     6
# under the terms of the GNU General Public License as published by the
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
     7
# Free Software Foundation; either version 2 of the License, or (at your
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
     8
# option) any later version.
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
     9
#
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    10
# This program is distributed in the hope that it will be useful, but
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    11
# WITHOUT ANY WARRANTY; without even the implied warranty of
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    13
# Public License for more details.
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    14
#
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    15
# You should have received a copy of the GNU General Public License along
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    16
# with this program; if not, write to the Free Software Foundation, Inc.,
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    17
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    18
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    19
'''http authentication with factotum
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    20
16582
cbb916e2d7c5 factotum: add man reference to help output
Steven Stallion <sstallion@gmail.com>
parents: 16463
diff changeset
    21
This extension allows the factotum(4) facility on Plan 9 from Bell Labs
cbb916e2d7c5 factotum: add man reference to help output
Steven Stallion <sstallion@gmail.com>
parents: 16463
diff changeset
    22
platforms to provide authentication information for HTTP access. Configuration
cbb916e2d7c5 factotum: add man reference to help output
Steven Stallion <sstallion@gmail.com>
parents: 16463
diff changeset
    23
entries specified in the auth section as well as authentication information
cbb916e2d7c5 factotum: add man reference to help output
Steven Stallion <sstallion@gmail.com>
parents: 16463
diff changeset
    24
provided in the repository URL are fully supported. If no prefix is specified,
cbb916e2d7c5 factotum: add man reference to help output
Steven Stallion <sstallion@gmail.com>
parents: 16463
diff changeset
    25
a value of "*" will be assumed.
16383
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    26
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    27
By default, keys are specified as::
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    28
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    29
  proto=pass service=hg prefix=<prefix> user=<username> !password=<password>
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    30
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    31
If the factotum extension is unable to read the required key, one will be
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    32
requested interactively.
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    33
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    34
A configuration section is available to customize runtime behavior. By
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    35
default, these entries are::
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    36
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    37
  [factotum]
16463
cef755f86d5c factotum: rename mount and path configuration entries
Steven Stallion <sstallion@gmail.com>
parents: 16383
diff changeset
    38
  executable = /bin/auth/factotum
cef755f86d5c factotum: rename mount and path configuration entries
Steven Stallion <sstallion@gmail.com>
parents: 16383
diff changeset
    39
  mountpoint = /mnt/factotum
16383
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    40
  service = hg
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    41
16463
cef755f86d5c factotum: rename mount and path configuration entries
Steven Stallion <sstallion@gmail.com>
parents: 16383
diff changeset
    42
The executable entry defines the full path to the factotum binary. The
cef755f86d5c factotum: rename mount and path configuration entries
Steven Stallion <sstallion@gmail.com>
parents: 16383
diff changeset
    43
mountpoint entry defines the path to the factotum file service. Lastly, the
cef755f86d5c factotum: rename mount and path configuration entries
Steven Stallion <sstallion@gmail.com>
parents: 16383
diff changeset
    44
service entry controls the service name used when reading keys.
16383
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    45
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    46
'''
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    47
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    48
from mercurial.i18n import _
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    49
from mercurial.url import passwordmgr
18647
c1d23b4a66d5 factotum: fix urllib2 import so it no longer relies on a demandimport bug
Mads Kiilerich <mads@kiilerich.com>
parents: 16582
diff changeset
    50
from mercurial import httpconnection, util
c1d23b4a66d5 factotum: fix urllib2 import so it no longer relies on a demandimport bug
Mads Kiilerich <mads@kiilerich.com>
parents: 16582
diff changeset
    51
import os, urllib2
16383
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    52
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    53
ERRMAX = 128
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    54
21228
be561a622100 factotum: initialize global variables to suppress pyflakes warning
Yuya Nishihara <yuya@tcha.org>
parents: 19614
diff changeset
    55
_executable = _mountpoint = _service = None
be561a622100 factotum: initialize global variables to suppress pyflakes warning
Yuya Nishihara <yuya@tcha.org>
parents: 19614
diff changeset
    56
16383
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    57
def auth_getkey(self, params):
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    58
    if not self.ui.interactive():
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    59
        raise util.Abort(_('factotum not interactive'))
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    60
    if 'user=' not in params:
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    61
        params = '%s user?' % params
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    62
    params = '%s !password?' % params
16463
cef755f86d5c factotum: rename mount and path configuration entries
Steven Stallion <sstallion@gmail.com>
parents: 16383
diff changeset
    63
    os.system("%s -g '%s'" % (_executable, params))
16383
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    64
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    65
def auth_getuserpasswd(self, getkey, params):
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    66
    params = 'proto=pass %s' % params
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    67
    while True:
16463
cef755f86d5c factotum: rename mount and path configuration entries
Steven Stallion <sstallion@gmail.com>
parents: 16383
diff changeset
    68
        fd = os.open('%s/rpc' % _mountpoint, os.O_RDWR)
16383
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    69
        try:
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    70
            try:
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    71
                os.write(fd, 'start %s' % params)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    72
                l = os.read(fd, ERRMAX).split()
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    73
                if l[0] == 'ok':
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    74
                    os.write(fd, 'read')
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    75
                    l = os.read(fd, ERRMAX).split()
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    76
                    if l[0] == 'ok':
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    77
                        return l[1:]
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    78
            except (OSError, IOError):
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    79
                raise util.Abort(_('factotum not responding'))
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    80
        finally:
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    81
            os.close(fd)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    82
        getkey(self, params)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    83
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    84
def monkeypatch_method(cls):
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    85
    def decorator(func):
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    86
        setattr(cls, func.__name__, func)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    87
        return func
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    88
    return decorator
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    89
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    90
@monkeypatch_method(passwordmgr)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    91
def find_user_password(self, realm, authuri):
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    92
    user, passwd = urllib2.HTTPPasswordMgrWithDefaultRealm.find_user_password(
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    93
        self, realm, authuri)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    94
    if user and passwd:
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    95
        self._writedebug(user, passwd)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    96
        return (user, passwd)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    97
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    98
    prefix = ''
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    99
    res = httpconnection.readauthforuri(self.ui, authuri, user)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   100
    if res:
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   101
        _, auth = res
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   102
        prefix = auth.get('prefix')
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   103
        user, passwd = auth.get('username'), auth.get('password')
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   104
    if not user or not passwd:
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   105
        if not prefix:
19614
1d50c69c1f0a factotum: clean up keychain for multiple hg repository authentication
Jeff Sickel <jas@corpus-callosum.com>
parents: 18647
diff changeset
   106
            prefix = realm.split(' ')[0].lower()
16383
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   107
        params = 'service=%s prefix=%s' % (_service, prefix)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   108
        if user:
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   109
            params = '%s user=%s' % (params, user)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   110
        user, passwd = auth_getuserpasswd(self, auth_getkey, params)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   111
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   112
    self.add_password(realm, authuri, user, passwd)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   113
    self._writedebug(user, passwd)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   114
    return (user, passwd)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   115
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   116
def uisetup(ui):
16463
cef755f86d5c factotum: rename mount and path configuration entries
Steven Stallion <sstallion@gmail.com>
parents: 16383
diff changeset
   117
    global _executable
cef755f86d5c factotum: rename mount and path configuration entries
Steven Stallion <sstallion@gmail.com>
parents: 16383
diff changeset
   118
    _executable = ui.config('factotum', 'executable', '/bin/auth/factotum')
cef755f86d5c factotum: rename mount and path configuration entries
Steven Stallion <sstallion@gmail.com>
parents: 16383
diff changeset
   119
    global _mountpoint
cef755f86d5c factotum: rename mount and path configuration entries
Steven Stallion <sstallion@gmail.com>
parents: 16383
diff changeset
   120
    _mountpoint = ui.config('factotum', 'mountpoint', '/mnt/factotum')
16383
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   121
    global _service
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   122
    _service = ui.config('factotum', 'service', 'hg')