Show More
@@ -1,8 +1,8 b'' | |||||
1 | .. -*- mode: rst; compile-command: "rst2html README.txt README.html" -*- |
|
1 | .. -*- mode: rst; compile-command: "rst2html README.txt README.html" -*- | |
2 |
|
2 | |||
3 | ================= |
|
3 | ======================================================= | |
4 | Mercurial Keyring |
|
4 | Mercurial Keyring | |
5 | ================= |
|
5 | ======================================================= | |
6 |
|
6 | |||
7 | Mercurial Keyring is a Mercurial_ extension used to securely save HTTP |
|
7 | Mercurial Keyring is a Mercurial_ extension used to securely save HTTP | |
8 | and SMTP authentication passwords in password databases (Gnome |
|
8 | and SMTP authentication passwords in password databases (Gnome | |
@@ -25,7 +25,7 b' extension glues it to Mercurial.' | |||||
25 | .. _Mercurial: http://mercurial.selenic.com |
|
25 | .. _Mercurial: http://mercurial.selenic.com | |
26 |
|
26 | |||
27 | How does it work |
|
27 | How does it work | |
28 | ================ |
|
28 | ======================================================= | |
29 |
|
29 | |||
30 | On your first pull or push to HTTP url (or first email sent via given |
|
30 | On your first pull or push to HTTP url (or first email sent via given | |
31 | SMTP server), you are prompted for the password, just like bare |
|
31 | SMTP server), you are prompted for the password, just like bare | |
@@ -35,15 +35,15 b' needed, ``mercurial_keyring`` checks for' | |||||
35 | database, and uses it without troubling you. |
|
35 | database, and uses it without troubling you. | |
36 |
|
36 | |||
37 | In case password turns out to be incorrect (for example, because you |
|
37 | In case password turns out to be incorrect (for example, because you | |
38 |
changed it, or entered it incorrectly), ``mercurial_keyring`` |
|
38 | changed it, or entered it incorrectly), ``mercurial_keyring`` prompts | |
39 | it, and prompts you again. |
|
39 | you again, and overwrites the password. | |
40 |
|
40 | |||
41 | You can use many passwords (for various remote urls). Saved passwords |
|
41 | You can use many passwords (for various remote urls). Saved passwords | |
42 | are identified by pair of username and url prefix. See below for |
|
42 | are identified by pair of username and url prefix. See below for | |
43 | information how to configure those properly. |
|
43 | information how to configure those properly. | |
44 |
|
44 | |||
45 | Installation |
|
45 | Installation | |
46 | ============ |
|
46 | ======================================================= | |
47 |
|
47 | |||
48 | Prerequisites |
|
48 | Prerequisites | |
49 | ------------- |
|
49 | ------------- | |
@@ -108,7 +108,7 b' and configure Mercurial by telling it fu' | |||||
108 | .. _mercurial_keyring.py: http://bitbucket.org/Mekk/mercurial_keyring/src/tip/mercurial_keyring.py |
|
108 | .. _mercurial_keyring.py: http://bitbucket.org/Mekk/mercurial_keyring/src/tip/mercurial_keyring.py | |
109 |
|
109 | |||
110 | Password backend configuration |
|
110 | Password backend configuration | |
111 | ============================== |
|
111 | ======================================================= | |
112 |
|
112 | |||
113 | The library should usually pick the most appropriate password backend |
|
113 | The library should usually pick the most appropriate password backend | |
114 | without configuration. Still, if necessary, it can be configured using |
|
114 | without configuration. Still, if necessary, it can be configured using | |
@@ -128,7 +128,7 b' without configuration. Still, if necessa' | |||||
128 |
|
128 | |||
129 |
|
129 | |||
130 | ``hgrc`` configuration (HTTP) |
|
130 | ``hgrc`` configuration (HTTP) | |
131 | =============================== |
|
131 | ======================================================= | |
132 |
|
132 | |||
133 | Mercurial Keyring uses standard Mercurial ``[auth]`` configuration to |
|
133 | Mercurial Keyring uses standard Mercurial ``[auth]`` configuration to | |
134 | detect your username (on given remote) and url prefix. You are |
|
134 | detect your username (on given remote) and url prefix. You are | |
@@ -214,7 +214,7 b' Additional advantage of this method is t' | |||||
214 |
|
214 | |||
215 |
|
215 | |||
216 | ``hgrc`` configuration (SMTP) |
|
216 | ``hgrc`` configuration (SMTP) | |
217 | =============================== |
|
217 | ======================================================= | |
218 |
|
218 | |||
219 | Edit either repository-local ``.hg/hgrc``, or ``~/.hgrc`` and set |
|
219 | Edit either repository-local ``.hg/hgrc``, or ``~/.hgrc`` and set | |
220 | there all standard email and smtp properties, including SMTP |
|
220 | there all standard email and smtp properties, including SMTP | |
@@ -237,7 +237,10 b' password here to use the extension, in o' | |||||
237 | the default behavior. |
|
237 | the default behavior. | |
238 |
|
238 | |||
239 | Usage |
|
239 | Usage | |
240 | ===== |
|
240 | ====================================================== | |
|
241 | ||||
|
242 | Saving and restoring passwords | |||
|
243 | ------------------------------------------------------- | |||
241 |
|
244 | |||
242 | Configure the repository as above, then just ``hg pull``, ``hg push``, |
|
245 | Configure the repository as above, then just ``hg pull``, ``hg push``, | |
243 | etc. You should be asked for the password only once (per every |
|
246 | etc. You should be asked for the password only once (per every | |
@@ -247,27 +250,61 b' Similarly, for email, configure as above' | |||||
247 | Again, you will be asked for the password once (per every username and |
|
250 | Again, you will be asked for the password once (per every username and | |
248 | email server address combination). |
|
251 | email server address combination). | |
249 |
|
252 | |||
|
253 | Checking password status (``hg keyring_check``) | |||
|
254 | ------------------------------------------------------- | |||
|
255 | ||||
|
256 | The ``keyring_check`` command can be used to check whether/which | |||
|
257 | password(s) are saved. It can be used in three ways: | |||
|
258 | ||||
|
259 | - without parameters, it prints info related to all HTTP paths | |||
|
260 | defined for current repository (everything from ``hg paths`` | |||
|
261 | that resolves to HTTP url):: | |||
|
262 | ||||
|
263 | hg keyring_check | |||
|
264 | ||||
|
265 | - given alias as param, it prints info about this alias:: | |||
|
266 | ||||
|
267 | hg keyring_check work | |||
|
268 | ||||
|
269 | - finally, any path can be checked:: | |||
|
270 | ||||
|
271 | hg keyring_check https://bitbucket.org/Mekk/mercurial_keyring | |||
|
272 | ||||
|
273 | Deleting saved password (``hg keyring_clear``) | |||
|
274 | ------------------------------------------------------- | |||
|
275 | ||||
|
276 | The ``keyring_clear`` command removes saved password related to given | |||
|
277 | path. It can be used in two ways: | |||
|
278 | ||||
|
279 | - given alias as param, it drops password used by this alias:: | |||
|
280 | ||||
|
281 | hg keyring_clear work | |||
|
282 | ||||
|
283 | - given full path, it drops password related to this path:: | |||
|
284 | ||||
|
285 | hg keyring_clear https://bitbucket.org/Mekk/mercurial_keyring | |||
|
286 | ||||
250 | Implementation details |
|
287 | Implementation details | |
251 | ====================== |
|
288 | ======================================================= | |
252 |
|
289 | |||
253 | The extension is monkey-patching the mercurial ``passwordmgr`` class |
|
290 | The extension is monkey-patching the mercurial ``passwordmgr`` class | |
254 | to replace the ``find_user_password`` method. Detailed order of operations |
|
291 | to replace the ``find_user_password`` method. Detailed order of operations | |
255 | is described in the comments inside `the code`_. |
|
292 | is described in the comments inside `the code`_. | |
256 |
|
293 | |||
257 | History |
|
294 | History | |
258 | ========== |
|
295 | ======================================================= | |
259 |
|
296 | |||
260 | See `HISTORY.txt`_. |
|
297 | See `HISTORY.txt`_. | |
261 |
|
298 | |||
262 | Development |
|
299 | Development | |
263 | =========== |
|
300 | ======================================================= | |
264 |
|
301 | |||
265 | Development is tracked on BitBucket, see |
|
302 | Development is tracked on BitBucket, see | |
266 | http://bitbucket.org/Mekk/mercurial_keyring/ |
|
303 | http://bitbucket.org/Mekk/mercurial_keyring/ | |
267 |
|
304 | |||
268 |
|
305 | |||
269 | Additional notes |
|
306 | Additional notes | |
270 | ================ |
|
307 | ======================================================= | |
271 |
|
308 | |||
272 | Information about this extension is also available |
|
309 | Information about this extension is also available | |
273 | on Mercurial Wiki: http://mercurial.selenic.com/wiki/KeyringExtension |
|
310 | on Mercurial Wiki: http://mercurial.selenic.com/wiki/KeyringExtension |
@@ -64,6 +64,7 b' import smtplib' | |||||
64 | import socket |
|
64 | import socket | |
65 | import os |
|
65 | import os | |
66 | import sys |
|
66 | import sys | |
|
67 | import re | |||
67 |
|
68 | |||
68 | # pylint: disable=invalid-name, line-too-long, protected-access, too-many-arguments |
|
69 | # pylint: disable=invalid-name, line-too-long, protected-access, too-many-arguments | |
69 |
|
70 | |||
@@ -677,14 +678,17 b' def _smtp(ui):' | |||||
677 | # Custom commands |
|
678 | # Custom commands | |
678 | ############################################################ |
|
679 | ############################################################ | |
679 |
|
680 | |||
680 | def cmd_keyring_check(ui, repo, *path_args, **opts): |
|
681 | _re_http_url = re.compile(r'^https?://') | |
|
682 | ||||
|
683 | def is_http_path(url): | |||
|
684 | return bool(_re_http_url.search(url)) | |||
|
685 | ||||
|
686 | ||||
|
687 | def cmd_keyring_check(ui, repo, *path_args, **opts): # pylint: disable=unused-argument | |||
681 | """ |
|
688 | """ | |
682 | Prints basic info (whether password is currently saved, and how is |
|
689 | Prints basic info (whether password is currently saved, and how is | |
683 | it identified) for given path or for all defined repo paths which are HTTP. |
|
690 | it identified) for given path or for all defined repo paths which are HTTP. | |
684 | """ |
|
691 | """ | |
685 | import re |
|
|||
686 |
|
||||
687 | re_http_url = re.compile(r'^https?://') |
|
|||
688 | defined_paths = [(name, url) |
|
692 | defined_paths = [(name, url) | |
689 | for name, url in ui.configitems('paths')] |
|
693 | for name, url in ui.configitems('paths')] | |
690 | if path_args: |
|
694 | if path_args: | |
@@ -696,17 +700,18 b' def cmd_keyring_check(ui, repo, *path_ar' | |||||
696 | paths = [(name, url) for name, url in defined_paths] |
|
700 | paths = [(name, url) for name, url in defined_paths] | |
697 |
|
701 | |||
698 | if not paths: |
|
702 | if not paths: | |
699 | ui.status(_("keyring_check: no paths defined")) |
|
703 | ui.status(_("keyring_check: no paths defined\n")) | |
700 |
|
704 | |||
701 | handler = HTTPPasswordHandler() |
|
705 | handler = HTTPPasswordHandler() | |
702 |
|
706 | |||
703 | ui.status(_("keyring password save status:\n")) |
|
707 | ui.status(_("keyring password save status:\n")) | |
704 | for name, url in paths: |
|
708 | for name, url in paths: | |
705 |
if not |
|
709 | if not is_http_path(url): | |
706 | if path_args: |
|
710 | if path_args: | |
707 | ui.status(_(" %s: non-http path (%s)\n") % (name, url)) |
|
711 | ui.status(_(" %s: non-http path (%s)\n") % (name, url)) | |
708 | continue |
|
712 | continue | |
709 |
user, pwd, source, final_url = handler.get_credentials( |
|
713 | user, pwd, source, final_url = handler.get_credentials( | |
|
714 | passwordmgr(ui), name, url) | |||
710 | if pwd: |
|
715 | if pwd: | |
711 | ui.status(_(" %s: password available, source: %s, bound to user %s, url %s\n") % ( |
|
716 | ui.status(_(" %s: password available, source: %s, bound to user %s, url %s\n") % ( | |
712 | name, source, user, final_url)) |
|
717 | name, source, user, final_url)) | |
@@ -718,12 +723,38 b' def cmd_keyring_check(ui, repo, *path_ar' | |||||
718 | name, final_url)) |
|
723 | name, final_url)) | |
719 |
|
724 | |||
720 |
|
725 | |||
721 | def cmd_keyring_clear(ui, repo, path, **opts): |
|
726 | def cmd_keyring_clear(ui, repo, path, **opts): # pylint: disable=unused-argument | |
|
727 | """ | |||
|
728 | Drops password bound to given path (if any is saved). | |||
722 |
|
|
729 | """ | |
723 | Drops password bound to given path (if any). |
|
730 | path_url = path | |
724 | """ |
|
731 | for name, url in ui.configitems('paths'): | |
725 | # TODO |
|
732 | if name == path: | |
726 | ui.status(_("Not yet implemented")) |
|
733 | path_url = url | |
|
734 | break | |||
|
735 | if not is_http_path(path_url): | |||
|
736 | ui.warn(_("%s is not a http path (%s)") % (path, path_url)) | |||
|
737 | return | |||
|
738 | ||||
|
739 | handler = HTTPPasswordHandler() | |||
|
740 | ||||
|
741 | user, pwd, source, final_url = handler.get_credentials( | |||
|
742 | passwordmgr(ui), path, path_url) | |||
|
743 | if not user: | |||
|
744 | ui.status(_("Username not configured for url %s\n") % final_url) | |||
|
745 | return | |||
|
746 | if not pwd: | |||
|
747 | ui.status(_("No password is saved for user %s, url %s\n") % ( | |||
|
748 | user, final_url)) | |||
|
749 | return | |||
|
750 | ||||
|
751 | if source != handler.SRC_KEYRING: | |||
|
752 | ui.status(_("Password for user %s, url %s is saved in %s, not in keyring\n") % ( | |||
|
753 | user, final_url, source)) | |||
|
754 | ||||
|
755 | password_store.clear_http_password(final_url, user) | |||
|
756 | ui.status(_("Password removed for user %s, url %s\n") % ( | |||
|
757 | user, final_url)) | |||
727 |
|
758 | |||
728 |
|
759 | |||
729 | cmdtable = { |
|
760 | cmdtable = { |
General Comments 0
You need to be logged in to leave comments.
Login now