<commit_before>package main

import (
	"bytes"
	"code.google.com/p/go.crypto/ssh"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
	"os"
	"time"
)

// An SSHConnection manages an SSH connection to a server.
type SSHConnection struct {
	client *ssh.ClientConn
	logger *log.Logger
}

type singlePassword struct {
	password string
}

func (pw singlePassword) Password(user string) (string, error) {
	return pw.password, nil
}

type singleKeyring struct {
	signer ssh.Signer
}

func newSingleKeyring(path, passphrase string) (*singleKeyring, error) {
	privateKey, err := parseSSHKey(path, passphrase)
	if err != nil {
		return nil, err
	}

	signer, err := ssh.NewSignerFromKey(privateKey)
	if err != nil {
		return nil, err
	}

	return &singleKeyring{signer: signer}, nil
}

func (sk *singleKeyring) Key(i int) (ssh.PublicKey, error) {
	if i != 0 {
		return nil, nil
	}

	return sk.signer.PublicKey(), nil
}

func (sk *singleKeyring) Sign(i int, rand io.Reader, data []byte) ([]byte, error) {
	if i != 0 {
		return nil, fmt.Errorf("unknown key %d", i)
	}

	return sk.signer.Sign(rand, data)
}

func parseSSHKey(path, passphrase string) (*rsa.PrivateKey, error) {
	file, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	block, _ := pem.Decode(file)

	der, err := x509.DecryptPEMBlock(block, []byte(passphrase))
	if err != nil {
		return nil, err
	}

	return x509.ParsePKCS1PrivateKey(der)
}

func clientAuthFromSSHInfo(info VMSSHInfo) (auths []ssh.ClientAuth, err error) {
	if info.SSHKeyPath != "" {
		keyring, err := newSingleKeyring(info.SSHKeyPath, info.SSHKeyPassphrase)
		if err != nil {
			return nil, err
		}

		auths = append(auths, ssh.ClientAuthKeyring(keyring))
	}
	if info.Password != "" {
		auths = append(auths, ssh.ClientAuthPassword(singlePassword{info.Password}))
	}

	return
}

// NewSSHConnection creates an SSH connection using the connection information
// for the given server.
func NewSSHConnection(server VM, logPrefix string) (*SSHConnection, error) {
	sshInfo := server.SSHInfo()

	dial := func(info VMSSHInfo) (*ssh.ClientConn, error) {
		conn, err := net.DialTimeout("tcp", sshInfo.Addr, 5*time.Second)
		if err != nil {
			return nil, err
		}

		auths, err := clientAuthFromSSHInfo(sshInfo)
		if err != nil {
			return nil, err
		}
		sshConfig := &ssh.ClientConfig{
			User: sshInfo.Username,
			Auth: auths,
		}

		return ssh.Client(conn, sshConfig)
	}

	var client *ssh.ClientConn
	var err error
	for i := 0; i < 3; i++ {
		client, err = dial(sshInfo)
		if err == nil {
			break
		}
	}

	logger := log.New(os.Stdout, fmt.Sprintf("%s-ssh: ", logPrefix), log.Ldate|log.Ltime)
	return &SSHConnection{client: client, logger: logger}, err
}

// Start starts the given command and returns as soon as the command has
// started. It does not wait for the command to finish. The returned channel
// will send the exit code and then close when the command is finished. If the
// exit code sent is -1 then there was an error running the build.
func (c *SSHConnection) Start(cmd string, output io.Writer) (<-chan int, error) {
	session, err := c.createSession()
	if err != nil {<commit_msg>ssh: Add a sleep when retrying the dialing<commit_after>package main

import (
	"bytes"
	"code.google.com/p/go.crypto/ssh"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
	"os"
	"time"
)

// An SSHConnection manages an SSH connection to a server.
type SSHConnection struct {
	client *ssh.ClientConn
	logger *log.Logger
}

type singlePassword struct {
	password string
}

func (pw singlePassword) Password(user string) (string, error) {
	return pw.password, nil
}

type singleKeyring struct {
	signer ssh.Signer
}

func newSingleKeyring(path, passphrase string) (*singleKeyring, error) {
	privateKey, err := parseSSHKey(path, passphrase)
	if err != nil {
		return nil, err
	}

	signer, err := ssh.NewSignerFromKey(privateKey)
	if err != nil {
		return nil, err
	}

	return &singleKeyring{signer: signer}, nil
}

func (sk *singleKeyring) Key(i int) (ssh.PublicKey, error) {
	if i != 0 {
		return nil, nil
	}

	return sk.signer.PublicKey(), nil
}

func (sk *singleKeyring) Sign(i int, rand io.Reader, data []byte) ([]byte, error) {
	if i != 0 {
		return nil, fmt.Errorf("unknown key %d", i)
	}

	return sk.signer.Sign(rand, data)
}

func parseSSHKey(path, passphrase string) (*rsa.PrivateKey, error) {
	file, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	block, _ := pem.Decode(file)

	der, err := x509.DecryptPEMBlock(block, []byte(passphrase))
	if err != nil {
		return nil, err
	}

	return x509.ParsePKCS1PrivateKey(der)
}

func clientAuthFromSSHInfo(info VMSSHInfo) (auths []ssh.ClientAuth, err error) {
	if info.SSHKeyPath != "" {
		keyring, err := newSingleKeyring(info.SSHKeyPath, info.SSHKeyPassphrase)
		if err != nil {
			return nil, err
		}

		auths = append(auths, ssh.ClientAuthKeyring(keyring))
	}
	if info.Password != "" {
		auths = append(auths, ssh.ClientAuthPassword(singlePassword{info.Password}))
	}

	return
}

// NewSSHConnection creates an SSH connection using the connection information
// for the given server.
func NewSSHConnection(server VM, logPrefix string) (*SSHConnection, error) {
	sshInfo := server.SSHInfo()

	dial := func(info VMSSHInfo) (*ssh.ClientConn, error) {
		conn, err := net.DialTimeout("tcp", sshInfo.Addr, 5*time.Second)
		if err != nil {
			return nil, err
		}

		auths, err := clientAuthFromSSHInfo(sshInfo)
		if err != nil {
			return nil, err
		}
		sshConfig := &ssh.ClientConfig{
			User: sshInfo.Username,
			Auth: auths,
		}

		return ssh.Client(conn, sshConfig)
	}

	var client *ssh.ClientConn
	var err error
	for i := 0; i < 3; i++ {
		client, err = dial(sshInfo)
		if err == nil {
			break
		}
		time.Sleep(2 * time.Second)
	}

	logger := log.New(os.Stdout, fmt.Sprintf("%s-ssh: ", logPrefix), log.Ldate|log.Ltime)
	return &SSHConnection{client: client, logger: logger}, err
}

// Start starts the given command and returns as soon as the command has
// started. It does not wait for the command to finish. The returned channel
// will send the exit code and then close when the command is finished. If the
// exit code sent is -1 then there was an error running the build.
func (c *SSHConnection) Start(cmd string, output io.Writer) (<-chan int, error) {
	session, err := c.createSession()
	if err != nil {
{'fraction_non_alphanumeric': 0.129133364676383, 'fraction_numerical': 0.005171603196991067, 'mean_word_length': 3.8979278587874138, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2685766', 'n_tokens_mistral': 2442, 'n_tokens_neox': 2262, 'n_words': 673}