From 54caa88281dafe5d4d3cd6a2024d9411c60dec3f Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Fri, 26 Sep 2014 00:10:48 -0700 Subject: [PATCH] moved from datasql to datastore, added unit test for users --- .../datastore/{datasql => database}/commit.go | 12 +- server/datastore/database/commit_test.go | 1 + server/datastore/database/database.go | 67 ++++++ server/datastore/database/migrate/helper.go | 46 ++++ server/datastore/database/migrate/setup.go | 118 ++++++++++ server/datastore/database/migrate/version.go | 57 +++++ .../datastore/{datasql => database}/perm.go | 6 +- server/datastore/database/perm_test.go | 1 + .../datastore/{datasql => database}/repo.go | 8 +- server/datastore/database/repo_test.go | 1 + .../datastore/{datasql => database}/user.go | 24 +-- server/datastore/database/user_test.go | 203 ++++++++++++++++++ server/datastore/database/util.go | 32 +++ server/datastore/datasql/commit_test.go | 1 - server/datastore/datasql/datastore.go | 54 ----- server/datastore/datasql/perm_test.go | 1 - server/datastore/datasql/repo_test.go | 1 - server/datastore/datasql/user_test.go | 1 - 18 files changed, 551 insertions(+), 83 deletions(-) rename server/datastore/{datasql => database}/commit.go (89%) create mode 100644 server/datastore/database/commit_test.go create mode 100644 server/datastore/database/database.go create mode 100644 server/datastore/database/migrate/helper.go create mode 100644 server/datastore/database/migrate/setup.go create mode 100644 server/datastore/database/migrate/version.go rename server/datastore/{datasql => database}/perm.go (88%) create mode 100644 server/datastore/database/perm_test.go rename server/datastore/{datasql => database}/repo.go (89%) create mode 100644 server/datastore/database/repo_test.go rename server/datastore/{datasql => database}/user.go (69%) create mode 100644 server/datastore/database/user_test.go create mode 100644 server/datastore/database/util.go delete mode 100644 server/datastore/datasql/commit_test.go delete mode 100644 server/datastore/datasql/datastore.go delete mode 100644 server/datastore/datasql/perm_test.go delete mode 100644 server/datastore/datasql/repo_test.go delete mode 100644 server/datastore/datasql/user_test.go diff --git a/server/datastore/datasql/commit.go b/server/datastore/database/commit.go similarity index 89% rename from server/datastore/datasql/commit.go rename to server/datastore/database/commit.go index 2313b8bd1..78d86e603 100644 --- a/server/datastore/datasql/commit.go +++ b/server/datastore/database/commit.go @@ -1,4 +1,4 @@ -package datasql +package database import ( "github.com/drone/drone/shared/model" @@ -25,7 +25,7 @@ func (db *Commitstore) GetCommit(id int64) (*model.Commit, error) { // datastore for the specified repo and sha func (db *Commitstore) GetCommitSha(repo *model.Repo, branch, sha string) (*model.Commit, error) { var commit = new(model.Commit) - var err = meddler.QueryRow(db, commit, commitShaQuery, repo.ID, branch, sha) + var err = meddler.QueryRow(db, commit, rebind(commitShaQuery), repo.ID, branch, sha) return commit, err } @@ -34,7 +34,7 @@ func (db *Commitstore) GetCommitSha(repo *model.Repo, branch, sha string) (*mode // and branch. func (db *Commitstore) GetCommitLast(repo *model.Repo, branch string) (*model.Commit, error) { var commit = new(model.Commit) - var err = meddler.QueryRow(db, commit, commitLastQuery, repo.ID, branch) + var err = meddler.QueryRow(db, commit, rebind(commitLastQuery), repo.ID, branch) return commit, err } @@ -42,7 +42,7 @@ func (db *Commitstore) GetCommitLast(repo *model.Repo, branch string) (*model.Co // from the datastore for the specified repository. func (db *Commitstore) GetCommitList(repo *model.Repo) ([]*model.Commit, error) { var commits []*model.Commit - var err = meddler.QueryAll(db, &commits, commitListQuery) + var err = meddler.QueryAll(db, &commits, rebind(commitListQuery)) return commits, err } @@ -64,14 +64,14 @@ func (db *Commitstore) PutCommit(commit *model.Commit) error { // DelCommit removes the commit from the datastore. func (db *Commitstore) DelCommit(commit *model.Commit) error { - var _, err = db.Exec(commitDeleteStmt, commit.ID) + var _, err = db.Exec(rebind(commitDeleteStmt), commit.ID) return err } // KillCommits updates all pending or started commits // in the datastore settings the status to killed. func (db *Commitstore) KillCommits() error { - var _, err = db.Exec(commitKillStmt) + var _, err = db.Exec(rebind(commitKillStmt)) return err } diff --git a/server/datastore/database/commit_test.go b/server/datastore/database/commit_test.go new file mode 100644 index 000000000..636bab89a --- /dev/null +++ b/server/datastore/database/commit_test.go @@ -0,0 +1 @@ +package database diff --git a/server/datastore/database/database.go b/server/datastore/database/database.go new file mode 100644 index 000000000..51a83407b --- /dev/null +++ b/server/datastore/database/database.go @@ -0,0 +1,67 @@ +package database + +import ( + "database/sql" + + "github.com/drone/drone/server/datastore" + "github.com/drone/drone/server/datastore/database/migrate" + + "github.com/BurntSushi/migration" + _ "github.com/go-sql-driver/mysql" + _ "github.com/lib/pq" + _ "github.com/mattn/go-sqlite3" + "github.com/russross/meddler" +) + +const ( + driverPostgres = "postgres" + driverSqlite = "sqlite3" + driverMysql = "mysql" +) + +// Connect is a helper function that establishes a new +// database connection and auto-generates the database +// schema. If the database already exists, it will perform +// and update as needed. +func Connect(driver, datasource string) (*sql.DB, error) { + switch driver { + case driverPostgres: + meddler.Default = meddler.PostgreSQL + case driverSqlite: + meddler.Default = meddler.SQLite + case driverMysql: + meddler.Default = meddler.MySQL + } + migration.DefaultGetVersion = migrate.GetVersion + migration.DefaultSetVersion = migrate.SetVersion + var migrations = []migration.Migrator{ + migrate.Setup, + } + return migration.Open(driver, datasource, migrations) +} + +// MustConnect is a helper function that create a +// new database commention and auto-generates the +// database schema. An error causes a panic. +func MustConnect(driver, datasource string) *sql.DB { + db, err := Connect(driver, datasource) + if err != nil { + panic(err) + } + return db +} + +// New returns a new DataStore +func New(db *sql.DB) datastore.Datastore { + return struct { + *Userstore + *Permstore + *Repostore + *Commitstore + }{ + NewUserstore(db), + NewPermstore(db), + NewRepostore(db), + NewCommitstore(db), + } +} diff --git a/server/datastore/database/migrate/helper.go b/server/datastore/database/migrate/helper.go new file mode 100644 index 000000000..f4a948e6c --- /dev/null +++ b/server/datastore/database/migrate/helper.go @@ -0,0 +1,46 @@ +package migrate + +import ( + "strconv" + "strings" + + "github.com/russross/meddler" +) + +// transform is a helper function that transforms sql +// statements to work with multiple database types. +func transform(stmt string) string { + switch meddler.Default { + case meddler.MySQL: + stmt = strings.Replace(stmt, "AUTOINCREMENT", "AUTO_INCREMENT", -1) + case meddler.PostgreSQL: + stmt = strings.Replace(stmt, "INTEGER PRIMARY KEY AUTOINCREMENT", "SERIAL PRIMARY KEY", -1) + stmt = strings.Replace(stmt, "BLOB", "BYTEA", -1) + } + return stmt +} + +// rebind is a helper function that changes the sql +// bind type from ? to $ for postgres queries. +func rebind(query string) string { + if meddler.Default != meddler.PostgreSQL { + return query + } + + qb := []byte(query) + // Add space enough for 10 params before we have to allocate + rqb := make([]byte, 0, len(qb)+10) + j := 1 + for _, b := range qb { + if b == '?' { + rqb = append(rqb, '$') + for _, b := range strconv.Itoa(j) { + rqb = append(rqb, byte(b)) + } + j++ + } else { + rqb = append(rqb, b) + } + } + return string(rqb) +} diff --git a/server/datastore/database/migrate/setup.go b/server/datastore/database/migrate/setup.go new file mode 100644 index 000000000..527c40ef2 --- /dev/null +++ b/server/datastore/database/migrate/setup.go @@ -0,0 +1,118 @@ +package migrate + +import ( + "github.com/BurntSushi/migration" +) + +// Setup is the database migration function that +// will setup the initial SQL database structure. +func Setup(tx migration.LimitedTx) error { + var stmts = []string{ + blobTable, + userTable, + repoTable, + permTable, + commitTable, + } + for _, stmt := range stmts { + _, err := tx.Exec(transform(stmt)) + if err != nil { + return err + } + } + return nil +} + +var userTable = ` +CREATE TABLE IF NOT EXISTS users ( + user_id INTEGER PRIMARY KEY AUTOINCREMENT + ,user_remote VARCHAR(255) + ,user_login VARCHAR(255) + ,user_access VARCHAR(255) + ,user_secret VARCHAR(255) + ,user_name VARCHAR(255) + ,user_email VARCHAR(255) + ,user_gravatar VARCHAR(255) + ,user_token VARCHAR(255) + ,user_admin BOOLEAN + ,user_active BOOLEAN + ,user_syncing BOOLEAN + ,user_created INTEGER + ,user_updated INTEGER + ,user_synced INTEGER + ,UNIQUE(user_token) + ,UNIQUE(user_remote, user_login) +); +` + +var permTable = ` +CREATE TABLE IF NOT EXISTS perms ( + perm_id INTEGER PRIMARY KEY AUTOINCREMENT + ,user_id INTEGER + ,repo_id INTEGER + ,perm_read BOOLEAN + ,perm_write BOOLEAN + ,perm_admin BOOLEAN + ,perm_created INTEGER + ,perm_updated INTEGER + ,UNIQUE (repo_id, user_id) +); +` + +var repoTable = ` +CREATE TABLE IF NOT EXISTS repos ( + repo_id INTEGER PRIMARY KEY AUTOINCREMENT + ,user_id INTEGER + ,repo_remote VARCHAR(255) + ,repo_host VARCHAR(255) + ,repo_owner VARCHAR(255) + ,repo_name VARCHAR(255) + ,repo_url VARCHAR(1024) + ,repo_clone_url VARCHAR(255) + ,repo_git_url VARCHAR(255) + ,repo_ssh_url VARCHAR(255) + ,repo_active BOOLEAN + ,repo_private BOOLEAN + ,repo_privileged BOOLEAN + ,repo_post_commit BOOLEAN + ,repo_pull_request BOOLEAN + ,repo_public_key BLOB + ,repo_private_key BLOB + ,repo_params BLOB + ,repo_timeout INTEGER + ,repo_created INTEGER + ,repo_updated INTEGER + ,UNIQUE(repo_host, repo_owner, repo_name) +); +` + +var commitTable = ` +CREATE TABLE IF NOT EXISTS commits ( + commit_id INTEGER PRIMARY KEY AUTOINCREMENT + ,repo_id INTEGER + ,commit_status VARCHAR(255) + ,commit_started INTEGER + ,commit_finished INTEGER + ,commit_duration INTEGER + ,commit_sha VARCHAR(255) + ,commit_branch VARCHAR(255) + ,commit_pr VARCHAR(255) + ,commit_author VARCHAR(255) + ,commit_gravatar VARCHAR(255) + ,commit_timestamp VARCHAR(255) + ,commit_message VARCHAR(255) + ,commit_yaml BLOB + ,commit_created INTEGER + ,commit_updated INTEGER + ,UNIQUE(commit_sha, commit_branch, repo_id) +); +` + +var blobTable = ` +CREATE TABLE IF NOT EXISTS blobs ( + blob_id INTEGER PRIMARY KEY AUTOINCREMENT + ,blob_path VARCHAR(1024) + ,blob_data BLOB + ,UNIQUE(blob_path) +); +` diff --git a/server/datastore/database/migrate/version.go b/server/datastore/database/migrate/version.go new file mode 100644 index 000000000..ad96209e7 --- /dev/null +++ b/server/datastore/database/migrate/version.go @@ -0,0 +1,57 @@ +package migrate + +import ( + "github.com/BurntSushi/migration" +) + +// GetVersion gets the migration version from the database, +// creating the migration table if it does not already exist. +func GetVersion(tx migration.LimitedTx) (int, error) { + v, err := getVersion(tx) + if err != nil { + if err := createVersionTable(tx); err != nil { + return 0, err + } + return getVersion(tx) + } + return v, nil +} + +// SetVersion sets the migration version in the database, +// creating the migration table if it does not already exist. +func SetVersion(tx migration.LimitedTx, version int) error { + if err := setVersion(tx, version); err != nil { + if err := createVersionTable(tx); err != nil { + return err + } + return setVersion(tx, version) + } + return nil +} + +// setVersion updates the migration version in the database. +func setVersion(tx migration.LimitedTx, version int) error { + _, err := tx.Exec(rebind("UPDATE migration_version SET version = ?"), version) + return err +} + +// getVersion gets the migration version in the database. +func getVersion(tx migration.LimitedTx) (int, error) { + var version int + row := tx.QueryRow("SELECT version FROM migration_version") + if err := row.Scan(&version); err != nil { + return 0, err + } + return version, nil +} + +// createVersionTable creates the version table and inserts the +// initial value (0) into the database. +func createVersionTable(tx migration.LimitedTx) error { + _, err := tx.Exec("CREATE TABLE migration_version ( version INTEGER )") + if err != nil { + return err + } + _, err = tx.Exec("INSERT INTO migration_version (version) VALUES (0)") + return err +} diff --git a/server/datastore/datasql/perm.go b/server/datastore/database/perm.go similarity index 88% rename from server/datastore/datasql/perm.go rename to server/datastore/database/perm.go index 540ac8820..1a71c1953 100644 --- a/server/datastore/datasql/perm.go +++ b/server/datastore/database/perm.go @@ -1,4 +1,4 @@ -package datasql +package database import ( "github.com/drone/drone/shared/model" @@ -17,7 +17,7 @@ func NewPermstore(db meddler.DB) *Permstore { // the datastore for the given repository. func (db *Repostore) GetPerm(user *model.User, repo *model.Repo) (*model.Perm, error) { var perm = new(model.Perm) - var err = meddler.QueryRow(db, perm, permQuery, user.ID, repo.ID) + var err = meddler.QueryRow(db, perm, rebind(permQuery), user.ID, repo.ID) return perm, err } @@ -33,7 +33,7 @@ func (db *Repostore) PutPerm(perm *model.Perm) error { // DelPerm removes permission from the datastore. func (db *Repostore) DelPerm(perm *model.Perm) error { - var _, err = db.Exec(permDeleteStmt, perm.ID) + var _, err = db.Exec(rebind(permDeleteStmt), perm.ID) return err } diff --git a/server/datastore/database/perm_test.go b/server/datastore/database/perm_test.go new file mode 100644 index 000000000..636bab89a --- /dev/null +++ b/server/datastore/database/perm_test.go @@ -0,0 +1 @@ +package database diff --git a/server/datastore/datasql/repo.go b/server/datastore/database/repo.go similarity index 89% rename from server/datastore/datasql/repo.go rename to server/datastore/database/repo.go index 2e2def818..a0ae3e835 100644 --- a/server/datastore/datasql/repo.go +++ b/server/datastore/database/repo.go @@ -1,4 +1,4 @@ -package datasql +package database import ( "github.com/drone/drone/shared/model" @@ -25,7 +25,7 @@ func (db *Repostore) GetRepo(id int64) (*model.Repo, error) { // for the specified remote, owner and name. func (db *Repostore) GetRepoName(remote, owner, name string) (*model.Repo, error) { var repo = new(model.Repo) - var err = meddler.QueryRow(db, repo, repoNameQuery, remote, owner, name) + var err = meddler.QueryRow(db, repo, rebind(repoNameQuery), remote, owner, name) return repo, err } @@ -33,7 +33,7 @@ func (db *Repostore) GetRepoName(remote, owner, name string) (*model.Repo, error // the datastore accessible by the given user ID. func (db *Repostore) GetRepoList(user *model.User) ([]*model.Repo, error) { var repos []*model.Repo - var err = meddler.QueryAll(db, &repos, repoListQuery) + var err = meddler.QueryAll(db, &repos, rebind(repoListQuery)) return repos, err } @@ -49,7 +49,7 @@ func (db *Repostore) PutRepo(repo *model.Repo) error { // DelRepo removes the repo from the datastore. func (db *Repostore) DelRepo(repo *model.Repo) error { - var _, err = db.Exec(repoDeleteStmt, repo.ID) + var _, err = db.Exec(rebind(repoDeleteStmt), repo.ID) return err } diff --git a/server/datastore/database/repo_test.go b/server/datastore/database/repo_test.go new file mode 100644 index 000000000..636bab89a --- /dev/null +++ b/server/datastore/database/repo_test.go @@ -0,0 +1 @@ +package database diff --git a/server/datastore/datasql/user.go b/server/datastore/database/user.go similarity index 69% rename from server/datastore/datasql/user.go rename to server/datastore/database/user.go index cad545680..8c79fced5 100644 --- a/server/datastore/datasql/user.go +++ b/server/datastore/database/user.go @@ -1,4 +1,4 @@ -package datasql +package database import ( "github.com/drone/drone/shared/model" @@ -15,7 +15,7 @@ func NewUserstore(db meddler.DB) *Userstore { // GetUser retrieves a specific user from the // datastore for the given ID. -func (db *Repostore) GetUser(id int64) (*model.User, error) { +func (db *Userstore) GetUser(id int64) (*model.User, error) { var usr = new(model.User) var err = meddler.Load(db, userTable, usr, id) return usr, err @@ -23,41 +23,41 @@ func (db *Repostore) GetUser(id int64) (*model.User, error) { // GetUserLogin retrieves a user from the datastore // for the specified remote and login name. -func (db *Repostore) GetUserLogin(remote, login string) (*model.User, error) { +func (db *Userstore) GetUserLogin(remote, login string) (*model.User, error) { var usr = new(model.User) - var err = meddler.QueryRow(db, usr, userLoginQuery) + var err = meddler.QueryRow(db, usr, rebind(userLoginQuery), remote, login) return usr, err } // GetUserToken retrieves a user from the datastore // with the specified token. -func (db *Repostore) GetUserToken(token string) (*model.User, error) { +func (db *Userstore) GetUserToken(token string) (*model.User, error) { var usr = new(model.User) - var err = meddler.QueryRow(db, usr, userTokenQuery) + var err = meddler.QueryRow(db, usr, rebind(userTokenQuery), token) return usr, err } // GetUserList retrieves a list of all users from // the datastore that are registered in the system. -func (db *Repostore) GetUserList() ([]*model.User, error) { +func (db *Userstore) GetUserList() ([]*model.User, error) { var users []*model.User - var err = meddler.QueryAll(db, &users, userListQuery) + var err = meddler.QueryAll(db, &users, rebind(userListQuery)) return users, err } // PostUser saves a User in the datastore. -func (db *Repostore) PostUser(user *model.User) error { +func (db *Userstore) PostUser(user *model.User) error { return meddler.Save(db, userTable, user) } // PutUser saves a user in the datastore. -func (db *Repostore) PutUser(user *model.User) error { +func (db *Userstore) PutUser(user *model.User) error { return meddler.Save(db, userTable, user) } // DelUser removes the user from the datastore. -func (db *Repostore) DelUser(user *model.User) error { - var _, err = db.Exec(userDeleteStmt, user.ID) +func (db *Userstore) DelUser(user *model.User) error { + var _, err = db.Exec(rebind(userDeleteStmt), user.ID) return err } diff --git a/server/datastore/database/user_test.go b/server/datastore/database/user_test.go new file mode 100644 index 000000000..846899567 --- /dev/null +++ b/server/datastore/database/user_test.go @@ -0,0 +1,203 @@ +package database + +import ( + "testing" + + "github.com/drone/drone/shared/model" + "github.com/franela/goblin" +) + +func TestPackagestore(t *testing.T) { + db := MustConnect("sqlite3", ":memory:") + us := NewUserstore(db) + defer db.Close() + + g := goblin.Goblin(t) + g.Describe("Userstore", func() { + + // before each test be sure to purge the package + // table data from the database. + g.BeforeEach(func() { + db.Exec("DELETE FROM users") + }) + + g.It("Should Put a User", func() { + user := model.User{ + Login: "joe", + Remote: "github.com", + Name: "Joe Sixpack", + Email: "foo@bar.com", + Token: "e42080dddf012c718e476da161d21ad5", + } + err := us.PostUser(&user) + g.Assert(err == nil).IsTrue() + g.Assert(user.ID != 0).IsTrue() + }) + + g.It("Should Post a User", func() { + user := model.User{ + Login: "joe", + Remote: "github.com", + Name: "Joe Sixpack", + Email: "foo@bar.com", + Token: "e42080dddf012c718e476da161d21ad5", + } + err := us.PostUser(&user) + g.Assert(err == nil).IsTrue() + g.Assert(user.ID != 0).IsTrue() + }) + + g.It("Should Get a User", func() { + user := model.User{ + Login: "joe", + Remote: "github.com", + Access: "f0b461ca586c27872b43a0685cbc2847", + Secret: "976f22a5eef7caacb7e678d6c52f49b1", + Name: "Joe Sixpack", + Email: "foo@bar.com", + Gravatar: "b9015b0857e16ac4d94a0ffd9a0b79c8", + Token: "e42080dddf012c718e476da161d21ad5", + Active: true, + Admin: true, + Created: 1398065343, + Updated: 1398065344, + Synced: 1398065345, + } + us.PostUser(&user) + getuser, err := us.GetUser(user.ID) + g.Assert(err == nil).IsTrue() + g.Assert(user.ID).Equal(getuser.ID) + g.Assert(user.Login).Equal(getuser.Login) + g.Assert(user.Remote).Equal(getuser.Remote) + g.Assert(user.Access).Equal(getuser.Access) + g.Assert(user.Secret).Equal(getuser.Secret) + g.Assert(user.Name).Equal(getuser.Name) + g.Assert(user.Email).Equal(getuser.Email) + g.Assert(user.Gravatar).Equal(getuser.Gravatar) + g.Assert(user.Token).Equal(getuser.Token) + g.Assert(user.Active).Equal(getuser.Active) + g.Assert(user.Admin).Equal(getuser.Admin) + g.Assert(user.Created).Equal(getuser.Created) + g.Assert(user.Updated).Equal(getuser.Updated) + g.Assert(user.Synced).Equal(getuser.Synced) + }) + + g.It("Should Get a User By Login", func() { + user := model.User{ + Login: "joe", + Remote: "github.com", + Name: "Joe Sixpack", + Email: "foo@bar.com", + Token: "e42080dddf012c718e476da161d21ad5", + } + us.PostUser(&user) + getuser, err := us.GetUserLogin(user.Remote, user.Login) + g.Assert(err == nil).IsTrue() + g.Assert(user.ID).Equal(getuser.ID) + g.Assert(user.Login).Equal(getuser.Login) + g.Assert(user.Remote).Equal(getuser.Remote) + }) + + g.It("Should Get a User By Token", func() { + user := model.User{ + Login: "joe", + Remote: "github.com", + Name: "Joe Sixpack", + Email: "foo@bar.com", + Token: "e42080dddf012c718e476da161d21ad5", + } + us.PostUser(&user) + getuser, err := us.GetUserToken(user.Token) + g.Assert(err == nil).IsTrue() + g.Assert(user.ID).Equal(getuser.ID) + g.Assert(user.Token).Equal(getuser.Token) + }) + + g.It("Should Enforce Unique User Token", func() { + user1 := model.User{ + Login: "jane", + Remote: "github.com", + Name: "Jane Doe", + Email: "foo@bar.com", + Token: "e42080dddf012c718e476da161d21ad5", + } + user2 := model.User{ + Login: "joe", + Remote: "github.com", + Name: "Joe Sixpack", + Email: "foo@bar.com", + Token: "e42080dddf012c718e476da161d21ad5", + } + err1 := us.PostUser(&user1) + err2 := us.PostUser(&user2) + g.Assert(err1 == nil).IsTrue() + g.Assert(err2 == nil).IsFalse() + }) + + g.It("Should Enforce Unique User Remote and Login", func() { + user1 := model.User{ + Login: "joe", + Remote: "github.com", + Name: "Joe Sixpack", + Email: "foo@bar.com", + Token: "e42080dddf012c718e476da161d21ad5", + } + user2 := model.User{ + Login: "joe", + Remote: "github.com", + Name: "Joe Sixpack", + Email: "foo@bar.com", + Token: "ab20g0ddaf012c744e136da16aa21ad9", + } + err1 := us.PostUser(&user1) + err2 := us.PostUser(&user2) + g.Assert(err1 == nil).IsTrue() + g.Assert(err2 == nil).IsFalse() + }) + + g.It("Should Get a User List", func() { + user1 := model.User{ + Login: "jane", + Remote: "github.com", + Name: "Jane Doe", + Email: "foo@bar.com", + Token: "ab20g0ddaf012c744e136da16aa21ad9", + } + user2 := model.User{ + Login: "joe", + Remote: "github.com", + Name: "Joe Sixpack", + Email: "foo@bar.com", + Token: "e42080dddf012c718e476da161d21ad5", + } + us.PostUser(&user1) + us.PostUser(&user2) + users, err := us.GetUserList() + g.Assert(err == nil).IsTrue() + g.Assert(len(users)).Equal(2) + g.Assert(users[0].Login).Equal(user1.Login) + g.Assert(users[0].Remote).Equal(user1.Remote) + g.Assert(users[0].Name).Equal(user1.Name) + g.Assert(users[0].Email).Equal(user1.Email) + g.Assert(users[0].Token).Equal(user1.Token) + }) + + g.It("Should Del a User", func() { + user := model.User{ + Login: "joe", + Remote: "github.com", + Name: "Joe Sixpack", + Email: "foo@bar.com", + Token: "e42080dddf012c718e476da161d21ad5", + } + us.PostUser(&user) + _, err1 := us.GetUser(user.ID) + err2 := us.DelUser(&user) + _, err3 := us.GetUser(user.ID) + g.Assert(err1 == nil).IsTrue() + g.Assert(err2 == nil).IsTrue() + g.Assert(err3 == nil).IsFalse() + }) + + }) +} diff --git a/server/datastore/database/util.go b/server/datastore/database/util.go new file mode 100644 index 000000000..dc03c8432 --- /dev/null +++ b/server/datastore/database/util.go @@ -0,0 +1,32 @@ +package database + +import ( + "strconv" + + "github.com/russross/meddler" +) + +// rebind is a helper function that changes the sql +// bind type from ? to $ for postgres queries. +func rebind(query string) string { + if meddler.Default != meddler.PostgreSQL { + return query + } + + qb := []byte(query) + // Add space enough for 10 params before we have to allocate + rqb := make([]byte, 0, len(qb)+10) + j := 1 + for _, b := range qb { + if b == '?' { + rqb = append(rqb, '$') + for _, b := range strconv.Itoa(j) { + rqb = append(rqb, byte(b)) + } + j++ + } else { + rqb = append(rqb, b) + } + } + return string(rqb) +} diff --git a/server/datastore/datasql/commit_test.go b/server/datastore/datasql/commit_test.go deleted file mode 100644 index 0b4ee0ade..000000000 --- a/server/datastore/datasql/commit_test.go +++ /dev/null @@ -1 +0,0 @@ -package datasql diff --git a/server/datastore/datasql/datastore.go b/server/datastore/datasql/datastore.go deleted file mode 100644 index 6299908fa..000000000 --- a/server/datastore/datasql/datastore.go +++ /dev/null @@ -1,54 +0,0 @@ -package datasql - -import ( - "database/sql" - - "github.com/drone/drone/server/blobstore/blobsql" - "github.com/drone/drone/server/datastore" - "github.com/drone/drone/shared/model" - - "github.com/astaxie/beego/orm" - _ "github.com/mattn/go-sqlite3" -) - -const ( - driverPostgres = "postgres" - driverSqlite = "sqlite3" - driverMysql = "mysql" - databaseName = "default" -) - -// Connect is a helper function that establishes a new -// database connection and auto-generates the database -// schema. If the database already exists, it will perform -// and update as needed. -func Connect(driver, datasource string) (*sql.DB, error) { - defer orm.ResetModelCache() - orm.RegisterDriver(driverSqlite, orm.DR_Sqlite) - orm.RegisterDataBase(databaseName, driver, datasource) - orm.RegisterModel(new(model.User)) - orm.RegisterModel(new(model.Perm)) - orm.RegisterModel(new(model.Repo)) - orm.RegisterModel(new(model.Commit)) - orm.RegisterModel(new(blobsql.Blob)) - var err = orm.RunSyncdb(databaseName, true, true) - if err != nil { - return nil, err - } - return orm.GetDB(databaseName) -} - -// New returns a new DataStore -func New(db *sql.DB) datastore.Datastore { - return struct { - *Userstore - *Permstore - *Repostore - *Commitstore - }{ - NewUserstore(db), - NewPermstore(db), - NewRepostore(db), - NewCommitstore(db), - } -} diff --git a/server/datastore/datasql/perm_test.go b/server/datastore/datasql/perm_test.go deleted file mode 100644 index 0b4ee0ade..000000000 --- a/server/datastore/datasql/perm_test.go +++ /dev/null @@ -1 +0,0 @@ -package datasql diff --git a/server/datastore/datasql/repo_test.go b/server/datastore/datasql/repo_test.go deleted file mode 100644 index 0b4ee0ade..000000000 --- a/server/datastore/datasql/repo_test.go +++ /dev/null @@ -1 +0,0 @@ -package datasql diff --git a/server/datastore/datasql/user_test.go b/server/datastore/datasql/user_test.go deleted file mode 100644 index 0b4ee0ade..000000000 --- a/server/datastore/datasql/user_test.go +++ /dev/null @@ -1 +0,0 @@ -package datasql