Add extension to push shell variables to server side hg

Summary:
Create an extension that allows shell variables to be passed to the
server via command line option. When pushing with the following command:

 hg push --pushvars "DEBUG=1"

will make HG_SCM_DEBUG=1 available to the hooks. Note the prepending of HG_SCM_

Test Plan: Run run_tests

Reviewers: pyd, rmcelroy, durham

Reviewed By: durham

Differential Revision: https://phabricator.fb.com/D1991994

Tasks: 4841351

Signature: t1:1991994:1430417209:9a05fb11f9ecdeab3a1d89cf331014dafe7d959f
This commit is contained in:
Aaron Kushner 2015-04-14 16:43:51 -04:00
parent d4caf4168e
commit 215c96605c
2 changed files with 125 additions and 0 deletions

67
pushvars.py Normal file
View File

@ -0,0 +1,67 @@
# pushvars.py - enable pushing environment variables to the server
#
# Copyright 2015 Facebook, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
#
# When we want to modify how a hook works or to disable it, we
# can send environment variables that the hooks can read. The
# environment variables are prepended with HG_USERVAR_ and are thus
# not a security vulnerability. For example:
#
# hg push --pushvars="BYPASS_REVIEWERS=true" --pushvars="DEBUG=1"
#
# will result in both HG_USERVAR_BYPASS_REVIEWERS and HG_USERVAR_DEBUG
# available to the hook environment.
from mercurial import bundle2, cmdutil, exchange, extensions, hg
from mercurial import util, error, commands
from mercurial.i18n import _
import errno, urllib
cmdtable = {}
command = cmdutil.command(cmdtable)
@exchange.b2partsgenerator('pushvars')
def _getbundlesendvars(pushop, bundler):
'''send shellvars via bundle2'''
if getattr(pushop.repo, '_shellvars', ()):
part = bundler.newpart('pushvars')
for entry in pushop.repo._shellvars:
try:
key, value = entry.split('=', 1)
except Exception, e:
raise util.Abort(
_('passed in variable needs to be of form var= or var=val. '
'Instead, this was given "%s"' % entry))
part.addparam(key, value, mandatory=False)
# Ugly hack suggested by pyd to ensure pushvars part comes before
# hook part. Pyd has a fix for this in in he works.
exchange.b2partsgenorder.insert(0, exchange.b2partsgenorder.pop())
# Eventually, this will be used when we update to an Hg that supports this.
#@exchange.b2partsgenerator('pushvars', idx=0)
@bundle2.parthandler('pushvars')
def bundle2getvars(op, part):
'''unbundle a bundle2 containing shellvars on the server'''
tr = op.gettransaction()
for key, value in part.advisoryparams:
key = key.upper()
# We want pushed variables to have USERVAR_ prepended so we know
# they came from the pushvar extension.
key = "USERVAR_" + key
tr.hookargs[key] = value
def push(orig, ui, repo, *args, **opts):
repo._shellvars = opts['pushvars']
try:
return orig(ui, repo, *args, **opts)
finally:
del repo._shellvars
def extsetup(ui):
entry = extensions.wrapcommand(commands.table, 'push', push)
entry[1].append(('', 'pushvars', [], "variables that can be sent to the server"))

58
tests/test-pushvars.t Normal file
View File

@ -0,0 +1,58 @@
$ extpath=$(dirname $TESTDIR)
$ cat > $TESTTMP/pretxnchangegroup.sh << EOF
> #!/bin/bash
> env | grep -E "^HG_USERVAR_DEBUG"
> env | grep -E "^HG_USERVAR_BYPASS_REVIEW"
> exit 0
> EOF
$ chmod +x $TESTTMP/pretxnchangegroup.sh
$ cp $extpath/pushvars.py $TESTTMP # use $TESTTMP substitution in message
$ cat >> $HGRCPATH << EOF
> [extensions]
> pushvars=$TESTTMP/pushvars.py
> [hooks]
> pretxnchangegroup = $TESTTMP/pretxnchangegroup.sh
> [experimental]
> bundle2-exp = true
> EOF
$ hg init repo
$ hg clone -q repo child
$ cd child
Test pushing vars to repo
$ echo b > a
$ hg commit -Aqm a
$ hg push --pushvars "DEBUG=1" --pushvars "BYPASS_REVIEW=true"
pushing to $TESTTMP/repo
searching for changes
HG_USERVAR_DEBUG=1
HG_USERVAR_BYPASS_REVIEW=true
remote: adding changesets
remote: adding manifests
remote: adding file changes
remote: added 1 changesets with 1 changes to 1 files
Test pushing var with empty right-hand side
$ echo b >> a
$ hg commit -Aqm a
$ hg push --pushvars "DEBUG="
pushing to $TESTTMP/repo
searching for changes
HG_USERVAR_DEBUG=
remote: adding changesets
remote: adding manifests
remote: adding file changes
remote: added 1 changesets with 1 changes to 1 files
Test pushing bad vars
$ echo b >> a
$ hg commit -Aqm b
$ hg push --pushvars "DEBUG"
pushing to $TESTTMP/repo
searching for changes
abort: passed in variable needs to be of form var= or var=val. Instead, this was given "DEBUG"
[255]