Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork940
Add 'sshkey' context manager#242
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
1287f69
261aedd
34c0831
2a9b2f2
98a17a2
6f03861
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -5,13 +5,15 @@ | ||
# the BSD License: http://www.opensource.org/licenses/bsd-license.php | ||
import os | ||
import os.path | ||
import sys | ||
import select | ||
import logging | ||
import threading | ||
import errno | ||
import mmap | ||
from contextlib import contextmanager | ||
from subprocess import ( | ||
call, | ||
Popen, | ||
@@ -139,7 +141,7 @@ def deplete_buffer(fno, handler, buf_list, wg=None): | ||
if hasattr(select, 'poll'): | ||
# poll is preferred, as select is limited to file handles up to 1024 ... . This could otherwise be | ||
# an issue for us, as it matters how many handlesour own process has | ||
poll = select.poll() | ||
READ_ONLY = select.POLLIN | select.POLLPRI | select.POLLHUP | select.POLLERR | ||
CLOSED = select.POLLHUP | select.POLLERR | ||
@@ -223,7 +225,7 @@ class Git(LazyMixin): | ||
Set its value to 'full' to see details about the returned values. | ||
""" | ||
__slots__ = ("_working_dir", "cat_file_all", "cat_file_header", "_version_info", | ||
"_git_options", "_environment") | ||
# CONFIGURATION | ||
# The size in bytes read from stdout when copying git's output to another stream | ||
@@ -413,6 +415,9 @@ def __init__(self, working_dir=None): | ||
self._working_dir = working_dir | ||
self._git_options = () | ||
# Extra environment variables to pass to git commands | ||
self._environment = {} | ||
# cached command slots | ||
self.cat_file_header = None | ||
self.cat_file_all = None | ||
@@ -536,6 +541,8 @@ def execute(self, command, | ||
# Start the process | ||
env = os.environ.copy() | ||
env["LC_MESSAGES"] = "C" | ||
env.update(self._environment) | ||
proc = Popen(command, | ||
env=env, | ||
cwd=cwd, | ||
@@ -608,6 +615,76 @@ def as_text(stdout_value): | ||
else: | ||
return stdout_value | ||
def environment(self): | ||
return self._environment | ||
def update_environment(self, **kwargs): | ||
""" | ||
Set environment variables for future git invocations. Return all changed | ||
values in a format that can be passed back into this function to revert | ||
the changes: | ||
``Examples``:: | ||
old_env = self.update_environment(PWD='/tmp') | ||
self.update_environment(**old_env) | ||
:param kwargs: environment variables to use for git processes | ||
:return: dict that maps environment variables to their old values | ||
""" | ||
old_env = {} | ||
for key, value in kwargs.iteritems(): | ||
# set value if it is None | ||
if value is not None: | ||
if key in self._environment: | ||
old_env[key] = self._environment[key] | ||
else: | ||
old_env[key] = None | ||
self._environment[key] = value | ||
# remove key from environment if its value is None | ||
elif key in self._environment: | ||
old_env[key] = self._environment[key] | ||
del self._environment[key] | ||
return old_env | ||
@contextmanager | ||
def with_environment(self, **kwargs): | ||
""" | ||
A context manager around the above update_environment to restore the | ||
environment back to its previous state after operation. | ||
``Examples``:: | ||
with self.with_environment(GIT_SSH='/bin/ssh_wrapper'): | ||
repo.remotes.origin.fetch() | ||
:param kwargs: see update_environment | ||
""" | ||
old_env = self.update_environment(**kwargs) | ||
try: | ||
yield | ||
finally: | ||
self.update_environment(**old_env) | ||
@contextmanager | ||
def sshkey(self, sshkey_file): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. For a moment I thought this method is to specific, but on the other hand, it makes setting ssh-keys (by using key-files) really easy. | ||
""" | ||
A context manager to temporarily set an SSH key for all operations that | ||
run inside it. | ||
``Examples``:: | ||
with self.environment(GIT_SSH=project_dir+'deployment_key'): | ||
repo.remotes.origin.fetch() | ||
:param sshkey_file: Path to a private SSH key file | ||
""" | ||
this_dir = os.path.dirname(__file__) | ||
ssh_wrapper = os.path.join(this_dir, '..', 'scripts', 'ssh_wrapper.py') | ||
with self.with_environment(GIT_SSH_KEY_FILE=sshkey_file, GIT_SSH=ssh_wrapper): | ||
yield | ||
def transform_kwargs(self, split_single_char_options=False, **kwargs): | ||
"""Transforms Python style kwargs into git command line options.""" | ||
args = list() | ||
@@ -731,7 +808,7 @@ def make_call(): | ||
import warnings | ||
msg = "WARNING: Automatically switched to use git.cmd as git executable" | ||
msg += ", which reduces performance by ~70%." | ||
msg += "It is recommended to put git.exe into the PATH or to " | ||
msg += "set the %s " % self._git_exec_env_var | ||
msg += "environment variable to the executable's location" | ||
warnings.warn(msg) | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -153,3 +153,23 @@ def test_env_vars_passed_to_git(self): | ||
editor = 'non_existant_editor' | ||
with mock.patch.dict('os.environ', {'GIT_EDITOR': editor}): | ||
assert self.git.var("GIT_EDITOR") == editor | ||
def test_environment(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. I don't see how I could test the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Something that could work is to adjust the script for the test to actually fail with a distinct error code, and possibly emit something distinctive to STDERR. | ||
# sanity check | ||
assert self.git.environment() == {} | ||
# make sure the context manager works and cleans up after itself | ||
with self.git.with_environment(PWD='/tmp'): | ||
assert self.git.environment() == {'PWD': '/tmp'} | ||
assert self.git.environment() == {} | ||
old_env = self.git.update_environment(VARKEY='VARVALUE') | ||
# The returned dict can be used to revert the change, hence why it has | ||
# an entry with value 'None'. | ||
assert old_env == {'VARKEY': None} | ||
assert self.git.environment() == {'VARKEY': 'VARVALUE'} | ||
new_env = self.git.update_environment(**old_env) | ||
assert new_env == {'VARKEY': 'VARVALUE'} | ||
assert self.git.environment() == {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#!/usr/bin/env python | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Possibly the MANIFEST.in file needs adjustment to assure this file also gets distributed when making new releases through setuptools. | ||
import os | ||
import subprocess | ||
import sys | ||
ssh_options = ['-i', os.environ['GIT_SSH_KEY_FILE']] | ||
ret_code = subprocess.call(['ssh'] + ssh_options + sys.argv[1:]) | ||
sys.exit(ret_code) |