def handlewsgirequest(orig, rctx, req, res, checkperm): """Wrap wireprotoserver.handlewsgirequest() to possibly process an LFS request if it is left unprocessed by the wrapped method. """ if orig(rctx, req, res, checkperm): return True if not rctx.repo.ui.configbool(b'experimental', b'lfs.serve'): return False if not util.safehasattr(rctx.repo.svfs, 'lfslocalblobstore'): return False if not req.dispatchpath: return False try: if req.dispatchpath == b'.git/info/lfs/objects/batch': checkperm(rctx, req, b'pull') return _processbatchrequest(rctx.repo, req, res) # TODO: reserve and use a path in the proposed http wireprotocol /api/ # namespace? elif req.dispatchpath.startswith(b'.hg/lfs/objects'): return _processbasictransfer( rctx.repo, req, res, lambda perm: checkperm(rctx, req, perm)) return False except hgwebcommon.ErrorResponse as e: # XXX: copied from the handler surrounding wireprotoserver._callhttp() # in the wrapped function. Should this be moved back to hgweb to # be a common handler? for k, v in e.headers: res.headers[k] = v res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e)) res.setbodybytes(b'0\n%s\n' % pycompat.bytestr(e)) return True
def parseoptions(ui, cmdoptions, args): cmdoptions = list(cmdoptions) opts = {} args = list(args) while True: try: args = fancyopts.fancyopts(list(args), cmdoptions, opts, True) break except getopt.GetoptError as ex: if "requires argument" in ex.msg: raise if ('--' + ex.opt) in ex.msg: flag = b'--' + pycompat.bytestr(ex.opt) elif ('-' + ex.opt) in ex.msg: flag = b'-' + pycompat.bytestr(ex.opt) else: raise error.Abort( _(b"unknown option %s") % pycompat.bytestr(ex.opt)) try: args.remove(flag) except Exception: msg = _(b"unknown option '%s' packed with other options") hint = _(b"please try passing the option as its own flag: -%s") raise error.Abort( msg % pycompat.bytestr(ex.opt), hint=hint % pycompat.bytestr(ex.opt), ) ui.warn(_(b"ignoring unknown option %s\n") % flag) args = list([convert(x) for x in args]) opts = dict([(k, convert(v)) if isinstance(v, bytes) else (k, v) for k, v in pycompat.iteritems(opts)]) return args, opts
def find_profiles_path(): """Find the path containing Firefox profiles. The location of Firefox profiles is OS dependent. This function handles the differences. """ path = None if platform.system() == 'Darwin': from Carbon import Folder, Folders pathref = Folder.FSFindFolder(Folders.kUserDomain, Folders.kApplicationSupportFolderType, Folders.kDontCreateFolder) basepath = pathref.FSRefMakePath() path = pycompat.bytestr(os.path.join(basepath, 'Firefox')) elif platform.system() == 'Windows': # From http://msdn.microsoft.com/en-us/library/windows/desktop/bb762494%28v=vs.85%29.aspx CSIDL_APPDATA = 26 path = pycompat.bytestr(win_get_folder_path(CSIDL_APPDATA)) if path: path = os.path.join(path, b'Mozilla', b'Firefox') else: # Assume POSIX # Pretty simple in comparison, eh? path = pycompat.bytestr(os.path.expanduser('~/.mozilla/firefox')) # This is a backdoor to facilitate testing, since find_profiles_path() # doesn't need to be run-time configurable. path = pycompat.bytestr(os.environ.get('FIREFOX_PROFILES_DIR', path)) return path
def makecommandline(self, fieldname, value): if self.bzvermajor >= 4: return "@%s %s" % (fieldname, pycompat.bytestr(value)) else: if fieldname == "id": fieldname = "bug_id" return "@%s = %s" % (fieldname, pycompat.bytestr(value))
def _basictransfer(self, obj, action, localstore): """Download or upload a single object using basic transfer protocol obj: dict, an object description returned by batch API action: string, one of ['upload', 'download'] localstore: blobstore.local See https://github.com/git-lfs/git-lfs/blob/master/docs/api/\ basic-transfers.md """ oid = pycompat.bytestr(obj['oid']) href = pycompat.bytestr(obj['actions'][action].get('href')) headers = obj['actions'][action].get('header', {}).items() request = util.urlreq.request(href) if action == 'upload': # If uploading blobs, read data from local blobstore. if not localstore.verify(oid): raise error.Abort(_('detected corrupt lfs object: %s') % oid, hint=_('run hg verify')) request.data = filewithprogress(localstore.open(oid), None) request.get_method = lambda: 'PUT' request.add_header('Content-Type', 'application/octet-stream') for k, v in headers: request.add_header(k, v) response = b'' try: req = self.urlopener.open(request) if self.ui.debugflag: self.ui.debug('Status: %d\n' % req.status) # lfs-test-server and hg serve return headers in different order self.ui.debug('%s\n' % '\n'.join(sorted(str(req.info()).splitlines()))) if action == 'download': # If downloading blobs, store downloaded data to local blobstore localstore.download(oid, req) else: while True: data = req.read(1048576) if not data: break response += data if response: self.ui.debug('lfs %s response: %s' % (action, response)) except util.urlerr.httperror as ex: if self.ui.debugflag: self.ui.debug('%s: %s\n' % (oid, ex.read())) raise LfsRemoteError(_('HTTP error: %s (oid=%s, action=%s)') % (ex, oid, action))
def get_bugzilla_login_cookie_from_profile(profile, url): """Given a Firefox profile path, try to find the login cookies for the given bugzilla URL.""" try: import sqlite3 except: raise NoSQLiteError() cookies = os.path.join(profile, b'cookies.sqlite') if not os.path.exists(cookies): return None, None host = pycompat.sysstr(urllibcompat.urlreq.urlparse(url).hostname) path = pycompat.sysstr(urllibcompat.urlreq.urlparse(url).path) # Firefox locks this file, so if we can't open it (browser is running) # then copy it somewhere else and try to open it. tempdir = None try: tempdir = tempfile.mkdtemp() tempcookies = os.path.join(tempdir, 'cookies.sqlite') shutil.copyfile(cookies, tempcookies) # Firefox uses sqlite's WAL feature, which bumps the sqlite # version number. Older sqlites will refuse to open the db, # but the actual format is the same (just the journalling is different). # Patch the file to give it an older version number so we can open it. with open(tempcookies, 'r+b') as f: f.seek(18, 0) f.write(b'\x01\x01') conn = sqlite3.connect(tempcookies) logins = conn.execute( "select value, path from moz_cookies " "where name = 'Bugzilla_login' and (host = ? or host = ?)", (host, "." + host)).fetchall() row = sorted(logins, key=lambda row: -matching_path_len(row[1], path))[0] login = row[0] cookie = conn.execute( "select value from moz_cookies " "where name = 'Bugzilla_logincookie' " " and (host = ? or host= ?) " " and path = ?", (host, "." + host, row[1])).fetchone()[0] conn.close() login = pycompat.bytestr(login) cookie = pycompat.bytestr(cookie) return login, cookie except IndexError: return None, None finally: if tempdir: shutil.rmtree(tempdir)
def feedentrygenerator(_context, entries, repo, url, urlbase): """Generator of mappings for pushlog feed entries field """ for pushid, user, date, node in entries: ctx = scmutil.revsingle(repo, node) filesgen = [{b'name': fn} for fn in ctx.files()] yield { b'node': pycompat.bytestr(node), b'date': isotime(date), b'user': xmlescape(pycompat.bytestr(user)), b'urlbase': pycompat.bytestr(urlbase), b'url': pycompat.bytestr(url), b'files': templateutil.mappinglist(filesgen), }
def bzauth(ui, require=False, fakegetpass=None, ffprofile=None): if fakegetpass: def newgetpass(arg): return fakegetpass getpass.getpass = newgetpass a = getbugzillaauth(ui, require=require, profile=ffprofile) if a: ui.write(b'userid: %s\n' % pycompat.bytestr(a.userid)) ui.write(b'cookie: %s\n' % pycompat.bytestr(a.cookie)) ui.write(b'username: %s\n' % pycompat.bytestr(a.username)) ui.write(b'password: %s\n' % pycompat.bytestr(a.password)) ui.write(b'apikey: %s\n' % pycompat.bytestr(a.apikey)) else: ui.write(b'no auth\n')
def hook(ui, repo, hooktype, node=None, **kwargs): if hooktype != b"pretxnclose": raise error.Abort( _(b'Unsupported hook type %r') % pycompat.bytestr(hooktype)) ctx = repo.unfiltered()[node] branches = set() for rev in repo.changelog.revs(start=ctx.rev()): rev = repo[rev] branches.add(rev.branch()) for branch in branches: if len(repo.revs("head() and not closed() and branch(%s)", branch)) > 1: raise error.Abort( _(b'Changes on branch %r resulted in multiple heads') % pycompat.bytestr(branch))
def wrappedcommit(orig, repo, *args, **kwargs): try: path_matcher = args[3] except IndexError: # In a rebase for example return orig(repo, *args, **kwargs) # In case hg changes the position of the arg # path_matcher will be empty in case of histedit assert isinstance(path_matcher, match.basematcher) or path_matcher is None try: lock = repo.wlock() status = repo.status(match=path_matcher) changed_files = sorted(status.modified + status.added) if changed_files: call_js_format(repo, changed_files) except Exception as e: repo.ui.warn(b'Exception %s\n' % pycompat.bytestr(str(e))) finally: lock.release() return orig(repo, *args, **kwargs)
def __init__(self, path): self.path = path self._random = pycompat.bytestr(uuid.uuid4()) lines = [] if os.path.exists(path): with open(path, 'rb') as fh: for line in fh: # Mercurial has special syntax to include other files. # ConfigObj doesn't recognize it. Normalize on read and # restore on write to preserve it. if line.startswith(b'%include'): line = b'#%s %s' % (self._random, line) if line.startswith(b';'): raise error.Abort( b'semicolon (;) comments in config ' b'files not supported', hint=b'use # for comments') lines.append(line) self.c = ConfigObj(infile=lines, encoding='utf-8', write_empty_values=True, list_values=False)
def _vcthome(): # Returns the directory where the vct clone is located here = os.path.dirname(os.path.abspath(__file__)) ext_dir = os.path.normpath(os.path.join(here, '..')) vct_dir = os.path.normpath(os.path.join(ext_dir, '..')) vcthome_dir = os.path.normpath(os.path.join(vct_dir, '..')) return pycompat.bytestr(vcthome_dir)
def pushlogwireproto(repo, proto, firstpush): """Return pushlog data from a start offset. The response is a series of lines. The first line starts with "0" or "1". This indicates success. If the line starts with "0", an error message should follow. e.g. ``0 exception when accessing sqlite``. All subsequent lines describe individual pushes. The format of these lines is: <push ID> <author> <when> <node0> [<node1> [<node2> ...]] That is: * An integer ID for the push. * A string of the user (SSH username) who performed the push * Integer seconds since UNIX epoch when this push was performed * A list of 40 byte hex changesets included in the push, in revset order """ lines = [b'1'] try: firstpush = int(firstpush) for pushid, who, when, nodes in repo.pushlog.pushes(start_id=firstpush): lines.append(b'%d %s %d %s' % (pushid, who, when, b' '.join(nodes))) return b'\n'.join(lines) except Exception as e: return b'\n'.join([b'0', pycompat.bytestr(e)])
def _runwsgi(self, req, res, repo): bytelimit = repo.ui.configint(b'badserver', b'bytelimit') untilgoodcount = repo.vfs.tryread(b'badserveruntilgood') if untilgoodcount: untilgoodcount = int(untilgoodcount) # This check is different than the one above because it is # comparing an int type instead of a string. The first check could # be true for "0" but this check would be false for int(0). if untilgoodcount: repo.vfs.write(b'badserveruntilgood', pycompat.bytestr(untilgoodcount - 1)) bytecount = 0 for r in super(droppinghgweb, self)._runwsgi(req, res, repo): # We serviced the requested number of requests. Do everything # like normal. if untilgoodcount == 0: yield r continue if bytelimit: if bytecount + len(r) >= bytelimit: yield r[0:bytelimit - bytecount] return bytecount += len(r) yield r bytecount += len(r)
def diffpatch(ui, repo, node1, node2, tmproot, matcher, cmdline): template = b'hg-%h.patch' # write patches to temporary files with formatter.nullformatter(ui, b'extdiff', {}) as fm: cmdutil.export( repo, [repo[node1].rev(), repo[node2].rev()], fm, fntemplate=repo.vfs.reljoin(tmproot, template), match=matcher, ) label1 = cmdutil.makefilename(repo[node1], template) label2 = cmdutil.makefilename(repo[node2], template) file1 = repo.vfs.reljoin(tmproot, label1) file2 = repo.vfs.reljoin(tmproot, label2) cmdline = formatcmdline( cmdline, repo.root, # no 3way while comparing patches do3way=False, parent1=file1, plabel1=label1, # while comparing patches, there is no second parent parent2=None, plabel2=None, child=file2, clabel=label2, ) ui.debug(b'running %r in %s\n' % (pycompat.bytestr(cmdline), tmproot)) ui.system(cmdline, cwd=tmproot, blockedtag=b'extdiff') return 1
def wrappeddispatch(orig, repo, proto, command): """Wraps wireprotov1server.dispatch() to record command requests.""" # TRACKING hg46 # For historical reasons, SSH and HTTP use different log events. With # the unification of the dispatch code in 4.6, we could likely unify these. # Keep in mind this function is only called on 4.6+: 4.5 has a different # code path completely. if isinstance(proto, wireprotoserver.httpv1protocolhandler): logevent(repo.ui, repo._serverlog, 'BEGIN_PROTOCOL', command) elif isinstance(proto, wireprotoserver.sshv1protocolhandler): logevent(repo.ui, repo._serverlog, 'BEGIN_SSH_COMMAND', command) startusage = resource.getrusage(resource.RUSAGE_SELF) repo._serverlog.update({ 'requestid': pycompat.bytestr(uuid.uuid1()), 'startcpu': startusage.ru_utime + startusage.ru_stime, 'starttime': time.time(), 'ui': weakref.ref(repo.ui), }) else: raise error.ProgrammingError(b'unhandled protocol handler: %r' % proto) # If the return type is a `pushres`, `_sshv1respondbytes` will be called twice. # We only want to log a completed SSH event on the second call, so flip the # `ignorecall` flag here. res = orig(repo, proto, command) if isinstance(res, wireprototypes.pushres): repo._serverlog['ignorecall'] = True return res
def debuginstall(ui, fm): fm.write( b"fsmonitor-watchman", _(b"fsmonitor checking for watchman binary... (%s)\n"), ui.configpath(b"fsmonitor", b"watchman_exe"), ) root = tempfile.mkdtemp() c = watchmanclient.client(ui, root) err = None try: v = c.command(b"version") fm.write( b"fsmonitor-watchman-version", _(b" watchman binary version %s\n"), pycompat.bytestr(v["version"]), ) except watchmanclient.Unavailable as e: err = stringutil.forcebytestr(e) fm.condwrite( err, b"fsmonitor-watchman-error", _(b" watchman binary missing or broken: %s\n"), err, ) return 1 if err else 0
def _handleconfigchange(ui, cw): # Obtain the old and new content so we can show a diff. newbuf = pycompat.bytesio() cw.write(newbuf) newbuf.seek(0) newlines = [pycompat.sysstr(l.rstrip()) for l in newbuf.readlines()] oldlines = [] if os.path.exists(cw.path): with open(cw.path, 'rb') as fh: oldlines = [pycompat.sysstr(l.rstrip()) for l in fh.readlines()] diff = list(difflib.unified_diff(oldlines, newlines, 'hgrc.old', 'hgrc.new', lineterm='')) if len(diff): ui.write(b'Your config file needs updating.\n') if not ui.promptchoice(b'Would you like to see a diff of the changes first (Yn)? $$ &Yes $$ &No'): for line in diff: ui.write(b'%s\n' % pycompat.bytestr(line)) ui.write(b'\n') if not ui.promptchoice(b'Write changes to hgrc file (Yn)? $$ &Yes $$ &No'): with open(cw.path, 'wb') as fh: fh.write(newbuf.getvalue()) else: ui.write(b'config changes not written; we would have written the following:\n') ui.write(newbuf.getvalue()) return 1
def _releases_mapped_generator(context, builds): """Generates build object mappings for use in the template layer """ for i, build in enumerate(builds): build[b'parity'] = pycompat.bytestr(i % 2) build[b'anchor'] = releasedb.build_anchor(build) yield build
def hook(ui, repo, hooktype, node=None, **kwargs): if hooktype != b"txnclose-phase": raise error.Abort( _(b'Unsupported hook type %r') % pycompat.bytestr(hooktype)) ctx = repo.unfiltered()[node] if kwargs['oldphase'] == b'draft' and kwargs['phase'] == b'public': _report_commit(ui, repo, ctx)
def send_message(self, o, partition): """Send a single message from a Python object. The partition, if specified, overwrites whatever the default partition is configured as. """ # Add the message created time to all messages. This is used to monitor # latency. o['_created'] = time.time() # We currently only support 1 message format. It is # "1\n" followed by a JSON payload. No length is encoded, # as Kafka does this for us. j = pycompat.bytestr(json.dumps(o, sort_keys=True)) msg = b''.join([MESSAGE_HEADER_V1, j]) try: return super(Producer, self).send_messages(self.topic, partition, msg) except KafkaError: logger.exception('error sending message to Kafka; ' 'reinitializing client to retry') self.client.reinit() return super(Producer, self).send_messages(self.topic, partition, msg)
def description(self): if self.querystart == QueryType.COUNT and not self.userquery and not self.changesetquery: return b'' bits = [] isotime = lambda x: pycompat.bytestr( datetime.fromtimestamp(x).isoformat(' ')) if self.querystart == QueryType.DATE: bits.append(b'after %s' % isotime(self.querystart_value)) elif self.querystart == QueryType.CHANGESET: bits.append(b'after changeset %s' % self.querystart_value) elif self.querystart == QueryType.PUSHID: bits.append(b'after push ID %s' % self.querystart_value) if self.queryend == QueryType.DATE: bits.append(b'before %s' % isotime(self.queryend_value)) elif self.queryend == QueryType.CHANGESET: bits.append(b'up to and including changeset %s' % self.queryend_value) elif self.queryend == QueryType.PUSHID: bits.append(b'up to and including push ID %s' % self.queryend_value) if self.userquery: bits.append(b'by user %s' % b' or '.join(self.userquery)) if self.changesetquery: bits.append(b'with changeset %s' % b' and '.join(self.changesetquery)) return b'Changes pushed ' + b', '.join(bits)
def run_command(client, args): """Run a Mercurial command through a client. This is kind of like ``client.rawcommand()`` except it performs logging and doesn't do fancy error handling. """ combined = io.BytesIO() out = io.BytesIO() err = io.BytesIO() def log_combined(): v = combined.getvalue() if not v or b'\n' not in v: return lines = v.splitlines() for line in lines: logger.warn(' > %s' % pycompat.sysstr(line)) # Truncate the stream. combined.seek(0) combined.truncate() # Restore the final line fragment if there is one. if not v.endswith(b'\n'): combined.write(lines[-1]) def write_out(s): out.write(s) combined.write(s) log_combined() def write_err(s): err.write(s) combined.write(s) log_combined() channels = { b'o': write_out, b'e': write_err, } quoteable_args = [ pycompat.sysstr(arg) for arg in [hglib.HGPATH] + args ] logger.warn(' $ %s' % ' '.join( map(pipes.quote, quoteable_args))) unquotable_args = [ pycompat.bytestr(arg) for arg in quoteable_args ] ret = client.runcommand(unquotable_args[1:], {}, channels) logger.warn(' [%d]' % ret) return ret, out.getvalue(), err.getvalue()
def update(self, bugid, newstate, ctx): '''update bugzilla bug with reference to changeset.''' def webroot(root): '''strip leading prefix of repo root and turn into url-safe path.''' count = int(self.ui.config('bugzilla', 'strip')) root = util.pconvert(root) while count > 0: c = root.find('/') if c == -1: break root = root[c + 1:] count -= 1 return root mapfile = None tmpl = self.ui.config('bugzilla', 'template') if not tmpl: mapfile = self.ui.config('bugzilla', 'style') if not mapfile and not tmpl: tmpl = _('changeset {node|short} in repo {root} refers ' 'to bug {bug}.\ndetails:\n\t{desc|tabindent}') spec = logcmdutil.templatespec(tmpl, mapfile) t = logcmdutil.changesettemplater(self.ui, self.repo, spec) self.ui.pushbuffer() t.show(ctx, changes=ctx.changeset(), bug=pycompat.bytestr(bugid), hgweb=self.ui.config('web', 'baseurl'), root=self.repo.root, webroot=webroot(self.repo.root)) data = self.ui.popbuffer() self.bzdriver.updatebug(bugid, newstate, data, stringutil.email(ctx.user()))
def load(cls, repo): version = cls._getversion(repo) if version < cls._version: d = cls._readold(repo) elif version == cls._version: d = scmutil.simplekeyvaluefile(repo.vfs, cls._filename)\ .read(firstlinenonkeyval=True) else: raise error.Abort(_('this version of shelve is incompatible ' 'with the version used in this repo')) cls._verifyandtransform(d) try: obj = cls() obj.name = d['name'] obj.wctx = repo[d['originalwctx']] obj.pendingctx = repo[d['pendingctx']] obj.parents = d['parents'] obj.nodestoremove = d['nodestoremove'] obj.branchtorestore = d.get('branchtorestore', '') obj.keep = d.get('keep') == cls._keep obj.activebookmark = '' if d.get('activebook', '') != cls._noactivebook: obj.activebookmark = d.get('activebook', '') except (error.RepoLookupError, KeyError) as err: raise error.CorruptedState(pycompat.bytestr(err)) return obj
def servehgmo(orig, ui, repo, *args, **kwargs): """Wraps commands.serve to provide --hgmo flag.""" if kwargs.get('hgmo', False): kwargs['style'] = b'gitweb_mozilla' kwargs['templates'] = os.path.join(pycompat.bytestr(ROOT), b'hgtemplates') # ui.copy() is funky. Unless we do this, extension settings get # lost when calling hg.repository(). ui = ui.copy() def setconfig(name, paths): ui.setconfig( b'extensions', name, os.path.join(pycompat.bytestr(ROOT), b'hgext', *paths)) setconfig(b'firefoxreleases', [b'firefoxreleases']) setconfig(b'pushlog', [b'pushlog']) setconfig(b'pushlog-feed', [b'pushlog', b'feed.py']) ui.setconfig(b'web', b'logoimg', b'moz-logo-bw-rgb.svg') # Since new extensions may have been flagged for loading, we need # to obtain a new repo instance to a) trigger loading of these # extensions b) force extensions' reposetup function to run. repo = hg.repository(ui, repo.root) return orig(ui, repo, *args, **kwargs)
def hook(ui, repo, hooktype, node=None, **kwargs): if hooktype != b"txnclose": raise error.Abort( _(b'Unsupported hook type %r') % pycompat.bytestr(hooktype)) for rev in obsutil.getobsoleted(repo, changes=kwargs['changes']): ctx = repo.unfiltered()[rev] if not has_successor(repo, ctx.node()): _report_commit(ui, repo, ctx)
def narrow_widen(repo, proto, oldincludes, oldexcludes, newincludes, newexcludes, commonheads, cgversion, known, ellipses): """wireprotocol command to send data when a narrow clone is widen. We will be sending a changegroup here. The current set of arguments which are required: oldincludes: the old includes of the narrow copy oldexcludes: the old excludes of the narrow copy newincludes: the new includes of the narrow copy newexcludes: the new excludes of the narrow copy commonheads: list of heads which are common between the server and client cgversion(maybe): the changegroup version to produce known: list of nodes which are known on the client (used in ellipses cases) ellipses: whether to send ellipses data or not """ preferuncompressed = False try: oldincludes = wireprototypes.decodelist(oldincludes) newincludes = wireprototypes.decodelist(newincludes) oldexcludes = wireprototypes.decodelist(oldexcludes) newexcludes = wireprototypes.decodelist(newexcludes) # validate the patterns narrowspec.validatepatterns(set(oldincludes)) narrowspec.validatepatterns(set(newincludes)) narrowspec.validatepatterns(set(oldexcludes)) narrowspec.validatepatterns(set(newexcludes)) common = wireprototypes.decodelist(commonheads) known = None if known: known = wireprototypes.decodelist(known) if ellipses == '0': ellipses = False else: ellipses = bool(ellipses) cgversion = cgversion newmatch = narrowspec.match(repo.root, include=newincludes, exclude=newexcludes) oldmatch = narrowspec.match(repo.root, include=oldincludes, exclude=oldexcludes) bundler = bundle2.widen_bundle(repo, oldmatch, newmatch, common, known, cgversion, ellipses) except error.Abort as exc: bundler = bundle2.bundle20(repo.ui) manargs = [('message', pycompat.bytestr(exc))] advargs = [] if exc.hint is not None: advargs.append(('hint', exc.hint)) bundler.addpart(bundle2.bundlepart('error:abort', manargs, advargs)) preferuncompressed = True chunks = bundler.getchunks() return wireprototypes.streamres(gen=chunks, prefer_uncompressed=preferuncompressed)
def pre(self, node): self.repo_level = repo_owner(self.repo) # `privilege_level` has only three allowable states: None, SCM_ALLOW_DIRECT_PUSH, and # and self.repo_level self.privilege_level = None self.head = None self.justification = None try: # The hit on LDAP should only happen once at the beginning of the check process. # `pre` is the only opportunity to do so before the iteration through the # commits in the changegroup by the `check` method. self.user_name, self.user_groups = get_user_and_group_affiliations( ) except Exception as e: # The `_get_user_and_group_affiliations` method has raised an unexpected exception. # It is not likely an LDAP connection error because the `get_scm_groups` method # suppresses all LDAP exceptions in favor of logging to stderr and returning None. # However,`get_scm_groups` does have other opportunities to raise exceptions that # have not been suppressed. As we have no user information at this point, we cannot # let the push proceed. # Since this method `pre` cannot react to fatal errors, the `None` value in # `privilege_level` will abort this check in the future call to method `check` print_banner( self.ui, b"error", LDAP_USER_EXCEPTION_FAILURE_MESSAGE % pycompat.bytestr(e)) return if not self.user_groups: # Since this method `pre` cannot react to fatal errors, the `None` value in # `privilege_level` will abort this check in the future call to method `check` print_banner(self.ui, b"error", LDAP_USER_FAILURE_MESSAGE) return elif ((self.direct_push_enabled or pycompat.bytestr(self.user_name) in self.landing_users) and SCM_ALLOW_DIRECT_PUSH in self.user_groups): self.privilege_level = SCM_ALLOW_DIRECT_PUSH elif self.repo_level in self.user_groups: self.privilege_level = self.repo_level else: # neither SCM_ALLOW_DIRECT_PUSH nor self.repo_level # Since this method `pre` cannot react to fatal errors, the `None` value in # `privilege_level` will abort this check in the future call to method `check` # Note: We should never get here, as the user will not have permission to start # a transaction on this repository, but provide a good error message anyway. print_banner(self.ui, b"error", INSUFFICIENT_PRIVILEGE_FAILURE_MESSAGE)
def publish(name, desc, path, port): global server, localip if not server: ip = getip() if ip.startswith('127.'): # if we have no internet connection, this can happen. return localip = socket.inet_aton(ip) server = Zeroconf.Zeroconf(ip) hostname = socket.gethostname().split('.')[0] host = hostname + ".local" name = "%s-%s" % (hostname, name) # advertise to browsers svc = Zeroconf.ServiceInfo( b'_http._tcp.local.', pycompat.bytestr(name + '._http._tcp.local.'), server=host, port=port, properties={ b'description': desc, b'path': b"/" + path }, address=localip, weight=0, priority=0, ) server.registerService(svc) # advertise to Mercurial clients svc = Zeroconf.ServiceInfo( b'_hg._tcp.local.', pycompat.bytestr(name + '._hg._tcp.local.'), server=host, port=port, properties={ b'description': desc, b'path': b"/" + path }, address=localip, weight=0, priority=0, ) server.registerService(svc)
def dodiff(ui, repo, cmdline, pats, opts): """Do the actual diff.""" revs = opts.get('rev') old, new = scmutil.revpair(repo, revs) subrepos = opts.get('subrepos') matcher = scmutil.match(new, pats, opts) status = old.status(new, matcher, listsubrepos=subrepos) copy = copies.pathcopies(old, new, matcher) mod, add, rem = map(set, status[:3]) paths_new = mod | add paths_old = mod | set(copy.values()) paths_all = paths_old | paths_new if not paths_all: return 0 tmproot = pycompat.mkdtemp(prefix='extdiff2.') try: # Always make a copy of old dir_old = snapshot(ui, repo, paths_old, old.node(), tmproot, subrepos) dir_old = os.path.join(tmproot, dir_old) label_old = '@%d' % old.rev() # If new in not the wc, copy it if new.node(): dir_new = snapshot(ui, repo, paths_new, new.node(), tmproot, subrepos) label_new = '@%d' % new.rev() else: # This lets the diff tool open the changed file(s) directly dir_new = '' label_new = '' # Diff the files instead of the directories # Handle bogus modifies correctly by checking if the files exist for path in paths_new: path = util.localpath(path) path_old = os.path.join(dir_old, copy.get(path, path)) label_old = path + label_old #if not os.path.isfile(path_old): #path_old = os.devnull path_new = os.path.join(repo.root, path) if not dir_new: path_new = os.path.relpath(path_new) label_new = path + label_new # Function to quote file/dir names in the argument string. replace = { 'old': path_old, 'olabel': label_old, 'nlabel': label_new, 'new': path_new, 'root': repo.root } def quote(match): pre = match.group(2) key = match.group(3) return pre + procutil.shellquote(replace[key]) regex = (br"""(['"]?)([^\s'"$]*)""" br'\$(old|new|olabel|nlabel|root)\1') if not re.search(regex, cmdline): cmdline2 = cmdline + ' $old $new' else: cmdline2 = cmdline cmdline3 = re.sub(regex, quote, cmdline2) ui.write(pycompat.bytestr(cmdline3) + b'\n') ui.system(cmdline3, blockedtag='extdiff2') return 1 finally: ui.note(_('cleaning up temp directory\n')) shutil.rmtree(tmproot)