Example #1
0
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
Example #2
0
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
Example #3
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()
Example #4
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()
Example #5
0
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
Example #8
0
 def _RunCommand(self, cmd, dry_run):
   log.debug('Executing %s', cmd)
   if dry_run:
     log.out.Print(' '.join(cmd))
   else:
     subprocess.check_call(cmd)
Example #9
0
  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
Example #10
0
  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
Example #12
0
    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)
Example #13
0
  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