+ if not user and not uid: return self.call(*args, **kwargs)
+ if os.getenv("SSH_GSSAPI_NAME"):
+ # This might be generalized as "preserve some environment"
+ args = list(args)
+ args.insert(0, "SSH_GSSAPI_NAME=" + os.getenv("SSH_GSSAPI_NAME"))
+ if uid: return self.call("sudo", "-u", "#" + str(uid), *args, **kwargs)
+ if user: return self.call("sudo", "-u", user, *args, **kwargs)
+ def safeCall(self, *args, **kwargs):
+ """
+ Checks if the owner of the current working directory is the same
+ as the current user, and if it isn't, attempts to sudo to be
+ that user. The intended use case is for calling Git commands
+ when running as root, but this method should be used when
+ interfacing with any moderately complex program that depends
+ on working directory context. Keyword arguments are the
+ same as :meth:`call`.
+ """
+ if os.getuid():
+ return self.call(*args, **kwargs)
+ uid = os.stat(os.getcwd()).st_uid
+ # consider also checking ruid?
+ if uid != os.geteuid():
+ kwargs['uid'] = uid
+ return self.callAsUser(*args, **kwargs)
+ else:
+ return self.call(*args, **kwargs)
+ def eval(self, *args, **kwargs):
+ """
+ Evaluates a command and returns its output, with trailing newlines
+ stripped (like backticks in Bash). This is a convenience method for
+ calling :meth:`call` with ``strip``.
+
+ >>> sh = Shell()
+ >>> sh.eval("echo", "Foobar")
+ 'Foobar'
+ """
+ kwargs["strip"] = True
+ return self.call(*args, **kwargs)
+ def setcwd(self, cwd):
+ """
+ Sets the directory processes are executed in. This sets a value
+ to be passed as the ``cwd`` argument to ``subprocess.Popen``.
+ """
+ self.cwd = cwd