# HG changeset patch # User Marcin Kasperski # Date 2015-11-13 20:42:46 # Node ID 03cb673d2a832008f5df47923d7da8c53f91e3f7 # Parent ed776eb571d5bd4d1ac4487527914fe03c4e1853 #45 Added hg keyring_clear diff --git a/README.txt b/README.txt --- a/README.txt +++ b/README.txt @@ -1,8 +1,8 @@ .. -*- mode: rst; compile-command: "rst2html README.txt README.html" -*- -================= +======================================================= Mercurial Keyring -================= +======================================================= Mercurial Keyring is a Mercurial_ extension used to securely save HTTP and SMTP authentication passwords in password databases (Gnome @@ -25,7 +25,7 @@ extension glues it to Mercurial. .. _Mercurial: http://mercurial.selenic.com How does it work -================ +======================================================= On your first pull or push to HTTP url (or first email sent via given SMTP server), you are prompted for the password, just like bare @@ -35,15 +35,15 @@ needed, ``mercurial_keyring`` checks for database, and uses it without troubling you. In case password turns out to be incorrect (for example, because you -changed it, or entered it incorrectly), ``mercurial_keyring`` wipes -it, and prompts you again. +changed it, or entered it incorrectly), ``mercurial_keyring`` prompts +you again, and overwrites the password. You can use many passwords (for various remote urls). Saved passwords are identified by pair of username and url prefix. See below for information how to configure those properly. Installation -============ +======================================================= Prerequisites ------------- @@ -108,7 +108,7 @@ and configure Mercurial by telling it fu .. _mercurial_keyring.py: http://bitbucket.org/Mekk/mercurial_keyring/src/tip/mercurial_keyring.py Password backend configuration -============================== +======================================================= The library should usually pick the most appropriate password backend without configuration. Still, if necessary, it can be configured using @@ -128,7 +128,7 @@ without configuration. Still, if necessa ``hgrc`` configuration (HTTP) -=============================== +======================================================= Mercurial Keyring uses standard Mercurial ``[auth]`` configuration to detect your username (on given remote) and url prefix. You are @@ -214,7 +214,7 @@ Additional advantage of this method is t ``hgrc`` configuration (SMTP) -=============================== +======================================================= Edit either repository-local ``.hg/hgrc``, or ``~/.hgrc`` and set there all standard email and smtp properties, including SMTP @@ -237,7 +237,10 @@ password here to use the extension, in o the default behavior. Usage -===== +====================================================== + +Saving and restoring passwords +------------------------------------------------------- Configure the repository as above, then just ``hg pull``, ``hg push``, etc. You should be asked for the password only once (per every @@ -247,27 +250,61 @@ Similarly, for email, configure as above Again, you will be asked for the password once (per every username and email server address combination). +Checking password status (``hg keyring_check``) +------------------------------------------------------- + +The ``keyring_check`` command can be used to check whether/which +password(s) are saved. It can be used in three ways: + +- without parameters, it prints info related to all HTTP paths + defined for current repository (everything from ``hg paths`` + that resolves to HTTP url):: + + hg keyring_check + +- given alias as param, it prints info about this alias:: + + hg keyring_check work + +- finally, any path can be checked:: + + hg keyring_check https://bitbucket.org/Mekk/mercurial_keyring + +Deleting saved password (``hg keyring_clear``) +------------------------------------------------------- + +The ``keyring_clear`` command removes saved password related to given +path. It can be used in two ways: + +- given alias as param, it drops password used by this alias:: + + hg keyring_clear work + +- given full path, it drops password related to this path:: + + hg keyring_clear https://bitbucket.org/Mekk/mercurial_keyring + Implementation details -====================== +======================================================= The extension is monkey-patching the mercurial ``passwordmgr`` class to replace the ``find_user_password`` method. Detailed order of operations is described in the comments inside `the code`_. History -========== +======================================================= See `HISTORY.txt`_. Development -=========== +======================================================= Development is tracked on BitBucket, see http://bitbucket.org/Mekk/mercurial_keyring/ Additional notes -================ +======================================================= Information about this extension is also available on Mercurial Wiki: http://mercurial.selenic.com/wiki/KeyringExtension diff --git a/mercurial_keyring.py b/mercurial_keyring.py --- a/mercurial_keyring.py +++ b/mercurial_keyring.py @@ -64,6 +64,7 @@ import smtplib import socket import os import sys +import re # pylint: disable=invalid-name, line-too-long, protected-access, too-many-arguments @@ -677,14 +678,17 @@ def _smtp(ui): # Custom commands ############################################################ -def cmd_keyring_check(ui, repo, *path_args, **opts): +_re_http_url = re.compile(r'^https?://') + +def is_http_path(url): + return bool(_re_http_url.search(url)) + + +def cmd_keyring_check(ui, repo, *path_args, **opts): # pylint: disable=unused-argument """ Prints basic info (whether password is currently saved, and how is it identified) for given path or for all defined repo paths which are HTTP. """ - import re - - re_http_url = re.compile(r'^https?://') defined_paths = [(name, url) for name, url in ui.configitems('paths')] if path_args: @@ -696,17 +700,18 @@ def cmd_keyring_check(ui, repo, *path_ar paths = [(name, url) for name, url in defined_paths] if not paths: - ui.status(_("keyring_check: no paths defined")) + ui.status(_("keyring_check: no paths defined\n")) handler = HTTPPasswordHandler() ui.status(_("keyring password save status:\n")) for name, url in paths: - if not re_http_url.search(url): + if not is_http_path(url): if path_args: ui.status(_(" %s: non-http path (%s)\n") % (name, url)) continue - user, pwd, source, final_url = handler.get_credentials(passwordmgr(ui), name, url) + user, pwd, source, final_url = handler.get_credentials( + passwordmgr(ui), name, url) if pwd: ui.status(_(" %s: password available, source: %s, bound to user %s, url %s\n") % ( name, source, user, final_url)) @@ -718,12 +723,38 @@ def cmd_keyring_check(ui, repo, *path_ar name, final_url)) -def cmd_keyring_clear(ui, repo, path, **opts): +def cmd_keyring_clear(ui, repo, path, **opts): # pylint: disable=unused-argument + """ + Drops password bound to given path (if any is saved). """ - Drops password bound to given path (if any). - """ - # TODO - ui.status(_("Not yet implemented")) + path_url = path + for name, url in ui.configitems('paths'): + if name == path: + path_url = url + break + if not is_http_path(path_url): + ui.warn(_("%s is not a http path (%s)") % (path, path_url)) + return + + handler = HTTPPasswordHandler() + + user, pwd, source, final_url = handler.get_credentials( + passwordmgr(ui), path, path_url) + if not user: + ui.status(_("Username not configured for url %s\n") % final_url) + return + if not pwd: + ui.status(_("No password is saved for user %s, url %s\n") % ( + user, final_url)) + return + + if source != handler.SRC_KEYRING: + ui.status(_("Password for user %s, url %s is saved in %s, not in keyring\n") % ( + user, final_url, source)) + + password_store.clear_http_password(final_url, user) + ui.status(_("Password removed for user %s, url %s\n") % ( + user, final_url)) cmdtable = {