def getreviewboard(ui, opts): '''We are going to fetch the setting string from hg prefs, there we can set our own proxy, or specify 'none' to pass an empty dictionary to urllib2 which overides the default autodetection when we want to force no proxy''' http_proxy = ui.config('reviewboard', 'http_proxy' ) if http_proxy: if http_proxy == 'none': proxy = {} else: proxy = { 'http':http_proxy } else: proxy=None server = find_server(ui, opts) ui.status('reviewboard:\t%s\n' % server) ui.status('\n') username = opts.get('username') or ui.config('reviewboard', 'user') if username: ui.status('username: %s\n' % username) password = opts.get('password') or ui.config('reviewboard', 'password') if password: ui.status('password: %s\n' % '**********') try: return make_rbclient(server, username, password, proxy=proxy, apiver=opts.get('apiver')) except ReviewBoardError, msg: raise error.Abort(_(unicode(msg)))
def _get_authtoken_from_kilnauth(ui): """Attempts to use kilnauth, if it is installed, to find a kiln token.""" kilnauth_path = ui.config('extensions', 'kilnauth') if kilnauth_path: sys.path.append(os.path.dirname(os.path.expanduser(kilnauth_path))) try: import kilnauth except ImportError: return None class FakeRepo: def local(self): return True kilnauth.reposetup(ui, FakeRepo()) hostname = ui.config('auth', 'kiln.prefix') if '://' in hostname: hostname = hostname[hostname.find('://')+3:] if hostname.endswith('/'): hostname = hostname[:-1] for cookie in kilnauth.get_cookiejar(ui): if cookie.domain == hostname and cookie.name == 'fbToken': return cookie.value return None
def getfromaddr(ui): """Get sender address in the same manner as patchbomb""" addr = ui.config('email', 'from') or ui.config('patchbomb', 'from') if addr: return addr try: return repo.ui.username() except error.Abort: return ''
def find_reviewboard_repo_id(ui, reviewboard, opts): if opts.get('repoid'): return opts.get('repoid') elif ui.config('reviewboard','repoid'): return ui.config('reviewboard','repoid') try: repositories = reviewboard.repositories() except ReviewBoardError, msg: raise error.Abort(_(unicode(msg)))
def besttool(ui, tools): 'Select preferred or highest priority tool from dictionary' preferred = ui.config('tortoisehg', 'vdiff') or ui.config('ui', 'merge') if preferred and preferred in tools: return preferred pris = [] for t in tools.keys(): p = int(ui.config('merge-tools', t + '.priority', 0)) pris.append((-p, t)) tools = sorted(pris) return tools[0][1]
def difftools(ui): global _difftools if _difftools: return _difftools def fixup_extdiff(diffopts): if "$child" not in diffopts: diffopts.append("$parent1") diffopts.append("$child") if "$parent2" in diffopts: mergeopts = diffopts[:] diffopts.remove("$parent2") else: mergeopts = [] return diffopts, mergeopts tools = {} for cmd, path in ui.configitems("extdiff"): if cmd.startswith("cmd."): cmd = cmd[4:] if not path: path = cmd diffopts = ui.config("extdiff", "opts." + cmd, "") diffopts = shlex.split(diffopts) diffopts, mergeopts = fixup_extdiff(diffopts) tools[cmd] = [path, diffopts, mergeopts] elif cmd.startswith("opts."): continue else: # command = path opts if path: diffopts = shlex.split(path) path = diffopts.pop(0) else: path, diffopts = cmd, [] diffopts, mergeopts = fixup_extdiff(diffopts) tools[cmd] = [path, diffopts, mergeopts] mt = [] mergetools(ui, mt) for t in mt: if t.startswith("internal:"): continue dopts = ui.config("merge-tools", t + ".diffargs", "") mopts = ui.config("merge-tools", t + ".diff3args", "") dopts, mopts = shlex.split(dopts), shlex.split(mopts) tools[t] = [filemerge._findtool(ui, t), dopts, mopts] _difftools = tools return tools
def difftools(ui): global _difftools if _difftools: return _difftools def fixup_extdiff(diffopts): if '$child' not in diffopts: diffopts.append('$parent1') diffopts.append('$child') if '$parent2' in diffopts: mergeopts = diffopts[:] diffopts.remove('$parent2') else: mergeopts = [] return diffopts, mergeopts tools = {} for cmd, path in ui.configitems('extdiff'): if cmd.startswith('cmd.'): cmd = cmd[4:] if not path: path = cmd diffopts = ui.config('extdiff', 'opts.' + cmd, '') diffopts = shlex.split(diffopts) diffopts, mergeopts = fixup_extdiff(diffopts) tools[cmd] = [path, diffopts, mergeopts] elif cmd.startswith('opts.'): continue else: # command = path opts if path: diffopts = shlex.split(path) path = diffopts.pop(0) else: path, diffopts = cmd, [] diffopts, mergeopts = fixup_extdiff(diffopts) tools[cmd] = [path, diffopts, mergeopts] mt = [] mergetools(ui, mt) for t in mt: if t.startswith('internal:'): continue dopts = ui.config('merge-tools', t + '.diffargs', '') mopts = ui.config('merge-tools', t + '.diff3args', '') dopts, mopts = shlex.split(dopts), shlex.split(mopts) tools[t] = [filemerge._findtool(ui, t), dopts, mopts] _difftools = tools return tools
def sendchoicestoidea(ui, msg, choices, default): port = int(ui.config("hg4ideaprompt", "port", None, True)) if not port: raise util.Abort("No port was specified") numOfChoices = len(choices) if not numOfChoices: return default client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: client.connect(("127.0.0.1", port)) send(client, msg) sendInt(client, numOfChoices) for choice in choices: send(client, choice) sendInt(client, default) answer = receiveInt(client) if answer == -1: raise util.Abort("User cancelled") else: return answer except: raise
def get_config(ui: ui, item: str) -> str: try: # config returns configuration value. return ui.config('zulip', item) except IndexError: ui.warn("Zulip: Could not find required item {} in hg config.".format(item)) sys.exit(1)
def review(ui, repo, rev='.', **opts): from urllib2 import HTTPError from getpass import getpass server = _find_server(ui, opts) ctx = repo['.'] parent = opts.get("parent") or ctx.parents()[0] username = opts.get("username") or ui.config("hgerickson", "username") if not username: raise _abort( "please specify Erickson account username in your .hgrc file " "or using the --username flag") rr = https_requests(server, insecure=opts.get("insecure")) try: rr.post( "/login", { "username": username, "password": getpass("Password for {}: ".format(username)) }) except HTTPError, e: raise _abort( "could not login to the server due to network error: {}".format(e))
def _find_server(ui, opts): server = opts.get("server") or ui.config("hgerickson", "server") if not server: raise _abort("please specify a reviewboard server in your .hgrc file " "or using the --server flag") return server
def get_config(ui: ui, item: str) -> str: try: # config returns configuration value. return ui.config("zulip", item) except IndexError: ui.warn(f"Zulip: Could not find required item {item} in hg config.") sys.exit(1)
def gethidetags(ui): global _hidetags if _hidetags is None: tags = toutf(ui.config('tortoisehg', 'hidetags', '')) taglist = [t.strip() for t in tags.split()] _hidetags = taglist return _hidetags
def sendchangestoidea(ui, msg, choices, default): port = int(ui.config('hg4ideaprompt', 'port', None, True)) if not port: raise util.Abort("No port was specified") numOfChoices = len(choices) if numOfChoices == 0: return default client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: client.connect(('127.0.0.1', port)) send(client, msg) sendInt(client, numOfChoices) for choice in choices: send(client, choice) sendInt(client, default) answer = receiveInt(client) print "Received answer: %s" % answer if answer == -1: raise util.Abort("User cancelled") else: return answer except: raise
def start(ui, repo): m = Master(ui, repo) sys.stdout.flush() sys.stderr.flush() pid = os.fork() if pid: return pid os.setsid() fd = os.open('/dev/null', os.O_RDONLY) os.dup2(fd, 0) if fd > 0: os.close(fd) fd = os.open(ui.config('inotify', 'log', '/dev/null'), os.O_RDWR | os.O_CREAT | os.O_TRUNC) os.dup2(fd, 1) os.dup2(fd, 2) if fd > 2: os.close(fd) try: m.run() finally: m.shutdown() os._exit(0)
def sendchoicestoidea(ui, msg, choices, default): port = int(ui.config(b'hg4ideaprompt', b'port', None, True)) if not port: raise error.Abort("No port was specified") if (type(choices) is int) and (type(msg) is str): # since Mercurial 2.7 the promptchoice method doesn't accept 'choices' as parameter, so we need to parse them from msg # see ui.py -> promptchoice(self, prompt, default=0) parts = msg.split('$$') msg = parts[0].rstrip(' ') choices = [p.strip(' ') for p in parts[1:]] numOfChoices = len(choices) if not numOfChoices: return default client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: client.connect(('127.0.0.1', port)) send(client, msg) sendInt(client, numOfChoices) for choice in choices: send(client, choice) sendInt(client, default) answer = receiveInt(client) if answer == -1: raise error.Abort("User cancelled") else: return answer except: raise
def sendchoicestoidea(ui, msg, choices, default): port = int(ui.config( 'hg4ideaprompt', 'port', None, True)) if not port: raise util.Abort("No port was specified") if (type(choices) is int) and (type(msg) is str): # since Mercurial 2.7 the promptchoice method doesn't accept 'choices' as parameter, so we need to parse them from msg # see ui.py -> promptchoice(self, prompt, default=0) parts = msg.split('$$') msg = parts[0].rstrip(' ') choices = [p.strip(' ') for p in parts[1:]] numOfChoices = len(choices) if not numOfChoices: return default client = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) try: client.connect( ('127.0.0.1', port) ) send( client, msg ) sendInt( client, numOfChoices ) for choice in choices: send( client, choice ) sendInt( client, default ) answer = receiveInt( client ) if answer == -1: raise util.Abort("User cancelled") else: return answer except: raise
def find_server(ui, opts): server = opts.get('server') if not server: server = ui.config('reviewboard', 'server') if not server: msg = 'please specify a reviewboard server in your .hgrc file or using the --server flag' raise error.Abort(_(unicode(msg))) return server
def get_config(ui, item): # type: (ui, str) -> str try: # config returns configuration value. return ui.config('zulip', item) except IndexError: ui.warn("Zulip: Could not find required item {} in hg config.".format(item)) sys.exit(1)
def getdeadbranch(ui): """return a list of dead branch names in UTF-8""" global _deadbranch if _deadbranch is None: db = toutf(ui.config("tortoisehg", "deadbranch", "")) dblist = [b.strip() for b in db.split(",")] _deadbranch = dblist return _deadbranch
def getdeadbranch(ui): '''return a list of dead branch names in UTF-8''' global _deadbranch if _deadbranch is None: db = toutf(ui.config('tortoisehg', 'deadbranch', '')) dblist = [b.strip() for b in db.split(',')] _deadbranch = dblist return _deadbranch
def incoming(ui, repo, remote="default", **opts): """show new changesets found in source""" _checklocal(repo) adjust = remote and not ui.config('paths', remote) st = opts.get('subtrees') repocount = len(_list(ui, repo, st and {'subtrees': st} or {})) rc = _docmd2(_origcmd('incoming'), ui, repo, remote, adjust, **opts) # return 0 if any of the repos have incoming changes; 1 otherwise. return int(rc == repocount)
def outgoing(ui, repo, remote=None, **opts): '''show changesets not found in the destination''' _checklocal(repo) adjust = remote and not ui.config('paths', remote) st = opts.get('subtrees') repocount = len(_list(ui, repo, st and {'subtrees': st} or {})) rc = _docmd2(_origcmd('outgoing'), ui, repo, remote, adjust, **opts) # return 0 if any of the repos have outgoing changes; 1 otherwise. return int(rc == repocount)
def get_config(ui, item): # type: (ui, str) -> str try: # config returns configuration value. return ui.config('yakkl', item) except IndexError: ui.warn("Yakkl: Could not find required item {} in hg config.".format( item)) sys.exit(1)
def shortreponame(ui): name = ui.config('web', 'name') if not name: return src = ui.configsource('web', 'name') # path:line if '/.hg/hgrc:' not in util.pconvert(src): # global web.name will set the same name to all repositories ui.debug('ignoring global web.name defined at %s\n' % src) return return name
def push(ui, repo, remote=None, **opts): '''push changes to the specified destination''' _checklocal(repo) adjust = remote and not ui.config('paths', remote) st = opts.get('subtrees') repocount = len(_list(ui, repo, st and {'subtrees': st} or {})) rc = _docmd2(_origcmd('push'), ui, repo, remote, adjust, **opts) # return 0 if all pushes were successful; 1 if none of the repos had # anything to push. return int(rc == repocount)
def pull(ui, repo, remote="default", **opts): '''pull changes from the specified source''' _checklocal(repo) adjust = remote and not ui.config('paths', remote) st = opts.get('subtrees') repocount = len(_list(ui, repo, st and {'subtrees': st} or {})) rc = _docmd2(_origcmd('pull'), ui, repo, remote, adjust, **opts) # Sadly, pull returns 1 if there was nothing to pull *or* if there are # unresolved files on update. No way to distinguish between them. # return 0 if any subtree pulled successfully. return int(rc == repocount)
def backlog(ui, repo, issue_or_rev=None, **opts): if issue_or_rev is None: issue_id = get_issue_id(repo.changectx(".")) elif issue_or_rev.startswith("#"): issue_id = issue_or_rev[1:] else: node = repo.changectx(issue_or_rev) issue_id = get_issue_id(node) endpoint = ui.config('backlog', 'endpoint') project_key = ui.config('backlog', 'project_key') username = ui.config('backlog', 'username') password = ui.config('backlog', 'password') uri = build_uri(endpoint, username, password) server = xmlrpclib.ServerProxy(uri) data = server.backlog.getIssue("%s-%s" % (project_key, issue_id)) subject = data['summary'] status = data['status']['name'] print (u"[%s] %s" % (status, subject)).encode('utf-8') print data['url']
def getmaxdiffsize(ui): global _maxdiff if _maxdiff is not None: return _maxdiff maxdiff = ui.config('tortoisehg', 'maxdiff') try: maxdiff = int(maxdiff) if maxdiff < 1: maxdiff = sys.maxint except (ValueError, TypeError): maxdiff = 1024 # 1MB by default _maxdiff = maxdiff * 1024 return _maxdiff
def show_ticket_summary(ui, repo, ticket_or_rev=None, **opts): if ticket_or_rev is None: ticket_id = get_ticket_id(repo.changectx(".")) elif ticket_or_rev.startswith("#"): ticket_id = ticket_or_rev[1:] else: node = repo.changectx(ticket_or_rev) ticket_id = get_ticket_id(node) base_url = ui.config('redmine', 'base_url') api_key = ui.config('redmine', 'api_key') issue_url = base_url.rstrip('/') + '/issues/%s' % ticket_id res = urllib.urlopen(issue_url + ".json?key=" + api_key) content = res.read() res.close() d = json.loads(content) status = d["issue"]["status"]["name"] subject = d["issue"]["subject"] print (u"[%s] %s" % (status, subject)).encode('utf-8') print issue_url
def gettabwidth(ui): global _tabwidth if _tabwidth is not None: return _tabwidth tabwidth = ui.config('tortoisehg', 'tabwidth') try: tabwidth = int(tabwidth) if tabwidth < 1 or tabwidth > 16: tabwidth = 0 except (ValueError, TypeError): tabwidth = 0 _tabwidth = tabwidth return tabwidth
def retrieve_pass_from_server(ui, uri, path, proposed_user): port = int(ui.config(b'hg4ideapass', b'port', None, True)) if port is None: raise error.Abort("No port was specified") client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ui.debug("connecting ...") client.connect(('127.0.0.1', port)) ui.debug("connected, sending data ...") send(client, "getpass") send(client, uri) send(client, path) send(client, proposed_user) user = receiveWithMessage(client, b"http authorization required") password = receiveWithMessage(client, b"http authorization required") return user, password
def _publish(ui, repo, commitlog_path, rebuild=False): u"发布一个库至svn" # 编译当前库 publish_path = ui.config("opm", "publish-path") if not publish_path: ui.warn("%s: no publish path\n" % repo.root) else: # 编译当前库 runcmd(ui, repo, "svn update %s --force --accept theirs-full" % publish_path) commands.ui.prefix = repo.root + ": " commands.ui.fout = ui.fout # 输入导出到客户端 commands.publish(repo.root, publish_path, rebuild=rebuild) commands.ui.prefix = "" runcmd(ui, repo, "svn commit %s -F %s" % (publish_path, commitlog_path), "nothing to commit.")
def retrieve_pass_from_server(ui, uri, path, proposed_user): port = int(ui.config("hg4ideapass", "port", None, True)) if port is None: raise util.Abort("No port was specified") client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ui.debug("connecting ...") client.connect(("127.0.0.1", port)) ui.debug("connected, sending data ...") send(client, "getpass") send(client, uri) send(client, path) send(client, proposed_user) user = receiveWithMessage(client, "http authorization required") password = receiveWithMessage(client, "http authorization required") return user, password
def publish(ui, repo, source="", node="default", **opts): # 只对静态编译框架维护的库进行操作 if not opm.StaticPackage.is_root(repo.root) or source == "pull": return publish_branch = ui.config("opm", "publish-branch", "default") # 默认作为发布源的分支名称 node = repo[node] node_branch = node.branch() # 不是需要被编译的分支 # 不判断分支,因为通过changegroup hook触发编译时,获取到的分支信息有可能不是default,导致不编译 # if node_branch != publish_branch: # ui.warn('%s: ignore branch %s\n' % (repo.root, node_branch)) # return # update到需要编译的分支 mergemod.update(repo, publish_branch, False, False, None) # 生成commitlog commitlog_path = os.path.realpath(os.path.join(repo.root, "./commitlog.txt")) parent = node.parents()[0].rev() rev = node.rev() ui.write("%s: update version from %s to %s\n" % (repo.root, parent, rev)) os.chdir(repo.root) os.system("hg log -b %s -r %s:%s > %s" % (node_branch, parent, rev, commitlog_path)) # 编译自己 _publish(ui, repo, commitlog_path, rebuild=True) # 编译依赖自己的库 package = opm.StaticPackage(repo.root) for repo_path in package.get_reverse_libs(all=True): sub_repo = hg.repository(ui, repo_path) _publish(sub_repo.ui, sub_repo, commitlog_path, rebuild=False) # 删除commitlog os.remove(commitlog_path)
def review(ui, repo, rev='.', **opts): from urllib2 import HTTPError from getpass import getpass server = _find_server(ui, opts) ctx = repo['.'] parent = opts.get("parent") or ctx.parents()[0] username = opts.get("username") or ui.config("hgerickson", "username") if not username: raise _abort("please specify Erickson account username in your .hgrc file " "or using the --username flag") rr = https_requests(server, insecure=opts.get("insecure")) try: rr.post("/login", { "username": username, "password": getpass("Password for {}: ".format(username)) }) except HTTPError, e: raise _abort("could not login to the server due to network error: {}".format(e))
def _toolstr(ui, tool, part, default=""): return ui.config("terminal-tools", tool + "." + part, default)
def createfields(ui, repo, c, parentc, opts): fields = {} all_contexts = find_contexts(repo, parentc, c, opts) # The latest unambiguous prefix of global changeset id (Commit field on UI) # Should be set on creation and on any update of review request. # commit_id field is introduced in reviewboard API 2.0 fields['commit_id'] = str(all_contexts[0]) changesets_string = 'changesets:\n' changesets_string += \ ''.join(['\t%s:%s "%s"\n' % (ctx.rev(), ctx, ctx.description()) \ for ctx in all_contexts]) if opts['branch']: branch_msg = "review of branch: %s\n\n" % (c.branch()) changesets_string = branch_msg + changesets_string ui.status(changesets_string + '\n') interactive = opts['interactive'] request_id = opts['existing'] # Don't clobber the summary and description for an existing request # unless specifically asked for if opts['update'] or not request_id: # summary if opts["summary"] and opts["summary"] != " ": default_summary = opts["summary"] else: default_summary = c.description().splitlines()[0] if interactive: ui.status('default summary: %s\n' % default_summary) ui.status('enter summary (or return for default):\n') summary = readline().strip() if summary: fields['summary'] = summary else: fields['summary'] = default_summary else: fields['summary'] = default_summary # description if interactive: ui.status('enter description:\n') description = readline().strip() ui.status('append changesets to description? (Y/n):\n') choice = readline().strip() if choice != 'n': if description: description += '\n\n' description += changesets_string else: description = changesets_string fields['description'] = description if not opts.get('bugs_closed') and fields['summary']: bugs_list = re.findall( r'([A-Z]+-[0-9]+)', fields['summary']) bugs_list = list(set(bugs_list)) augumented_bugs_list = [] for bug in bugs_list: if bug is bugs_list[-1]: augumented_bugs_list.append(str(bug)) else: augumented_bugs_list.append(str(bug) + ", ") fields['bugs_closed'] = "".join(augumented_bugs_list) fields['branch'] = c.branch() for field in ('target_groups', 'target_people', 'bugs_closed'): if opts.get(field): value = opts.get(field) else: value = ui.config('reviewboard', field) if value: fields[field] = value return fields
def _ns(ui, opts): return _nsnormalize(opts.get('tns') or ui.config('trees', 'namespace', 'trees'))
def install_style_hooks(env): hgdir = env.Dir('#.hg') style_hook = True style_hooks = tuple() hgrc = hgdir.File('hgrc') hgrc_old = hgdir.File('hgrc.old') try: from mercurial import ui ui = ui.ui() ui.readconfig(hgrc.abspath) style_hooks = (ui.config('hooks', 'pretxncommit.style', None), ui.config('hooks', 'pre-qrefresh.style', None)) style_hook = all(style_hooks) style_extension = ui.config('extensions', 'style', None) except ImportError: print(mercurial_lib_not_found) if "python:style.check_style" in style_hooks: # Try to upgrade the style hooks print(mercurial_style_upgrade_message) # continue unless user does ctrl-c/ctrl-d etc. try: raw_input() except: print("Input exception, exiting scons.\n") sys.exit(1) shutil.copyfile(hgrc.abspath, hgrc_old.abspath) re_style_hook = re.compile(r"^([^=#]+)\.style\s*=\s*([^#\s]+).*") re_style_extension = re.compile("style\s*=\s*([^#\s]+).*") old, new = open(hgrc_old.abspath, 'r'), open(hgrc.abspath, 'w') for l in old: m_hook = re_style_hook.match(l) m_ext = re_style_extension.match(l) if m_hook: hook, check = m_hook.groups() if check != "python:style.check_style": print("Warning: %s.style is using a non-default " \ "checker: %s" % (hook, check)) if hook not in ("pretxncommit", "pre-qrefresh"): print("Warning: Updating unknown style hook: %s" % hook) l = "%s.style = python:hgstyle.check_style\n" % hook elif m_ext and m_ext.group(1) == style_extension: l = "hgstyle = %s/util/hgstyle.py\n" % env.root.abspath new.write(l) elif not style_hook: print(mercurial_style_message, end=' ') # continue unless user does ctrl-c/ctrl-d etc. try: raw_input() except: print("Input exception, exiting scons.\n") sys.exit(1) hgrc_path = '%s/.hg/hgrc' % env.root.abspath print("Adding style hook to", hgrc_path, "\n") try: with open(hgrc_path, 'a') as f: f.write(mercurial_style_hook_template % env.root.abspath) except: print("Error updating", hgrc_path) sys.exit(1)
rr = https_requests(server, insecure=opts.get("insecure")) try: rr.post("/login", { "username": username, "password": getpass("Password for {}: ".format(username)) }) except HTTPError, e: raise _abort("could not login to the server due to network error: {}".format(e)) try: rr.post("/reviews", { "diff": _get_diff(ui, repo, ctx, repo[parent]), "commitmsg": _get_summary(repo, ctx, repo[parent]), "repository": ui.config("paths", "default"), "submitter": username, }) except HTTPError, e: raise _abort("could not submit the review due network error: {}".format(e)) def _find_server(ui, opts): server = opts.get("server") or ui.config("hgerickson", "server") if not server: raise _abort("please specify a reviewboard server in your .hgrc file " "or using the --server flag") return server
def postreview(ui, repo, rev='.', **opts): '''post a changeset to a Review Board server This command creates a new review request on a Review Board server, or updates an existing review request, based on a changeset in the repository. If no revision number is specified the parent revision of the working directory is used. By default, the diff uploaded to the server is based on the parent of the revision to be reviewed. A different parent may be specified using the --parent or --longdiff options. --parent r specifies the revision to use on the left side while --longdiff looks at the upstream repository specified in .hg/hgrc to find a common ancestor to use on the left side. --parent may need one of the options below if the Review Board server can't see the parent. If the parent revision is not available to the Review Board server (e.g. it exists in your local repository but not in the one that Review Board has access to) you must tell postreview how to determine the base revision to use for a parent diff. The --outgoing, --outgoingrepo or --master options may be used for this purpose. The --outgoing option is the simplest of these; it assumes that the upstream repository specified in .hg/hgrc is the same as the one known to Review Board. The other two options offer more control if this is not the case. In these cases two diffs are uploaded to Review Board: the first is the difference between Reviewboard's view of the repo and your parent revision(left side), the second is the difference between your parent revision and your review revision(right side). Only the second diff is under review. If you wish to review all the changes local to your repo use the --longdiff option above. The --outgoing option recognizes the path entries 'reviewboard', 'default-push' and 'default' in this order of precedence. 'reviewboard' may be used if the repository accessible to Review Board is not the upstream repository. The --git option causes postreview to generate diffs in Git extended format, which includes information about file renames and copies. ReviewBoard 1.6 beta 2 or later is required in order to use this feature. The --submit_as option allows to submit the review request as another user. This requires that the actual logged in user is either a superuser or has the "reviews.can_submit_as_another_user" permission. The reviewboard extension may be configured by adding a [reviewboard] section to your .hgrc or mercurial.ini file, or to the .hg/hgrc file of an individual repository. The following options are available:: [reviewboard] # REQUIRED server = <server_url> # The URL of your ReviewBoard server # OPTIONAL http_proxy = <proxy_url> # HTTP proxy to use for the connection user = <rb_username> # Username to use for ReviewBoard # connections password = <rb_password> # Password to use for ReviewBoard # connections repoid = <repoid> # ReviewBoard repository ID (normally only # useful in a repository-specific hgrc) target_groups = <groups> # Default groups for new review requests # (comma-separated list) target_people = <users> # Default users for new review requests # (comma-separated list) explicit_publish_update = <bool> # If True, updates posted using the -e # option will not be published immediately # unless the -p option is also used launch_webbrowser = <bool> # If True, new or updated requests will # always be shown in a web browser after # posting. ''' server = opts.get('server') if not server: server = ui.config('reviewboard', 'server') if not server: raise util.Abort( _('please specify a reviewboard server in your .hgrc file')) '''We are going to fetch the setting string from hg prefs, there we can set our own proxy, or specify 'none' to pass an empty dictionary to urllib2 which overides the default autodetection when we want to force no proxy''' http_proxy = ui.config('reviewboard', 'http_proxy') if http_proxy: if http_proxy == 'none': proxy = {} else: proxy = {'http': http_proxy} else: proxy = None def getdiff(ui, repo, r, parent, opts): '''return diff for the specified revision''' output = "" if opts.get('git') or ui.configbool('diff', 'git'): # Git diffs don't include the revision numbers with each file, so # we have to put them in the header instead. output += "# Node ID " + node.hex(r.node()) + "\n" output += "# Parent " + node.hex(parent.node()) + "\n" diffopts = patch.diffopts(ui, opts) for chunk in patch.diff(repo, parent.node(), r.node(), opts=diffopts): output += chunk return output parent = opts.get('parent') if parent: parent = repo[parent] else: parent = repo[rev].parents()[0] outgoing = opts.get('outgoing') outgoingrepo = opts.get('outgoingrepo') master = opts.get('master') repo_id_opt = opts.get('repoid') longdiff = opts.get('longdiff') if not repo_id_opt: repo_id_opt = ui.config('reviewboard', 'repoid') if master: rparent = repo[master] elif outgoingrepo: rparent = remoteparent(ui, repo, opts, rev, upstream=outgoingrepo) elif outgoing: rparent = remoteparent(ui, repo, opts, rev) elif longdiff: parent = remoteparent(ui, repo, opts, rev) rparent = None else: rparent = None ui.debug(_('Parent is %s\n' % parent)) ui.debug(_('Remote parent is %s\n' % rparent)) request_id = None if opts.get('existing'): request_id = opts.get('existing') fields = {} c = repo.changectx(rev) changesets_string = get_changesets_string(repo, parent, c) # Don't clobber the summary and description for an existing request # unless specifically asked for if opts.get('update') or not request_id: fields['summary'] = toascii(c.description().splitlines()[0]) fields['description'] = toascii(changesets_string) fields['branch'] = toascii(c.branch()) if opts.get('summary'): fields['summary'] = toascii(opts.get('summary')) if opts.get('description'): fields['description'] = toascii(opts.get('description')) diff = getdiff(ui, repo, c, parent, opts) ui.debug('\n=== Diff from parent to rev ===\n') ui.debug(diff + '\n') if rparent and parent != rparent: parentdiff = getdiff(ui, repo, parent, rparent, opts) ui.debug('\n=== Diff from rparent to parent ===\n') ui.debug(parentdiff + '\n') else: parentdiff = '' if opts.get('update') or not request_id: for field in ('target_groups', 'target_people', 'bugs_closed'): if opts.get(field): value = ','.join(opts.get(field)) else: value = ui.config('reviewboard', field) if value: fields[field] = toascii(value) ui.status('\n%s\n' % changesets_string) ui.status('reviewboard:\t%s\n' % server) ui.status('\n') username = opts.get('username') or ui.config('reviewboard', 'user') if username: ui.status('username: %s\n' % username) password = opts.get('password') or ui.config('reviewboard', 'password') if password: ui.status('password: %s\n' % '**********') try: reviewboard = make_rbclient(server, username, password, proxy=proxy, apiver=opts.get('apiver'), trace=opts.get('apitrace')) except Exception, e: raise util.Abort(_(str(e)))
def postreview(ui, repo, rev='.', **opts): '''post a changeset to a Review Board server This command creates a new review request on a Review Board server, or updates an existing review request, based on a changeset in the repository. If no revision number is specified the parent revision of the working directory is used. By default, the diff uploaded to the server is based on the parent of the revision to be reviewed. A different parent may be specified using the --parent or --longdiff options. --parent r specifies the revision to use on the left side while --longdiff looks at the upstream repository specified in .hg/hgrc to find a common ancestor to use on the left side. --parent may need one of the options below if the Review Board server can't see the parent. If the parent revision is not available to the Review Board server (e.g. it exists in your local repository but not in the one that Review Board has access to) you must tell postreview how to determine the base revision to use for a parent diff. The --outgoing, --outgoingrepo or --master options may be used for this purpose. The --outgoing option is the simplest of these; it assumes that the upstream repository specified in .hg/hgrc is the same as the one known to Review Board. The other two options offer more control if this is not the case. In these cases two diffs are uploaded to Review Board: the first is the difference between Reviewboard's view of the repo and your parent revision(left side), the second is the difference between your parent revision and your review revision(right side). Only the second diff is under review. If you wish to review all the changes local to your repo use the --longdiff option above. The --outgoing option recognizes the path entries 'reviewboard', 'default-push' and 'default' in this order of precedence. 'reviewboard' may be used if the repository accessible to Review Board is not the upstream repository. The --git option causes postreview to generate diffs in Git extended format, which includes information about file renames and copies. ReviewBoard 1.6 beta 2 or later is required in order to use this feature. The --submit_as option allows to submit the review request as another user. This requires that the actual logged in user is either a superuser or has the "reviews.can_submit_as_another_user" permission. The reviewboard extension may be configured by adding a [reviewboard] section to your .hgrc or mercurial.ini file, or to the .hg/hgrc file of an individual repository. The following options are available:: [reviewboard] # REQUIRED server = <server_url> # The URL of your ReviewBoard server # OPTIONAL http_proxy = <proxy_url> # HTTP proxy to use for the connection user = <rb_username> # Username to use for ReviewBoard # connections password = <rb_password> # Password to use for ReviewBoard # connections repoid = <repoid> # ReviewBoard repository ID (normally only # useful in a repository-specific hgrc) target_groups = <groups> # Default groups for new review requests # (comma-separated list) target_people = <users> # Default users for new review requests # (comma-separated list) explicit_publish_update = <bool> # If True, updates posted using the -e # option will not be published immediately # unless the -p option is also used launch_webbrowser = <bool> # If True, new or updated requests will # always be shown in a web browser after # posting. ''' server = opts.get('server') if not server: server = ui.config('reviewboard', 'server') if not server: raise util.Abort( _('please specify a reviewboard server in your .hgrc file') ) '''We are going to fetch the setting string from hg prefs, there we can set our own proxy, or specify 'none' to pass an empty dictionary to urllib2 which overides the default autodetection when we want to force no proxy''' http_proxy = ui.config('reviewboard', 'http_proxy' ) if http_proxy: if http_proxy == 'none': proxy = {} else: proxy = { 'http':http_proxy } else: proxy=None def getdiff(ui, repo, r, parent, opts): '''return diff for the specified revision''' output = "" if opts.get('git') or ui.configbool('diff', 'git'): # Git diffs don't include the revision numbers with each file, so # we have to put them in the header instead. output += "# Node ID " + node.hex(r.node()) + "\n" output += "# Parent " + node.hex(parent.node()) + "\n" diffopts = patch.diffopts(ui, opts) for chunk in patch.diff(repo, parent.node(), r.node(), opts=diffopts): output += chunk return output parent = opts.get('parent') if parent: parent = repo[parent] else: parent = repo[rev].parents()[0] outgoing = opts.get('outgoing') outgoingrepo = opts.get('outgoingrepo') master = opts.get('master') repo_id_opt = opts.get('repoid') longdiff = opts.get('longdiff') if not repo_id_opt: repo_id_opt = ui.config('reviewboard','repoid') if master: rparent = repo[master] elif outgoingrepo: rparent = remoteparent(ui, repo, opts, rev, upstream=outgoingrepo) elif outgoing: rparent = remoteparent(ui, repo, opts, rev) elif longdiff: parent = remoteparent(ui, repo, opts, rev) rparent = None else: rparent = None ui.debug(_('Parent is %s\n' % parent)) ui.debug(_('Remote parent is %s\n' % rparent)) request_id = None if opts.get('existing'): request_id = opts.get('existing') fields = {} c = repo.changectx(rev) changesets_string = get_changesets_string(repo, parent, c) # Don't clobber the summary and description for an existing request # unless specifically asked for if opts.get('update') or not request_id: fields['summary'] = toascii(c.description().splitlines()[0]) fields['description'] = toascii(changesets_string) fields['branch'] = toascii(c.branch()) if opts.get('summary'): fields['summary'] = toascii(opts.get('summary')) if opts.get('description'): fields['description'] = toascii(opts.get('description')) diff = getdiff(ui, repo, c, parent, opts) ui.debug('\n=== Diff from parent to rev ===\n') ui.debug(diff + '\n') if rparent and parent != rparent: parentdiff = getdiff(ui, repo, parent, rparent, opts) ui.debug('\n=== Diff from rparent to parent ===\n') ui.debug(parentdiff + '\n') else: parentdiff = '' if opts.get('update') or not request_id: for field in ('target_groups', 'target_people', 'bugs_closed'): if opts.get(field): value = ','.join(opts.get(field)) else: value = ui.config('reviewboard', field) if value: fields[field] = toascii(value) ui.status('\n%s\n' % changesets_string) ui.status('reviewboard:\t%s\n' % server) ui.status('\n') username = opts.get('username') or ui.config('reviewboard', 'user') if username: ui.status('username: %s\n' % username) password = opts.get('password') or ui.config('reviewboard', 'password') if password: ui.status('password: %s\n' % '**********') try: reviewboard = make_rbclient(server, username, password, proxy=proxy, apiver=opts.get('apiver'), trace=opts.get('apitrace')) except Exception, e: raise util.Abort(_(str(e)))
try: rr.post( "/login", { "username": username, "password": getpass("Password for {}: ".format(username)) }) except HTTPError, e: raise _abort( "could not login to the server due to network error: {}".format(e)) try: rr.post( "/reviews", { "diff": _get_diff(ui, repo, ctx, repo[parent]), "commitmsg": _get_summary(repo, ctx, repo[parent]), "repository": ui.config("paths", "default"), "submitter": username, }) except HTTPError, e: raise _abort( "could not submit the review due network error: {}".format(e)) def _find_server(ui, opts): server = opts.get("server") or ui.config("hgerickson", "server") if not server: raise _abort("please specify a reviewboard server in your .hgrc file " "or using the --server flag") return server
def _ns(ui, opts): return _nsnormalize( opts.get('tns') or ui.config('trees', 'namespace', 'trees'))
def install_style_hooks(env): hgdir = env.Dir('#.hg') style_hook = True style_hooks = tuple() hgrc = hgdir.File('hgrc') hgrc_old = hgdir.File('hgrc.old') try: from mercurial import ui ui = ui.ui() ui.readconfig(hgrc.abspath) style_hooks = (ui.config('hooks', 'pretxncommit.style', None), ui.config('hooks', 'pre-qrefresh.style', None)) style_hook = all(style_hooks) style_extension = ui.config('extensions', 'style', None) except ImportError: print mercurial_lib_not_found if "python:style.check_style" in style_hooks: # Try to upgrade the style hooks print mercurial_style_upgrade_message # continue unless user does ctrl-c/ctrl-d etc. try: raw_input() except: print "Input exception, exiting scons.\n" sys.exit(1) shutil.copyfile(hgrc.abspath, hgrc_old.abspath) re_style_hook = re.compile(r"^([^=#]+)\.style\s*=\s*([^#\s]+).*") re_style_extension = re.compile("style\s*=\s*([^#\s]+).*") old, new = open(hgrc_old.abspath, 'r'), open(hgrc.abspath, 'w') for l in old: m_hook = re_style_hook.match(l) m_ext = re_style_extension.match(l) if m_hook: hook, check = m_hook.groups() if check != "python:style.check_style": print "Warning: %s.style is using a non-default " \ "checker: %s" % (hook, check) if hook not in ("pretxncommit", "pre-qrefresh"): print "Warning: Updating unknown style hook: %s" % hook l = "%s.style = python:hgstyle.check_style\n" % hook elif m_ext and m_ext.group(1) == style_extension: l = "hgstyle = %s/util/hgstyle.py\n" % env.root.abspath new.write(l) elif not style_hook: print mercurial_style_message, # continue unless user does ctrl-c/ctrl-d etc. try: raw_input() except: print "Input exception, exiting scons.\n" sys.exit(1) hgrc_path = '%s/.hg/hgrc' % env.root.abspath print "Adding style hook to", hgrc_path, "\n" try: with open(hgrc_path, 'a') as f: f.write(mercurial_style_hook_template % env.root.abspath) except: print "Error updating", hgrc_path sys.exit(1)
second return value is a toolpath or user configured command line ''' # first check for tool specified in terminal-tools tools = {} for k, v in ui.configitems("terminal-tools"): t = k.split('.')[0] if t not in tools: try: priority = int(_toolstr(ui, t, "priority", "0")) except ValueError, e: priority = -100 tools[t] = priority names = tools.keys() tools = sorted([(-p, t) for t, p in tools.items()]) terminal = ui.config('tortoisehg', 'shell') if terminal: if terminal not in names: # if tortoisehg.terminal does not match an terminal-tools entry, take # the value directly return (None, terminal) # else select this terminal as highest priority (may still use another if # it is not found on this machine) tools.insert(0, (None, terminal)) for p, t in tools: toolpath = _findtool(ui, t) if toolpath: return (t, util.shellquote(toolpath)) # fallback to the default shell global _defaultshell