Skip to content

Commit 261aedd

Browse files
committed
Add 'sshkey' context manager
1 parent 1287f69 commit 261aedd

File tree

3 files changed

+90
-1
lines changed

3 files changed

+90
-1
lines changed

doc/source/tutorial.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,12 @@ You can easily access configuration information for a remote by accessing option
383383
Change configuration for a specific remote only::
384384
385385
o.config_writer.set("pushurl", "other_url")
386+
387+
You can also specify an SSH key to use for any operations on the remotes:
388+
389+
private_key_file = project_dir+'id_rsa_deployment_key'
390+
with repo.git.sshkey(private_key_file):
391+
o.fetch()
386392

387393

388394
Submodule Handling

git/cmd.py

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
66

77
import os
8+
import os.path
89
import sys
910
import select
1011
import logging
1112
import threading
1213
import errno
1314
import mmap
1415

16+
from contextlib import contextmanager
1517
from subprocess import (
1618
call,
1719
Popen,
@@ -223,7 +225,7 @@ class Git(LazyMixin):
223225
Set its value to 'full' to see details about the returned values.
224226
"""
225227
__slots__ = ("_working_dir", "cat_file_all", "cat_file_header", "_version_info",
226-
"_git_options")
228+
"_git_options", "_environment")
227229

228230
# CONFIGURATION
229231
# 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):
413415
self._working_dir = working_dir
414416
self._git_options = ()
415417

418+
# Extra environment variables to pass to git commands
419+
self._environment = {}
420+
416421
# cached command slots
417422
self.cat_file_header = None
418423
self.cat_file_all = None
@@ -536,6 +541,8 @@ def execute(self, command,
536541
# Start the process
537542
env = os.environ.copy()
538543
env["LC_MESSAGES"] = "C"
544+
env.update(self._environment)
545+
539546
proc = Popen(command,
540547
env=env,
541548
cwd=cwd,
@@ -608,6 +615,73 @@ def as_text(stdout_value):
608615
else:
609616
return stdout_value
610617

618+
def set_environment(self, **kwargs):
619+
"""
620+
Set environment variables for future git invocations. Return all changed
621+
values in a format that can be passed back into this function to revert
622+
the changes:
623+
624+
``Examples``::
625+
626+
old_env = self.set_environment(PWD='/tmp')
627+
self.set_environment(**old_env)
628+
629+
:param kwargs: environment variables to use for git processes
630+
:return: dict that maps environment variables to their old values
631+
"""
632+
old_env = {}
633+
for key, value in kwargs.iteritems():
634+
# set value if it is None
635+
if value is not None:
636+
if key in self._environment:
637+
old_env[key] = self._environment[key]
638+
else:
639+
old_env[key] = None
640+
self._environment[key] = value
641+
# remove key from environment if its value is None
642+
elif key in self._environment:
643+
old_env[key] = self._environment[key]
644+
del self._environment[key]
645+
return old_env
646+
647+
@contextmanager
648+
def environment(self, **kwargs):
649+
"""
650+
A context manager around the above set_environment to restore the
651+
environment back to its previous state after operation.
652+
653+
``Examples``::
654+
655+
with self.environment(GIT_SSH='/bin/ssh_wrapper'):
656+
repo.remotes.origin.fetch()
657+
658+
:param kwargs: see set_environment
659+
"""
660+
old_env = self.set_environment(**kwargs)
661+
try:
662+
yield
663+
finally:
664+
self.set_environment(**old_env)
665+
666+
@contextmanager
667+
def sshkey(self, sshkey_file):
668+
"""
669+
A context manager to temporarily set an SSH key for all operations that
670+
run inside it.
671+
672+
``Examples``::
673+
674+
with self.environment(GIT_SSH=project_dir+'deployment_key'):
675+
repo.remotes.origin.fetch()
676+
677+
:param sshkey_file: Path to a private SSH key file
678+
"""
679+
this_dir = os.path.dirname(__file__)
680+
ssh_wrapper = os.path.join(this_dir, '..', 'scripts', 'ssh_wrapper.py')
681+
682+
with self.environment(GIT_SSH_KEY_FILE=sshkey_file, GIT_SSH=ssh_wrapper):
683+
yield
684+
611685
def transform_kwargs(self, split_single_char_options=False, **kwargs):
612686
"""Transforms Python style kwargs into git command line options."""
613687
args = list()

scripts/ssh_wrapper.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/usr/bin/env python
2+
3+
import os
4+
import subprocess
5+
import sys
6+
7+
ssh_options = ['-i', os.environ['GIT_SSH_KEY_FILE']]
8+
ret_code = subprocess.call(['ssh'] + ssh_options + sys.argv[1:])
9+
sys.exit(ret_code)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy