diff -r 62b0fa0d8787 -r c347d532bb56 mercurial/exchange.py --- a/mercurial/exchange.py Tue Oct 13 12:31:19 2015 -0700 +++ b/mercurial/exchange.py Tue Oct 13 12:30:39 2015 -0700 @@ -1622,7 +1622,7 @@ 'operator)\n')) return - # TODO sort entries by user preferences. + entries = sortclonebundleentries(repo.ui, entries) url = entries[0]['URL'] repo.ui.status(_('applying clone bundle from %s\n') % url) @@ -1700,6 +1700,51 @@ return newentries +def sortclonebundleentries(ui, entries): + # experimental config: experimental.clonebundleprefers + prefers = ui.configlist('experimental', 'clonebundleprefers', default=[]) + if not prefers: + return list(entries) + + prefers = [p.split('=', 1) for p in prefers] + + # Our sort function. + def compareentry(a, b): + for prefkey, prefvalue in prefers: + avalue = a.get(prefkey) + bvalue = b.get(prefkey) + + # Special case for b missing attribute and a matches exactly. + if avalue is not None and bvalue is None and avalue == prefvalue: + return -1 + + # Special case for a missing attribute and b matches exactly. + if bvalue is not None and avalue is None and bvalue == prefvalue: + return 1 + + # We can't compare unless attribute present on both. + if avalue is None or bvalue is None: + continue + + # Same values should fall back to next attribute. + if avalue == bvalue: + continue + + # Exact matches come first. + if avalue == prefvalue: + return -1 + if bvalue == prefvalue: + return 1 + + # Fall back to next attribute. + continue + + # If we got here we couldn't sort by attributes and prefers. Fall + # back to index order. + return 0 + + return sorted(entries, cmp=compareentry) + def trypullbundlefromurl(ui, repo, url): """Attempt to apply a bundle from a URL.""" lock = repo.lock()