(drak)
2013-08-07: merge operhiem1 into bab merge operhiem1 into bab
diff --git a/infocalypse/__init__.py b/infocalypse/__init__.py --- a/infocalypse/__init__.py +++ b/infocalypse/__init__.py @@ -568,7 +568,7 @@ extensions.wrapfunction(discovery, 'find # wrap the commands -def freenetpathtouri(ui, path, pull=True): +def freenetpathtouri(ui, path, repo=None, pull=True): """ Return a usable request or insert URI. Expects a freenet:// or freenet: protocol to be specified. @@ -588,9 +588,7 @@ def freenetpathtouri(ui, path, pull=True if not path.startswith("USK"): import wot if pull: - cfg = Config.from_ui(ui) - # TODO: Check for ID associated with this repo first. - truster = cfg.defaults['DEFAULT_TRUSTER'] + truster = get_truster(ui, repo) return wot.resolve_pull_uri(ui, path, truster) else: return wot.resolve_push_uri(ui, path) @@ -615,7 +613,7 @@ def freenetpull(orig, *args, **opts): # only act differently, if the target is an infocalypse repo. if not isfreenetpath(path): return orig(*args, **opts) - uri = freenetpathtouri(ui, path) + uri = freenetpathtouri(ui, path, repo) opts["uri"] = uri opts["aggressive"] = True # always search for the latest revision. return infocalypse_pull(ui, repo, **opts) @@ -652,7 +650,7 @@ def freenetpush(orig, *args, **opts): # only act differently, if the target is an infocalypse repo. if not isfreenetpath(path): return orig(*args, **opts) - uri = parse_repo_path(freenetpathtouri(ui, path, pull=False)) + uri = parse_repo_path(freenetpathtouri(ui, path, repo, pull=False)) if uri is None: return # if the uri is the short form (USK@/name/#), generate the key and preprocess the uri. @@ -703,6 +701,8 @@ def freenetclone(orig, *args, **opts): if dest.endswith(".R1") or dest.endswith(".R0"): dest = dest[:-3] + # TODO: source holds the "repo" argument, but the naming is confusing in + # the context of freenetpathtouri(). # check whether to create, pull or copy pulluri, pushuri = None, None if isfreenetpath(source): diff --git a/infocalypse/commands.py b/infocalypse/commands.py --- a/infocalypse/commands.py +++ b/infocalypse/commands.py @@ -89,8 +89,7 @@ def infocalypse_create(ui_, repo, **opts import fcp node = fcp.FCPNode() vcs_response =\ - node.fcpPluginMessage(async=False, - plugin_name="plugins.WebOfTrust.WebOfTrust", + node.fcpPluginMessage(plugin_name="plugins.WebOfTrust.WebOfTrust", plugin_params=msg_params)[0] if vcs_response['header'] != 'FCPPluginReply' or\ @@ -197,7 +196,7 @@ def infocalypse_pull(ui_, repo, **opts): request_uri = get_uri_from_hash(ui_, repo, params, stored_cfg) elif opts['wot']: import wot - truster = get_truster(ui_, repo, opts) + truster = get_truster(ui_, repo, opts['truster']) request_uri = wot.resolve_pull_uri(ui_, opts['wot'], truster) elif opts['uri']: @@ -223,7 +222,7 @@ def infocalypse_pull_request(ui, repo, * "--wot.\n") wot_id, repo_name = opts['wot'].split('/', 1) - from_identity = get_truster(ui, repo, opts) + from_identity = get_truster(ui, repo, opts['truster']) to_identity = WoT_ID(wot_id, from_identity) wot.send_pull_request(ui, repo, from_identity, to_identity, repo_name) @@ -510,23 +509,34 @@ def infocalypse_setupfreemail(ui, repo, import wot # TODO: Here --truster doesn't make sense. There is no trust involved. # TODO: Should this be part of the normal fn-setup? - wot.execute_setup_freemail(ui, get_truster(ui, repo, opts)) + wot.execute_setup_freemail(ui, get_truster(ui, repo, opts['truster'])) -def get_truster(ui, repo, opts): +def get_truster(ui, repo=None, truster_identifier=None): """ - Return a local WoT ID - either one that published this repository or the - default. + Return a local WoT ID. + + Search for a local identity from most to least specific: + 1. truster_identifier (if given) + 2. identity that published this respository (if repo is given and an + identity is set) + 3. default truster + :rtype : Local_WoT_ID """ from wot_id import Local_WoT_ID - if opts['truster']: - return Local_WoT_ID(opts['truster']) + if truster_identifier: + return Local_WoT_ID(truster_identifier) else: - cfg = Config().from_ui(ui) + cfg = Config.from_ui(ui) - # Value is identity ID. - identity = cfg.get_wot_identity(cfg.get_request_uri(repo.root)) + # Value is identity ID, so '@' prefix makes it an identifier with an + # empty nickname. + identity = None + if repo: + identity = cfg.get_wot_identity(cfg.get_request_uri(repo.root)) + + # Either repo is not given or there is no associated identity. if not identity: identity = cfg.defaults['DEFAULT_TRUSTER'] diff --git a/infocalypse/devnotes.txt b/infocalypse/devnotes.txt --- a/infocalypse/devnotes.txt +++ b/infocalypse/devnotes.txt @@ -9,14 +9,8 @@ WoT identifier - Web of Trust identifier. This is MyNickname@public-key-hash. Often abbreviated "wot_id". Not to be confused with a WoT identity. -WoT identity - +WoT identity ID - name given to the public key hash when returned by WoT. - Can also refer to a dictionary containing the Identity and - other attributes such as a request URI and contexts. - - TODO: Apparently in the WoT code this is actually called - "identity ID". "ID" -> "identification" ~ "identifier", - right? What does that leave to call "nick@public key hash"? ------------------------------------------------------------ Dev log: diff --git a/infocalypse/wot_id.py b/infocalypse/wot_id.py --- a/infocalypse/wot_id.py +++ b/infocalypse/wot_id.py @@ -107,6 +107,11 @@ class Local_WoT_ID(WoT_ID): """ def __init__(self, wot_identifier): + """ + Create a WoT_ID for a local identity matching the identifier. + + :type wot_identifier: str + """ id_num, message = _get_local_identity(wot_identifier) self.insert_uri = USK(message['Replies.InsertURI{0}'.format(id_num)]) @@ -120,6 +125,9 @@ def _get_identity(wot_identifier, truste Return an FCP reply from WoT for an identity on the truster's trust list matching the identifier. Abort if anything but exactly one match is found. + + :type wot_identifier: str + :type truster: Local_WoT_ID """ nickname_prefix, key_prefix = _parse_name(wot_identifier) # TODO: Support different FCP IP / port. @@ -131,52 +139,52 @@ def _get_identity(wot_identifier, truste # TODO: Should this manually ensure an identity has a vcs context # otherwise? - # LCWoT can have * to allow a wildcard match, but a wildcard alone is - # not allowed. See Lucine Term Modifiers documentation. The nickname - # uses this syntax but the ID is inherently startswith(). - params = {'Message': 'GetIdentitiesByPartialNickname', - 'Truster': truster.identity_id, - 'PartialNickname': - nickname_prefix + '*' if nickname_prefix else '', - 'PartialID': key_prefix, - 'MaxIdentities': 2, - 'Context': 'vcs'} + # GetIdentitiesByPartialNickname does not support empty nicknames. + if nickname_prefix: + params = {'Message': 'GetIdentitiesByPartialNickname', + 'Truster': truster.identity_id, + 'PartialNickname': + nickname_prefix + '*', + 'PartialID': key_prefix, + 'MaxIdentities': 2, + 'Context': 'vcs'} - response = \ - node.fcpPluginMessage(async=False, - plugin_name="plugins.WebOfTrust.WebOfTrust", - plugin_params=params)[0] + response = \ + node.fcpPluginMessage(plugin_name="plugins.WebOfTrust.WebOfTrust", + plugin_params=params)[0] - if response['header'] != 'FCPPluginReply' or \ - 'Replies.Message' not in response: - raise util.Abort('Unexpected reply. Got {0}\n'.format(response)) - elif response['Replies.Message'] == 'Identities': - matches = response['Replies.IdentitiesMatched'] - if matches == 0: - raise util.Abort("No identities match '{0}'\n".format( - wot_identifier)) - elif matches == 1: - return response - else: - raise util.Abort("'{0}' is ambiguous.\n".format(wot_identifier)) + if response['header'] != 'FCPPluginReply' or \ + 'Replies.Message' not in response: + raise util.Abort('Unexpected reply. Got {0}\n'.format(response)) + elif response['Replies.Message'] == 'Identities': + matches = response['Replies.IdentitiesMatched'] + if matches == 0: + raise util.Abort("No identities match '{0}'\n".format( + wot_identifier)) + elif matches == 1: + return response + else: + raise util.Abort("'{0}' matches more than one identity.\n" + .format(wot_identifier)) - # Partial matching not supported, or unknown truster. The only - # difference in the errors is human-readable, so just try the exact - # match. - assert response['Replies.Message'] == 'Error' + # Partial matching not supported, or unknown truster. The only + # difference in the errors is human-readable, so try the exact match. + assert response['Replies.Message'] == 'Error' # key_prefix must be a complete key for the lookup to succeed. params = {'Message': 'GetIdentity', - 'Truster': truster, + 'Truster': truster.identity_id, 'Identity': key_prefix} response = \ - node.fcpPluginMessage(async=False, - plugin_name="plugins.WebOfTrust.WebOfTrust", + node.fcpPluginMessage(plugin_name="plugins.WebOfTrust.WebOfTrust", plugin_params=params)[0] if response['Replies.Message'] == 'Error': # Searching by exact public key hash, not matching. - raise util.Abort("No such identity '{0}'.\n".format(wot_identifier)) + raise util.Abort("No identity has the complete public key hash '{0}'. " + "({1}) To flexibly match by partial nickname and key " + "use LCWoT for now.\n".format(key_prefix, + wot_identifier)) # There should be only one result. # Depends on https://bugs.freenetproject.org/view.php?id=5729 @@ -189,13 +197,14 @@ def _get_local_identity(wot_identifier): Return (id_number, FCP reply) from WoT for a local identity matching the identifier. Abort if anything but exactly one match is found. + + :type wot_identifier: str """ nickname_prefix, key_prefix = _parse_name(wot_identifier) node = fcp.FCPNode() response = \ - node.fcpPluginMessage(async=False, - plugin_name="plugins.WebOfTrust.WebOfTrust", + node.fcpPluginMessage(plugin_name="plugins.WebOfTrust.WebOfTrust", plugin_params={'Message': 'GetOwnIdentities'})[0]