def _RunExecutable(cmd_args, strict_error_checking=True): """Run the given command, handling errors appropriately. Args: cmd_args: list of str, the arguments (including executable path) to run strict_error_checking: bool, whether a non-zero, non-255 exit code should be considered a failure. Returns: int, the return code of the command Raises: SshLikeCmdFailed: if the command failed (based on the command exit code and the strict_error_checking flag) """ with open(os.devnull, 'w') as devnull: if log.IsUserOutputEnabled(): stdout, stderr = None, None else: stdout, stderr = devnull, devnull try: subprocess.check_call(cmd_args, stdout=stdout, stderr=stderr) except OSError as e: raise SshLikeCmdFailed(cmd_args[0], message=e.strerror) except subprocess.CalledProcessError as e: if strict_error_checking or e.returncode == _SSH_ERROR_EXIT_CODE: raise SshLikeCmdFailed(cmd_args[0], return_code=e.returncode) return e.returncode return 0
def OnlineEdit(text): """Edit will edit the provided text. Args: text: The initial text blob to provide for editing. Returns: The edited text blob. Raises: NoSaveException: If the user did not save the temporary file. subprocess.CalledProcessError: If the process running the editor has a problem. """ fname = tempfile.NamedTemporaryFile(suffix='.txt').name with open(fname, 'w') as f_out: f_out.write(text) # Get the mod time, so we can check if anything was actually done. start_mtime = os.stat(fname).st_mtime if os.name == 'nt': subprocess.check_call([fname], shell=True) else: editor = os.getenv('EDITOR', 'vi') # We use shell=True and manual smashing of the args to permit users to set # EDITOR="emacs -nw", or similar things. subprocess.check_call('{editor} {file}'.format(editor=editor, file=fname), shell=True) end_mtime = os.stat(fname).st_mtime if start_mtime == end_mtime: raise NoSaveException('edit aborted by user') with open(fname) as f_done: return f_done.read()
def SubprocessCheckCall(*args, **kargs): """Enables mocking in the unit test.""" return subprocess.check_call(*args, **kargs)
def _RunCommand(self, cmd, dry_run): log.debug('Executing %s', cmd) if dry_run: log.out.Print(' '.join(cmd)) else: subprocess.check_call(cmd)
def Clone(self, destination_path, dry_run=False): """Clone a git repository into a gcloud workspace. If the resulting clone does not have a .gcloud directory, create one. Also, sets the credential.helper to use the gcloud credential helper. Args: destination_path: str, The relative path for the repository clone. dry_run: bool, If true do not run but print commands instead. Returns: str, The absolute path of cloned repository. Raises: CannotInitRepositoryException: If there is already a file or directory in the way of creating this repository. CannotFetchRepositoryException: If there is a problem fetching the repository from the remote host, or if the repository is otherwise misconfigured. """ abs_repository_path = os.path.abspath(destination_path) if os.path.exists(abs_repository_path): CheckGitVersion( ) # Do this here, before we start running git commands # First check if it's already the repository we're looking for. with files.ChDir(abs_repository_path) as _: try: output = subprocess.check_output( ['git', 'remote', 'show', 'origin']) except subprocess.CalledProcessError: raise CannotFetchRepositoryException( 'Repository in [{path}] is misconfigured.'.format( path=abs_repository_path)) output_match = _ORIGIN_URL_RE.search(output) if not output_match or output_match.group('url') != self._uri: raise CannotInitRepositoryException(( 'Repository [{url}] cannot be cloned to [{path}]: there' ' is something already there.').format( url=self._uri, path=abs_repository_path)) else: # Repository exists and is correctly configured: abort. log.err.Print(( 'Repository in [{path}] already exists and maps to [{uri}].' .format(path=abs_repository_path, uri=self._uri))) return None # Nothing is there, make a brand new repository. try: if (self._uri.startswith('https://code.google.com') or self._uri.startswith( 'https://source.developers.google.com')): # If this is a Google-hosted repo, clone with the cred helper. try: CheckGitVersion(_HELPER_MIN) except GitVersionException: log.warn( textwrap.dedent("""\ You are cloning a Google-hosted repository with a version of git older than 1.7.9. If you upgrade to 1.7.9 or later, gcloud can handle authentication to this repository. Otherwise, to authenticate, use your Google account and the password found by running the following command. $ gcloud auth print-refresh-token """)) cmd = ['git', 'clone', self._uri, abs_repository_path] else: cmd = [ 'git', 'clone', self._uri, abs_repository_path, '--config', 'credential.helper="{0}"'.format( _GetCredentialHelper()) ] self._RunCommand(cmd, dry_run) else: # Otherwise, just do a simple clone. We do this clone, without the # credential helper, because a user may have already set a default # credential helper that would know the repo's auth info. subprocess.check_call( ['git', 'clone', self._uri, abs_repository_path]) except subprocess.CalledProcessError as e: raise CannotFetchRepositoryException(e) return abs_repository_path
def Clone(self, destination_path, dry_run=False): """Clone a git repository into a gcloud workspace. If the resulting clone does not have a .gcloud directory, create one. Also, sets the credential.helper to use the gcloud credential helper. Args: destination_path: str, The relative path for the repository clone. dry_run: bool, If true do not run but print commands instead. Returns: str, The absolute path of cloned repository. Raises: CannotInitRepositoryException: If there is already a file or directory in the way of creating this repository. CannotFetchRepositoryException: If there is a problem fetching the repository from the remote host, or if the repository is otherwise misconfigured. """ abs_repository_path = os.path.abspath(destination_path) if os.path.exists(abs_repository_path): CheckGitVersion() # Do this here, before we start running git commands if os.listdir(abs_repository_path): # Raise exception if dir is not empty and not a git repository raise CannotInitRepositoryException( 'Directory path specified exists and is not empty') # Make a brand new repository if directory does not exist or # clone if directory exists and is empty try: if (self._uri.startswith('https://code.google.com') or self._uri.startswith('https://source.developers.google.com')): # If this is a Google-hosted repo, clone with the cred helper. try: CheckGitVersion(_HELPER_MIN) except GitVersionException as e: helper_min = '.'.join(str(i) for i in _HELPER_MIN) log.warn(textwrap.dedent("""\ You are cloning a Google-hosted repository with a {current} which is older than {min_version}. If you upgrade to {min_version} or later, gcloud can handle authentication to this repository. Otherwise, to authenticate, use your Google account and the password found by running the following command. $ gcloud auth print-access-token""".format( current=e.cur_version, min_version=helper_min))) cmd = ['git', 'clone', self._uri, abs_repository_path] else: cmd = ['git', 'clone', self._uri, abs_repository_path, '--config', 'credential.helper="{0}"'.format(_GetCredentialHelper())] self._RunCommand(cmd, dry_run) else: # Otherwise, just do a simple clone. We do this clone, without the # credential helper, because a user may have already set a default # credential helper that would know the repo's auth info. subprocess.check_call( ['git', 'clone', self._uri, abs_repository_path]) except subprocess.CalledProcessError as e: raise CannotFetchRepositoryException(e) return abs_repository_path
def CloneGitRepository(self, repository_url, repository_path): """Clone a git repository into a gcloud workspace. If the resulting clone does not have a .gcloud directory, create one. Also, sets the credential.helper to use the gcloud credential helper. Args: repository_url: str, The URL of the repository to clone. repository_path: str, The relative path from the root of the workspace to the repository clone. Raises: InvalidWorkspaceException: If workspace_dir_path is not a workspace. CannotInitRepositoryException: If there is already a file or directory in the way of creating this repository. CannotFetchRepositoryException: If there is a problem fetching the repository from the remote host, or if the repository is otherwise misconfigured. """ abs_repository_path = os.path.join(self.root_directory, repository_path) if os.path.exists(abs_repository_path): # First check if it's already the repository we're looking for. with files.ChDir(abs_repository_path) as _: try: output = subprocess.check_output(['git', 'remote', 'show', 'origin']) except subprocess.CalledProcessError: raise CannotFetchRepositoryException( 'Repository in [{path}] is misconfigured.'.format( path=abs_repository_path)) output_match = _ORIGIN_URL_RE.search(output) if not output_match or output_match.group('url') != repository_url: raise CannotInitRepositoryException( ('Repository [{url}] cannot be cloned to [{path}]: there' ' is something already there.').format( url=repository_url, path=os.path.join(self.root_directory, repository_path))) else: # Repository exists and is correctly configured: abort. log.err.Print( ('Repository in [{path}] exists and is correctly configured.' .format(path=abs_repository_path))) return # Nothing is there, make a brand new repository. try: if (repository_url.startswith('https://code.google.com') or repository_url.startswith('https://source.developers.google.com')): # If this is a Google-hosted repo, clone with the cred helper. try: CheckGitVersion(_HELPER_MIN) except GitVersionException: log.warn(textwrap.dedent("""\ You are cloning a Google-hosted repository with a version of git older than 1.7.9. If you upgrade to 1.7.9 or later, gcloud can handle authentication to this repository. Otherwise, to authenticate, use your Google account and the password found by running the following command. $ gcloud auth print-refresh-token """)) subprocess.check_call( ['git', 'clone', repository_url, abs_repository_path]) else: if (platforms.OperatingSystem.Current() == platforms.OperatingSystem.WINDOWS): helper_name = 'gcloud.cmd' else: helper_name = 'gcloud.sh' subprocess.check_call( ['git', 'clone', repository_url, abs_repository_path, '--config', 'credential.helper=%s' % helper_name]) else: # Otherwise, just do a simple clone. We do this clone, without the # credential helper, because a user may have already set a default # credential helper that would know the repo's auth info. subprocess.check_call( ['git', 'clone', repository_url, abs_repository_path]) except subprocess.CalledProcessError as e: raise CannotFetchRepositoryException(e)
def Clone(self, destination_path, dry_run=False): """Clone a git repository into a gcloud workspace. If the resulting clone does not have a .gcloud directory, create one. Also, sets the credential.helper to use the gcloud credential helper. Args: destination_path: str, The relative path for the repository clone. dry_run: bool, If true do not run but print commands instead. Returns: str, The absolute path of cloned repository. Raises: CannotInitRepositoryException: If there is already a file or directory in the way of creating this repository. CannotFetchRepositoryException: If there is a problem fetching the repository from the remote host, or if the repository is otherwise misconfigured. """ abs_repository_path = os.path.abspath(destination_path) if os.path.exists(abs_repository_path): CheckGitVersion( ) # Do this here, before we start running git commands if os.listdir(abs_repository_path): # Raise exception if dir is not empty and not a git repository raise CannotInitRepositoryException( 'Directory path specified exists and is not empty') # Make a brand new repository if directory does not exist or # clone if directory exists and is empty try: if (self._uri.startswith('https://code.google.com') or self._uri.startswith( 'https://source.developers.google.com')): # If this is a Google-hosted repo, clone with the cred helper. try: CheckGitVersion(_HELPER_MIN) except GitVersionException as e: helper_min = '.'.join(str(i) for i in _HELPER_MIN) log.warn( textwrap.dedent("""\ You are cloning a Google-hosted repository with a {current} which is older than {min_version}. If you upgrade to {min_version} or later, gcloud can handle authentication to this repository. Otherwise, to authenticate, use your Google account and the password found by running the following command. $ gcloud auth print-access-token""".format(current=e.cur_version, min_version=helper_min))) cmd = ['git', 'clone', self._uri, abs_repository_path] else: cmd = [ 'git', 'clone', self._uri, abs_repository_path, '--config', 'credential.helper="{0}"'.format( _GetCredentialHelper()) ] self._RunCommand(cmd, dry_run) else: # Otherwise, just do a simple clone. We do this clone, without the # credential helper, because a user may have already set a default # credential helper that would know the repo's auth info. subprocess.check_call( ['git', 'clone', self._uri, abs_repository_path]) except subprocess.CalledProcessError as e: raise CannotFetchRepositoryException(e) return abs_repository_path
def CloneGitRepository(self, repository_url, repository_path): """Clone a git repository into a gcloud workspace. If the resulting clone does not have a .gcloud directory, create one. Also, sets the credential.helper to use the gcloud credential helper. Args: repository_url: str, The URL of the repository to clone. repository_path: str, The relative path from the root of the workspace to the repository clone. Raises: InvalidWorkspaceException: If workspace_dir_path is not a workspace. CannotInitRepositoryException: If there is already a file or directory in the way of creating this repository. CannotFetchRepositoryException: If there is a problem fetching the repository from the remote host, or if the repository is otherwise misconfigured. """ abs_repository_path = os.path.join(self.root_directory, repository_path) if os.path.exists(abs_repository_path): # First check if it's already the repository we're looking for. with files.ChDir(abs_repository_path) as _: try: output = subprocess.check_output( ['git', 'remote', 'show', 'origin']) except subprocess.CalledProcessError: raise CannotFetchRepositoryException( 'Repository in [{path}] is misconfigured.'.format( path=abs_repository_path)) output_match = _ORIGIN_URL_RE.search(output) if not output_match or output_match.group( 'url') != repository_url: raise CannotInitRepositoryException(( 'Repository [{url}] cannot be cloned to [{path}]: there' ' is something already there.').format( url=repository_url, path=os.path.join(self.root_directory, repository_path))) else: # Repository exists and is correctly configured: abort. log.err.Print(( 'Repository in [{path}] exists and is correctly configured.' .format(path=abs_repository_path))) return # Nothing is there, make a brand new repository. try: if (repository_url.startswith('https://code.google.com') or repository_url.startswith( 'https://source.developers.google.com')): # If this is a Google-hosted repo, clone with the cred helper. try: CheckGitVersion(_HELPER_MIN) except GitVersionException: log.warn( textwrap.dedent("""\ You are cloning a Google-hosted repository with a version of git older than 1.7.9. If you upgrade to 1.7.9 or later, gcloud can handle authentication to this repository. Otherwise, to authenticate, use your Google account and the password found by running the following command. $ gcloud auth print-refresh-token """)) subprocess.check_call( ['git', 'clone', repository_url, abs_repository_path]) else: if (platforms.OperatingSystem.Current() == platforms.OperatingSystem.WINDOWS): helper_name = 'gcloud.cmd' else: helper_name = 'gcloud.sh' subprocess.check_call([ 'git', 'clone', repository_url, abs_repository_path, '--config', 'credential.helper=%s' % helper_name ]) else: # Otherwise, just do a simple clone. We do this clone, without the # credential helper, because a user may have already set a default # credential helper that would know the repo's auth info. subprocess.check_call( ['git', 'clone', repository_url, abs_repository_path]) except subprocess.CalledProcessError as e: raise CannotFetchRepositoryException(e)
def Clone(self, destination_path, dry_run=False): """Clone a git repository into a gcloud workspace. If the resulting clone does not have a .gcloud directory, create one. Also, sets the credential.helper to use the gcloud credential helper. Args: destination_path: str, The relative path for the repository clone. dry_run: bool, If true do not run but print commands instead. Returns: str, The absolute path of cloned repository. Raises: CannotInitRepositoryException: If there is already a file or directory in the way of creating this repository. CannotFetchRepositoryException: If there is a problem fetching the repository from the remote host, or if the repository is otherwise misconfigured. """ abs_repository_path = os.path.abspath(destination_path) if os.path.exists(abs_repository_path): CheckGitVersion() # Do this here, before we start running git commands # First check if it's already the repository we're looking for. with files.ChDir(abs_repository_path) as _: try: output = subprocess.check_output(['git', 'remote', 'show', 'origin']) except subprocess.CalledProcessError: raise CannotFetchRepositoryException( 'Repository in [{path}] is misconfigured.'.format( path=abs_repository_path)) output_match = _ORIGIN_URL_RE.search(output) if not output_match or output_match.group('url') != self._uri: raise CannotInitRepositoryException( ('Repository [{url}] cannot be cloned to [{path}]: there' ' is something already there.').format( url=self._uri, path=abs_repository_path)) else: # Repository exists and is correctly configured: abort. log.err.Print( ('Repository in [{path}] already exists and maps to [{uri}].' .format(path=abs_repository_path, uri=self._uri))) return None # Nothing is there, make a brand new repository. try: if (self._uri.startswith('https://code.google.com') or self._uri.startswith('https://source.developers.google.com')): # If this is a Google-hosted repo, clone with the cred helper. try: CheckGitVersion(_HELPER_MIN) except GitVersionException: log.warn(textwrap.dedent("""\ You are cloning a Google-hosted repository with a version of git older than 1.7.9. If you upgrade to 1.7.9 or later, gcloud can handle authentication to this repository. Otherwise, to authenticate, use your Google account and the password found by running the following command. $ gcloud auth print-refresh-token """)) cmd = ['git', 'clone', self._uri, abs_repository_path] else: cmd = ['git', 'clone', self._uri, abs_repository_path, '--config', 'credential.helper="{0}"'.format(_GetCredentialHelper())] self._RunCommand(cmd, dry_run) else: # Otherwise, just do a simple clone. We do this clone, without the # credential helper, because a user may have already set a default # credential helper that would know the repo's auth info. subprocess.check_call( ['git', 'clone', self._uri, abs_repository_path]) except subprocess.CalledProcessError as e: raise CannotFetchRepositoryException(e) return abs_repository_path