Mercurial > hg > easyhg
comparison easyhg2.py @ 427:8edf76b57bd9
Alternative approach to asking for username/password
author | Chris Cannam |
---|---|
date | Thu, 23 Jun 2011 20:36:23 +0100 |
parents | |
children | a47eac9c7fea |
comparison
equal
deleted
inserted
replaced
426:8530c31536a7 | 427:8edf76b57bd9 |
---|---|
1 # -*- coding: utf-8 -*- | |
2 # | |
3 # EasyMercurial | |
4 # | |
5 # Based on hgExplorer by Jari Korhonen | |
6 # Copyright (c) 2010 Jari Korhonen | |
7 # Copyright (c) 2010 Chris Cannam | |
8 # Copyright (c) 2010 Queen Mary, University of London | |
9 # | |
10 # This program is free software; you can redistribute it and/or | |
11 # modify it under the terms of the GNU General Public License as | |
12 # published by the Free Software Foundation; either version 2 of the | |
13 # License, or (at your option) any later version. See the file | |
14 # COPYING included with this distribution for more information. | |
15 | |
16 import sys | |
17 | |
18 import urllib, urllib2, urlparse | |
19 | |
20 from mercurial import ui, getpass, util | |
21 try: | |
22 from mercurial.url import passwordmgr | |
23 except: | |
24 from mercurial.httprepo import passwordmgr | |
25 | |
26 from mercurial.i18n import _ | |
27 | |
28 #!!! do this later? as for Qt? also see notes on demandimport in mercurial_keyring | |
29 import keyring | |
30 | |
31 # The value assigned here may be modified during installation, by | |
32 # replacing its default value with another one. We can't compare | |
33 # against its default value, because then the comparison text would | |
34 # get modified as well. So, compare using prefix only. | |
35 # | |
36 easyhg_import_path = 'NO_EASYHG_IMPORT_PATH' | |
37 if not easyhg_import_path.startswith('NO_'): | |
38 # We have an installation path: append it twice, once with | |
39 # the Python version suffixed | |
40 version_suffix = "Py" + str(sys.version_info[0]) + "." + str(sys.version_info[1]); | |
41 sys.path.append(easyhg_import_path + "/" + version_suffix) | |
42 sys.path.append(easyhg_import_path) | |
43 | |
44 # Try to load the PyQt4 module that we need. If this fails, we should | |
45 # bail out later (in uisetup), because if we bail out now, Mercurial | |
46 # will just continue without us and report success. The invoking | |
47 # application needs to be able to discover whether the module load | |
48 # succeeded or not, so we need to ensure that Mercurial itself returns | |
49 # failure if it didn't. | |
50 # | |
51 easyhg_pyqt_ok = True | |
52 try: | |
53 from PyQt4 import Qt, QtGui | |
54 except ImportError: | |
55 easyhg_pyqt_ok = False | |
56 | |
57 easyhg_qtapp = None | |
58 | |
59 def monkeypatch_method(cls): | |
60 def decorator(func): | |
61 setattr(cls, func.__name__, func) | |
62 return func | |
63 return decorator | |
64 | |
65 def uisetup(ui): | |
66 if not easyhg_pyqt_ok: | |
67 raise util.Abort(_('Failed to load PyQt4 module required by easyhg.py')) | |
68 global easyhg_qtapp | |
69 easyhg_qtapp = QtGui.QApplication([]) | |
70 | |
71 orig_find = passwordmgr.find_user_password | |
72 | |
73 # from mercurial_keyring by Marcin Kasperski | |
74 def canonical_url(authuri): | |
75 """ | |
76 Strips query params from url. Used to convert urls like | |
77 https://repo.machine.com/repos/apps/module?pairs=0000000000000000000000000000000000000000-0000000000000000000000000000000000000000&cmd=between | |
78 to | |
79 https://repo.machine.com/repos/apps/module | |
80 """ | |
81 parsed_url = urlparse.urlparse(authuri) | |
82 return "%s://%s%s" % (parsed_url.scheme, parsed_url.netloc, | |
83 parsed_url.path) | |
84 | |
85 @monkeypatch_method(passwordmgr) | |
86 def find_user_password(self, realm, authuri): | |
87 | |
88 if not self.ui.interactive(): | |
89 return orig_find(self, realm, authuri) | |
90 if not easyhg_pyqt_ok: | |
91 return orig_find(self, realm, authuri) | |
92 | |
93 authinfo = urllib2.HTTPPasswordMgrWithDefaultRealm.find_user_password( | |
94 self, realm, authuri) | |
95 user, passwd = authinfo | |
96 | |
97 if user and passwd: | |
98 return orig_find(self, realm, authuri) | |
99 | |
100 self.ui.write("want username and/or password for %s\n" % authuri) | |
101 | |
102 uri = canonical_url(authuri) | |
103 | |
104 from_keyring = False | |
105 keyring_key = '' | |
106 if user and not passwd: | |
107 keyring_key = '%s@@%s' % (uri, user) | |
108 self.ui.write("keyring_key is %s" % keyring_key) | |
109 # passwd = keyring.get_password('Mercurial', keyring_key) | |
110 self.ui.write("got passwd: %s\n" % passwd) | |
111 if passwd: | |
112 from_keyring = True | |
113 | |
114 dialog = QtGui.QDialog() | |
115 layout = QtGui.QGridLayout() | |
116 dialog.setLayout(layout) | |
117 | |
118 layout.addWidget(QtGui.QLabel(_('Please supply your user name and password for\n%s:') % uri), 0, 0, 1, 2) | |
119 | |
120 userfield = QtGui.QLineEdit() | |
121 if user: | |
122 userfield.setText(user) | |
123 layout.addWidget(QtGui.QLabel(_('User:')), 1, 0) | |
124 layout.addWidget(userfield, 1, 1) | |
125 | |
126 passfield = QtGui.QLineEdit() | |
127 passfield.setEchoMode(QtGui.QLineEdit.Password) | |
128 if passwd: | |
129 userfield.setText(passwd) | |
130 layout.addWidget(QtGui.QLabel(_('Password:')), 2, 0) | |
131 layout.addWidget(passfield, 2, 1) | |
132 | |
133 bb = QtGui.QDialogButtonBox() | |
134 ok = bb.addButton(bb.Ok) | |
135 cancel = bb.addButton(bb.Cancel) | |
136 cancel.setDefault(False) | |
137 cancel.setAutoDefault(False) | |
138 ok.setDefault(True) | |
139 bb.connect(ok, Qt.SIGNAL("clicked()"), dialog, Qt.SLOT("accept()")) | |
140 bb.connect(cancel, Qt.SIGNAL("clicked()"), dialog, Qt.SLOT("reject()")) | |
141 layout.addWidget(bb, 3, 0, 1, 2) | |
142 | |
143 dialog.setWindowTitle(_('EasyMercurial: Password')) | |
144 dialog.show() | |
145 dialog.raise_() | |
146 ok = dialog.exec_() | |
147 if ok: | |
148 self.ui.write('Dialog accepted\n') | |
149 user = userfield.text() | |
150 passwd = passfield.text() | |
151 if passwd and keyring_key != '' and not from_keyring: | |
152 keyring_key = '%s@@%s' % (uri, user) | |
153 keyring.set_password('Mercurial', keyring_key, passwd) | |
154 self.add_password(realm, authuri, user, passwd) | |
155 else: | |
156 raise util.Abort(_('password entry cancelled')) | |
157 return (user, passwd) | |
158 | |
159 | |
160 |