woodpecker/pkg/store/builtin/commit.go
2015-06-13 18:40:07 -07:00

151 lines
3.6 KiB
Go

package builtin
import (
"database/sql"
"time"
"github.com/drone/drone/pkg/types"
)
type Commitstore struct {
*sql.DB
}
func NewCommitstore(db *sql.DB) *Commitstore {
return &Commitstore{db}
}
// Commit gets a commit by ID
func (db *Commitstore) Commit(id int64) (*types.Commit, error) {
return getCommit(db, rebind(stmtCommitSelect), id)
}
// CommitSeq gets the specified commit sequence for the
// named repository and commit number
func (db *Commitstore) CommitSeq(repo *types.Repo, seq int) (*types.Commit, error) {
return getCommit(db, rebind(stmtCommitSelectCommitSeq), repo.ID, seq)
}
// CommitLast gets the last executed commit for the
// named repository.
func (db *Commitstore) CommitLast(repo *types.Repo, branch string) (*types.Commit, error) {
return getCommit(db, rebind(commitLastQuery), repo.ID, branch)
}
// CommitList gets a list of recent commits for the
// named repository.
func (db *Commitstore) CommitList(repo *types.Repo, limit, offset int) ([]*types.Commit, error) {
return getCommits(db, rebind(commitListQuery), repo.ID, limit, offset)
}
// AddCommit inserts a new commit in the datastore.
func (db *Commitstore) AddCommit(commit *types.Commit) error {
tx, err := db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
// extract the next commit number from the database
row := tx.QueryRow(rebind(commitNumberLast), commit.RepoID)
if row != nil {
row.Scan(&commit.Sequence)
}
commit.Sequence = commit.Sequence + 1 // increment
commit.Created = time.Now().UTC().Unix()
commit.Updated = time.Now().UTC().Unix()
err = createCommit(tx, rebind(stmtCommitInsert), commit)
if err != nil {
return err
}
for _, build := range commit.Builds {
build.CommitID = commit.ID
build.Created = commit.Created
build.Updated = commit.Updated
err := createBuild(tx, rebind(stmtBuildInsert), build)
if err != nil {
return err
}
}
return tx.Commit()
}
// SetCommit updates an existing commit and commit tasks.
func (db *Commitstore) SetCommit(commit *types.Commit) error {
tx, err := db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
commit.Updated = time.Now().UTC().Unix()
err = updateCommit(tx, rebind(stmtCommitUpdate), commit)
if err != nil {
return err
}
for _, build := range commit.Builds {
build.Updated = commit.Updated
err = updateBuild(tx, rebind(stmtBuildUpdate), build)
if err != nil {
return err
}
}
return tx.Commit()
}
// KillCommits updates all pending or started commits
// in the datastore settings the status to killed.
func (db *Commitstore) KillCommits() error {
var _, err1 = db.Exec(rebind(buildKillStmt))
if err1 != nil {
return err1
}
var _, err2 = db.Exec(rebind(commitKillStmt))
return err2
}
// Commit table name in database.
const commitTable = "commits"
// SQL query to retrieve the latest commits across all branches.
const commitListQuery = `
SELECT *
FROM commits
WHERE commit_repo_id = ?
ORDER BY commit_sequence DESC
LIMIT ? OFFSET ?
`
// SQL query to retrieve the most recent commit.
// TODO exclude pull requests
const commitLastQuery = `
SELECT *
FROM commits
WHERE commit_repo_id = ?
AND commit_branch = ?
ORDER BY commit_sequence DESC
LIMIT 1
`
// SQL statement to cancel all running commits.
const commitKillStmt = `
UPDATE commits SET commit_state = 'killed'
WHERE commit_state IN ('pending', 'running');
`
// SQL statement to cancel all running commits.
const buildKillStmt = `
UPDATE builds SET build_state = 'killed'
WHERE build_state IN ('pending', 'running');
`
// SQL statement to retrieve the commit number for
// a commit
const commitNumberLast = `
SELECT MAX(commit_sequence)
FROM commits
WHERE commit_repo_id = ?
`