def gc(ui, *args, **opts): '''garbage collect the client and server filelog caches ''' cachepaths = set() # get the system client cache systemcache = ui.config("remotefilelog", "cachepath") if systemcache: systemcache = util.expandpath(systemcache) cachepaths.add(systemcache) # get repo client and server cache repopaths = [ui.environ['PWD']] repopaths.extend(args) repos = [] for repopath in repopaths: try: repo = hg.peer(ui, {}, repopath) repos.append(repo) repocache = repo.ui.config("remotefilelog", "cachepath") if repocache: repocache = util.expandpath(repocache) cachepaths.add(repocache) except error.RepoError: pass # gc client cache for cachepath in cachepaths: gcclient(ui, cachepath) # gc server cache for repo in repos: remotefilelogserver.gcserver(ui, repo._repo)
def __init__(self, ui, path, path2): localrepo.localrepository.__init__(self, ui, path) self.ui.setconfig('phases', 'publish', False) self._url = 'union:%s+%s' % (util.expandpath(path), util.expandpath(path2)) self.repo2 = localrepo.localrepository(ui, path2)
def openshell(root, reponame, ui=None): if not os.path.exists(root): WarningMsgBox( _('Failed to open path in terminal'), _('"%s" is not a valid directory') % hglib.tounicode(root)) return shell, args = terminal.detectterminal(ui) if shell: cwd = os.getcwd() try: if args: shell = shell + ' ' + util.expandpath(args) shellcmd = shell % {'root': root, 'reponame': reponame} # Unix: QProcess.startDetached(program) cannot parse single-quoted # parameters built using util.shellquote(). # Windows: subprocess.Popen(program, shell=True) cannot spawn # cmd.exe in new window, probably because the initial cmd.exe is # invoked with SW_HIDE. os.chdir(root) fullargs = shlex.split(shellcmd) started = QProcess.startDetached(fullargs[0], fullargs[1:]) finally: os.chdir(cwd) if not started: ErrorMsgBox(_('Failed to open path in terminal'), _('Unable to start the following command:'), shellcmd) else: InfoMsgBox(_('No shell configured'), _('A terminal shell must be configured'))
def readauthforuri(ui, uri): # Read configuration config = dict() for key, val in ui.configitems('auth'): if '.' not in key: ui.warn(_("ignoring invalid [auth] key '%s'\n") % key) continue group, setting = key.rsplit('.', 1) gdict = config.setdefault(group, dict()) if setting in ('username', 'cert', 'key'): val = util.expandpath(val) gdict[setting] = val # Find the best match scheme, hostpath = uri.split('://', 1) bestlen = 0 bestauth = None for group, auth in config.iteritems(): prefix = auth.get('prefix') if not prefix: continue p = prefix.split('://', 1) if len(p) > 1: schemes, prefix = [p[0]], p[1] else: schemes = (auth.get('schemes') or 'https').split() if (prefix == '*' or hostpath.startswith(prefix)) and \ len(prefix) > bestlen and scheme in schemes: bestlen = len(prefix) bestauth = group, auth return bestauth
def uisetup(ui): for cmd, path in ui.configitems('extdiff'): path = util.expandpath(path) if cmd.startswith('cmd.'): cmd = cmd[4:] if not path: path = util.findexe(cmd) if path is None: path = filemerge.findexternaltool(ui, cmd) or cmd diffopts = ui.config('extdiff', 'opts.' + cmd, '') cmdline = util.shellquote(path) if diffopts: cmdline += ' ' + diffopts elif cmd.startswith('opts.'): continue else: if path: # case "cmd = path opts" cmdline = path diffopts = len(shlex.split(cmdline)) > 1 else: # case "cmd =" path = util.findexe(cmd) if path is None: path = filemerge.findexternaltool(ui, cmd) or cmd cmdline = util.shellquote(path) diffopts = False # look for diff arguments in [diff-tools] then [merge-tools] if not diffopts: args = ui.config('diff-tools', cmd+'.diffargs') or \ ui.config('merge-tools', cmd+'.diffargs') if args: cmdline += ' ' + args command(cmd, extdiffopts[:], _('hg %s [OPTION]... [FILE]...') % cmd, inferrepo=True)(savedcmd(path, cmdline))
def _findtool(ui, tool): global toolcache if tool in toolcache: return toolcache[tool] for kn in ("regkey", "regkeyalt"): k = _toolstr(ui, tool, kn) if not k: continue p = util.lookupreg(k, _toolstr(ui, tool, "regname")) if p: p = util.findexe(p + _toolstr(ui, tool, "regappend")) if p: toolcache[tool] = p return p global _platformexecutablekey exe = _toolstr(ui, tool, _platformexecutablekey) if not exe: exe = _toolstr(ui, tool, 'executable', tool) path = util.findexe(util.expandpath(exe)) if path: toolcache[tool] = path return path elif tool != exe: path = util.findexe(tool) toolcache[tool] = path return path toolcache[tool] = None return None
def _ignore(self): files = [self._join('.hgignore')] for name, path in self._ui.configitems("ui"): if name == 'ignore' or name.startswith('ignore.'): files.append(util.expandpath(path)) patterns = [] # Only use .gitignore if there's no .hgignore try: fp = open(files[0]) fp.close() except: fns = self._finddotgitignores() for fn in fns: d = os.path.dirname(fn) fn = self.pathto(fn) if not os.path.exists(fn): continue fp = open(fn) pats, warnings = gignorepats(None, fp, root=d) for warning in warnings: self._ui.warn("%s: %s\n" % (fn, warning)) patterns.extend(pats) return gignore(self._root, files, self._ui.warn, extrapatterns=patterns)
def _promptvctextension(ui, cw, ext, msg): ext_path = _vctextpath(pycompat.sysstr(ext)) # Do nothing (return) if the user has configured this extension, unless it # points to the directory that we manage and that directory is missing. users_ext_path = ui.config(b'extensions', ext) if users_ext_path != None: users_ext_path = pycompat.fsdecode( util.normpath(util.expandpath(users_ext_path))) if users_ext_path != ext_path or os.path.exists(ext_path): return # Verify the extension loads before prompting to enable it. This is # done out of paranoia. # Even if we launch hg.exe, sys.argv[0] is "hg" on Windows. Since "hg" isn't # a Windows application, we can't simply run it. So change to the ".exe" # variant if necessary. hg = sys.argv[0] if sys.platform in ('win32', 'msys') and hg.endswith('hg'): hg += '.exe' result = subprocess.check_output([ hg, '--config', 'extensions.testmodule=%s' % ext_path, '--config', 'ui.traceback=true' ], stderr=subprocess.STDOUT) if b'Traceback' in result: return if uipromptchoice(ui, b'%s (Yn) $$ &Yes $$ &No' % msg): return _enableext(cw, pycompat.sysstr(ext), ext_path)
def uisetup(ui): for cmd, path in ui.configitems('extdiff'): path = util.expandpath(path) if cmd.startswith('cmd.'): cmd = cmd[4:] if not path: path = util.findexe(cmd) if path is None: path = filemerge.findexternaltool(ui, cmd) or cmd diffopts = ui.config('extdiff', 'opts.' + cmd, '') cmdline = util.shellquote(path) if diffopts: cmdline += ' ' + diffopts elif cmd.startswith('opts.'): continue else: if path: # case "cmd = path opts" cmdline = path diffopts = len(pycompat.shlexsplit(cmdline)) > 1 else: # case "cmd =" path = util.findexe(cmd) if path is None: path = filemerge.findexternaltool(ui, cmd) or cmd cmdline = util.shellquote(path) diffopts = False # look for diff arguments in [diff-tools] then [merge-tools] if not diffopts: args = ui.config('diff-tools', cmd+'.diffargs') or \ ui.config('merge-tools', cmd+'.diffargs') if args: cmdline += ' ' + args command(cmd, extdiffopts[:], _('hg %s [OPTION]... [FILE]...') % cmd, inferrepo=True)(savedcmd(path, cmdline))
def uisetup(ui): for cmd, path in ui.configitems('extdiff'): path = util.expandpath(path) if cmd.startswith('cmd.'): cmd = cmd[4:] if not path: path = util.findexe(cmd) if path is None: path = filemerge.findexternaltool(ui, cmd) or cmd diffopts = ui.config('extdiff', 'opts.' + cmd, '') cmdline = util.shellquote(path) if diffopts: cmdline += ' ' + diffopts elif cmd.startswith('opts.'): continue else: if path: # case "cmd = path opts" cmdline = path diffopts = len(shlex.split(cmdline)) > 1 else: # case "cmd =" path = util.findexe(cmd) if path is None: path = filemerge.findexternaltool(ui, cmd) or cmd cmdline = util.shellquote(path) diffopts = False # look for diff arguments in [diff-tools] then [merge-tools] if not diffopts: args = ui.config('diff-tools', cmd+'.diffargs') or \ ui.config('merge-tools', cmd+'.diffargs') if args: cmdline += ' ' + args def save(cmdline): '''use closure to save diff command to use''' def mydiff(ui, repo, *pats, **opts): options = ' '.join(map(util.shellquote, opts['option'])) if options: options = ' ' + options return dodiff(ui, repo, cmdline + options, pats, opts) # We can't pass non-ASCII through docstrings (and path is # in an unknown encoding anyway) docpath = path.encode("string-escape") mydiff.__doc__ = '''\ use %(path)s to diff repository (or selected files) Show differences between revisions for the specified files, using the %(path)s program. When two revision arguments are given, then changes are shown between those revisions. If only one revision is specified then that revision is compared to the working directory, and, when no revisions are specified, the working directory files are compared to its parent.\ ''' % {'path': util.uirepr(docpath)} return mydiff command(cmd, extdiffopts[:], _('hg %s [OPTION]... [FILE]...') % cmd, inferrepo=True)(save(cmdline))
def getcachepath(ui, allowempty=False): cachepath = ui.config("remotefilelog", "cachepath") if not cachepath: if allowempty: return None else: raise error.Abort(_("could not find config option " "remotefilelog.cachepath")) return util.expandpath(cachepath)
def sslkwargs(ui, host): cacerts = ui.config("web", "cacerts") hostfingerprint = ui.config("hostfingerprints", host) if cacerts and not hostfingerprint: cacerts = util.expandpath(cacerts) if not os.path.exists(cacerts): raise util.Abort(_("could not find web.cacerts: %s") % cacerts) return {"ca_certs": cacerts, "cert_reqs": CERT_REQUIRED} return {}
def _import(ui, repo, files, opts, force=False): with repo.wlock(): # load union of current active profile revs = [repo.changelog.rev(node) for node in repo.dirstate.parents() if node != nullid] # read current configuration raw = '' if repo.vfs.exists('sparse'): raw = repo.vfs.read('sparse') oincludes, oexcludes, oprofiles = repo.readsparseconfig(raw) includes, excludes, profiles = map( set, (oincludes, oexcludes, oprofiles)) # all active rules aincludes, aexcludes, aprofiles = set(), set(), set() for rev in revs: rincludes, rexcludes, rprofiles = repo.getsparsepatterns(rev) aincludes.update(rincludes) aexcludes.update(rexcludes) aprofiles.update(rprofiles) # import rules on top; only take in rules that are not yet # part of the active rules. changed = False for file in files: with util.posixfile(util.expandpath(file)) as importfile: iincludes, iexcludes, iprofiles = repo.readsparseconfig( importfile.read()) oldsize = len(includes) + len(excludes) + len(profiles) includes.update(iincludes - aincludes) excludes.update(iexcludes - aexcludes) profiles.update(set(iprofiles) - aprofiles) if len(includes) + len(excludes) + len(profiles) > oldsize: changed = True profilecount = includecount = excludecount = 0 fcounts = (0, 0, 0) if changed: profilecount = len(profiles - aprofiles) includecount = len(includes - aincludes) excludecount = len(excludes - aexcludes) oldstatus = repo.status() oldsparsematch = repo.sparsematch() repo.writesparseconfig(includes, excludes, profiles) try: fcounts = map( len, _refresh(ui, repo, oldstatus, oldsparsematch, force)) except Exception: repo.writesparseconfig(oincludes, oexcludes, oprofiles) raise _verbose_output(ui, opts, profilecount, includecount, excludecount, *fcounts)
def _alert(ui, repo, error): """Run the alert program, if defined.""" alert = repo.ui.config("autosync", "alert") if alert: alert = util.expandpath(alert) try: subprocess.call([alert, repo.root, str(error)]) except OSError, e: ui.warn("sync: failed to run alert tool %s (%s)" % (alert, e))
def _checkevolve(ui, cw, hg_version): if hg_version < (4, 3, 0): ui.warn(EVOLVE_INCOMPATIBLE) return remote_evolve_path = b'https://www.mercurial-scm.org/repo/evolve/' # Install to the same dir as v-c-t, unless the mozbuild directory path is passed (testing) evolve_clone_dir = ui.config(b'mozilla', b'mozbuild_state_path', _vcthome()) local_evolve_path = b'%(evolve_clone_dir)s/evolve' % {b'evolve_clone_dir': evolve_clone_dir} evolve_config_value = os.path.normpath('%(evolve_path)s/hgext3rd/evolve' % \ {'evolve_path': pycompat.sysstr(local_evolve_path)}) users_evolve_path = ui.config(b'extensions', b'evolve') if users_evolve_path: users_evolve_path = os.path.normpath(pycompat.fsdecode(util.normpath(util.expandpath(users_evolve_path)))) # If evolve is not installed, install it. (If the user's path to evolve is # the path that we manage, but it doesn't exist yet, assume that their # config file has been copied to a new machine and we need to clone evolve. if users_evolve_path == None or \ (users_evolve_path == evolve_config_value and not os.path.exists(evolve_config_value)): if uipromptchoice(ui, EVOLVE_INFO_WARNING): return try: # Clone the evolve extension and enable hg.clone(ui, {}, remote_evolve_path, branch=(b'stable',), dest=local_evolve_path) _enableext(cw, 'evolve', evolve_config_value) ui.write(b'Evolve was downloaded successfully.\n') except error.Abort as hg_err: ui.write(pycompat.bytestr(hg_err)) ui.write(EVOLVE_CLONE_ERROR) return # If evolve is installed and managed by this wizard, # update it via pull/update if users_evolve_path == evolve_config_value: if uipromptchoice(ui, EVOLVE_UPDATE_PROMPT % {b'evolve_dir': local_evolve_path}): return try: local_evolve_repo = hg.repository(ui, local_evolve_path) # Pull the latest stable, update to tip hgpull(ui, local_evolve_repo, source=remote_evolve_path, branch=(b'stable',)) hgupdate(ui, local_evolve_repo, rev=b'stable') ui.write(b'Evolve was updated successfully.\n') except error.Abort as hg_err: ui.write(EVOLVE_CLONE_ERROR)
def clone(orig, ui, source, *args, **opts): pool = ui.config('share', 'pool', None) if pool: pool = util.expandpath(pool) opts['shareopts'] = dict( pool=pool, mode=ui.config('share', 'poolnaming', 'identity'), ) return orig(ui, source, *args, **opts)
def sslkwargs(ui, host): cacerts = ui.config('web', 'cacerts') hostfingerprint = ui.config('hostfingerprints', host) if cacerts and not hostfingerprint: cacerts = util.expandpath(cacerts) if not os.path.exists(cacerts): raise util.Abort(_('could not find web.cacerts: %s') % cacerts) return {'ca_certs': cacerts, 'cert_reqs': CERT_REQUIRED, } return {}
def __init__(self, repo): ui = repo.ui self.repo = repo self.ui = ui self.cacheprocess = ui.config("remotefilelog", "cacheprocess") if self.cacheprocess: self.cacheprocess = util.expandpath(self.cacheprocess) self.debugoutput = ui.configbool("remotefilelog", "debug") self.localcache = localcache(repo) self.remotecache = cacheconnection()
def clone(orig, ui, source, *args, **opts): pool = ui.config('share', 'pool') if pool: pool = util.expandpath(pool) opts[r'shareopts'] = { 'pool': pool, 'mode': ui.config('share', 'poolnaming'), } return orig(ui, source, *args, **opts)
def _gettooldetails(ui, cmd, path): """ returns following things for a ``` [extdiff] <cmd> = <path> ``` entry: cmd: command/tool name path: path to the tool cmdline: the command which should be run isgui: whether the tool uses GUI or not Reads all external tools related configs, whether it be extdiff section, diff-tools or merge-tools section, or its specified in an old format or the latest format. """ path = util.expandpath(path) if cmd.startswith(b'cmd.'): cmd = cmd[4:] if not path: path = procutil.findexe(cmd) if path is None: path = filemerge.findexternaltool(ui, cmd) or cmd diffopts = ui.config(b'extdiff', b'opts.' + cmd) cmdline = procutil.shellquote(path) if diffopts: cmdline += b' ' + diffopts isgui = ui.configbool(b'extdiff', b'gui.' + cmd) else: if path: # case "cmd = path opts" cmdline = path diffopts = len(pycompat.shlexsplit(cmdline)) > 1 else: # case "cmd =" path = procutil.findexe(cmd) if path is None: path = filemerge.findexternaltool(ui, cmd) or cmd cmdline = procutil.shellquote(path) diffopts = False isgui = ui.configbool(b'extdiff', b'gui.' + cmd) # look for diff arguments in [diff-tools] then [merge-tools] if not diffopts: key = cmd + b'.diffargs' for section in (b'diff-tools', b'merge-tools'): args = ui.config(section, key) if args: cmdline += b' ' + args if isgui is None: isgui = ui.configbool(section, cmd + b'.gui') or False break return cmd, path, cmdline, isgui
def __init__(self, repo): ui = repo.ui self.repo = repo self.ui = ui self.cacheprocess = ui.config("remotefilelog", "cacheprocess") if self.cacheprocess: self.cacheprocess = util.expandpath(self.cacheprocess) # This option causes remotefilelog to pass the full file path to the # cacheprocess instead of a hashed key. self.cacheprocesspasspath = ui.configbool("remotefilelog", "cacheprocess.includepath") self.debugoutput = ui.configbool("remotefilelog", "debug") self.remotecache = cacheconnection()
def __init__(self, repo): ui = repo.ui self.repo = repo self.ui = ui self.cacheprocess = ui.config("remotefilelog", "cacheprocess") if self.cacheprocess: self.cacheprocess = util.expandpath(self.cacheprocess) # This option causes remotefilelog to pass the full file path to the # cacheprocess instead of a hashed key. self.cacheprocesspasspath = ui.configbool( "remotefilelog", "cacheprocess.includepath") self.debugoutput = ui.configbool("remotefilelog", "debug") self.remotecache = cacheconnection()
def uisetup(ui): for cmd, path in ui.configitems(b'extdiff'): path = util.expandpath(path) if cmd.startswith(b'cmd.'): cmd = cmd[4:] if not path: path = procutil.findexe(cmd) if path is None: path = filemerge.findexternaltool(ui, cmd) or cmd diffopts = ui.config(b'extdiff', b'opts.' + cmd) cmdline = procutil.shellquote(path) if diffopts: cmdline += b' ' + diffopts isgui = ui.configbool(b'extdiff', b'gui.' + cmd) elif cmd.startswith(b'opts.') or cmd.startswith(b'gui.'): continue else: if path: # case "cmd = path opts" cmdline = path diffopts = len(pycompat.shlexsplit(cmdline)) > 1 else: # case "cmd =" path = procutil.findexe(cmd) if path is None: path = filemerge.findexternaltool(ui, cmd) or cmd cmdline = procutil.shellquote(path) diffopts = False isgui = ui.configbool(b'extdiff', b'gui.' + cmd) # look for diff arguments in [diff-tools] then [merge-tools] if not diffopts: key = cmd + b'.diffargs' for section in (b'diff-tools', b'merge-tools'): args = ui.config(section, key) if args: cmdline += b' ' + args if isgui is None: isgui = ui.configbool(section, cmd + b'.gui') or False break command( cmd, extdiffopts[:], _(b'hg %s [OPTION]... [FILE]...') % cmd, helpcategory=command.CATEGORY_FILE_CONTENTS, inferrepo=True, )(savedcmd(path, cmdline, isgui))
def readauthforuri(ui, uri, user): # Read configuration config = dict() for key, val in ui.configitems('auth'): if '.' not in key: ui.warn(_("ignoring invalid [auth] key '%s'\n") % key) continue group, setting = key.rsplit('.', 1) gdict = config.setdefault(group, dict()) if setting in ('username', 'cert', 'key'): val = util.expandpath(val) gdict[setting] = val # Find the best match if '://' in uri: scheme, hostpath = uri.split('://', 1) else: # py2.4.1 doesn't provide the full URI scheme, hostpath = 'http', uri bestuser = None bestlen = 0 bestauth = None for group, auth in config.iteritems(): if user and user != auth.get('username', user): # If a username was set in the URI, the entry username # must either match it or be unset continue prefix = auth.get('prefix') if not prefix: continue p = prefix.split('://', 1) if len(p) > 1: schemes, prefix = [p[0]], p[1] else: schemes = (auth.get('schemes') or 'https').split() if (prefix == '*' or hostpath.startswith(prefix)) and \ (len(prefix) > bestlen or (len(prefix) == bestlen and \ not bestuser and 'username' in auth)) \ and scheme in schemes: bestlen = len(prefix) bestauth = group, auth bestuser = auth.get('username') if user and not bestuser: auth['username'] = user return bestauth
def readauthforuri(ui, uri, user): # Read configuration config = dict() for key, val in ui.configitems('auth'): if '.' not in key: ui.warn(_("ignoring invalid [auth] key '%s'\n") % key) continue group, setting = key.rsplit('.', 1) gdict = config.setdefault(group, dict()) if setting in ('username', 'cert', 'key'): val = util.expandpath(val) gdict[setting] = val # Find the best match if '://' in uri: scheme, hostpath = uri.split('://', 1) else: # Python 2.4.1 doesn't provide the full URI scheme, hostpath = 'http', uri bestuser = None bestlen = 0 bestauth = None for group, auth in config.iteritems(): if user and user != auth.get('username', user): # If a username was set in the URI, the entry username # must either match it or be unset continue prefix = auth.get('prefix') if not prefix: continue p = prefix.split('://', 1) if len(p) > 1: schemes, prefix = [p[0]], p[1] else: schemes = (auth.get('schemes') or 'https').split() if (prefix == '*' or hostpath.startswith(prefix)) and \ (len(prefix) > bestlen or (len(prefix) == bestlen and \ not bestuser and 'username' in auth)) \ and scheme in schemes: bestlen = len(prefix) bestauth = group, auth bestuser = auth.get('username') if user and not bestuser: auth['username'] = user return bestauth
def sslkwargs(ui, host): cacerts = ui.config('web', 'cacerts') forcetls = ui.configbool('ui', 'tls', default=True) if forcetls: ssl_version = PROTOCOL_TLSv1 else: ssl_version = PROTOCOL_SSLv23 hostfingerprint = ui.config('hostfingerprints', host) kws = {'ssl_version': ssl_version, } if cacerts and not hostfingerprint: cacerts = util.expandpath(cacerts) if not os.path.exists(cacerts): raise util.Abort(_('could not find web.cacerts: %s') % cacerts) kws.update({'ca_certs': cacerts, 'cert_reqs': CERT_REQUIRED, }) return kws
def openshell(root, reponame, ui=None): if not os.path.exists(root): WarningMsgBox( _('Failed to open path in terminal'), _('"%s" is not a valid directory') % hglib.tounicode(root)) return shell, args = terminal.detectterminal(ui) if shell: if args: shell = shell + ' ' + util.expandpath(args) # check invalid expression in tortoisehg.shell. we shouldn't apply # string formatting to untrusted value, but too late to change syntax. try: shell % {'root': '', 'reponame': ''} except (KeyError, TypeError, ValueError): # KeyError: "%(invalid)s", TypeError: "%(root)d", ValueError: "%" ErrorMsgBox( _('Failed to open path in terminal'), _('Invalid configuration: %s') % hglib.tounicode(shell)) return shellcmd = shell % {'root': root, 'reponame': reponame} cwd = os.getcwd() try: # Unix: QProcess.startDetached(program) cannot parse single-quoted # parameters built using util.shellquote(). # Windows: subprocess.Popen(program, shell=True) cannot spawn # cmd.exe in new window, probably because the initial cmd.exe is # invoked with SW_HIDE. os.chdir(root) if os.name == 'nt': # can't parse shellcmd in POSIX way started = QProcess.startDetached(hglib.tounicode(shellcmd)) else: fullargs = map(hglib.tounicode, shlex.split(shellcmd)) started = QProcess.startDetached(fullargs[0], fullargs[1:]) finally: os.chdir(cwd) if not started: ErrorMsgBox(_('Failed to open path in terminal'), _('Unable to start the following command:'), shellcmd) else: InfoMsgBox(_('No shell configured'), _('A terminal shell must be configured'))
def openshell(root, reponame, ui=None): if not os.path.exists(root): WarningMsgBox( _('Failed to open path in terminal'), _('"%s" is not a valid directory') % hglib.tounicode(root)) return shell, args = terminal.detectterminal(ui) if shell: if args: shell = shell + ' ' + util.expandpath(args) # check invalid expression in tortoisehg.shell. we shouldn't apply # string formatting to untrusted value, but too late to change syntax. try: shell % {'root': '', 'reponame': ''} except (KeyError, TypeError, ValueError): # KeyError: "%(invalid)s", TypeError: "%(root)d", ValueError: "%" ErrorMsgBox(_('Failed to open path in terminal'), _('Invalid configuration: %s') % hglib.tounicode(shell)) return shellcmd = shell % {'root': root, 'reponame': reponame} cwd = os.getcwd() try: # Unix: QProcess.startDetached(program) cannot parse single-quoted # parameters built using util.shellquote(). # Windows: subprocess.Popen(program, shell=True) cannot spawn # cmd.exe in new window, probably because the initial cmd.exe is # invoked with SW_HIDE. os.chdir(root) if os.name == 'nt': # can't parse shellcmd in POSIX way started = QProcess.startDetached(hglib.tounicode(shellcmd)) else: fullargs = map(hglib.tounicode, shlex.split(shellcmd)) started = QProcess.startDetached(fullargs[0], fullargs[1:]) finally: os.chdir(cwd) if not started: ErrorMsgBox(_('Failed to open path in terminal'), _('Unable to start the following command:'), shellcmd) else: InfoMsgBox(_('No shell configured'), _('A terminal shell must be configured'))
def __init__(self, ui): self.ui = ui self.fin = sys.stdin self.fout = sys.stdout logfilename = self.ui.config('bfiles', 'bfserve.logfile') if logfilename: logfilename = util.expandpath(logfilename) self.logfile = open(logfilename, 'a') self.log = lambda fmt, *args: self.logfile.write((fmt % args) + '\n') else: self.log = lambda fmt, *args: None self.log('-------------\nbfserve: starting a session') sys.stdout = sys.stderr # Prevent insertion/deletion of CRs bfutil.setbinary(self.fin) bfutil.setbinary(self.fout)
def _ignore(self): files = [self._join(b'.hgignore')] for name, path in self._ui.configitems(b"ui"): if name == b'ignore' or name.startswith(b'ignore.'): files.append(util.expandpath(path)) patterns = [] # Only use .gitignore if there's no .hgignore if not os.access(files[0], os.R_OK): for fn in self._finddotgitignores(): d = os.path.dirname(fn) fn = self.pathto(fn) if not os.path.exists(fn): continue fp = open(fn, 'rb') pats, warnings = gignorepats(None, fp, root=d) for warning in warnings: self._ui.warn(b"%s: %s\n" % (fn, warning)) patterns.extend(pats) return gignore(self._root, files, self._ui, extrapatterns=patterns)
def _checkmultiplevct(ui, cw): # References to multiple version-control-tools checkouts can confuse # version-control-tools since various Mercurial extensions resolve # dependencies via __file__. Files from different revisions could lead # to unexpected environments and break things. seenvct = set() for k, v in ui.configitems('extensions'): # mercurial.extensions.loadpath() does variable and user expansion. # We need to match behavior. v = os.path.realpath(util.normpath(util.expandpath(v))) if 'version-control-tools' not in v: continue i = v.index('version-control-tools') vct = v[0:i + len('version-control-tools')] seenvct.add(vct) if len(seenvct) > 1: ui.write(MULTIPLE_VCT % cw.path)
def postinitskel(ui, repo, hooktype, result, pats, **kwargs): """create common files in new repository""" assert hooktype == 'post-init' if result: return dest = ui.expandpath(pats and pats[0] or '.') skel = ui.config('tortoisehg', 'initskel') if skel: # copy working tree from user-defined path if any skel = util.expandpath(skel) for name in os.listdir(skel): if name == '.hg': continue util.copyfiles(os.path.join(skel, name), os.path.join(dest, name), hardlink=False) return # create .hg* files, mainly to workaround Explorer's problem in creating # files with a name beginning with a dot open(os.path.join(dest, '.hgignore'), 'a').close()
def sslkwargs(ui, host): cacerts = ui.config('web', 'cacerts') forcetls = ui.configbool('ui', 'tls', default=True) if forcetls: ssl_version = PROTOCOL_TLSv1 else: ssl_version = PROTOCOL_SSLv23 hostfingerprint = ui.config('hostfingerprints', host) kws = { 'ssl_version': ssl_version, } if cacerts and not hostfingerprint: cacerts = util.expandpath(cacerts) if not os.path.exists(cacerts): raise util.Abort(_('could not find web.cacerts: %s') % cacerts) kws.update({ 'ca_certs': cacerts, 'cert_reqs': CERT_REQUIRED, }) return kws
def sslkwargs(ui, host): kws = {} hostfingerprint = ui.config('hostfingerprints', host) if hostfingerprint: return kws cacerts = ui.config('web', 'cacerts') if cacerts: cacerts = util.expandpath(cacerts) if not os.path.exists(cacerts): raise util.Abort(_('could not find web.cacerts: %s') % cacerts) elif cacerts is None and _plainapplepython(): dummycert = os.path.join(os.path.dirname(__file__), 'dummycert.pem') if os.path.exists(dummycert): ui.debug('using %s to enable OS X system CA\n' % dummycert) ui.setconfig('web', 'cacerts', dummycert, 'dummy') cacerts = dummycert if cacerts: kws.update({'ca_certs': cacerts, 'cert_reqs': CERT_REQUIRED, }) return kws
def _ignore(self): files = [self._join('.hgignore')] for name, path in self._ui.configitems("ui"): if name == 'ignore' or name.startswith('ignore.'): files.append(util.expandpath(path)) patterns = [] # Only use .gitignore if there's no .hgignore try: fp = open(files[0]) fp.close() except: fns = self._finddotgitignores() for fn in fns: d = os.path.dirname(fn) fn = self.pathto(fn) fp = open(fn) pats, warnings = gignorepats(None,fp,root=d) for warning in warnings: self._ui.warn("%s: %s\n" % (fn, warning)) patterns.extend(pats) return ignore.ignore(self._root, files, self._ui.warn, extrapatterns=patterns)
def __init__(self, repo): self.ui = repo.ui self.repo = repo self.cachepath = self.ui.config("remotefilelog", "cachepath") self._validatecachelog = self.ui.config("remotefilelog", "validatecachelog") if self.cachepath: self.cachepath = util.expandpath(self.cachepath) self.uid = os.getuid() if not os.path.exists(self.cachepath): oldumask = os.umask(0o002) try: os.makedirs(self.cachepath) groupname = self.ui.config("remotefilelog", "cachegroup") if groupname: gid = grp.getgrnam(groupname).gr_gid if gid: os.chown(self.cachepath, os.getuid(), gid) os.chmod(self.cachepath, 0o2775) finally: os.umask(oldumask)
def sslkwargs(ui, host): kws = {} hostfingerprint = ui.config('hostfingerprints', host) if hostfingerprint: return kws cacerts = ui.config('web', 'cacerts') if cacerts: cacerts = util.expandpath(cacerts) if not os.path.exists(cacerts): raise util.Abort(_('could not find web.cacerts: %s') % cacerts) elif cacerts is None and _plainapplepython(): dummycert = os.path.join(os.path.dirname(__file__), 'dummycert.pem') if os.path.exists(dummycert): ui.debug('using %s to enable OS X system CA\n' % dummycert) ui.setconfig('web', 'cacerts', dummycert, 'dummy') cacerts = dummycert if cacerts: kws.update({ 'ca_certs': cacerts, 'cert_reqs': CERT_REQUIRED, }) return kws
def sslkwargs(ui, host): kws = {'ui': ui} hostfingerprint = ui.config('hostfingerprints', host) if hostfingerprint: return kws cacerts = ui.config('web', 'cacerts') if cacerts == '!': pass elif cacerts: cacerts = util.expandpath(cacerts) if not os.path.exists(cacerts): raise util.Abort(_('could not find web.cacerts: %s') % cacerts) else: cacerts = _defaultcacerts() if cacerts and cacerts != '!': ui.debug('using %s to enable OS X system CA\n' % cacerts) ui.setconfig('web', 'cacerts', cacerts, 'defaultcacerts') if cacerts != '!': kws.update({'ca_certs': cacerts, 'cert_reqs': ssl.CERT_REQUIRED, }) return kws
def sslkwargs(ui, host): kws = {} hostfingerprint = ui.config('hostfingerprints', host) if hostfingerprint: return kws cacerts = ui.config('web', 'cacerts') if cacerts == '!': pass elif cacerts: cacerts = util.expandpath(cacerts) if not os.path.exists(cacerts): raise util.Abort(_('could not find web.cacerts: %s') % cacerts) else: cacerts = _defaultcacerts() if cacerts and cacerts != '!': ui.debug('using %s to enable OS X system CA\n' % cacerts) ui.setconfig('web', 'cacerts', cacerts, 'defaultcacerts') if cacerts != '!': kws.update({ 'ca_certs': cacerts, 'cert_reqs': CERT_REQUIRED, }) return kws
def __init__(self, ui, repo, url): super(localstore, self).__init__(ui, repo, util.expandpath(url))
def __init__(self, repoagent, parent=None, *pats): 'Initialize the Dialog' QDialog.__init__(self, parent) self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint | Qt.WindowMaximizeButtonHint) self._repoagent = repoagent repo = repoagent.rawRepo() self.pats = pats self.setWindowTitle(_('Ignore filter - %s') % repo.displayname) self.setWindowIcon(qtlib.geticon('ignore')) vbox = QVBoxLayout() self.setLayout(vbox) # layer 1 hbox = QHBoxLayout() vbox.addLayout(hbox) recombo = QComboBox() recombo.addItems([_('Glob'), _('Regexp')]) hbox.addWidget(recombo) le = QLineEdit() hbox.addWidget(le, 1) le.returnPressed.connect(self.addEntry) add = QPushButton(_('Add')) add.clicked.connect(self.addEntry) hbox.addWidget(add, 0) # layer 2 hbox = QHBoxLayout() vbox.addLayout(hbox) ignorefiles = [repo.wjoin('.hgignore')] for name, value in repo.ui.configitems('ui'): if name == 'ignore' or name.startswith('ignore.'): ignorefiles.append(util.expandpath(value)) filecombo = QComboBox() hbox.addWidget(filecombo) for f in ignorefiles: filecombo.addItem(hglib.tounicode(f)) filecombo.currentIndexChanged.connect(self.fileselect) self.ignorefile = ignorefiles[0] edit = QPushButton(_('Edit File')) edit.clicked.connect(self.editClicked) hbox.addWidget(edit) hbox.addStretch(1) # layer 3 - main widgets split = QSplitter() vbox.addWidget(split, 1) ignoregb = QGroupBox() ivbox = QVBoxLayout() ignoregb.setLayout(ivbox) lbl = QLabel(_('<b>Ignore Filter</b>')) ivbox.addWidget(lbl) split.addWidget(ignoregb) unknowngb = QGroupBox() uvbox = QVBoxLayout() unknowngb.setLayout(uvbox) lbl = QLabel(_('<b>Untracked Files</b>')) uvbox.addWidget(lbl) split.addWidget(unknowngb) ignorelist = QListWidget() ivbox.addWidget(ignorelist) ignorelist.setSelectionMode(QAbstractItemView.ExtendedSelection) unknownlist = QListWidget() uvbox.addWidget(unknownlist) unknownlist.setSelectionMode(QAbstractItemView.ExtendedSelection) unknownlist.currentTextChanged.connect(self.setGlobFilter) unknownlist.setContextMenuPolicy(Qt.CustomContextMenu) unknownlist.customContextMenuRequested.connect(self.menuRequest) unknownlist.itemDoubleClicked.connect(self.unknownDoubleClicked) lbl = QLabel(_('Backspace or Del to remove row(s)')) ivbox.addWidget(lbl) # layer 4 - dialog buttons BB = QDialogButtonBox bb = QDialogButtonBox(BB.Close) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) vbox.addWidget(bb) self.bb = bb le.setFocus() self.le, self.recombo, self.filecombo = le, recombo, filecombo self.ignorelist, self.unknownlist = ignorelist, unknownlist ignorelist.installEventFilter(self) QTimer.singleShot(0, self.refresh) s = QSettings() self.restoreGeometry(s.value('hgignore/geom').toByteArray())
def __init__(self, ui, repo, remote): url = os.path.join(remote.path, '.hg', lfutil.longname) super(localstore, self).__init__(ui, repo, util.expandpath(url)) self.remote = remote
def __init__(self, ui, repo, remote): url = os.path.join(remote.path, '.hg', bfutil.longname) super(localstore, self).__init__(ui, repo, util.expandpath(url))
def normreporoot(path): """Normalize repo root path in the same manner as localrepository""" # see localrepo.localrepository and scmutil.vfs lpath = fromunicode(path) lpath = os.path.realpath(util.expandpath(lpath)) return tounicode(lpath)
self.openPrompt() return cmd = args.pop(0) try: self._cmdtable[cmd](self, args) except KeyError: return self._runextcommand(cmdline) def _parsecmdline(self, cmdline): """Split command line string to imitate a unix shell""" try: args = shlex.split(hglib.fromunicode(cmdline)) except ValueError, e: raise ValueError(_("command parse error: %s") % e) for e in args: e = util.expandpath(e) if util.any(c in e for c in "*?[]"): expanded = glob.glob(os.path.join(self.cwd, e)) if not expanded: raise ValueError(_("no matches found: %s") % hglib.tounicode(e)) for p in expanded: yield p else: yield e def _runextcommand(self, cmdline): self._extproc.setWorkingDirectory(hglib.tounicode(self.cwd)) self._extproc.start(cmdline, QIODevice.ReadOnly) @_cmdtable def _cmd_hg(self, args):
def list_files(ui, repo, *args, **opts): """list files and related information For each name given that is a file of a type other than a directory, displays its name as well as any requested, associated information. For each name given that is a directory, displays the names of files within that directory, as well as any requested, associated information. If no names are given, the contents of the working directory are displayed. N.B. the :hg:`list` command *only displays items that are checked in to the repository*. It specifically *does not* display items that are merely present in the working directory, even if you have used :hg:`add` on them. Use the -s/--sort option to change the sort order for the files; the argument is a comma-separated list of any of the following items: :name: the name of the file :rev: the last revision at which the file was changed :date: the date of the last revision at which the file was changed :author: the name of the user who last changed the file :user: the short name of the user who last changed the file :size: the size of the file :subrepo: the name of the subrepository :linkurl: the URL for a subrepository link :linkrev: the revision for a subrepository link (for hg, a node value) :linktype: the type of a subrepository link Each item may optionally be preceded by a '+' or a '-' character to control sort direction. If the -l/--long option is given, the following information is displayed for each file: - file flags - short user (pass -v to change to full username) - size of the file (pass -H to view in human-readable form) - revision of last change (in rev:node format) - date of last change - file name Additionally, if you use the -S option to recurse into subrepositories, a column will be inserted before the revision column naming the subrepository. Subrepository recursion only works for Mercurial subrepositories; foreign subrepositories are not supported. When you are using the -S option, the subrepository roots will be listed as if they were directories. If you want to see the subrepositories as links instead, specify --links. The --links option and the -S option are mutually exclusive; also note that -S is fragile and cannot support non-Mercurial subrepositories, whereas --links is robust and will work with any kind of subrepository supported by Mercurial. If the -F/--flags option is specified, an '@', '*', or '/' character will be appended to the name to indicate symbolic links, executable files, subrepositories and directories respectively. If --links is specified, subrepositories will be listed with an '&' character appended. You can also customise the output using the --template argument; this uses the same template system as :hg:`log`; the following keywords are defined: :name: the name of the file :mode: the UNIX mode of the file :size: the size of the file, in bytes :kind: an '@', '*', '&' or '/' character depending on the type of the file :subrepo: if this file is in a subrepository, the path within the outer repository :rev: the last revision at which the file was changed :node: the changeset ID for that revision :date: the date of the last revision at which the file was changed :author: the name of the user who last changed the file :branch: the branch of the last revision at which the file was changed :desc: the description of that revision :linkurl: the URL for a subrepository link :linkrev: the revision for a subrepository link :linktype: the type of a subrepository link If you pass the --columns switch as well as the --template switch, you can obtain column-aligned output. The --columns switch takes a string, each character of which corresponds to a column in the output. An 'l' character left-justifies within the column, while an 'r' right-justifies and a 'c' character will center within the column. Any other character will cause right-justification. If you are using the --columns switch, your template should use '\0' characters (i.e. NULs) to separate the columns. If you have more columns than the number of alignment specifications, the extra columns will be left-justified by default. A trailing left-aligned column will not be padded.""" rev = opts['rev'] ctx = repo[rev] all = opts['all'] flags = opts['flags'] sort = [s.lower().strip() for s in opts['sort'].split(',')] template = opts['template'] style = opts['style'] should_format = ui.formatted() long_format = opts['long'] human = opts['human'] subrepos = opts['subrepos'] links = opts['links'] recursive = opts['recursive'] dumb = opts['dumb'] align_columns = opts['columns'] file_buffer = [] # Work out where to get our template from if not (style or template): template = ui.config('ui', 'listtemplate') if template: try: template = templater.parsestring(template) except SyntaxError: template = templater.parsestring(template, quoted=False) else: style = util.expandpath(ui.config('ui', 'style', '')) elif template: try: template = templater.parsestring(template, quoted=False) except SyntaxError, e: raise util.Abort('bad template: %s' % e.args[0])
def uisetup(ui): for cmd, path in ui.configitems('extdiff'): path = util.expandpath(path) if cmd.startswith('cmd.'): cmd = cmd[4:] if not path: path = util.findexe(cmd) if path is None: path = filemerge.findexternaltool(ui, cmd) or cmd diffopts = ui.config('extdiff', 'opts.' + cmd, '') cmdline = util.shellquote(path) if diffopts: cmdline += ' ' + diffopts elif cmd.startswith('opts.'): continue else: if path: # case "cmd = path opts" cmdline = path diffopts = len(shlex.split(cmdline)) > 1 else: # case "cmd =" path = util.findexe(cmd) if path is None: path = filemerge.findexternaltool(ui, cmd) or cmd cmdline = util.shellquote(path) diffopts = False # look for diff arguments in [diff-tools] then [merge-tools] if not diffopts: args = ui.config('diff-tools', cmd+'.diffargs') or \ ui.config('merge-tools', cmd+'.diffargs') if args: cmdline += ' ' + args def save(cmdline): '''use closure to save diff command to use''' def mydiff(ui, repo, *pats, **opts): options = ' '.join(map(util.shellquote, opts['option'])) if options: options = ' ' + options return dodiff(ui, repo, cmdline + options, pats, opts) doc = _('''\ use %(path)s to diff repository (or selected files) Show differences between revisions for the specified files, using the %(path)s program. When two revision arguments are given, then changes are shown between those revisions. If only one revision is specified then that revision is compared to the working directory, and, when no revisions are specified, the working directory files are compared to its parent.\ ''') % {'path': util.uirepr(path)} # We must translate the docstring right away since it is # used as a format string. The string will unfortunately # be translated again in commands.helpcmd and this will # fail when the docstring contains non-ASCII characters. # Decoding the string to a Unicode string here (using the # right encoding) prevents that. mydiff.__doc__ = doc.decode(encoding.encoding) return mydiff command(cmd, extdiffopts[:], _('hg %s [OPTION]... [FILE]...') % cmd, inferrepo=True)(save(cmdline))
def _normreporoot(path): """Normalize repo root path in the same manner as localrepository""" # see localrepo.localrepository and scmutil.vfs lpath = hglib.fromunicode(path) lpath = os.path.realpath(util.expandpath(lpath)) return hglib.tounicode(lpath)
def __init__(self, repoagent, parent=None, *pats): 'Initialize the Dialog' QDialog.__init__(self, parent) self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint | Qt.WindowMaximizeButtonHint) self._repoagent = repoagent self.pats = pats self.setWindowTitle(_('Ignore filter - %s') % repoagent.displayName()) self.setWindowIcon(qtlib.geticon('thg-ignore')) vbox = QVBoxLayout() self.setLayout(vbox) # layer 1 hbox = QHBoxLayout() vbox.addLayout(hbox) recombo = QComboBox() recombo.addItems([_('Glob'), _('Regexp')]) hbox.addWidget(recombo) le = QLineEdit() hbox.addWidget(le, 1) le.returnPressed.connect(self.addEntry) add = QPushButton(_('Add')) add.setAutoDefault(False) add.clicked.connect(self.addEntry) hbox.addWidget(add, 0) # layer 2 repo = repoagent.rawRepo() hbox = QHBoxLayout() vbox.addLayout(hbox) ignorefiles = [repo.wjoin('.hgignore')] for name, value in repo.ui.configitems('ui'): if name == 'ignore' or name.startswith('ignore.'): ignorefiles.append(util.expandpath(value)) filecombo = QComboBox() hbox.addWidget(filecombo) for f in ignorefiles: filecombo.addItem(hglib.tounicode(f)) filecombo.currentIndexChanged.connect(self.fileselect) self.ignorefile = ignorefiles[0] edit = QPushButton(_('Edit File')) edit.setAutoDefault(False) edit.clicked.connect(self.editClicked) hbox.addWidget(edit) hbox.addStretch(1) # layer 3 - main widgets split = QSplitter() vbox.addWidget(split, 1) ignoregb = QGroupBox() ivbox = QVBoxLayout() ignoregb.setLayout(ivbox) lbl = QLabel(_('<b>Ignore Filter</b>')) ivbox.addWidget(lbl) split.addWidget(ignoregb) unknowngb = QGroupBox() uvbox = QVBoxLayout() unknowngb.setLayout(uvbox) lbl = QLabel(_('<b>Untracked Files</b>')) uvbox.addWidget(lbl) split.addWidget(unknowngb) ignorelist = QListWidget() ivbox.addWidget(ignorelist) ignorelist.setSelectionMode(QAbstractItemView.ExtendedSelection) unknownlist = QListWidget() uvbox.addWidget(unknownlist) unknownlist.setSelectionMode(QAbstractItemView.ExtendedSelection) unknownlist.currentTextChanged.connect(self.setGlobFilter) unknownlist.setContextMenuPolicy(Qt.CustomContextMenu) unknownlist.customContextMenuRequested.connect(self.menuRequest) unknownlist.itemDoubleClicked.connect(self.unknownDoubleClicked) lbl = QLabel(_('Backspace or Del to remove row(s)')) ivbox.addWidget(lbl) # layer 4 - dialog buttons BB = QDialogButtonBox bb = QDialogButtonBox(BB.Close) bb.button(BB.Close).setAutoDefault(False) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) vbox.addWidget(bb) self.bb = bb le.setFocus() self.le, self.recombo, self.filecombo = le, recombo, filecombo self.ignorelist, self.unknownlist = ignorelist, unknownlist ignorelist.installEventFilter(self) QTimer.singleShot(0, self.refresh) s = QSettings() self.restoreGeometry(qtlib.readByteArray(s, 'hgignore/geom'))
self._commandHistory.append(ucmdline) # execute the command cmd = args.pop(0) try: self._cmdtable[cmd](self, args) except KeyError: return self._runextcommand(cmdline) def _parsecmdline(self, cmdline): """Split command line string to imitate a unix shell""" try: args = shlex.split(hglib.fromunicode(cmdline)) except ValueError, e: raise ValueError(_('command parse error: %s') % e) for e in args: e = util.expandpath(e) if util.any(c in e for c in '*?[]'): expanded = glob.glob(os.path.join(self.cwd, e)) if not expanded: raise ValueError( _('no matches found: %s') % hglib.tounicode(e)) for p in expanded: yield p else: yield e def _runextcommand(self, cmdline): self._extproc.setWorkingDirectory(hglib.tounicode(self.cwd)) self._extproc.start(cmdline, QIODevice.ReadOnly) @_cmdtable
def configpath(ui, name): path = ui.config('hgsubversion', name) return path and hgutil.expandpath(path)