Changeset 50302f954e2f…
Parent eb3f0219a412…
by Kevin Gessner <kevin@fogcreek.com>
Changes to 6 files · Browse files at 50302f954e2f Showing diff from parent eb3f0219a412 Diff from another changeset...
@@ -1,4 +1,4 @@ - # Copyright (C) 2009-2011 Fog Creek Software. All rights reserved.
+# Copyright (C) 2009-2013 Fog Creek Software. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@
max_push_size = 1000
+
def findoutgoing(repo, other):
try:
# Mercurial 1.6 through 1.8
@@ -34,6 +35,7 @@ # Mercurial 1.5 and lower
return repo.findoutgoing(other, force=False)
+
def prepush(repo, other, force, revs):
try:
from mercurial import discovery
@@ -51,6 +53,7 @@ # Mercurial 1.5 and lower
return repo.prepush(other, False, revs)
+
def remoteui(repo, opts):
if hasattr(cmdutil, 'remoteui'):
# Mercurial 1.5 and lower
@@ -59,6 +62,7 @@ # Mercurial 1.6 and higher
return hg.remoteui(repo, opts)
+
def bigpush(push_fn, ui, repo, dest=None, *files, **opts):
'''Pushes this repository to a target repository.
@@ -99,12 +103,12 @@ ui.debug('pushing: %d\n' % current_push_size)
# force the push, because we checked above that by the time the whole push is done, we'll have merged back to one head
remote_heads = repo.push(other, force=True, revs=outgoing[:current_push_size])
- if remote_heads: # push succeeded
+ if remote_heads: # push succeeded
outgoing = outgoing[current_push_size:]
ui.debug('pushed %d ok\n' % current_push_size)
if push_size < max_push_size:
push_size *= 2
- else: # push failed; try again with a smaller size
+ else: # push failed; try again with a smaller size
push_size /= 2
ui.debug('failed, trying %d\n' % current_push_size)
if push_size == 0:
@@ -113,13 +117,16 @@ ui.status(_('unable to push changeset %s\n') % outgoing[0])
ui.debug('done\n')
+
def parseurl(source):
'''wrap hg.parseurl to work on 1.3 -> 1.5'''
return hg.parseurl(source, None)[:2]
+
def uisetup(ui):
push_cmd = extensions.wrapcommand(commands.table, 'push', bigpush)
push_cmd[1].extend([('', 'chunked', None, 'push large repository in chunks')])
+
class UnpushableChangesetError(Exception):
pass
|
|
|
@@ -1,4 +1,4 @@ - # Copyright (C) 2009-2012 Fog Creek Software. All rights reserved.
+# Copyright (C) 2009-2013 Fog Creek Software. All rights reserved.
#
# To enable the "gestalt" extension put these lines in your ~/.hgrc:
# [extensions]
@@ -66,6 +66,7 @@ return repo.changelog.findmissing(common)
demandimport.enable()
+
@apply
def _HG_VERSION():
'''return the mercurial version as a tuple rather than a string
@@ -79,6 +80,7 @@ version[i] = part
return tuple(version)
+
def parseurl(source):
'''wrap hg.parseurl to work on 1.5 and 1.6
@@ -96,6 +98,7 @@ hashbranch = branches and branches[0] or None
return uri, hashbranch
+
def addbranchrevs(lrepo, repo, hashbranch):
'''wrap hg.addbranchrevs to work on 1.5 and 1.6 and returns the
first value (revs) only
@@ -111,6 +114,7 @@ revs, checkout = hg.addbranchrevs(lrepo, repo, branches, None)
return revs
+
##
# Private utility functions for determining advice output
def _isrepo(ui, repo, files, opts):
@@ -122,12 +126,14 @@ return True
return False
+
def _ismerging(ui, repo, files, opts):
if repo.dirstate.parents()[1] != node.nullid:
ui.status(_('It appears there is a merge in progress.\n'))
return True
return False
+
def _haschanges(ui, repo, files, opts):
changed = any(repo.status())
if changed:
@@ -139,6 +145,7 @@ return True
return False
+
def _shouldmerge(ui, repo, files, opts):
heads = repo.branchheads(closed=False)
if len(heads) > 1:
@@ -150,6 +157,7 @@ return True
return False
+
def _shouldsync(ui, repo, files, opts):
source, hashbranch = parseurl(ui.expandpath('default'))
@@ -194,6 +202,7 @@ return True
return False
+
def _istip(ui, repo, files, opts):
tip = repo['tip']
cwd = repo['.']
@@ -206,10 +215,12 @@ return True
return False
+
def _shouldwritemorecode(ui, *ignored):
ui.status(_('Everything is up-to-date. Write more code!\n'))
return True
+
##
# General utility methods
def outgoing(repo, origin):
@@ -219,6 +230,7 @@ out = repo.changelog.nodesbetween(out, None)[0]
return out
+
def incoming(repo, origin, revs):
'''return a list of incoming changesets'''
if revs:
@@ -235,13 +247,14 @@ cg = origin.changegroup(incoming, 'incoming')
else:
cg = origin.changegroupsubset(incoming, revs, 'incoming')
- fname = changegroup.writebundle(cg, None, "HG10UN")
+ fname = changegroup.writebundle(cg, None, "HG10UN")
origin = bundlerepo.bundlerepository(repo.ui, repo.root, fname)
incoming = origin.changelog.findmissing(common, revs)
if hasattr(origin, 'close'):
origin.close()
return incoming
+
##
# commands
def overview(ui, repo, source=None, **opts):
@@ -316,6 +329,7 @@ for l in status.splitlines():
print ' %s' % l
+
def advice(ui, repo, *files, **opts):
'''provides a suggestion of your next step
@@ -336,6 +350,7 @@ if fun(ui, repo, files, opts):
return
+
def next(ui, repo, *files, **opts):
'''provides an overview and explanation of what to do next
@@ -357,6 +372,6 @@ (next,
[('d', 'detail', None, _('provide verbose output'))],
_('hg next [OPTION] [REMOTE REPOSITORY]')),
- }
+}
commands.optionalrepo += 'wtf advice overview next'
|
|
|
@@ -1,4 +1,4 @@ - # Copyright (C) 2011, 2012 Fog Creek Software. All rights reserved.
+# Copyright (C) 2011-2013 Fog Creek Software. All rights reserved.
#
# To enable the "kiln" extension put these lines in your ~/.hgrc:
# [extensions]
@@ -40,6 +40,7 @@pushing to Kiln. See :hg:`help push` and
http://kiln.stackexchange.com/questions/4679/ for more information.
'''
+
import itertools
import os
import re
@@ -52,7 +53,7 @@from cookielib import MozillaCookieJar
from hashlib import md5
from mercurial import (commands, cmdutil, demandimport, extensions, hg,
- localrepo, match, util)
+ localrepo, match, util)
from mercurial import ui as hgui
from mercurial import url as hgurl
from mercurial.error import RepoError
@@ -73,17 +74,20 @@
try:
import webbrowser
+
def browse(url):
webbrowser.open(escape_reserved(url))
except ImportError:
if os.name == 'nt':
import win32api
+
def browse(url):
win32api.ShellExecute(0, 'open', escape_reserved(url), None, None, 0)
demandimport.enable()
_did_version_check = False
+
class APIError(Exception):
def __init__(self, obj):
'''takes a json object for debugging
@@ -95,6 +99,7 @@ def __str__(self):
return '\n'.join('%s: %s' % (k, v) for k, v in self.errors.items())
+
class Review(dict):
def __init__(self, json, ui=None, token=None, baseurl=None):
self.ui = ui
@@ -119,29 +124,32 @@ 'token': self.token,
'ixBug': self.key,
'revs': revs,
- }
+ }
call_api(self.ui, self.baseurl, 'Api/1.0/Repo/%d/CaseAssociation/Create' % ixRepo, params, post=True)
else:
params = {
'token': self.token,
'revs': revs,
'ixRepo': ixRepo,
- }
+ }
call_api(self.ui, self.baseurl, 'Api/2.0/Review/%s/Association/Create' % self.key, params, post=True)
return urljoin(self.baseurl, 'Review', self.key)
@classmethod
def get_reviews(klass, ui, token, baseurl, ixRepo):
- review_lists = call_api(ui, baseurl, 'Api/2.0/Reviews', dict(token=token))
+ review_lists = call_api(ui, baseurl, 'Api/2.0/Reviews', dict(token=token, fReviewed="false", fAwaitingReview="false", nDaysActive=14))
reviews = {}
for key, review_list in review_lists.iteritems():
- if not key.startswith('reviews'): continue
+ if not key.startswith('reviews'):
+ continue
for review in review_list:
review = Review(review, ui, token, baseurl)
- if not review.belongs_to(ixRepo): continue
+ if not review.belongs_to(ixRepo):
+ continue
reviews[review.key.lower()] = review
return reviews
+
def urljoin(*components):
url = components[0]
for next in components[1:]:
@@ -152,6 +160,7 @@ url += next
return url
+
def _baseurl(ui, path):
try:
url = str(util.url(util.removeauth(path)))
@@ -168,12 +177,13 @@ else:
return None
+
def escape_reserved(path):
reserved = re.compile(
- r'^(((com[1-9]|lpt[1-9]|con|prn|aux)(\..*)?)|web\.config' +
- r'|clock\$|app_data|app_code|app_browsers' +
- r'|app_globalresources|app_localresources|app_themes' +
- r'|app_webreferences|bin|.*\.(cs|vb)html?)$', re.IGNORECASE)
+ r'^(((com[1-9]|lpt[1-9]|con|prn|aux)(\..*)?)|web\.config' +
+ r'|clock\$|app_data|app_code|app_browsers' +
+ r'|app_globalresources|app_localresources|app_themes' +
+ r'|app_webreferences|bin|.*\.(cs|vb)html?|.*\.(svc|xamlx|xoml|rules))$', re.IGNORECASE)
p = path.split('?')
path = p[0]
query = '?' + p[1] if len(p) > 1 else ''
@@ -182,9 +192,11 @@ else part
for part in path.split('/')) + query
+
def normalize_name(s):
return s.lower().replace(' ', '-')
+
def call_api(ui, baseurl, urlsuffix, params, post=False):
'''returns the json object for the url and the data dictionary
@@ -206,14 +218,18 @@ raise util.Abort(_('kiln: an error occurred while trying to reach %s') % url)
if isinstance(obj, dict) and 'errors' in obj:
- if 'token' in params and obj['errors'][0]['codeError'] == 'InvalidToken':
+ error_code = obj['errors'][0]['codeError']
+ if 'token' in params and error_code == 'InvalidToken':
token = login(ui, baseurl)
add_kilnapi_token(ui, baseurl, token)
params['token'] = token
return call_api(ui, baseurl, urlsuffix, params, post)
+ elif error_code == 'BadAuthentication':
+ raise util.Abort(_('authorization failed'))
raise APIError(obj)
return obj
+
def login(ui, url):
ui.write(_('realm: %s\n') % url)
user = ui.prompt('username:')
@@ -225,6 +241,7 @@ return token
raise util.Abort(_('authorization failed'))
+
def get_domain(url):
temp = url[url.find('://') + len('://'):]
domain = temp[:temp.find('/')]
@@ -236,6 +253,7 @@
return domain
+
def _get_path(path):
if os.name == 'nt':
ret = os.path.expanduser('~\\_' + path)
@@ -246,6 +264,7 @@ ret = re.sub(r'([A-Za-z]):', r'\1:\\', ret)
return ret
+
def _upgradecheck(ui, repo):
global _did_version_check
if _did_version_check or not ui.configbool('kiln', 'autoupdate', True):
@@ -253,6 +272,7 @@ _did_version_check = True
_upgrade(ui, repo)
+
def _upgrade(ui, repo):
ext_dir = os.path.dirname(os.path.abspath(__file__))
ui.debug(_('kiln: checking for extensions upgrade for %s\n') % ext_dir)
@@ -282,6 +302,7 @@ ui.debug(_('kiln: error updating extensions: %s\n') % e)
ui.debug(_('kiln: traceback: %s\n') % traceback.format_exc())
+
def is_dest_a_path(ui, dest):
paths = ui.configitems('paths')
for pathname, path in paths:
@@ -289,6 +310,7 @@ return True
return False
+
def is_dest_a_scheme(ui, dest):
destscheme = dest[:dest.find('://')]
if destscheme:
@@ -297,12 +319,14 @@ return True
return False
+
def create_match_list(matchlist):
ret = ''
for m in matchlist:
ret += ' ' + m + '\n'
return ret
+
def get_username(url):
url = re.sub(r'https?://', '', url)
url = re.sub(r'/.*', '', url)
@@ -316,6 +340,7 @@ # Didn't find anything...
return ''
+
def get_dest(ui):
from mercurial.dispatch import _parse
try:
@@ -332,6 +357,7 @@ dest = 'default'
return ui.expandpath(dest)
+
def check_kilnapi_token(ui, url):
tokenpath = _get_path('hgkiln')
@@ -355,6 +381,7 @@ fp.close()
return ret
+
def add_kilnapi_token(ui, url, fbToken):
if not fbToken:
return
@@ -369,12 +396,14 @@ fp.write(domain + ' ' + userhash + ' ' + fbToken + '\n')
fp.close()
+
def delete_kilnapi_tokens():
# deletes the hgkiln file
tokenpath = _get_path('hgkiln')
if os.path.exists(tokenpath) and not os.path.isdir(tokenpath):
os.remove(tokenpath)
+
def check_kilnauth_token(ui, url):
cookiepath = _get_path('hgcookies')
if (not os.path.exists(cookiepath)) or (not os.path.isdir(cookiepath)):
@@ -396,14 +425,17 @@ if cookie.name == 'fbToken':
return cookie.value
+
def remember_path(ui, repo, path, value):
'''appends the path to the working copy's hgrc and backs up the original'''
paths = dict(ui.configitems('paths'))
# This should never happen.
- if path in paths: return
+ if path in paths:
+ return
# ConfigParser only cares about these three characters.
- if re.search(r'[:=\s]', path): return
+ if re.search(r'[:=\s]', path):
+ return
try:
audit_path = scmutil.pathauditor(repo.root)
@@ -428,6 +460,7 @@ except IOError:
return
+
def unremember_path(ui, repo):
'''restores the working copy's hgrc'''
@@ -446,6 +479,7 @@ else:
os.remove(hgrc)
+
def guess_kilnpath(orig, ui, repo, dest=None, **opts):
if not dest:
return orig(ui, repo, **opts)
@@ -465,24 +499,24 @@
if (ndest.count('/') == 0 and
(ntarget[0] == ndest or
- ntarget[1] == ndest or
- ntarget[2] == ndest or
- ndest in aliases)):
+ ntarget[1] == ndest or
+ ntarget[2] == ndest or
+ ndest in aliases)):
matches.append(url)
elif (ndest.count('/') == 1 and
- '/'.join(ntarget[0:2]) == ndest or
- '/'.join(ntarget[1:3]) == ndest):
+ '/'.join(ntarget[0:2]) == ndest or
+ '/'.join(ntarget[1:3]) == ndest):
matches.append(url)
elif (ndest.count('/') == 2 and
- '/'.join(ntarget[0:3]) == ndest):
+ '/'.join(ntarget[0:3]) == ndest):
matches.append(url)
if (ntarget[0].startswith(ndest) or
- ntarget[1].startswith(ndest) or
- ntarget[2].startswith(ndest) or
- '/'.join(ntarget[0:2]).startswith(ndest) or
- '/'.join(ntarget[1:3]).startswith(ndest) or
- '/'.join(ntarget[0:3]).startswith(ndest)):
+ ntarget[1].startswith(ndest) or
+ ntarget[2].startswith(ndest) or
+ '/'.join(ntarget[0:2]).startswith(ndest) or
+ '/'.join(ntarget[1:3]).startswith(ndest) or
+ '/'.join(ntarget[0:3]).startswith(ndest)):
prefixmatches.append(url)
if len(matches) == 0:
@@ -503,6 +537,7 @@ finally:
unremember_path(ui, repo)
+
def get_tails(repo):
tails = []
for rev in xrange(repo['tip'].rev() + 1):
@@ -513,6 +548,7 @@ raise util.Abort(_('Path guessing is only enabled for non-empty repositories.'))
return tails
+
def get_targets(repo):
def get_kiln_repo_url_prefix(default_prefix):
'''Checks repo paths and returns server url for ssh:. For http(s) falls back to default_prefix.'''
@@ -536,9 +572,10 @@ related_repo['sProjectSlug'],
related_repo['sGroupSlug'],
related_repo['sSlug'],
- related_repo.get('rgAliases', [])] for related_repo in related_repos])
+ [a['sSlug'] for a in related_repo.get('rgAliases', [])]] for related_repo in related_repos])
return targets
+
def display_targets(repo):
targets = get_targets(repo)
repo.ui.write(_('The following Kiln targets are available for this repository:\n\n'))
@@ -549,6 +586,7 @@ alias_text = ''
repo.ui.write(' %s/%s/%s/%s%s\n' % (target[0], target[1], target[2], target[3], alias_text))
+
def get_token(ui, url):
'''Checks for an existing API token. If none, returns a new valid token.'''
token = check_kilnapi_token(ui, url)
@@ -560,6 +598,7 @@ add_kilnapi_token(ui, url, token)
return token
+
def get_api_url(url):
'''Given a URL, returns the URL of the Kiln installation.'''
if '/kiln/' in url.lower():
@@ -570,6 +609,7 @@ baseurl = url
return baseurl
+
class HTTPNoRedirectHandler(urllib2.HTTPRedirectHandler):
def http_error_302(self, req, fp, code, msg, headers):
# Doesn't allow multiple redirects so repo alias URLs will not
@@ -578,6 +618,7 @@
http_error_301 = http_error_303 = http_error_307 = http_error_302
+
def get_repo_record(repo, url, token=None):
'''Returns a Kiln repository record that corresponds to the given repo.'''
baseurl = get_api_url(url)
@@ -585,7 +626,7 @@ token = get_token(repo.ui, baseurl)
try:
- data = urllib.urlencode({ 'token': token }, doseq=True)
+ data = urllib.urlencode({'token': token}, doseq=True)
opener = urllib2.build_opener(HTTPNoRedirectHandler)
urllib2.install_opener(opener)
fd = urllib2.urlopen(url + '?' + data)
@@ -614,6 +655,7 @@ repo = find_slug(repo, group, 'repos')
return repo
+
def new_branch(repo, url, name):
'''Creates a new, decentralized branch off of the specified repo.'''
baseurl = get_api_url(url)
@@ -634,33 +676,40 @@ return
raise
+
def normalize_user(s):
'''Takes a Unicode string and returns an ASCII string.'''
return unicodedata.normalize('NFKD', s).encode('ASCII', 'ignore')
+
def encode_out(s):
'''Takes a Unicode string and returns a string encoded for output.'''
return s.encode(sys.stdout.encoding, 'ignore')
+
def record_base(ui, repo, node, **kwargs):
'''Stores the first changeset committed in the repo UI so we do not need to expensively recalculate.'''
repo.ui.setconfig('kiln', 'node', node)
+
def walk(repo, revs):
'''Returns revisions in repo specified by the string revs'''
return cmdutil.walkchangerevs(repo, match.always(repo.root, None), {'rev': [revs.encode('ascii', 'ignore')]}, lambda *args: None)
+
def print_list(ui, l, header):
'''Prints a list l to ui using list notation, with header being the first line'''
ui.write(_('%s\n' % header))
for item in l:
ui.write(_('- %s\n') % item)
+
def wrap_push(orig, ui, repo, dest=None, **opts):
'''Wraps `hg push' so a review will be created after path guessing and a successful push.'''
guess_kilnpath(orig, ui, repo, dest, **opts)
review(ui, repo, dest, opts)
+
def add_unique_reviewer(ui, reviewer, reviewers, name_to_ix, ix_to_name):
'''Adds a reviewer to reviewers if it is not already added. Otherwise, print an error.'''
if name_to_ix[reviewer] in reviewers:
@@ -669,6 +718,7 @@ reviewers.append(name_to_ix[reviewer])
print_list(ui, [ix_to_name[r] for r in reviewers], 'reviewers:')
+
def review(ui, repo, dest, opts):
'''Associates the pushed changesets with a new or existing Kiln review.'''
if not opts['review'] or not repo.ui.config('kiln', 'node'):
@@ -770,7 +820,7 @@ 'ixReviewers': reviewers,
'sTitle': '(Multiple changesets)' if len(revs) > 1 else repo[revs[0]].description(),
'sDescription': 'Review created from push.'
- }
+ }
r = Review(call_api(repo.ui, baseurl, 'Api/2.0/Review/Create', params, post=True))
ui.write(_('new review created: %s\n' % urljoin(baseurl, 'Review', r.key)))
else:
@@ -778,6 +828,7 @@ url = reviews[choice].associate(kiln_repo['ixRepo'], revs)
ui.write(_('updated review: %s\n' % url))
+
def dummy_command(ui, repo, dest=None, **opts):
'''dummy command to pass to guess_path() for hg kiln
@@ -786,6 +837,7 @@ '''
return opts['path'] != dest and dest or None
+
def _standin_expand(paths):
'''given a sequence of filenames, returns a set of filenames --
relative to the current working directory! -- prefixed with all
@@ -795,6 +847,7 @@ choices = [[p, os.path.join('.kbf', p), os.path.join('.hglf', p)] for p in paths]
return set(itertools.chain(*choices))
+
def _filename_match(repo, ctx, paths):
'''returns a set of filenames contained in both paths and the
ctx's manifest, accounting for standins'''
@@ -812,6 +865,7 @@ haystacks = set(map(os.path.normpath, haystacks))
return needles.intersection(haystacks)
+
def kiln(ui, repo, **opts):
'''show the relevant page of the repository in Kiln
@@ -894,6 +948,7 @@ if default or opts['changes']:
browse(url)
+
def uisetup(ui):
extensions.wrapcommand(commands.table, 'outgoing', guess_kilnpath)
extensions.wrapcommand(commands.table, 'pull', guess_kilnpath)
@@ -902,6 +957,7 @@ # Add --review as a valid flag to push's command table
push_cmd[1].extend([('', 'review', None, 'associate changesets with Kiln review')])
+
def reposetup(ui, repo):
try:
from mercurial.httprepo import httprepository
@@ -913,6 +969,7 @@ _upgradecheck(ui, repo)
repo.ui.setconfig('hooks', 'outgoing.kilnreview', 'python:kiln.record_base')
+
def extsetup(ui):
try:
g = extensions.find('gestalt')
@@ -943,4 +1000,4 @@ ('n', 'new-branch', '', _('asynchronously create a new branch from the current repository')),
('', 'logout', None, _('log out of Kiln sessions'))],
_('hg kiln [-p url] [-r rev|-a file|-f file|-c|-o|-s|-t|-n branchName|--logout]'))
- }
+}
|
|
@@ -0,0 +1,59 @@ + # Copyright (C) 2011, 2012 Fog Creek Software. All rights reserved.
+#
+# This extension is used internally by Kiln Importer.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+'''fix a _filecache invalidation bug so hg convert works
+
+See
+
+ * http://our.fogbugz.com/f/cases/2338914/importer-does-not-work-with-hg-2-3-1 and
+ * http://www.selenic.com/pipermail/mercurial-devel/2012-November/046159.html
+
+ for more details. Until Mercurial fixes this bug or accepts my patch,
+this bug affects any tags in this revset:
+
+ * hg log -r 'descendants(9f94358) and tag()' --template '{tags}\n'
+
+As of writing, that's every 2.3 release and 2.4-rc and 2.4.
+'''
+
+from mercurial import util
+
+def reposetup(ui, repo):
+ if util.version()[:3] < '2.3':
+ # This bug was first introduced in 9f94358f9f93, which
+ # occurred between 2.3-rc and 2.3.
+ return
+
+ from mercurial import localrepo
+ if not issubclass(repo.__class__, localrepo.localrepository):
+ return
+
+ class kilnfilecacherepo(repo.__class__):
+ def destroyed(self, *args, **kwargs):
+ # By saving _filecache before it's cleared, we can
+ # restore it and then call invalidate() afterward so
+ # localrepo can delattr() the relevant attributes off
+ # the repo object. See my mercurial-devel patch for
+ # more details.
+ oldfilecache = dict(self._filecache)
+ super(kilnfilecacherepo, self).destroyed(*args, **kwargs)
+ self._filecache = oldfilecache
+ self.invalidate()
+
+ repo.__class__ = kilnfilecacherepo
|
@@ -1,4 +1,4 @@ - # Copyright (C) 2009-2011 Fog Creek Software. All rights reserved.
+# Copyright (C) 2009-2013 Fog Creek Software. All rights reserved.
#
# To enable the "kilnpath" extension put these lines in your ~/.hgrc:
# [extensions]
@@ -18,7 +18,7 @@# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-'''Lets users identify repository paths by custom schemes like kiln://Project/Group/Repository.
+'''allow users identify repository paths by custom schemes like kiln://Project/Group/Repository (DEPRECATED)
This extensions knows how to expand Kiln repository paths from
kiln://Project/Group/Repository to
@@ -31,10 +31,36 @@To specify the Kiln path prefix, add a [kiln_scheme] section to your hg config like so:
[kiln_scheme]
kiln = https://your.fogbugz.com/kiln/Repo
+
+This extensions is deprecated, and does not work in Mercurial 2.4 and later.
+You should use the built-in `schemes` extension instead instead. Type `hg help schemes`
+for more information.
'''
-import os
-from mercurial import extensions, commands, hg, ui
+import re
+
+from mercurial import hg, ui, util, __version__
+
+
+@apply
+def _HG_VERSION():
+ '''return the mercurial version as a tuple rather than a string
+
+ Python does the right thing when comparing tuples, so the return
+ value can be used to compare and detect versions.
+ '''
+ version = [0, 0, 0]
+ parts = [re.match(r'\d+', v).group(0) for v in __version__.version.split('.')[:3]]
+ for i, part in enumerate(map(int, parts)):
+ version[i] = part
+ return tuple(version)
+
+
+if _HG_VERSION >= (2, 3, 0):
+ raise util.Abort(
+ 'kilnpath is deprecated, and does not work in Mercurial 2.3 or higher. '
+ 'Use the official schemes extension instead')
+
def urlcombine(pre, suff):
if pre.endswith("/"):
@@ -43,11 +69,13 @@ suff = "/" + suff
return pre + suff
+
def add_schemes(ui):
schemes = ui.configitems('kiln_scheme')
for scheme, prefix in schemes:
hg.schemes[scheme] = KilnRepo(scheme, prefix)
+
class KilnRepo(object):
def __init__(self, scheme, prefix):
self.scheme = scheme
@@ -70,9 +98,9 @@ # Mercurial <= 1.8
return hg._lookup(path_full).instance(ui, path_full, create)
+
def extsetup(*args):
if len(args) > 0:
add_schemes(args[0])
else:
add_schemes(ui.ui())
-
|
@@ -3,7 +3,8 @@ import zipfile
def compile_extensions():
- compileall.compile_dir(os.path.dirname(__file__), force=1)
+ curdir = os.path.dirname(os.path.abspath(__file__))
+ compileall.compile_dir(curdir, force=True)
def walk(dir_root):
for dirpath, dirnames, filenames in os.walk(dir_root):
|
Loading...