def _diverge(ui, b, path, localmarks, remotenode): '''Return appropriate diverged bookmark for specified ``path`` This returns None, if it is failed to assign any divergent bookmark name. This reuses already existing one with "@number" suffix, if it refers ``remotenode``. ''' if b == '@': b = '' # try to use an @pathalias suffix # if an @pathalias already exists, we overwrite (update) it if path.startswith("file:"): path = util.url(path).path for p, u in ui.configitems("paths"): if u.startswith("file:"): u = util.url(u).path if path == u: return '%s@%s' % (b, p) # assign a unique "@number" suffix newly for x in range(1, 100): n = '%s@%d' % (b, x) if n not in localmarks or localmarks[n] == remotenode: return n return None
def readurltoken(repo): """return conduit url, token and make sure they exist Currently read from [auth] config section. In the future, it might make sense to read from .arcconfig and .arcrc as well. """ url = repo.ui.config(b'phabricator', b'url') if not url: raise error.Abort(_(b'config %s.%s is required') % (b'phabricator', b'url')) res = httpconnectionmod.readauthforuri(repo.ui, url, util.url(url).user) token = None if res: group, auth = res repo.ui.debug(b"using auth.%s.* for authentication\n" % group) token = auth.get(b'phabtoken') if not token: token = readlegacytoken(repo, url) if not token: raise error.Abort(_(b'Can\'t find conduit token associated to %s') % (url,)) return url, token
def callconduit(repo, name, params): """call Conduit API, params is a dict. return json.loads result, or None""" host, token = readurltoken(repo) url, authinfo = util.url(b'/'.join([host, b'api', name])).authinfo() repo.ui.debug(b'Conduit Call: %s %s\n' % (url, params)) params = params.copy() params[b'api.token'] = token data = urlencodenested(params) curlcmd = repo.ui.config(b'phabricator', b'curlcmd') if curlcmd: sin, sout = procutil.popen2(b'%s -d @- %s' % (curlcmd, procutil.shellquote(url))) sin.write(data) sin.close() body = sout.read() else: urlopener = urlmod.opener(repo.ui, authinfo) request = util.urlreq.request(url, data=data) body = urlopener.open(request).read() repo.ui.debug(b'Conduit Response: %s\n' % body) parsed = json.loads(body) if parsed.get(r'error_code'): msg = (_(b'Conduit Error (%s): %s') % (parsed[r'error_code'], parsed[r'error_info'])) raise error.Abort(msg) return parsed[r'result']
def debuggethostfingerprint(ui, repo, source='default'): """retrieve a fingerprint of the server certificate The server certificate is not verified. """ source = ui.expandpath(source) u = util.url(source) scheme = (u.scheme or '').split('+')[-1] host = u.host port = util.getport(u.port or scheme or '-1') if scheme != 'https' or not host or not (0 <= port <= 65535): raise util.Abort(_('unsupported URL: %s') % source) sock = socket.socket() try: sock.connect((host, port)) sock = sslutil.wrapsocket(sock, None, None, ui, serverhostname=host) peercert = sock.getpeercert(True) if not peercert: raise util.Abort(_('%s certificate error: no certificate received') % host) finally: sock.close() s = util.sha1(peercert).hexdigest() ui.write(':'.join([s[x:x + 2] for x in xrange(0, len(s), 2)]), '\n')
def nclone(ui, source, dest=None, **opts): '''make a copy of an existing repository and all nested repositories Create a copy of an existing repository in a new directory. Look at the help of clone command for more informations.''' origsource = ui.expandpath(source) remotesource, remotebranch = hg.parseurl(origsource, opts.get('branch')) if hasattr(hg, 'peer'): remoterepo = hg.peer(ui, opts, remotesource) localrepo = remoterepo.local() if localrepo: remoterepo = localrepo else: remoterepo = hg.repository(hg.remoteui(ui, opts), remotesource) if dest is None: dest = hg.defaultdest(source) ui.status(_("destination directory: %s\n") % dest) for npath in remoterepo.nested: if npath == '.': npath = '' u = util.url(source) if u.scheme: nsource = '%s/%s' % (source, npath) else: nsource = os.path.join(source, npath) ndest = os.path.join(dest, npath) ui.status('[%s]\n' % os.path.normpath( os.path.join(os.path.basename(dest), ndest[len(dest) + 1:]))) commands.clone(ui, nsource, dest=ndest, **opts) ui.status('\n')
def __init__(self, ui=None, serverurl=None, cachepath=None, anonymous=None, unc=True, index=None, conf=None): self.ui = ui or uimod.ui() if conf: self.ui.readconfig(conf, trust=True) self.ui.setconfig('server', 'preferuncompressed', str(bool(unc))), self.serverurl = (serverurl or self.ui.config('hgwebcachingproxy', 'serverurl')) self.cachepath = (cachepath or self.ui.config('hgwebcachingproxy', 'cachepath')) if anonymous is None: anonymous = self.ui.configbool('hgwebcachingproxy', 'anonymous') self.anonymous = anonymous if not self.serverurl: raise error.Abort(_('no server url')) u = util.url(self.serverurl) if u.scheme not in ['http', 'https']: raise error.Abort(_('invalid scheme in server url %s') % serverurl) if not self.cachepath or not os.path.isdir(self.cachepath): raise error.Abort(_('cache path %s is not a directory') % self.cachepath) self.ttl = self.ui.configint('hgwebcachingproxy', 'ttl', 30) self.authheaders = [('WWW-Authenticate', 'Basic realm="%s"' % self.ui.config('hgwebcachingproxy', 'realm', 'Mercurial Proxy Authentication'))] self.clone = self.ui.configbool('hgwebcachingproxy', 'clone', True) self.index = (index or self.ui.config('hgwebcachingproxy', 'index'))
def geturlcgivars(baseurl, port): """ Extract CGI variables from baseurl >>> geturlcgivars("http://host.org/base", "80") ('host.org', '80', '/base') >>> geturlcgivars("http://host.org:8000/base", "80") ('host.org', '8000', '/base') >>> geturlcgivars('/base', 8000) ('', '8000', '/base') >>> geturlcgivars("base", '8000') ('', '8000', '/base') >>> geturlcgivars("http://host", '8000') ('host', '8000', '/') >>> geturlcgivars("http://host/", '8000') ('host', '8000', '/') """ u = util.url(baseurl) name = u.host or '' if u.port: port = u.port path = u.path or "" if not path.startswith('/'): path = '/' + path return name, str(port), path
def updatereqenv(self, env): if self._baseurl is not None: u = util.url(self._baseurl) env['SERVER_NAME'] = u.host if u.port: env['SERVER_PORT'] = u.port env['SCRIPT_NAME'] = '/' + u.path
def fixuppath(ui, path, substitutions, announce=True): for ipprefixes, pathprefix, pathsubst in substitutions: if not _is_match_path(path, pathprefix): ui.debug( _("path %s didn't match prefix %s\n") % (util.hidepassword(path), util.hidepassword(pathprefix))) continue try: u = util.url(pathsubst) probehost = u.host or '1.0.0.1' except Exception: probehost = '1.0.0.1' for ip in localips(ui, probehost): if any( ipaddress.ip_address(unicode(ip)) in ipaddress.ip_network( unicode(ipprefix), False) for ipprefix in ipprefixes): new = _rewrite_path(path, pathsubst, pathprefix) if announce and not ui.quiet: ui.write_err( _("ip %s matched, " "path changed from %s to %s\n") % (ip, util.hidepassword(path), util.hidepassword(new))) return new ui.debug("ip %s does not match any of the ip prefixes %s\n" % (ip, ', '.join(ipprefixes))) ui.debug( _("path %s was not matched by any prefix\n" % util.hidepassword(path))) return path
def remote(repo): """remotestore factory. return a store in _storemap depending on config""" url = util.url(repo.ui.config('lfs', 'url') or '') scheme = url.scheme if scheme not in _storemap: raise error.Abort(_('lfs: unknown url scheme: %s') % scheme) return _storemap[scheme](repo, url)
def readurltoken(repo): """return conduit url, token and make sure they exist Currently read from [auth] config section. In the future, it might make sense to read from .arcconfig and .arcrc as well. """ url = repo.ui.config(b'phabricator', b'url') if not url: raise error.Abort(_(b'config %s.%s is required') % (b'phabricator', b'url')) res = httpconnectionmod.readauthforuri(repo.ui, url, util.url(url).user) token = None if res: group, auth = res repo.ui.debug(b"using auth.%s.* for authentication\n" % group) token = auth.get(b'phabtoken') if not token: raise error.Abort(_(b'Can\'t find conduit token associated to %s') % (url,)) return url, token
def callconduit(ui, name, params): """call Conduit API, params is a dict. return json.loads result, or None""" host, token = readurltoken(ui) url, authinfo = util.url(b'/'.join([host, b'api', name])).authinfo() ui.debug(b'Conduit Call: %s %s\n' % (url, pycompat.byterepr(params))) params = params.copy() params[b'api.token'] = token data = urlencodenested(params) curlcmd = ui.config(b'phabricator', b'curlcmd') if curlcmd: sin, sout = procutil.popen2(b'%s -d @- %s' % (curlcmd, procutil.shellquote(url))) sin.write(data) sin.close() body = sout.read() else: urlopener = urlmod.opener(ui, authinfo) request = util.urlreq.request(pycompat.strurl(url), data=data) with contextlib.closing(urlopener.open(request)) as rsp: body = rsp.read() ui.debug(b'Conduit Response: %s\n' % body) parsed = pycompat.rapply( lambda x: encoding.unitolocal(x) if isinstance(x, pycompat.unicode) else x, json.loads(body)) if parsed.get(b'error_code'): msg = (_(b'Conduit Error (%s): %s') % (parsed[b'error_code'], parsed[b'error_info'])) raise error.Abort(msg) return parsed[b'result']
def _local(path): p = hgutil.url(path).localpath() if _isgitdir(p): return gitrepo # detect git ssh urls (which mercurial thinks is a file-like path) if util.isgitsshuri(p): return gitrepo return _oldlocal(path)
def _activepath(self, remote): conf = config.config() try: rc = self.vfs.join('hgrc') except AttributeError: # old hg rc = self.join('hgrc') if os.path.exists(rc): with open(rc) as fp: conf.parse('.hgrc', fp.read(), include=conf.read) realpath = '' if 'paths' in conf: for path, uri in conf['paths'].items(): for s in schemes.schemes.iterkeys(): if uri.startswith('%s://' % s): # TODO: refactor schemes so we don't # duplicate this logic ui.note('performing schemes expansion with ' 'scheme %s\n' % s) scheme = hg.schemes[s] parts = uri.split('://', 1)[1].split('/', scheme.parts) if len(parts) > scheme.parts: tail = parts[-1] parts = parts[:-1] else: tail = '' context = dict((str(i+1), v) for i, v in enumerate(parts)) uri = ''.join(scheme.templater.process( scheme.url, context)) + tail uri = self.ui.expandpath(uri) if remote.local(): uri = os.path.realpath(uri) rpath = getattr(remote, 'root', None) if rpath is None: # Maybe a localpeer? (hg@1ac628cd7113, 2.3) rpath = getattr(getattr(remote, '_repo', None), 'root', None) else: rpath = getattr(remote, 'url', lambda : remote._url)() if uri.startswith('http'): try: uri = url.url(uri).authinfo()[0] except AttributeError: try: uri = util.url(uri).authinfo()[0] except AttributeError: uri = url.getauthinfo(uri)[0] uri = uri.rstrip('/') rpath = rpath.rstrip('/') if uri == rpath: realpath = path # prefer a non-default name to default if path != 'default': break return realpath
def _diverge(ui, b, path, localmarks): if b == '@': b = '' # find a unique @ suffix for x in range(1, 100): n = '%s@%d' % (b, x) if n not in localmarks: break # try to use an @pathalias suffix # if an @pathalias already exists, we overwrite (update) it if path.startswith("file:"): path = util.url(path).path for p, u in ui.configitems("paths"): if u.startswith("file:"): u = util.url(u).path if path == u: n = '%s@%s' % (b, p) return n
def __init__(self, ui, repo, remote): self.baseurl = bfutil.urljoin(remote.url(), 'bfile') try: # Mercurial >= 1.9 self.baseurl, authinfo = util.url(self.baseurl).authinfo() except AttributeError: # Mercurial <= 1.8 self.baseurl, authinfo = url_.getauthinfo(self.baseurl) self.opener = url_.opener(repo.ui, authinfo) super(kilnstore, self).__init__(ui, repo, remote.url())
def _test(uri): print 'URI:', uri try: pm = url.passwordmgr(ui) u, authinfo = util.url(uri).authinfo() if authinfo is not None: pm.add_password(*authinfo) print ' ', pm.find_user_password('test', u) except Abort: print 'abort'
def _test(uri): print('URI:', uri) try: pm = url.passwordmgr(ui, urlreq.httppasswordmgrwithdefaultrealm()) u, authinfo = util.url(uri).authinfo() if authinfo is not None: pm.add_password(*authinfo) print(' ', pm.find_user_password('test', u)) except error.Abort: print(' ', 'abort')
def remote(repo, remote=None): """remotestore factory. return a store in _storemap depending on config If ``lfs.url`` is specified, use that remote endpoint. Otherwise, try to infer the endpoint, based on the remote repository using the same path adjustments as git. As an extension, 'http' is supported as well so that ``hg serve`` works out of the box. https://github.com/git-lfs/git-lfs/blob/master/docs/api/server-discovery.md """ lfsurl = repo.ui.config('lfs', 'url') url = util.url(lfsurl or '') if lfsurl is None: if remote: path = remote elif util.safehasattr(repo, '_subtoppath'): # The pull command sets this during the optional update phase, which # tells exactly where the pull originated, whether 'paths.default' # or explicit. path = repo._subtoppath else: # TODO: investigate 'paths.remote:lfsurl' style path customization, # and fall back to inferring from 'paths.remote' if unspecified. path = repo.ui.config('paths', 'default') or '' defaulturl = util.url(path) # TODO: support local paths as well. # TODO: consider the ssh -> https transformation that git applies if defaulturl.scheme in (b'http', b'https'): if defaulturl.path and defaulturl.path[:-1] != b'/': defaulturl.path += b'/' defaulturl.path = (defaulturl.path or b'') + b'.git/info/lfs' url = util.url(bytes(defaulturl)) repo.ui.note(_('lfs: assuming remote store: %s\n') % url) scheme = url.scheme if scheme not in _storemap: raise error.Abort(_('lfs: unknown url scheme: %s') % scheme) return _storemap[scheme](repo, url)
def _activepath(self, remote): conf = config.config() rc = self.join("hgrc") if os.path.exists(rc): fp = open(rc) conf.parse(".hgrc", fp.read()) fp.close() realpath = "" if "paths" in conf: for path, uri in conf["paths"].items(): for s in schemes.schemes.iterkeys(): if uri.startswith("%s://" % s): # TODO: refactor schemes so we don't # duplicate this logic ui.note("performing schemes expansion with " "scheme %s\n" % s) scheme = hg.schemes[s] parts = uri.split("://", 1)[1].split("/", scheme.parts) if len(parts) > scheme.parts: tail = parts[-1] parts = parts[:-1] else: tail = "" context = dict((str(i + 1), v) for i, v in enumerate(parts)) uri = "".join(scheme.templater.process(scheme.url, context)) + tail uri = self.ui.expandpath(uri) if remote.local(): uri = os.path.realpath(uri) rpath = getattr(remote, "root", None) if rpath is None: # Maybe a localpeer? (hg@1ac628cd7113, 2.3) rpath = getattr(getattr(remote, "_repo", None), "root", None) else: rpath = remote._url if uri.startswith("http"): try: uri = url.url(uri).authinfo()[0] except AttributeError: try: uri = util.url(uri).authinfo()[0] except AttributeError: uri = url.getauthinfo(uri)[0] uri = uri.rstrip("/") rpath = rpath.rstrip("/") if uri == rpath: realpath = path # prefer a non-default name to default if path != "default": break return realpath
def _rewrite_path(path, pathsubst, pathprefix): """Change path into the substituted path up to the path prefix match If the substitution does not specify authentication information and either the path or the prefix does, then that authentication is copied to the substituted path. """ pathurl = util.url(path) substurl = util.url(pathsubst) prefixurl = util.url(pathprefix) if not substurl.user: if pathurl.user: substurl.user = pathurl.user else: substurl.user = prefixurl.user if not substurl.passwd: if pathurl.passwd: substurl.passwd = pathurl.passwd else: substurl.passwd = prefixurl.passwd substurl.path += pathurl.path[len(prefixurl.path):] return str(substurl)
def _baseurl(ui, path): try: url = str(util.url(util.removeauth(path))) except util.Abort: remote = hg.repository(ui, path) try: # Mercurial >= 1.9 url = util.removeauth(remote.url()) except AttributeError: # Mercurial <= 1.8 url = hgurl.removeauth(remote.url()) if url.lower().find('/kiln/') > 0 or url.lower().find('kilnhg.com/') > 0: return url else: return None
def _mirrorrepo(ui, repo, url): """Mirror a source repository into the .hg directory of another.""" u = util.url(url) if u.islocal(): raise error.Abort(_('source repo cannot be local')) # Remove scheme from path and normalize reserved characters. path = url.replace('%s://' % u.scheme, '').replace('/', '_') mirrorpath = repo.vfs.join(store.encodefilename(path)) peer = hg.peer(ui, {}, url) mirrorrepo = hg.repository(ui, mirrorpath, create=not os.path.exists(mirrorpath)) missingheads = [head for head in peer.heads() if head not in mirrorrepo] if missingheads: ui.write(_('pulling %s into %s\n' % (url, mirrorpath))) exchange.pull(mirrorrepo, peer) return mirrorrepo
def nshare(ui, source, dest=None, noupdate=False): '''create a new shared repository and all nested repositories ''' sourcerepo = hg.repository(ui, source) if dest is None: dest = hg.defaultdest(source) ui.status(_("destination directory: %s\n") % dest) for npath in sourcerepo.nested: if npath == '.': npath = '' u = util.url(source) if u.scheme: nsource = '%s/%s' % (source, npath) else: nsource = os.path.join(source, npath) ndest = os.path.join(dest, npath) ui.status('[%s]\n' % os.path.normpath( os.path.join(os.path.basename(dest), ndest[len(dest) + 1:]))) hg.share(ui, nsource, ndest, not noupdate) ui.status('\n')
def run_wsgi(self, req): path = req.env['PATH_INFO'].replace('\\', '/').strip('/') u = util.url(self.serverurl) # Forward HTTP basic authorization headers through the layers authheader = req.env.get('HTTP_AUTHORIZATION') if authheader and authheader.lower().startswith('basic '): userpasswd = authheader[6:].decode('base64') if ':' in userpasswd: u.user, u.passwd = userpasswd.split(':', 1) proto = protocol.webproto(req, self.ui) # MIME and HTTP allows multiple headers by the same name - we only # use and care about one args = dict((k, v[0]) for k, v in proto._args().items()) cmd = args.pop('cmd', None) self.ui.write("%s@%s cmd: %s args: %s\n" % (u.user, path or '/', cmd, ' '.join('%s=%s' % (k, v) for k, v in sorted(args.items())))) if not cmd: if self.index: req.respond(common.HTTP_OK, 'text/html' if self.index.endswith('.html') else 'text/plain') return file(self.index) self.ui.warn(_('no command in request\n')) req.respond(common.HTTP_BAD_REQUEST, protocol.HGTYPE) return [] # Simple path validation - probably only sufficient on Linux if ':' in path or path.startswith('.') or '/.' in path: self.ui.warn(_('bad request path %r\n') % path) req.respond(common.HTTP_BAD_REQUEST, protocol.HGTYPE) return [] # Bounce early on missing credentials if not (self.anonymous or u.user and u.passwd): er = common.ErrorResponse(common.HTTP_UNAUTHORIZED, 'Authentication is mandatory', self.authheaders) req.respond(er, protocol.HGTYPE) return ['HTTP authentication required'] u.path = posixpath.join(u.path or '', req.env['PATH_INFO']).strip('/') url = str(u) repopath = os.path.join(self.cachepath, path) path = path or '/' try: # Reuse auth if possible - checking remotely is expensive peer, ts = peercache.get((u.user, u.passwd, path), (None, None)) if peer is not None and time.time() > ts + self.ttl: self.ui.note(_('%s@%s expired, age %s\n') % (u.user, path, time.time() - ts)) peer = None peercache[(u.user, u.passwd, path)] = (peer, ts) # peer is now None or valid try: repo = hg.repository(self.ui, path=repopath) except error.RepoError as e: hg.peer(self.ui, {}, url) # authenticate / authorize first if os.path.exists(repopath) or not self.clone: self.ui.warn(_("error with path %r: %s\n") % (path, e)) req.respond(common.HTTP_NOT_FOUND, protocol.HGTYPE) return ['repository %s not found in proxy' % path] self.ui.warn(_("%r not found locally - cloning\n") % path) try: repodir = os.path.dirname(repopath) if not os.path.exists(repodir): os.makedirs(repodir) peer, destpeer = hg.clone(self.ui, {}, url, repopath, stream=True, update=False) except Exception as e: self.ui.warn(_("error cloning %r: %s\n") % (path, e)) req.respond(common.HTTP_NOT_FOUND, protocol.HGTYPE) return ['repository %s not available' % path] repo = destpeer.local() if cmd in ['capabilities', 'batch', 'lookup', 'branchmap'] and not peer: # new session on expired repo - do auth and pull again self.ui.note(_('%s@%s - pulling\n') % (u.user, path)) t0 = time.time() peer = hg.peer(self.ui, {}, url) with repo.lock(): try: r = pull(repo, peer) except error.RepoError as e: self.ui.debug('got %s on pull - running recover\n' % (e,)) repo.recover() # should also run hg.verify(repo) ... but too expensive r = pull(repo, peer) self.ui.debug('pull got %r after %s\n' % (r, time.time() - t0)) peercache[(u.user, u.passwd, path)] = (peer, time.time()) elif ts is None: # never authenticated self.ui.note('%s@%s - authenticating\n' % (u.user, path)) peer = hg.peer(self.ui, {}, url) self.ui.debug('%s@%s - authenticated\n' % (u.user, path)) peercache[(u.user, u.passwd, path)] = (peer, time.time()) # user is now auth'ed for this session # fetch largefiles whenever they are referenced # (creating fake/combined batch statlfile responses is too complex) shas = [] if cmd in ['statlfile', 'getlfile']: shas.append(args['sha']) if cmd == 'batch': for x in args['cmds'].split(';'): if x.startswith('statlfile sha='): shas.append(x[14:]) missingshas = [sha for sha in shas if not lfutil.findfile(repo, sha)] if missingshas: self.ui.debug('%s@%s - missing %s\n' % (u.user, path, ' '.join(missingshas))) if not peer: peer = hg.peer(self.ui, {}, url) store = openstore(repo, peer, False) existsremotely = store.exists(missingshas) for sha, available in sorted(existsremotely.iteritems()): if not available: self.ui.warn('%s@%s - %s not available remotely\n' % (u.user, path, sha)) continue self.ui.write('%s@%s - fetching %s\n' % (u.user, path, sha)) gotit = store._gethash(sha, sha) if not gotit: self.ui.warn(_('failed to get %s for %s@%s remotely\n' ) % (sha, u.user, path)) peercache[(u.user, u.passwd, path)] = (peer, time.time()) # Forward write commands to the remote server. # Lookup and listkeys are also forwarded so we get # local tags, bookmarks and phases from the server if cmd in ['putlfile', 'unbundle', 'pushkey', 'lookup', 'listkeys']: size = req.env.get('CONTENT_LENGTH') self.ui.debug('reading %s bytes content before forwarding\n' % size) data = None if req.env['REQUEST_METHOD'] == 'POST' or size is not None: data = req.read(int(size or 0)) if not peer: peer = hg.peer(self.ui, {}, url) self.ui.note(_('calling %s remotely\n') % cmd) with repo.lock(): r = peer._call(cmd, data=data, **args) if cmd == 'unbundle': self.ui.debug('fetching pushed changes back\n') # we could perhaps just have pulled from data ... but it # could be tricky to make sure the repo stays in sync ... pull(repo, peer) peercache[(u.user, u.passwd, path)] = (peer, time.time()) req.respond(common.HTTP_OK, protocol.HGTYPE) return [r] # Now serve it locally return protocol.call(repo, req, cmd) except urllib2.HTTPError as inst: self.ui.warn(_('HTTPError connecting to server: %s\n') % inst) req.respond(inst.code, protocol.HGTYPE) return ['HTTP error'] except error.Abort as e: # hg.peer will abort when it gets 401 if e.args not in [('http authorization required',), ('authorization failed',)]: raise self.ui.warn('%s@%s error: %r\n' % (u.user, path, e.args[0])) er = common.ErrorResponse( common.HTTP_UNAUTHORIZED if e.args == ('http authorization required',) else common.HTTP_BAD_REQUEST, 'Authentication is required', self.authheaders) req.respond(er, protocol.HGTYPE) return ['HTTP authentication required'] except Exception as e: msg = 'Internal proxy server error - please contact the administrator: %s' % e self.ui.warn('%s\n' % msg) # TODO: log traceback? req.respond(common.ErrorResponse(common.HTTP_SERVER_ERROR, msg), 'text/plain') return [msg]
def testauthinfo(fullurl, authurl): print 'URIs:', fullurl, authurl pm = urllib2.HTTPPasswordMgrWithDefaultRealm() pm.add_password(*util.url(fullurl).authinfo()[1]) print pm.find_user_password('test', authurl)
def showbuildstatus(context, mapping): """:build_status: String. Status of build. """ repo = context.resource(mapping, b'repo') ui = repo.ui debug = ui.debugflag ctx = context.resource(mapping, b'ctx') store = jenkinsstore(repo.svfs, repo[b'tip'].rev()) storecache = store.load(ui) if debug: if len(storecache) <= 1: ui.debug(b'jenkins cache is empty\n') else: ui.debug(b'jenkins cache: {}\n'.format(storecache)) url = ui.config(b'jenkins', b'url') if not url: raise error.Abort('jenkins.url configuration option is not defined') res = httpconnectionmod.readauthforuri(repo.ui, url, util.url(url).user) if res: group, auth = res ui.debug(b"using auth.%s.* for authentication\n" % group) username = auth.get('username') password = auth.get('password') if not username or not password: raise error.Abort( "cannot fine 'username' and/or 'password' values for %s" % url) else: ui.debug(b"no 'auth' configuration for %s\n" % url) username, password = None, None username = ui.config(b'jenkins', b'username') password = ui.config(b'jenkins', b'password') server = Jenkins(url.decode('utf-8'), username=username, password=password) if 'jobs' not in storecache: jobnames = ui.config(b'jenkins', b'job').decode('utf-8') jobs = [n.strip() for n in jobnames.split(',')] storecache['jobs'] = {name: {} for name in jobs} elif debug: ui.debug(b'using cached jobs\n') def gen_jobs_buildinfo(): for job, jobcache in storecache['jobs'].items(): if not jobcache: jobcache.update(buildinfo_for_job(server, job)) elif debug: ui.debug(b'using cached build info for job %s\n' % job) build_info = jobcache.get(ctx.hex().decode('utf-8')) if not build_info: yield '{}: NOT BUILT\n'.format(job) continue if build_info['building']: status = 'BUILDING' else: status = build_info['status'] build_url = build_info['url'] yield '{}: {} - {}\n'.format(job, status, build_url) jobs_buildinfo = [v.encode('utf-8') for v in gen_jobs_buildinfo()] store.save() if not jobs_buildinfo: jobs_buildinfo.append(b'NOT BUILT') return templatekw.compatlist(context, mapping, b'build_status', jobs_buildinfo)
def _url_without_authentication(url): """return an url instance without user or password entries""" u = util.url(url) u.user = None u.passwd = None return u
def wrappedpush(orig, repo, remote, force=False, revs=None, newbranch=False, **kwargs): """Wraps exchange.push to enforce restrictions for review pushes.""" # The repository does not support pushing reviews. caps = getreviewcaps(remote) if "pushreview" not in caps: # See if this repository is a special "discovery" repository # and follow the link, if present. if "listreviewrepos2" not in caps: return orig(repo, remote, force=force, revs=revs, newbranch=newbranch, **kwargs) rootnode = repo[0].hex() repo.ui.status(_("searching for appropriate review repository\n")) for line in remote._call("listreviewrepos").splitlines(): node, urls = line.split(" ", 1) if node == rootnode: newurls = urls.split(" ") break else: raise util.Abort(_("no review repository found")) oldurl = util.url(remote._url) if oldurl.scheme in ("http", "https"): newurl = newurls[0] elif oldurl.scheme == "ssh": newurl = newurls[1] else: raise util.Abort("can only use autoreview repos over HTTP or SSH") newurl = util.url(newurl) # We don't currently allow redirecting to different hosts out of an # abundance of caution around security concerns. In theory, this should # be OK since if we talked to the host, we presumably trusted it. So # why shouldn't we trust a redirect? # If this ever changes, watch out for credential copying when modifying # the remote below. if newurl.host != oldurl.host: raise util.Abort(_("refusing to redirect due to URL mismatch: %s" % newurl)) repo.ui.status(_("redirecting push to %s\n") % newurl) if isinstance(remote, httppeer.httppeer): remote._url = str(newurl) newurl.user = oldurl.user newurl.passwd = oldurl.passwd remote.path = str(newurl) # Wipe out cached capabilities. remote.caps = None newremote = remote elif isinstance(remote, sshpeer.sshpeer): newurl.user = oldurl.user # SSH remotes establish processes. We can't simply monkeypatch # the instance. newremote = type(remote)(remote.ui, str(newurl)) else: raise util.Abort(_("do not know how to talk to this remote type\n")) return wrappedpush(orig, repo, newremote, force=False, revs=revs, newbranch=False, **kwargs) ircnick = repo.ui.config("mozilla", "ircnick", None) if not ircnick: raise util.Abort( _( "you must set mozilla.ircnick in your hgrc config " "file to your IRC nickname in order to perform code reviews" ) ) # We filter the "extension isn't installed" message from the server. # This is a bit hacky, but it's easier than sending a signal over the # wire protocol (at least until bundle2). def filterwrite(messages): # Mercurial 3.5 sends the output as one string. if messages[0].startswith("%sREVIEWBOARD" % _("remote: ")): return True # Older versions have separate components. if messages[0] == _("remote: ") and len(messages) >= 2 and messages[1].startswith("REVIEWBOARD: "): return True return False # Starting with Mercurial 3.5 or possibly bundle2, remote messages are # now written to the repo's ui instance as opposed to the remote's. We # wrap both instances until we drop support for Mercurial 3.4. oldrepocls = repo.ui.__class__ oldremotecls = remote.ui.__class__ class repofilteringwrite(repo.ui.__class__): def write(self, *args, **kwargs): if not filterwrite(args): return oldrepocls.write(self, *args, **kwargs) class remotefilteringwrite(remote.ui.__class__): def write(self, *args, **kwargs): if not filterwrite(args): return oldremotecls.write(self, *args, **kwargs) repo.ui.__class__ = repofilteringwrite remote.ui.__class__ = remotefilteringwrite try: # We always do force push because we don't want users to need to # specify it. The big danger here is pushing multiple heads or # branches or mq patches. We check the former above and we don't # want to limit user choice on the latter two. return orig(repo, remote, force=True, revs=revs, newbranch=newbranch, **kwargs) finally: repo.ui.__class__ = oldrepocls remote.ui.__class__ = oldremotecls
def clone_cache_cmd(ui, source, dest=None, **opts): source_url = url(source) if source_url.fragment is not None: raise ValueError('Someone is being clever! We are not clever. Bail.') orig_source = source cache_source = os.path.join(CACHE, url_to_filename(source)) was_cached = False clone_source = source if not opts.get('nocache'): was_cached = os.path.exists(cache_source) if was_cached: ui.status('cloning from cache {}\n'.format(cache_source)) clone_source = cache_source if dest is None: dest = hg.defaultdest(source) if opts.get('rev'): ui.status('updating cache {} to rev {}\n'.format(cache_source, opts.get('rev'))) cache_peer = hg.peer(ui, {}, cache_source) commands.pull(cache_peer.ui, cache_peer.local(), noupdate=True, rev=opts.get('rev')) else: ui.status('no cache found at {}, cloning from source {}\n'.format( cache_source, source)) if opts.get('noupdate') and opts.get('updaterev'): raise util.Abort(_("cannot specify both --noupdate and --updaterev")) r = hg.clone(ui, opts, clone_source, dest, pull=opts.get('pull'), stream=opts.get('uncompressed'), rev=opts.get('rev'), update=opts.get('updaterev') or not opts.get('noupdate'), branch=opts.get('branch')) if r is None: return True source_peer, dest_peer = r if was_cached: dest_repo = dest_peer.local() if dest_repo: orig_source = dest_repo.ui.expandpath(orig_source) abspath = orig_source if hg.islocal(orig_source): abspath = os.path.abspath(hg.util.urllocalpath(orig_source)) u = url(abspath) u.passwd = None defaulturl = str(u) fp = dest_repo.opener("hgrc", "w", text=True) fp.write("[paths]\n") fp.write("default = %s\n" % defaulturl) fp.write('\n') fp.write('[clonecache]\n') fp.write('cache = %s\n' % cache_source) fp.close() dest_repo.ui.setconfig('paths', 'default', defaulturl, 'clone') commands.pull(dest_repo.ui, dest_repo) commands.update(ui, dest_repo) return False
def islocal(path): if isgitsshuri(path): return True u = util.url(path) return not u.scheme or u.scheme == 'file'
def wrappedpush(orig, repo, remote, force=False, revs=None, newbranch=False, **kwargs): """Wraps exchange.push to enforce restrictions for review pushes.""" # The repository does not support pushing reviews. caps = getreviewcaps(remote) if 'pushreview' not in caps: # See if this repository is a special "discovery" repository # and follow the link, if present. if 'listreviewrepos2' not in caps: return orig(repo, remote, force=force, revs=revs, newbranch=newbranch, **kwargs) rootnode = repo[0].hex() repo.ui.status(_('searching for appropriate review repository\n')) data = calljsoncommand(repo.ui, remote, 'listreviewrepos') for node, urls in data.iteritems(): if node == rootnode: newurls = urls break else: raise util.Abort(_('no review repository found')) oldurl = util.url(remote._url) if oldurl.scheme in ('http', 'https'): newurl = newurls[0] elif oldurl.scheme == 'ssh': newurl = newurls[1] else: raise util.Abort('can only use autoreview repos over HTTP or SSH') newurl = util.url(newurl) # We don't currently allow redirecting to different hosts out of an # abundance of caution around security concerns. In theory, this should # be OK since if we talked to the host, we presumably trusted it. So # why shouldn't we trust a redirect? # If this ever changes, watch out for credential copying when modifying # the remote below. if newurl.host != oldurl.host: raise util.Abort( _('refusing to redirect due to URL mismatch: %s' % newurl)) repo.ui.status(_('redirecting push to %s\n') % newurl) if isinstance(remote, httppeer.httppeer): remote._url = str(newurl) newurl.user = oldurl.user newurl.passwd = oldurl.passwd remote.path = str(newurl) # Wipe out cached capabilities. remote.caps = None newremote = remote elif isinstance(remote, sshpeer.sshpeer): newurl.user = oldurl.user # SSH remotes establish processes. We can't simply monkeypatch # the instance. newremote = type(remote)(remote.ui, str(newurl)) else: raise util.Abort( _('do not know how to talk to this remote type\n')) return wrappedpush(orig, repo, newremote, force=False, revs=revs, newbranch=False, **kwargs) ircnick = repo.ui.config('mozilla', 'ircnick', None) if not ircnick: raise util.Abort( _('you must set mozilla.ircnick in your hgrc config ' 'file to your IRC nickname in order to perform code reviews')) # We filter the "extension isn't installed" message from the server. # This is a bit hacky, but it's easier than sending a signal over the # wire protocol (at least until bundle2). def filterwrite(messages): # Mercurial 3.5 sends the output as one string. # Starting with Mercurial 3.9.1, the string is localized with # _('remote: '). if messages[0].startswith('%sREVIEWBOARD' % _('remote: ')): return True # Older versions have separate components. if messages[0] == _('remote: ') and len(messages) >= 2 and \ messages[1].startswith('REVIEWBOARD: '): return True return False # Starting with Mercurial 3.5 or possibly bundle2, remote messages are # now written to the repo's ui instance as opposed to the remote's. We # wrap both instances until we drop support for Mercurial 3.4. oldrepocls = repo.ui.__class__ oldremotecls = remote.ui.__class__ class repofilteringwrite(repo.ui.__class__): def write(self, *args, **kwargs): if not filterwrite(args): return oldrepocls.write(self, *args, **kwargs) class remotefilteringwrite(remote.ui.__class__): def write(self, *args, **kwargs): if not filterwrite(args): return oldremotecls.write(self, *args, **kwargs) repo.ui.__class__ = repofilteringwrite remote.ui.__class__ = remotefilteringwrite try: # We always do force push because we don't want users to need to # specify it. The big danger here is pushing multiple heads or # branches or mq patches. We check the former above and we don't # want to limit user choice on the latter two. return orig(repo, remote, force=True, revs=revs, newbranch=newbranch, **kwargs) finally: repo.ui.__class__ = oldrepocls remote.ui.__class__ = oldremotecls
def wrappedpush(orig, repo, remote, force=False, revs=None, newbranch=False, **kwargs): """Wraps exchange.push to enforce restrictions for review pushes.""" # The repository does not support pushing reviews. caps = getreviewcaps(remote) if 'pushreview' not in caps: # See if this repository is a special "discovery" repository # and follow the link, if present. if 'listreviewrepos' not in caps: return orig(repo, remote, force=force, revs=revs, newbranch=newbranch, **kwargs) repo.ui.status(_('searching for appropriate review repository\n')) repos = remote.listkeys('reviewrepos') rootnode = repo[0].hex() newurl = None for url, node in repos.items(): if rootnode == node: newurl = url break else: raise util.Abort(_('no review repository found')) newurl = util.url(newurl) oldurl = util.url(remote._url) # We don't currently allow redirecting to different protocols # or hosts. This is due to abundance of caution around # security concerns. if newurl.scheme != oldurl.scheme or newurl.host != oldurl.host: raise util.Abort(_('refusing to redirect due to URL mismatch: %s' % newurl)) repo.ui.status(_('redirecting push to %s\n') % newurl) if isinstance(remote, httppeer.httppeer): remote._url = str(newurl) newurl.user = oldurl.user newurl.passwd = oldurl.passwd remote.path = str(newurl) newremote = remote elif isinstance(remote, sshpeer.sshpeer): newurl.user = oldurl.user # SSH remotes establish processes. We can't simply monkeypatch # the instance. newremote = type(remote)(remote.ui, str(newurl)) else: raise util.Abort(_('do not know how to talk to this remote type\n')) return wrappedpush(orig, repo, newremote, force=False, revs=revs, newbranch=False, **kwargs) ircnick = repo.ui.config('mozilla', 'ircnick', None) if not ircnick: raise util.Abort(_('you must set mozilla.ircnick in your hgrc config ' 'file to your IRC nickname in order to perform code reviews')) # We filter the "extension isn't installed" message from the server. # This is a bit hacky, but it's easier than sending a signal over the # wire protocol (at least until bundle2). def filterwrite(messages): # Mercurial 3.5 sends the output as one string. if messages[0].startswith('%sREVIEWBOARD' % _('remote: ')): return True # Older versions have separate components. if messages[0] == _('remote: ') and len(messages) >= 2 and \ messages[1].startswith('REVIEWBOARD: '): return True return False # Starting with Mercurial 3.5 or possibly bundle2, remote messages are # now written to the repo's ui instance as opposed to the remote's. We # wrap both instances until we drop support for Mercurial 3.4. oldrepocls = repo.ui.__class__ oldremotecls = remote.ui.__class__ class repofilteringwrite(repo.ui.__class__): def write(self, *args, **kwargs): if not filterwrite(args): return oldrepocls.write(self, *args, **kwargs) class remotefilteringwrite(remote.ui.__class__): def write(self, *args, **kwargs): if not filterwrite(args): return oldremotecls.write(self, *args, **kwargs) repo.ui.__class__ = repofilteringwrite remote.ui.__class__ = remotefilteringwrite try: # We always do force push because we don't want users to need to # specify it. The big danger here is pushing multiple heads or # branches or mq patches. We check the former above and we don't # want to limit user choice on the latter two. return orig(repo, remote, force=True, revs=revs, newbranch=newbranch, **kwargs) finally: repo.ui.__class__ = oldrepocls remote.ui.__class__ = oldremotecls
def islocal(path): u = util.url(path) return not u.scheme or u.scheme == 'file'
def spliturl(url): return util.url(url).authinfo()
def testauthinfo(fullurl, authurl): print('URIs:', fullurl, authurl) pm = urlreq.httppasswordmgrwithdefaultrealm() pm.add_password(*util.url(fullurl).authinfo()[1]) print(pm.find_user_password('test', authurl))