def __del__(self): # copied from mercurial/httppeer.py urlopener = getattr(self, 'urlopener', None) if urlopener: for h in urlopener.handlers: h.close() getattr(h, "close_all", lambda: None)()
def kwpatchfile_init(orig, self, ui, gp, backend, store, eolmode=None): '''Monkeypatch/wrap patch.patchfile.__init__ to avoid rejects or conflicts due to expanded keywords in working dir.''' orig(self, ui, gp, backend, store, eolmode) kwt = getattr(getattr(backend, 'repo', None), '_keywordkwt', None) if kwt: # shrink keywords read from working dir self.lines = kwt.shrinklines(self.fname, self.lines)
def __init__(self, ui, path): self.ui = ui self.path = path # lastrefesh is 0 so we'll immediately check for new packs on the first # failure. self.lastrefresh = 0 packs = [] for filepath, __, __ in self._getavailablepackfilessorted(): try: pack = self.getpack(filepath) except Exception as ex: # An exception may be thrown if the pack file is corrupted # somehow. Log a warning but keep going in this case, just # skipping this pack file. # # If this is an ENOENT error then don't even bother logging. # Someone could have removed the file since we retrieved the # list of paths. if getattr(ex, 'errno', None) != errno.ENOENT: ui.warn( _(b'unable to load pack %s: %s\n') % (filepath, ex)) continue packs.append(pack) self.packs = _cachebackedpacks(packs, self.DEFAULTCACHESIZE)
def _create_auth_baton(pool): """Create a Subversion authentication baton.""" import svn.client # Give the client context baton a suite of authentication # providers.h providers = [ svn.client.get_simple_provider(pool), svn.client.get_username_provider(pool), svn.client.get_ssl_client_cert_file_provider(pool), svn.client.get_ssl_client_cert_pw_file_provider(pool), svn.client.get_ssl_server_trust_file_provider(pool), ] # Platform-dependent authentication methods getprovider = getattr(svn.core, 'svn_auth_get_platform_specific_provider', None) if getprovider: # Available in svn >= 1.6 for name in (b'gnome_keyring', b'keychain', b'kwallet', b'windows'): for type in (b'simple', b'ssl_client_cert_pw', b'ssl_server_trust'): p = getprovider(name, type, pool) if p: providers.append(p) else: if util.safehasattr(svn.client, b'get_windows_simple_provider'): providers.append(svn.client.get_windows_simple_provider(pool)) return svn.core.svn_auth_open(providers, pool)
def kw_copy(orig, ui, repo, pats, opts, rename=False): """Wraps cmdutil.copy so that copy/rename destinations do not contain expanded keywords. Note that the source of a regular file destination may also be a symlink: hg cp sym x -> x is symlink cp sym x; hg cp -A sym x -> x is file (maybe expanded keywords) For the latter we have to follow the symlink to find out whether its target is configured for expansion and we therefore must unexpand the keywords in the destination.""" kwt = getattr(repo, '_keywordkwt', None) if kwt is None: return orig(ui, repo, pats, opts, rename) with repo.wlock(): orig(ui, repo, pats, opts, rename) if opts.get(b'dry_run'): return wctx = repo[None] cwd = repo.getcwd() def haskwsource(dest): """Returns true if dest is a regular file and configured for expansion or a symlink which points to a file configured for expansion.""" source = repo.dirstate.copied(dest) if b'l' in wctx.flags(source): source = pathutil.canonpath(repo.root, cwd, os.path.realpath(source)) return kwt.match(source) candidates = [ f for f in repo.dirstate.copies() if b'l' not in wctx.flags(f) and haskwsource(f) ] kwt.overwrite(wctx, candidates, False, False)
def files(ui, repo, *pats, **opts): '''show files configured for keyword expansion List which files in the working directory are matched by the [keyword] configuration patterns. Useful to prevent inadvertent keyword expansion and to speed up execution by including only files that are actual candidates for expansion. See :hg:`help keyword` on how to construct patterns both for inclusion and exclusion of files. With -A/--all and -v/--verbose the codes used to show the status of files are:: K = keyword expansion candidate k = keyword expansion candidate (not tracked) I = ignored i = ignored (not tracked) ''' kwt = getattr(repo, '_keywordkwt', None) wctx = repo[None] status = _status(ui, repo, wctx, kwt, *pats, **opts) if pats: cwd = repo.getcwd() else: cwd = b'' files = [] opts = pycompat.byteskwargs(opts) if not opts.get(b'unknown') or opts.get(b'all'): files = sorted(status.modified + status.added + status.clean) kwfiles = kwt.iskwfile(files, wctx) kwdeleted = kwt.iskwfile(status.deleted, wctx) kwunknown = kwt.iskwfile(status.unknown, wctx) if not opts.get(b'ignore') or opts.get(b'all'): showfiles = kwfiles, kwdeleted, kwunknown else: showfiles = [], [], [] if opts.get(b'all') or opts.get(b'ignore'): showfiles += ( [f for f in files if f not in kwfiles], [f for f in status.unknown if f not in kwunknown], ) kwlabels = b'enabled deleted enabledunknown ignored ignoredunknown'.split() kwstates = zip(kwlabels, pycompat.bytestr(b'K!kIi'), showfiles) fm = ui.formatter(b'kwfiles', opts) fmt = b'%.0s%s\n' if opts.get(b'all') or ui.verbose: fmt = b'%s %s\n' for kwstate, char, filenames in kwstates: label = b'kwfiles.' + kwstate for f in filenames: fm.startitem() fm.data(kwstatus=char, path=f) fm.plain(fmt % (char, repo.pathto(f, cwd)), label=label) fm.end()
def filectxcmp(orig, self, fctx): """returns True if text is different than fctx""" # some fctx (ex. hg-git) is not based on basefilectx and do not have islfs if self.islfs() and getattr(fctx, 'islfs', lambda: False)(): # fast path: check LFS oid p1 = pointer.deserialize(self.rawdata()) p2 = pointer.deserialize(fctx.rawdata()) return p1.oid() != p2.oid() return orig(self, fctx)
def wrapname(name, wrapper): module, name = name.rsplit(b'.', 1) module = sys.modules[module] func = getattr(module, name) def f(*args, **kwds): return wrapper(func, args, kwds) f.__name__ = func.__name__ setattr(module, name, f)
def vfsinit(orig, self, othervfs): orig(self, othervfs) # copy lfs related options for k, v in othervfs.options.items(): if k.startswith(b'lfs'): self.options[k] = v # also copy lfs blobstores. note: this can run before reposetup, so lfs # blobstore attributes are not always ready at this time. for name in [b'lfslocalblobstore', b'lfsremoteblobstore']: if util.safehasattr(othervfs, name): setattr(self, name, getattr(othervfs, name))
def _kwfwrite(ui, repo, expand, *pats, **opts): '''Selects files and passes them to kwtemplater.overwrite.''' wctx = repo[None] if len(wctx.parents()) > 1: raise error.Abort(_(b'outstanding uncommitted merge')) kwt = getattr(repo, '_keywordkwt', None) with repo.wlock(): status = _status(ui, repo, wctx, kwt, *pats, **opts) if status.modified or status.added or status.removed or status.deleted: raise error.Abort(_(b'outstanding uncommitted changes')) kwt.overwrite(wctx, status.clean, True, expand)
def openstore(repo=None, remote=None, put=False, ui=None): if ui is None: ui = repo.ui if not remote: lfpullsource = getattr(repo, 'lfpullsource', None) if put: path = urlutil.get_unique_push_path( b'lfpullsource', repo, ui, lfpullsource ) else: path, _branches = urlutil.get_unique_pull_path( b'lfpullsource', repo, ui, lfpullsource ) # XXX we should not explicitly pass b'default', as this will result in # b'default' being returned if no `paths.default` was defined. We # should explicitely handle the lack of value instead. if repo is None: path, _branches = urlutil.get_unique_pull_path( b'lfs', repo, ui, b'default' ) remote = hg.peer(repo or ui, {}, path) elif path == b'default-push' or path == b'default': remote = repo else: path, _branches = urlutil.parseurl(path) remote = hg.peer(repo or ui, {}, path) # The path could be a scheme so use Mercurial's normal functionality # to resolve the scheme to a repository and use its path path = util.safehasattr(remote, b'url') and remote.url() or remote.path match = _scheme_re.match(path) if not match: # regular filesystem path scheme = b'file' else: scheme = match.group(1) try: storeproviders = _storeprovider[scheme] except KeyError: raise error.Abort(_(b'unsupported URL scheme %r') % scheme) for classobj in storeproviders: try: return classobj(ui, repo, remote) except lfutil.storeprotonotcapable: pass raise error.Abort( _(b'%s does not appear to be a largefile store') % urlutil.hidepassword(path) )
def kwweb_skip(orig, web): '''Wraps webcommands.x turning off keyword expansion.''' kwt = getattr(web.repo, '_keywordkwt', None) if kwt: origmatch = kwt.match kwt.match = util.never try: for chunk in orig(web): yield chunk finally: if kwt: kwt.match = origmatch
def kwdiff(orig, repo, *args, **kwargs): '''Monkeypatch patch.diff to avoid expansion.''' kwt = getattr(repo, '_keywordkwt', None) if kwt: restrict = kwt.restrict kwt.restrict = True try: for chunk in orig(repo, *args, **kwargs): yield chunk finally: if kwt: kwt.restrict = restrict
def kw_amend(orig, ui, repo, old, extra, pats, opts): '''Wraps cmdutil.amend expanding keywords after amend.''' kwt = getattr(repo, '_keywordkwt', None) if kwt is None: return orig(ui, repo, old, extra, pats, opts) with repo.wlock(): kwt.postcommit = True newid = orig(ui, repo, old, extra, pats, opts) if newid != old.node(): ctx = repo[newid] kwt.restrict = True kwt.overwrite(ctx, ctx.files(), False, True) kwt.restrict = False return newid
def openstore(repo=None, remote=None, put=False, ui=None): if ui is None: ui = repo.ui if not remote: lfpullsource = getattr(repo, 'lfpullsource', None) if lfpullsource: path = ui.expandpath(lfpullsource) elif put: path = ui.expandpath(b'default-push', b'default') else: path = ui.expandpath(b'default') # ui.expandpath() leaves 'default-push' and 'default' alone if # they cannot be expanded: fallback to the empty string, # meaning the current directory. if repo is None: path = ui.expandpath(b'default') path, _branches = hg.parseurl(path) remote = hg.peer(repo or ui, {}, path) elif path == b'default-push' or path == b'default': remote = repo else: path, _branches = hg.parseurl(path) remote = hg.peer(repo or ui, {}, path) # The path could be a scheme so use Mercurial's normal functionality # to resolve the scheme to a repository and use its path path = util.safehasattr(remote, b'url') and remote.url() or remote.path match = _scheme_re.match(path) if not match: # regular filesystem path scheme = b'file' else: scheme = match.group(1) try: storeproviders = _storeprovider[scheme] except KeyError: raise error.Abort(_(b'unsupported URL scheme %r') % scheme) for classobj in storeproviders: try: return classobj(ui, repo, remote) except lfutil.storeprotonotcapable: pass raise error.Abort( _(b'%s does not appear to be a largefile store') % util.hidepassword(path))
def kwfilectx_cmp(orig, self, fctx): if fctx._customcmp: return fctx.cmp(self) kwt = getattr(self._repo, '_keywordkwt', None) if kwt is None: return orig(self, fctx) # keyword affects data size, comparing wdir and filelog size does # not make sense if (fctx._filenode is None and (self._repo._encodefilterpats or kwt.match(fctx.path()) and b'l' not in fctx.flags() or self.size() - 4 == fctx.size()) or self.size() == fctx.size()): return self._filelog.cmp(self._filenode, fctx.data()) return True
def kw_dorecord(orig, ui, repo, commitfunc, *pats, **opts): '''Wraps record.dorecord expanding keywords after recording.''' kwt = getattr(repo, '_keywordkwt', None) if kwt is None: return orig(ui, repo, commitfunc, *pats, **opts) with repo.wlock(): # record returns 0 even when nothing has changed # therefore compare nodes before and after kwt.postcommit = True ctx = repo[b'.'] wstatus = ctx.status() ret = orig(ui, repo, commitfunc, *pats, **opts) recctx = repo[b'.'] if ctx != recctx: modified, added = _preselect(wstatus, recctx.files()) kwt.restrict = False kwt.overwrite(recctx, modified, False, True) kwt.overwrite(recctx, added, False, True, True) kwt.restrict = True return ret
def _checkforservererror(self, pointers, responses, action): """Scans errors from objects Raises LfsRemoteError if any objects have an error""" for response in responses: # The server should return 404 when objects cannot be found. Some # server implementation (ex. lfs-test-server) does not set "error" # but just removes "download" from "actions". Treat that case # as the same as 404 error. if b'error' not in response: if action == b'download' and action not in response.get( b'actions', [] ): code = 404 else: continue else: # An error dict without a code doesn't make much sense, so # treat as a server error. code = response.get(b'error').get(b'code', 500) ptrmap = {p.oid(): p for p in pointers} p = ptrmap.get(response[b'oid'], None) if p: filename = getattr(p, 'filename', b'unknown') errors = { 404: b'The object does not exist', 410: b'The object was removed by the owner', 422: b'Validation error', 500: b'Internal server error', } msg = errors.get(code, b'status code %d' % code) raise LfsRemoteError( _(b'LFS server error for "%s": %s') % (filename, msg) ) else: raise LfsRemoteError( _(b'LFS server error. Unsolicited response for oid %s') % response[b'oid'] )
def _urlerrorreason(urlerror): '''Create a friendly message for the given URLError to be used in an LfsRemoteError message. ''' inst = urlerror if isinstance(urlerror.reason, Exception): inst = urlerror.reason if util.safehasattr(inst, b'reason'): try: # usually it is in the form (errno, strerror) reason = inst.reason.args[1] except (AttributeError, IndexError): # it might be anything, for example a string reason = inst.reason if isinstance(reason, pycompat.unicode): # SSLError of Python 2.7.9 contains a unicode reason = encoding.unitolocal(reason) return reason elif getattr(inst, "strerror", None): return encoding.strtolocal(inst.strerror) else: return stringutil.forcebytestr(urlerror)
def __getattr__(self, name): return getattr(self._fctx, name)
def _sanitizemetacache(self): metacache = getattr(self._threaddata, 'metacache', None) if metacache is None: self._threaddata.metacache = (None, None) # (node, meta)
def _getloglevel(ui): loglevel = ui.config(b'infinitepush', b'loglevel', b'DEBUG') numeric_loglevel = getattr(logging, loglevel.upper(), None) if not isinstance(numeric_loglevel, int): raise error.Abort(_(b'invalid log level %s') % loglevel) return numeric_loglevel
def _connect(self): root = self.cvsroot conntype = None user, host = None, None cmd = [b'cvs', b'server'] self.ui.status(_(b"connecting to %s\n") % root) if root.startswith(b":pserver:"): root = root[9:] m = re.match( r'(?:(.*?)(?::(.*?))?@)?([^:\/]*)(?::(\d*))?(.*)', root ) if m: conntype = b"pserver" user, passw, serv, port, root = m.groups() if not user: user = b"anonymous" if not port: port = 2401 else: port = int(port) format0 = b":pserver:%s@%s:%s" % (user, serv, root) format1 = b":pserver:%s@%s:%d%s" % (user, serv, port, root) if not passw: passw = b"A" cvspass = os.path.expanduser(b"~/.cvspass") try: pf = open(cvspass, b'rb') for line in pf.read().splitlines(): part1, part2 = line.split(b' ', 1) # /1 :pserver:[email protected]:2401/cvsroot/foo # Ah<Z if part1 == b'/1': part1, part2 = part2.split(b' ', 1) format = format1 # :pserver:[email protected]:/cvsroot/foo Ah<Z else: format = format0 if part1 == format: passw = part2 break pf.close() except IOError as inst: if inst.errno != errno.ENOENT: if not getattr(inst, 'filename', None): inst.filename = cvspass raise sck = socket.socket() sck.connect((serv, port)) sck.send( b"\n".join( [ b"BEGIN AUTH REQUEST", root, user, passw, b"END AUTH REQUEST", b"", ] ) ) if sck.recv(128) != b"I LOVE YOU\n": raise error.Abort(_(b"CVS pserver authentication failed")) self.writep = self.readp = sck.makefile(b'r+') if not conntype and root.startswith(b":local:"): conntype = b"local" root = root[7:] if not conntype: # :ext:user@host/home/user/path/to/cvsroot if root.startswith(b":ext:"): root = root[5:] m = re.match(br'(?:([^@:/]+)@)?([^:/]+):?(.*)', root) # Do not take Windows path "c:\foo\bar" for a connection strings if os.path.isdir(root) or not m: conntype = b"local" else: conntype = b"rsh" user, host, root = m.group(1), m.group(2), m.group(3) if conntype != b"pserver": if conntype == b"rsh": rsh = encoding.environ.get(b"CVS_RSH") or b"ssh" if user: cmd = [rsh, b'-l', user, host] + cmd else: cmd = [rsh, host] + cmd # popen2 does not support argument lists under Windows cmd = [procutil.shellquote(arg) for arg in cmd] cmd = procutil.quotecommand(b' '.join(cmd)) self.writep, self.readp = procutil.popen2(cmd) self.realroot = root self.writep.write(b"Root %s\n" % root) self.writep.write( b"Valid-responses ok error Valid-requests Mode" b" M Mbinary E Checked-in Created Updated" b" Merged Removed\n" ) self.writep.write(b"valid-requests\n") self.writep.flush() r = self.readp.readline() if not r.startswith(b"Valid-requests"): raise error.Abort( _( b'unexpected response from CVS server ' b'(expected "Valid-requests", but got %r)' ) % r ) if b"UseUnchanged" in r: self.writep.write(b"UseUnchanged\n") self.writep.flush() self.readp.readline()
def hashdiffopts(diffopts): diffoptstr = stringutil.pprint( sorted((k, getattr(diffopts, k)) for k in mdiff.diffopts.defaults) ) return hex(hashutil.sha1(diffoptstr).digest())[:6]