public void run()

in git-agent/src/main/java/jetbrains/buildServer/buildTriggers/vcs/git/agent/JSchClient.java [110:234]


  public void run() throws Exception {
    myLogger.log(Logger.INFO, "SSH command to run: " + myCommand);
    ChannelExec channel = null;
    Session session = null;
    try {
      JSchConfigInitializer.initJSchConfig(JSch.class);
      JSch.setLogger(myLogger);
      JSch jsch = new JSch();
      String privateKeyPath = myEnvironmentAccessor.apply(GitSSHHandler.TEAMCITY_PRIVATE_KEY_PATH);
      if (privateKeyPath != null) {
        jsch.addIdentity(privateKeyPath, myEnvironmentAccessor.apply(GitSSHHandler.TEAMCITY_PASSPHRASE));
      } else {
        String userHome = System.getProperty("user.home");
        if (userHome != null) {
          File homeDir = new File(userHome);
          File ssh = new File(homeDir, ".ssh");
          File rsa = new File(ssh, "id_rsa");
          if (rsa.isFile()) {
            jsch.addIdentity(rsa.getAbsolutePath());
          }
          File dsa = new File(ssh, "id_dsa");
          if (dsa.isFile()) {
            jsch.addIdentity(dsa.getAbsolutePath());
          }
          File config = new File(ssh, "config");
          if (config.isFile()) {
            ConfigRepository configRepository = OpenSSHConfig.parseFile(config.getAbsolutePath());
            jsch.setConfigRepository(new TeamCityConfigRepository(configRepository, myUsername));
          }
        }
      }
      session = jsch.getSession(myUsername, myHost, myPort != null ? myPort : 22);
      SshPubkeyAcceptedAlgorithms.configureSession(session);

      String teamCityVersion = myEnvironmentAccessor.apply(GitSSHHandler.TEAMCITY_VERSION);
      if (teamCityVersion != null) {
        session.setClientVersion(GitUtils.getSshClientVersion(session.getClientVersion(), teamCityVersion));
      }

      if (Boolean.parseBoolean(myEnvironmentAccessor.apply(GitSSHHandler.SSH_IGNORE_KNOWN_HOSTS_ENV))) {
        session.setConfig("StrictHostKeyChecking", "no");
      } else {
        String knownHostsFilePath = myEnvironmentAccessor.apply(GitSSHHandler.SSH_KNOWN_HOSTS_FILE);
        File knownHosts = null;
        if (knownHostsFilePath != null) {
          knownHosts = new File(knownHostsFilePath);
        } else {
          String userHome = System.getProperty("user.home");
          if (userHome != null) {
            File homeDir = new File(userHome);
            File ssh = new File(homeDir, ".ssh");
            knownHosts = new File(ssh, "known_hosts");
          }
        }
        if (knownHosts != null && knownHosts.isFile()) {
          try {
            jsch.setKnownHosts(knownHosts.getAbsolutePath());
          } catch (Exception e) {
            myLogger.log(Logger.WARN, "Failed to configure known hosts: '" + e.toString() + "'");
          }
        }
      }

      String authMethods = myEnvironmentAccessor.apply(GitSSHHandler.TEAMCITY_SSH_PREFERRED_AUTH_METHODS);
      if (isNotEmpty(authMethods))
        session.setConfig("PreferredAuthentications", authMethods);

      if (!myOptions.isEmpty()) {
        for (final Map.Entry<String, String> opEntry : myOptions.entrySet()) {
          session.setConfig(opEntry.getKey(), opEntry.getValue());
        }
      }

      EmptySecurityCallbackHandler.install();

      // It looks like sometimes session/channel close() doesn't interrupt
      // all reads. Ask jsch to create daemon threads so that uninterrupted
      // threads don't prevent us from exit.
      session.setDaemonThread(true);

      final Integer connectTimeoutSeconds = getConnectTimeoutSeconds();
      if (connectTimeoutSeconds != null) {
        session.connect(connectTimeoutSeconds * 1000);
      } else {
        session.connect();
      }

      channel = (ChannelExec) session.openChannel("exec");
      channel.setPty(false);
      channel.setCommand(myCommand);
      channel.setInputStream(System.in);
      channel.setErrStream(System.err);

      final String sendEnv = myEnvironmentAccessor.apply(GitSSHHandler.TEAMCITY_SSH_REQUEST_TOKEN);
      if (isNotEmpty(sendEnv)) {
        channel.setEnv(GitSSHHandler.TEAMCITY_SSH_REQUEST_TOKEN, sendEnv);
      }

      InputStream input = channel.getInputStream();
      Integer timeoutSeconds = getTimeoutSeconds();
      if (timeoutSeconds != null) {
        channel.connect(timeoutSeconds * 1000);
      } else {
        channel.connect();
      }


      if (!channel.isConnected() && input.available() == 0) {
        throw new IOException("Connection failed");
      }

      Copy copyThread = new Copy(input);
      if (timeoutSeconds != null) {
        new Timer(copyThread, timeoutSeconds).start();
      }
      copyThread.start();
      copyThread.join();
      copyThread.rethrowError();
    } finally {
      if (channel != null)
        channel.disconnect();
      if (session != null)
        session.disconnect();
    }
  }