REST cleanup. Idiomatic naming of datastore funcs

This commit is contained in:
Brad Rydzewski 2015-04-14 22:04:38 -07:00
parent 1ad5e3f597
commit 0c3f9e5bde
28 changed files with 458 additions and 471 deletions

View file

@ -2,7 +2,10 @@ package bolt
import ( import (
"errors" "errors"
"github.com/boltdb/bolt" "github.com/boltdb/bolt"
"github.com/drone/drone/datastore"
) )
var ( var (
@ -54,6 +57,13 @@ func New(path string) (*DB, error) {
return nil return nil
}) })
// REMOVE BELOW
var ds datastore.Datastore
if ds == nil {
ds = &DB{db}
}
// REMOVE ABOVE
return &DB{db}, nil return &DB{db}, nil
} }

View file

@ -10,9 +10,9 @@ import (
"github.com/drone/drone/common" "github.com/drone/drone/common"
) )
// GetBuild gets the specified build number for the // Build gets the specified build number for the
// named repository and build number // named repository and build number.
func (db *DB) GetBuild(repo string, build int) (*common.Build, error) { func (db *DB) Build(repo string, build int) (*common.Build, error) {
build_ := &common.Build{} build_ := &common.Build{}
key := []byte(repo + "/" + strconv.Itoa(build)) key := []byte(repo + "/" + strconv.Itoa(build))
@ -23,12 +23,12 @@ func (db *DB) GetBuild(repo string, build int) (*common.Build, error) {
return build_, err return build_, err
} }
// GetBuildList gets a list of recent builds for the // BuildList gets a list of recent builds for the
// named repository. // named repository.
func (db *DB) GetBuildList(repo string) ([]*common.Build, error) { func (db *DB) BuildList(repo string) ([]*common.Build, error) {
// TODO (bradrydzewski) we can do this more efficiently // TODO (bradrydzewski) we can do this more efficiently
var builds []*common.Build var builds []*common.Build
build, err := db.GetBuildLast(repo) build, err := db.BuildLast(repo)
if err == ErrKeyNotFound { if err == ErrKeyNotFound {
return builds, nil return builds, nil
} else if err != nil { } else if err != nil {
@ -54,9 +54,9 @@ func (db *DB) GetBuildList(repo string) ([]*common.Build, error) {
return builds, err return builds, err
} }
// GetBuildLast gets the last executed build for the // BuildLast gets the last executed build for the
// named repository. // named repository.
func (db *DB) GetBuildLast(repo string) (*common.Build, error) { func (db *DB) BuildLast(repo string) (*common.Build, error) {
key := []byte(repo) key := []byte(repo)
build := &common.Build{} build := &common.Build{}
err := db.View(func(t *bolt.Tx) error { err := db.View(func(t *bolt.Tx) error {
@ -71,9 +71,49 @@ func (db *DB) GetBuildLast(repo string) (*common.Build, error) {
return build, err return build, err
} }
// GetBuildStatus gets the named build status for the // SetBuild inserts or updates a build for the named
// named repository and build number. // repository. The build number is incremented and
func (db *DB) GetBuildStatus(repo string, build int, status string) (*common.Status, error) { // assigned to the provided build.
func (db *DB) SetBuild(repo string, build *common.Build) error {
repokey := []byte(repo)
build.Updated = time.Now().UTC().Unix()
return db.Update(func(t *bolt.Tx) error {
if build.Number == 0 {
raw, err := raw(t, bucketBuildSeq, repokey)
var next_seq uint32
switch err {
case ErrKeyNotFound:
next_seq = 1
case nil:
next_seq = 1 + binary.LittleEndian.Uint32(raw)
default:
return err
}
// covert our seqno to raw value
raw = make([]byte, 4) // TODO(benschumacher) replace magic number 4 (uint32)
binary.LittleEndian.PutUint32(raw, next_seq)
err = t.Bucket(bucketBuildSeq).Put(repokey, raw)
if err != nil {
return err
}
// fill out the build structure
build.Number = int(next_seq)
build.Created = time.Now().UTC().Unix()
}
key := []byte(repo + "/" + strconv.Itoa(build.Number))
return update(t, bucketBuild, key, build)
})
}
// Status returns the status for the given repository
// and build number.
func (db *DB) Status(repo string, build int, status string) (*common.Status, error) {
status_ := &common.Status{} status_ := &common.Status{}
key := []byte(repo + "/" + strconv.Itoa(build) + "/" + status) key := []byte(repo + "/" + strconv.Itoa(build) + "/" + status)
@ -84,9 +124,9 @@ func (db *DB) GetBuildStatus(repo string, build int, status string) (*common.Sta
return status_, err return status_, err
} }
// GetBuildStatusList gets a list of all build statues for // StatusList returned a list of all build statues for
// the named repository and build number. // the given repository and build number.
func (db *DB) GetBuildStatusList(repo string, build int) ([]*common.Status, error) { func (db *DB) StatusList(repo string, build int) ([]*common.Status, error) {
// TODO (bradrydzewski) explore efficiency of cursor vs index // TODO (bradrydzewski) explore efficiency of cursor vs index
statuses := []*common.Status{} statuses := []*common.Status{}
@ -105,59 +145,13 @@ func (db *DB) GetBuildStatusList(repo string, build int) ([]*common.Status, erro
return statuses, err return statuses, err
} }
// InsertBuild inserts a new build for the named repository // SetStatus inserts a new build status for the
func (db *DB) InsertBuild(repo string, build *common.Build) error {
key := []byte(repo)
return db.Update(func(t *bolt.Tx) error {
raw, err := raw(t, bucketBuildSeq, key)
var next_seq uint32
switch err {
case ErrKeyNotFound:
next_seq = 1
case nil:
next_seq = 1 + binary.LittleEndian.Uint32(raw)
default:
return err
}
// covert our seqno to raw value
raw = make([]byte, 4) // TODO(benschumacher) replace magic number 4 (uint32)
binary.LittleEndian.PutUint32(raw, next_seq)
err = t.Bucket(bucketBuildSeq).Put(key, raw)
if err != nil {
return err
}
// fill out the build structure
build.Number = int(next_seq)
build.Created = time.Now().UTC().Unix()
key = []byte(repo + "/" + strconv.Itoa(build.Number))
return insert(t, bucketBuild, key, build)
})
}
// InsertBuildStatus inserts a new build status for the
// named repository and build number. If the status already // named repository and build number. If the status already
// exists an error is returned. // exists an error is returned.
func (db *DB) InsertBuildStatus(repo string, build int, status *common.Status) error { func (db *DB) SetStatus(repo string, build int, status *common.Status) error {
key := []byte(repo + "/" + strconv.Itoa(build) + "/" + status.Context) key := []byte(repo + "/" + strconv.Itoa(build) + "/" + status.Context)
return db.Update(func(t *bolt.Tx) error { return db.Update(func(t *bolt.Tx) error {
return update(t, bucketBuildStatus, key, status) return update(t, bucketBuildStatus, key, status)
}) })
} }
// UpdateBuild updates an existing build for the named
// repository. If the build already exists and error is
// returned.
func (db *DB) UpdateBuild(repo string, build *common.Build) error {
key := []byte(repo + "/" + strconv.Itoa(build.Number))
build.Updated = time.Now().UTC().Unix()
return db.Update(func(t *bolt.Tx) error {
return update(t, bucketBuild, key, build)
})
}

View file

@ -24,41 +24,41 @@ func TestBuild(t *testing.T) {
}) })
g.It("Should sequence builds", func() { g.It("Should sequence builds", func() {
err := db.InsertBuild(repo, &common.Build{State: "pending"}) err := db.SetBuild(repo, &common.Build{State: "pending"})
g.Assert(err).Equal(nil) g.Assert(err).Equal(nil)
// the first build should always be numero 1 // the first build should always be numero 1
build, err := db.GetBuild(repo, 1) build, err := db.Build(repo, 1)
g.Assert(err).Equal(nil) g.Assert(err).Equal(nil)
g.Assert(build.State).Equal("pending") g.Assert(build.State).Equal("pending")
// add another build, just for fun // add another build, just for fun
err = db.InsertBuild(repo, &common.Build{State: "success"}) err = db.SetBuild(repo, &common.Build{State: "success"})
g.Assert(err).Equal(nil) g.Assert(err).Equal(nil)
// get the next build // get the next build
build, err = db.GetBuild(repo, 2) build, err = db.Build(repo, 2)
g.Assert(err).Equal(nil) g.Assert(err).Equal(nil)
g.Assert(build.State).Equal("success") g.Assert(build.State).Equal("success")
}) })
g.It("Should get the latest builds", func() { g.It("Should get the latest builds", func() {
db.InsertBuild(repo, &common.Build{State: "success"}) db.SetBuild(repo, &common.Build{State: "success"})
db.InsertBuild(repo, &common.Build{State: "success"}) db.SetBuild(repo, &common.Build{State: "success"})
db.InsertBuild(repo, &common.Build{State: "pending"}) db.SetBuild(repo, &common.Build{State: "pending"})
build, err := db.GetBuildLast(repo) build, err := db.BuildLast(repo)
g.Assert(err).Equal(nil) g.Assert(err).Equal(nil)
g.Assert(build.State).Equal("pending") g.Assert(build.State).Equal("pending")
g.Assert(build.Number).Equal(3) g.Assert(build.Number).Equal(3)
}) })
g.It("Should get the recent list of builds", func() { g.It("Should get the recent list of builds", func() {
db.InsertBuild(repo, &common.Build{State: "success"}) db.SetBuild(repo, &common.Build{State: "success"})
db.InsertBuild(repo, &common.Build{State: "success"}) db.SetBuild(repo, &common.Build{State: "success"})
db.InsertBuild(repo, &common.Build{State: "pending"}) db.SetBuild(repo, &common.Build{State: "pending"})
builds, err := db.GetBuildList(repo) builds, err := db.BuildList(repo)
g.Assert(err).Equal(nil) g.Assert(err).Equal(nil)
g.Assert(len(builds)).Equal(3) g.Assert(len(builds)).Equal(3)
}) })

View file

@ -8,8 +8,8 @@ import (
"github.com/drone/drone/common" "github.com/drone/drone/common"
) )
// GetRepo gets the repository by name. // Repo returns the repository with the given name.
func (db *DB) GetRepo(repo string) (*common.Repo, error) { func (db *DB) Repo(repo string) (*common.Repo, error) {
repo_ := &common.Repo{} repo_ := &common.Repo{}
key := []byte(repo) key := []byte(repo)
@ -20,9 +20,42 @@ func (db *DB) GetRepo(repo string) (*common.Repo, error) {
return repo_, err return repo_, err
} }
// GetRepoParams gets the private environment parameters // RepoList returns a list of repositories for the
// given user account.
func (db *DB) RepoList(login string) ([]*common.Repo, error) {
repos := []*common.Repo{}
err := db.View(func(t *bolt.Tx) error {
// get the index of user tokens and unmarshal
// to a string array.
var keys [][]byte
err := get(t, bucketUserRepos, []byte(login), &keys)
if err != nil && err != ErrKeyNotFound {
return err
}
// for each item in the index, get the repository
// and append to the array
for _, key := range keys {
repo := &common.Repo{}
err := get(t, bucketRepo, key, repo)
if err == ErrKeyNotFound {
// TODO if we come across ErrKeyNotFound it means
// we need to re-build the index
continue
} else if err != nil {
return err
}
repos = append(repos, repo)
}
return nil
})
return repos, err
}
// RepoParams returns the private environment parameters
// for the given repository. // for the given repository.
func (db *DB) GetRepoParams(repo string) (map[string]string, error) { func (db *DB) RepoParams(repo string) (map[string]string, error) {
params := map[string]string{} params := map[string]string{}
key := []byte(repo) key := []byte(repo)
@ -33,9 +66,9 @@ func (db *DB) GetRepoParams(repo string) (map[string]string, error) {
return params, err return params, err
} }
// GetRepoParams gets the private and public rsa keys // RepoKeypair returns the private and public rsa keys
// for the given repository. // for the given repository.
func (db *DB) GetRepoKeys(repo string) (*common.Keypair, error) { func (db *DB) RepoKeypair(repo string) (*common.Keypair, error) {
keypair := &common.Keypair{} keypair := &common.Keypair{}
key := []byte(repo) key := []byte(repo)
@ -46,9 +79,8 @@ func (db *DB) GetRepoKeys(repo string) (*common.Keypair, error) {
return keypair, err return keypair, err
} }
// UpdateRepos updates a repository. If the repository // SetRepo inserts or updates a repository.
// does not exist an error is returned. func (db *DB) SetRepo(repo *common.Repo) error {
func (db *DB) UpdateRepo(repo *common.Repo) error {
key := []byte(repo.FullName) key := []byte(repo.FullName)
repo.Updated = time.Now().UTC().Unix() repo.Updated = time.Now().UTC().Unix()
@ -57,9 +89,9 @@ func (db *DB) UpdateRepo(repo *common.Repo) error {
}) })
} }
// InsertRepo inserts a repository in the datastore and // SetRepoNotExists updates a repository. If the repository
// subscribes the user to that repository. // already exists ErrConflict is returned.
func (db *DB) InsertRepo(user *common.User, repo *common.Repo) error { func (db *DB) SetRepoNotExists(user *common.User, repo *common.Repo) error {
repokey := []byte(repo.FullName) repokey := []byte(repo.FullName)
repo.Created = time.Now().UTC().Unix() repo.Created = time.Now().UTC().Unix()
repo.Updated = time.Now().UTC().Unix() repo.Updated = time.Now().UTC().Unix()
@ -78,9 +110,9 @@ func (db *DB) InsertRepo(user *common.User, repo *common.Repo) error {
}) })
} }
// UpsertRepoParams inserts or updates the private // SetRepoParams inserts or updates the private
// environment parameters for the named repository. // environment parameters for the named repository.
func (db *DB) UpsertRepoParams(repo string, params map[string]string) error { func (db *DB) SetRepoParams(repo string, params map[string]string) error {
key := []byte(repo) key := []byte(repo)
return db.Update(func(t *bolt.Tx) error { return db.Update(func(t *bolt.Tx) error {
@ -88,9 +120,9 @@ func (db *DB) UpsertRepoParams(repo string, params map[string]string) error {
}) })
} }
// UpsertRepoKeys inserts or updates the private and // SetRepoKeypair inserts or updates the private and
// public keypair for the named repository. // public keypair for the named repository.
func (db *DB) UpsertRepoKeys(repo string, keypair *common.Keypair) error { func (db *DB) SetRepoKeypair(repo string, keypair *common.Keypair) error {
key := []byte(repo) key := []byte(repo)
return db.Update(func(t *bolt.Tx) error { return db.Update(func(t *bolt.Tx) error {
@ -98,8 +130,8 @@ func (db *DB) UpsertRepoKeys(repo string, keypair *common.Keypair) error {
}) })
} }
// DeleteRepo deletes the repository. // DelRepo deletes the repository.
func (db *DB) DeleteRepo(repo *common.Repo) error { func (db *DB) DelRepo(repo *common.Repo) error {
//TODO(benschumacher) rework this to use BoltDB's txn wrapper //TODO(benschumacher) rework this to use BoltDB's txn wrapper
t, err := db.Begin(true) t, err := db.Begin(true)
@ -119,9 +151,13 @@ func (db *DB) DeleteRepo(repo *common.Repo) error {
return t.Commit() return t.Commit()
} }
// GetSubscriber gets the subscriber by login for the // Subscribed returns true if the user is subscribed
// named repository. // to the named repository.
func (db *DB) GetSubscriber(login, repo string) (*common.Subscriber, error) { //
// TODO (bradrydzewski) we are currently storing the subscription
// data in a wrapper element called common.Subscriber. This is
// no longer necessary.
func (db *DB) Subscribed(login, repo string) (bool, error) {
sub := &common.Subscriber{} sub := &common.Subscriber{}
err := db.View(func(t *bolt.Tx) error { err := db.View(func(t *bolt.Tx) error {
repokey := []byte(repo) repokey := []byte(repo)
@ -142,12 +178,12 @@ func (db *DB) GetSubscriber(login, repo string) (*common.Subscriber, error) {
} }
return nil return nil
}) })
return sub, err return sub.Subscribed, err
} }
// InsertSubscriber inserts a subscriber for the named // SetSubscriber inserts a subscriber for the named
// repository. // repository.
func (db *DB) InsertSubscriber(login, repo string) error { func (db *DB) SetSubscriber(login, repo string) error {
return db.Update(func(t *bolt.Tx) error { return db.Update(func(t *bolt.Tx) error {
userkey := []byte(login) userkey := []byte(login)
repokey := []byte(repo) repokey := []byte(repo)
@ -155,9 +191,9 @@ func (db *DB) InsertSubscriber(login, repo string) error {
}) })
} }
// DeleteSubscriber removes the subscriber by login for the // DelSubscriber removes the subscriber by login for the
// named repository. // named repository.
func (db *DB) DeleteSubscriber(login, repo string) error { func (db *DB) DelSubscriber(login, repo string) error {
return db.Update(func(t *bolt.Tx) error { return db.Update(func(t *bolt.Tx) error {
userkey := []byte(login) userkey := []byte(login)
repokey := []byte(repo) repokey := []byte(repo)

View file

@ -11,7 +11,7 @@ import (
// GetTask gets the task at index N for the named // GetTask gets the task at index N for the named
// repository and build number. // repository and build number.
func (db *DB) GetTask(repo string, build int, task int) (*common.Task, error) { func (db *DB) Task(repo string, build int, task int) (*common.Task, error) {
key := []byte(repo + "/" + strconv.Itoa(build) + "/" + strconv.Itoa(task)) key := []byte(repo + "/" + strconv.Itoa(build) + "/" + strconv.Itoa(task))
task_ := &common.Task{} task_ := &common.Task{}
err := db.View(func(t *bolt.Tx) error { err := db.View(func(t *bolt.Tx) error {
@ -20,27 +20,12 @@ func (db *DB) GetTask(repo string, build int, task int) (*common.Task, error) {
return task_, err return task_, err
} }
// GetTaskLogs gets the task logs at index N for // TaskList gets all tasks for the named repository
// the named repository and build number.
func (db *DB) GetTaskLogs(repo string, build int, task int) (io.Reader, error) {
key := []byte(repo + "/" + strconv.Itoa(build) + "/" + strconv.Itoa(task))
var log []byte
err := db.View(func(t *bolt.Tx) error {
var err error
log, err = raw(t, bucketBuildLogs, key)
return err
})
buf := bytes.NewBuffer(log)
return buf, err
}
// GetTaskList gets all tasks for the named repository
// and build number. // and build number.
func (db *DB) GetTaskList(repo string, build int) ([]*common.Task, error) { func (db *DB) TaskList(repo string, build int) ([]*common.Task, error) {
// fetch the build so that we can get the // fetch the build so that we can get the
// number of child tasks. // number of child tasks.
build_, err := db.GetBuild(repo, build) build_, err := db.Build(repo, build)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -70,18 +55,18 @@ func (db *DB) GetTaskList(repo string, build int) ([]*common.Task, error) {
return tasks, nil return tasks, nil
} }
// UpsertTask inserts or updates a task for the named // SetTask inserts or updates a task for the named
// repository and build number. // repository and build number.
func (db *DB) UpsertTask(repo string, build int, task *common.Task) error { func (db *DB) SetTask(repo string, build int, task *common.Task) error {
key := []byte(repo + "/" + strconv.Itoa(build) + "/" + strconv.Itoa(task.Number)) key := []byte(repo + "/" + strconv.Itoa(build) + "/" + strconv.Itoa(task.Number))
return db.Update(func(t *bolt.Tx) error { return db.Update(func(t *bolt.Tx) error {
return update(t, bucketBuildTasks, key, task) return update(t, bucketBuildTasks, key, task)
}) })
} }
// UpsertTaskLogs inserts or updates a task logs for the // SetLogs inserts or updates a task logs for the
// named repository and build number. // named repository and build number.
func (db *DB) UpsertTaskLogs(repo string, build int, task int, log []byte) error { func (db *DB) SetLogs(repo string, build int, task int, log []byte) error {
key := []byte(repo + "/" + strconv.Itoa(build) + "/" + strconv.Itoa(task)) key := []byte(repo + "/" + strconv.Itoa(build) + "/" + strconv.Itoa(task))
t, err := db.Begin(true) t, err := db.Begin(true)
if err != nil { if err != nil {
@ -94,3 +79,18 @@ func (db *DB) UpsertTaskLogs(repo string, build int, task int, log []byte) error
} }
return t.Commit() return t.Commit()
} }
// LogReader gets the task logs at index N for
// the named repository and build number.
func (db *DB) LogReader(repo string, build int, task int) (io.Reader, error) {
key := []byte(repo + "/" + strconv.Itoa(build) + "/" + strconv.Itoa(task))
var log []byte
err := db.View(func(t *bolt.Tx) error {
var err error
log, err = raw(t, bucketBuildLogs, key)
return err
})
buf := bytes.NewBuffer(log)
return buf, err
}

View file

@ -5,19 +5,48 @@ import (
"github.com/drone/drone/common" "github.com/drone/drone/common"
) )
// GetToken gets a token by sha value. // Token returns the token for the given user and label.
func (db *DB) GetToken(user, label string) (*common.Token, error) { func (db *DB) Token(user, label string) (*common.Token, error) {
token := &common.Token{} token := &common.Token{}
key := []byte(user + "/" + label) key := []byte(user + "/" + label)
err := db.View(func(t *bolt.Tx) error { err := db.View(func(t *bolt.Tx) error {
return get(t, bucketTokens, key, token) return get(t, bucketTokens, key, token)
}) })
return token, err return token, err
} }
// InsertToken inserts a new user token in the datastore. // TokenList returns a list of all tokens for the given
// If the token already exists and error is returned. // user login.
func (db *DB) InsertToken(token *common.Token) error { func (db *DB) TokenList(login string) ([]*common.Token, error) {
tokens := []*common.Token{}
userkey := []byte(login)
err := db.Update(func(t *bolt.Tx) error {
// get the index of user tokens and unmarshal
// to a string array.
var keys [][]byte
err := get(t, bucketUserTokens, userkey, &keys)
if err != nil && err != ErrKeyNotFound {
return err
}
// for each item in the index, get the repository
// and append to the array
for _, key := range keys {
token := &common.Token{}
raw := t.Bucket(bucketTokens).Get(key)
err = decode(raw, token)
if err != nil {
return err
}
tokens = append(tokens, token)
}
return nil
})
return tokens, err
}
// SetToken inserts a new user token in the datastore.
func (db *DB) SetToken(token *common.Token) error {
key := []byte(token.Login + "/" + token.Label) key := []byte(token.Login + "/" + token.Label)
return db.Update(func(t *bolt.Tx) error { return db.Update(func(t *bolt.Tx) error {
err := push(t, bucketUserTokens, []byte(token.Login), key) err := push(t, bucketUserTokens, []byte(token.Login), key)
@ -28,14 +57,14 @@ func (db *DB) InsertToken(token *common.Token) error {
}) })
} }
// DeleteUser deletes the token. // DelToken deletes the token.
func (db *DB) DeleteToken(token *common.Token) error { func (db *DB) DelToken(token *common.Token) error {
key := []byte(token.Login + "/" + token.Label) key := []byte(token.Login + "/" + token.Label)
return db.Update(func(t *bolt.Tx) error { return db.Update(func(t *bolt.Tx) error {
err := splice(t, bucketUserTokens, []byte(token.Login), key) err := splice(t, bucketUserTokens, []byte(token.Login), key)
if err != nil { if err != nil {
return err return err
} }
return delete(t, bucketUser, key) return delete(t, bucketTokens, key)
}) })
} }

View file

@ -22,20 +22,44 @@ func TestToken(t *testing.T) {
os.Remove(db.Path()) os.Remove(db.Path())
}) })
g.It("Should find by label")
g.It("Should list for user", func() { g.It("Should list for user", func() {
db.InsertUser(&common.User{Login: "octocat"}) db.SetUserNotExists(&common.User{Login: "octocat"})
err1 := db.InsertToken(&common.Token{Login: "octocat", Label: "gist"}) err1 := db.SetToken(&common.Token{Login: "octocat", Label: "gist"})
err2 := db.InsertToken(&common.Token{Login: "octocat", Label: "github"}) err2 := db.SetToken(&common.Token{Login: "octocat", Label: "github"})
g.Assert(err1).Equal(nil) g.Assert(err1).Equal(nil)
g.Assert(err2).Equal(nil) g.Assert(err2).Equal(nil)
list, err := db.GetUserTokens("octocat") list, err := db.TokenList("octocat")
g.Assert(err).Equal(nil) g.Assert(err).Equal(nil)
g.Assert(len(list)).Equal(2) g.Assert(len(list)).Equal(2)
}) })
g.It("Should delete")
g.It("Should insert") g.It("Should insert", func() {
g.It("Should not insert if exists") db.SetUserNotExists(&common.User{Login: "octocat"})
err := db.SetToken(&common.Token{Login: "octocat", Label: "gist"})
g.Assert(err).Equal(nil)
token, err := db.Token("octocat", "gist")
g.Assert(err).Equal(nil)
g.Assert(token.Label).Equal("gist")
g.Assert(token.Login).Equal("octocat")
})
g.It("Should delete", func() {
db.SetUserNotExists(&common.User{Login: "octocat"})
err := db.SetToken(&common.Token{Login: "octocat", Label: "gist"})
g.Assert(err).Equal(nil)
token, err := db.Token("octocat", "gist")
g.Assert(err).Equal(nil)
g.Assert(token.Label).Equal("gist")
g.Assert(token.Login).Equal("octocat")
err = db.DelToken(token)
g.Assert(err).Equal(nil)
token, err = db.Token("octocat", "gist")
g.Assert(err != nil).IsTrue()
})
}) })
} }

View file

@ -7,8 +7,8 @@ import (
"github.com/drone/drone/common" "github.com/drone/drone/common"
) )
// GetUser gets a user by user login. // User returns a user by user login.
func (db *DB) GetUser(login string) (*common.User, error) { func (db *DB) User(login string) (*common.User, error) {
user := &common.User{} user := &common.User{}
key := []byte(login) key := []byte(login)
@ -19,74 +19,8 @@ func (db *DB) GetUser(login string) (*common.User, error) {
return user, err return user, err
} }
// GetUserTokens gets a list of all tokens for // UserCount returns a count of all registered users.
// the given user login. func (db *DB) UserCount() (int, error) {
func (db *DB) GetUserTokens(login string) ([]*common.Token, error) {
t, err := db.Begin(false)
if err != nil {
return nil, err
}
defer t.Rollback()
tokens := []*common.Token{}
// get the index of user tokens and unmarshal
// to a string array.
var keys [][]byte
err = get(t, bucketUserTokens, []byte(login), &keys)
if err != nil && err != ErrKeyNotFound {
return nil, err
}
// for each item in the index, get the repository
// and append to the array
for _, key := range keys {
token := &common.Token{}
raw := t.Bucket(bucketTokens).Get(key)
err = decode(raw, token)
if err != nil {
return nil, err
}
tokens = append(tokens, token)
}
return tokens, nil
}
// GetUserRepos gets a list of repositories for the
// given user account.
func (db *DB) GetUserRepos(login string) ([]*common.Repo, error) {
repos := []*common.Repo{}
err := db.View(func(t *bolt.Tx) error {
// get the index of user tokens and unmarshal
// to a string array.
var keys [][]byte
err := get(t, bucketUserRepos, []byte(login), &keys)
if err != nil && err != ErrKeyNotFound {
return err
}
// for each item in the index, get the repository
// and append to the array
for _, key := range keys {
repo := &common.Repo{}
err := get(t, bucketRepo, key, repo)
if err == ErrKeyNotFound {
// TODO if we come across ErrKeyNotFound it means
// we need to re-build the index
continue
} else if err != nil {
return err
}
repos = append(repos, repo)
}
return nil
})
return repos, err
}
// GetUserCount gets a count of all registered users
// in the system.
func (db *DB) GetUserCount() (int, error) {
var out int var out int
var err = db.View(func(t *bolt.Tx) error { var err = db.View(func(t *bolt.Tx) error {
out = t.Bucket(bucketUser).Stats().KeyN out = t.Bucket(bucketUser).Stats().KeyN
@ -95,8 +29,8 @@ func (db *DB) GetUserCount() (int, error) {
return out, err return out, err
} }
// GetUserList gets a list of all registered users. // UserList returns a list of all registered users.
func (db *DB) GetUserList() ([]*common.User, error) { func (db *DB) UserList() ([]*common.User, error) {
users := []*common.User{} users := []*common.User{}
err := db.View(func(t *bolt.Tx) error { err := db.View(func(t *bolt.Tx) error {
return t.Bucket(bucketUser).ForEach(func(key, raw []byte) error { return t.Bucket(bucketUser).ForEach(func(key, raw []byte) error {
@ -112,9 +46,8 @@ func (db *DB) GetUserList() ([]*common.User, error) {
return users, err return users, err
} }
// UpdateUser updates an existing user. If the user // SetUser inserts or updates a user.
// does not exists an error is returned. func (db *DB) SetUser(user *common.User) error {
func (db *DB) UpdateUser(user *common.User) error {
key := []byte(user.Login) key := []byte(user.Login)
user.Updated = time.Now().UTC().Unix() user.Updated = time.Now().UTC().Unix()
@ -123,9 +56,9 @@ func (db *DB) UpdateUser(user *common.User) error {
}) })
} }
// InsertUser inserts a new user into the datastore. If // SetUserNotExists inserts a new user into the datastore.
// the user login already exists an error is returned. // If the user login already exists ErrConflict is returned.
func (db *DB) InsertUser(user *common.User) error { func (db *DB) SetUserNotExists(user *common.User) error {
key := []byte(user.Login) key := []byte(user.Login)
user.Created = time.Now().UTC().Unix() user.Created = time.Now().UTC().Unix()
user.Updated = time.Now().UTC().Unix() user.Updated = time.Now().UTC().Unix()
@ -135,8 +68,8 @@ func (db *DB) InsertUser(user *common.User) error {
}) })
} }
// DeleteUser deletes the user. // DelUser deletes the user.
func (db *DB) DeleteUser(user *common.User) error { func (db *DB) DelUser(user *common.User) error {
key := []byte(user.Login) key := []byte(user.Login)
// TODO(bradrydzewski) delete user subscriptions // TODO(bradrydzewski) delete user subscriptions
// TODO(bradrydzewski) delete user tokens // TODO(bradrydzewski) delete user tokens

View file

@ -23,17 +23,17 @@ func TestUser(t *testing.T) {
}) })
g.It("Should find", func() { g.It("Should find", func() {
db.InsertUser(&common.User{Login: "octocat"}) db.SetUserNotExists(&common.User{Login: "octocat"})
user, err := db.GetUser("octocat") user, err := db.User("octocat")
g.Assert(err).Equal(nil) g.Assert(err).Equal(nil)
g.Assert(user.Login).Equal("octocat") g.Assert(user.Login).Equal("octocat")
}) })
g.It("Should insert", func() { g.It("Should insert", func() {
err := db.InsertUser(&common.User{Login: "octocat"}) err := db.SetUserNotExists(&common.User{Login: "octocat"})
g.Assert(err).Equal(nil) g.Assert(err).Equal(nil)
user, err := db.GetUser("octocat") user, err := db.User("octocat")
g.Assert(err).Equal(nil) g.Assert(err).Equal(nil)
g.Assert(user.Login).Equal("octocat") g.Assert(user.Login).Equal("octocat")
g.Assert(user.Created != 0).IsTrue() g.Assert(user.Created != 0).IsTrue()
@ -41,50 +41,50 @@ func TestUser(t *testing.T) {
}) })
g.It("Should not insert if exists", func() { g.It("Should not insert if exists", func() {
db.InsertUser(&common.User{Login: "octocat"}) db.SetUser(&common.User{Login: "octocat"})
err := db.InsertUser(&common.User{Login: "octocat"}) err := db.SetUserNotExists(&common.User{Login: "octocat"})
g.Assert(err).Equal(ErrKeyExists) g.Assert(err).Equal(ErrKeyExists)
}) })
g.It("Should update", func() { g.It("Should update", func() {
db.InsertUser(&common.User{Login: "octocat"}) db.SetUserNotExists(&common.User{Login: "octocat"})
user, err := db.GetUser("octocat") user, err := db.User("octocat")
g.Assert(err).Equal(nil) g.Assert(err).Equal(nil)
user.Email = "octocat@github.com" user.Email = "octocat@github.com"
err = db.UpdateUser(user) err = db.SetUser(user)
g.Assert(err).Equal(nil) g.Assert(err).Equal(nil)
user_, err := db.GetUser("octocat") user_, err := db.User("octocat")
g.Assert(err).Equal(nil) g.Assert(err).Equal(nil)
g.Assert(user_.Login).Equal(user.Login) g.Assert(user_.Login).Equal(user.Login)
g.Assert(user_.Email).Equal(user.Email) g.Assert(user_.Email).Equal(user.Email)
}) })
g.It("Should delete", func() { g.It("Should delete", func() {
db.InsertUser(&common.User{Login: "octocat"}) db.SetUserNotExists(&common.User{Login: "octocat"})
user, err := db.GetUser("octocat") user, err := db.User("octocat")
g.Assert(err).Equal(nil) g.Assert(err).Equal(nil)
err = db.DeleteUser(user) err = db.DelUser(user)
g.Assert(err).Equal(nil) g.Assert(err).Equal(nil)
_, err = db.GetUser("octocat") _, err = db.User("octocat")
g.Assert(err).Equal(ErrKeyNotFound) g.Assert(err).Equal(ErrKeyNotFound)
}) })
g.It("Should list", func() { g.It("Should list", func() {
db.InsertUser(&common.User{Login: "bert"}) db.SetUserNotExists(&common.User{Login: "bert"})
db.InsertUser(&common.User{Login: "ernie"}) db.SetUserNotExists(&common.User{Login: "ernie"})
users, err := db.GetUserList() users, err := db.UserList()
g.Assert(err).Equal(nil) g.Assert(err).Equal(nil)
g.Assert(len(users)).Equal(2) g.Assert(len(users)).Equal(2)
}) })
g.It("Should count", func() { g.It("Should count", func() {
db.InsertUser(&common.User{Login: "bert"}) db.SetUserNotExists(&common.User{Login: "bert"})
db.InsertUser(&common.User{Login: "ernie"}) db.SetUserNotExists(&common.User{Login: "ernie"})
count, err := db.GetUserCount() count, err := db.UserCount()
g.Assert(err).Equal(nil) g.Assert(err).Equal(nil)
g.Assert(count).Equal(2) g.Assert(count).Equal(2)
}) })

View file

@ -6,138 +6,136 @@ import (
"github.com/drone/drone/common" "github.com/drone/drone/common"
) )
var (
ErrConflict = "Key not unique"
ErrNotFound = "Key not found"
)
type Datastore interface { type Datastore interface {
// GetUser gets a user by user login. // User returns a user by user login.
GetUser(string) (*common.User, error) User(string) (*common.User, error)
// GetUserTokens gets a list of all tokens for // UserCount returns a count of all registered users.
// the given user login. UserCount() (int, error)
GetUserTokens(string) ([]*common.Token, error)
// GetUserRepos gets a list of repositories for the // UserList returns a list of all registered users.
// given user account. UserList() ([]*common.User, error)
GetUserRepos(string) ([]*common.Repo, error)
// GetUserCount gets a count of all registered users // SetUser inserts or updates a user.
// in the system. SetUser(*common.User) error
GetUserCount() (int, error)
// GetUserList gets a list of all registered users. // SetUserNotExists inserts a new user into the datastore.
GetUserList() ([]*common.User, error) // If the user login already exists ErrConflict is returned.
SetUserNotExists(*common.User) error
// UpdateUser updates an existing user. If the user // Del deletes the user.
// does not exists an error is returned. DelUser(*common.User) error
UpdateUser(*common.User) error
// InsertUser inserts a new user into the datastore. If // Token returns the token for the given user and label.
// the user login already exists an error is returned. Token(string, string) (*common.Token, error)
InsertUser(*common.User) error
// DeleteUser deletes the user. // TokenList returns a list of all tokens for the given
DeleteUser(*common.User) error // user login.
TokenList(string) ([]*common.Token, error)
// GetToken gets a token by sha value. // SetToken inserts a new user token in the datastore.
GetToken(string, string) (*common.Token, error) SetToken(*common.Token) error
// InsertToken inserts a new user token in the datastore. // DelToken deletes the token.
// If the token already exists and error is returned. DelToken(*common.Token) error
InsertToken(*common.Token) error
// DeleteUser deletes the token. // Subscribed returns true if the user is subscribed
DeleteToken(*common.Token) error // to the named repository.
Subscribed(string, string) (bool, error)
// GetSubscriber gets the subscriber by login for the // SetSubscriber inserts a subscriber for the named
// named repository.
GetSubscriber(string, string) (*common.Subscriber, error)
// InsertSubscriber inserts a subscriber for the named
// repository. // repository.
InsertSubscriber(string, string) error SetSubscriber(string, string) error
// DeleteSubscriber removes the subscriber by login for the // DelSubscriber removes the subscriber by login for the
// named repository. // named repository.
DeleteSubscriber(string, string) error DelSubscriber(string, string) error
// GetRepo gets the repository by name. // Repo returns the repository with the given name.
GetRepo(string) (*common.Repo, error) Repo(string) (*common.Repo, error)
// GetRepoParams gets the private environment parameters // RepoList returns a list of repositories for the
// given user account.
RepoList(string) ([]*common.Repo, error)
// RepoParams returns the private environment parameters
// for the given repository. // for the given repository.
GetRepoParams(string) (map[string]string, error) RepoParams(string) (map[string]string, error)
// GetRepoParams gets the private and public rsa keys // RepoKeypair returns the private and public rsa keys
// for the given repository. // for the given repository.
GetRepoKeys(string) (*common.Keypair, error) RepoKeypair(string) (*common.Keypair, error)
// UpdateRepos updates a repository. If the repository // SetRepo inserts or updates a repository.
// does not exist an error is returned. SetRepo(*common.Repo) error
UpdateRepo(*common.Repo) error
// InsertRepo inserts a repository in the datastore and // SetRepo updates a repository. If the repository
// subscribes the user to that repository. // already exists ErrConflict is returned.
InsertRepo(*common.User, *common.Repo) error SetRepoNotExists(*common.User, *common.Repo) error
// UpsertRepoParams inserts or updates the private // SetRepoParams inserts or updates the private
// environment parameters for the named repository. // environment parameters for the named repository.
UpsertRepoParams(string, map[string]string) error SetRepoParams(string, map[string]string) error
// UpsertRepoKeys inserts or updates the private and // SetRepoKeypair inserts or updates the private and
// public keypair for the named repository. // public keypair for the named repository.
UpsertRepoKeys(string, *common.Keypair) error SetRepoKeypair(string, *common.Keypair) error
// DeleteRepo deletes the repository. // DelRepo deletes the repository.
DeleteRepo(*common.Repo) error DelRepo(*common.Repo) error
// GetBuild gets the specified build number for the // Build gets the specified build number for the
// named repository and build number // named repository and build number
GetBuild(string, int) (*common.Build, error) Build(string, int) (*common.Build, error)
// GetBuildList gets a list of recent builds for the // BuildList gets a list of recent builds for the
// named repository. // named repository.
GetBuildList(string) ([]*common.Build, error) BuildList(string) ([]*common.Build, error)
// GetBuildLast gets the last executed build for the // BuildLast gets the last executed build for the
// named repository. // named repository.
GetBuildLast(string) (*common.Build, error) BuildLast(string) (*common.Build, error)
// GetBuildStatus gets the named build status for the // SetBuild inserts or updates a build for the named
// named repository and build number. // repository. The build number is incremented and
GetBuildStatus(string, int, string) (*common.Status, error) // assigned to the provided build.
SetBuild(string, *common.Build) error
// GetBuildStatusList gets a list of all build statues for // Status returns the status for the given repository
// the named repository and build number. // and build number.
GetBuildStatusList(string, int) ([]*common.Status, error) Status(string, int, string) (*common.Status, error)
// InsertBuild inserts a new build for the named repository // StatusList returned a list of all build statues for
InsertBuild(string, *common.Build) error // the given repository and build number.
StatusList(string, int) ([]*common.Status, error)
// InsertBuildStatus inserts a new build status for the // SetStatus inserts a new build status for the
// named repository and build number. If the status already // named repository and build number. If the status already
// exists an error is returned. // exists an error is returned.
InsertBuildStatus(string, int, *common.Status) error SetStatus(string, int, *common.Status) error
// UpdateBuild updates an existing build for the named
// repository. If the build already exists and error is
// returned.
UpdateBuild(string, *common.Build) error
// GetTask gets the task at index N for the named // GetTask gets the task at index N for the named
// repository and build number. // repository and build number.
GetTask(string, int, int) (*common.Task, error) Task(string, int, int) (*common.Task, error)
// GetTaskLogs gets the task logs at index N for // TaskList gets all tasks for the named repository
// the named repository and build number.
GetTaskLogs(string, int, int) (io.Reader, error)
// GetTaskList gets all tasks for the named repository
// and build number. // and build number.
GetTaskList(string, int) ([]*common.Task, error) TaskList(string, int) ([]*common.Task, error)
// UpsertTask inserts or updates a task for the named // SetTask inserts or updates a task for the named
// repository and build number. // repository and build number.
UpsertTask(string, int, *common.Task) error SetTask(string, int, *common.Task) error
// UpsertTaskLogs inserts or updates a task logs for the // LogReader gets the task logs at index N for
// the named repository and build number.
LogReader(string, int, int) (io.Reader, error)
// SetLogs inserts or updates a task logs for the
// named repository and build number. // named repository and build number.
UpsertTaskLogs(string, int, int, []byte) error SetLogs(string, int, int, []byte) error
} }

View file

@ -42,7 +42,7 @@ func main() {
user.Use(server.SetSession(session)) user.Use(server.SetSession(session))
user.GET("", server.GetUserCurr) user.GET("", server.GetUserCurr)
user.PUT("", server.PutUserCurr) user.PATCH("", server.PutUserCurr)
user.GET("/repos", server.GetUserRepos) user.GET("/repos", server.GetUserRepos)
user.GET("/tokens", server.GetUserTokens) user.GET("/tokens", server.GetUserTokens)
user.POST("/tokens", server.PostToken) user.POST("/tokens", server.PostToken)
@ -55,8 +55,8 @@ func main() {
users.GET("", server.GetUsers) users.GET("", server.GetUsers)
users.GET("/:name", server.GetUser) users.GET("/:name", server.GetUser)
users.PUT("/:name", server.PutUser)
users.POST("/:name", server.PostUser) users.POST("/:name", server.PostUser)
users.PATCH("/:name", server.PutUser)
users.DELETE("/:name", server.DeleteUser) users.DELETE("/:name", server.DeleteUser)
} }
@ -72,67 +72,25 @@ func main() {
repo.Use(server.CheckPush()) repo.Use(server.CheckPush())
repo.GET("", server.GetRepo) repo.GET("", server.GetRepo)
repo.PUT("", server.PutRepo) repo.PATCH("", server.PutRepo)
repo.DELETE("", server.DeleteRepo) repo.DELETE("", server.DeleteRepo)
repo.POST("/watch", server.Subscribe)
repo.DELETE("/unwatch", server.Unsubscribe)
repo.GET("/builds", server.GetBuilds)
repo.GET("/builds/:number", server.GetBuild)
//TODO repo.POST("/builds/:number", server.RestartBuild)
//TODO repo.DELETE("/builds/:number", server.CancelBuild)
repo.GET("/builds/:number/tasks", server.GetTasks)
repo.GET("/builds/:number/tasks/:task", server.GetTask)
repo.GET("/builds/:number/tasks/:task/log", server.GetTaskLogs)
// repo.GET("/status/:number/status/:context", server.GetStatus)
repo.GET("/status/:number", server.GetStatusList)
repo.POST("/status/:number", server.PostStatus)
} }
} }
subscribers := api.Group("/subscribers/:owner/:name")
{
subscribers.Use(server.SetRepo())
subscribers.Use(server.SetPerm())
subscribers.Use(server.CheckPull())
subscribers.POST("", server.Subscribe)
subscribers.DELETE("", server.Unsubscribe)
}
builds := api.Group("/builds/:owner/:name")
{
builds.Use(server.SetRepo())
builds.Use(server.SetPerm())
builds.Use(server.CheckPull())
builds.Use(server.CheckPush())
builds.GET("", server.GetBuilds)
builds.GET("/:number", server.GetBuild)
//TODO builds.POST("/:number", server.RestartBuild)
//TODO builds.DELETE("/:number", server.CancelBuild)
}
tasks := api.Group("/tasks/:owner/:name/:number")
{
tasks.Use(server.SetRepo())
tasks.Use(server.SetPerm())
tasks.Use(server.CheckPull())
tasks.Use(server.CheckPush())
tasks.GET("", server.GetTasks)
tasks.GET("/:task", server.GetTask)
}
logs := api.Group("/logs/:owner/:name/:number/:task")
{
logs.Use(server.SetRepo())
logs.Use(server.SetPerm())
logs.Use(server.CheckPull())
logs.Use(server.CheckPush())
logs.GET("", server.GetTaskLogs)
}
status := api.Group("/status/:owner/:name/:number")
{
status.Use(server.SetRepo())
status.Use(server.SetPerm())
status.Use(server.CheckPull())
status.Use(server.CheckPush())
status.GET("/:context", server.GetStatus)
status.GET("", server.GetStatusList)
status.POST("", server.PostStatus)
}
badges := api.Group("/badges/:owner/:name") badges := api.Group("/badges/:owner/:name")
{ {
badges.Use(server.SetRepo()) badges.Use(server.SetRepo())

View file

@ -59,9 +59,9 @@ func GetBadge(c *gin.Context) {
// //
// TODO(bradrydzewski) this will not return in-progress builds, which it should // TODO(bradrydzewski) this will not return in-progress builds, which it should
func GetCC(c *gin.Context) { func GetCC(c *gin.Context) {
ds := ToDatastore(c) store := ToDatastore(c)
repo := ToRepo(c) repo := ToRepo(c)
last, err := ds.GetBuildLast(repo.FullName) last, err := store.BuildLast(repo.FullName)
if err != nil { if err != nil {
c.Fail(404, err) c.Fail(404, err)
return return

View file

@ -13,14 +13,14 @@ import (
// GET /api/builds/:owner/:name/:number // GET /api/builds/:owner/:name/:number
// //
func GetBuild(c *gin.Context) { func GetBuild(c *gin.Context) {
ds := ToDatastore(c) store := ToDatastore(c)
repo := ToRepo(c) repo := ToRepo(c)
num, err := strconv.Atoi(c.Params.ByName("number")) num, err := strconv.Atoi(c.Params.ByName("number"))
if err != nil { if err != nil {
c.Fail(400, err) c.Fail(400, err)
return return
} }
build, err := ds.GetBuild(repo.FullName, num) build, err := store.Build(repo.FullName, num)
if err != nil { if err != nil {
c.Fail(404, err) c.Fail(404, err)
} else { } else {
@ -34,9 +34,9 @@ func GetBuild(c *gin.Context) {
// GET /api/builds/:owner/:name // GET /api/builds/:owner/:name
// //
func GetBuilds(c *gin.Context) { func GetBuilds(c *gin.Context) {
ds := ToDatastore(c) store := ToDatastore(c)
repo := ToRepo(c) repo := ToRepo(c)
builds, err := ds.GetBuildList(repo.FullName) builds, err := store.BuildList(repo.FullName)
if err != nil { if err != nil {
c.Fail(404, err) c.Fail(404, err)
} else { } else {

View file

@ -42,7 +42,7 @@ func PostHook(c *gin.Context) {
return return
} }
repo, err := store.GetRepo(hook.Repo.FullName) repo, err := store.Repo(hook.Repo.FullName)
if err != nil { if err != nil {
log.Errorf("failure to find repo %s from hook. %s", hook.Repo.FullName, err) log.Errorf("failure to find repo %s from hook. %s", hook.Repo.FullName, err)
c.Fail(404, err) c.Fail(404, err)
@ -64,7 +64,7 @@ func PostHook(c *gin.Context) {
return return
} }
user, err := store.GetUser(repo.User.Login) user, err := store.User(repo.User.Login)
if err != nil { if err != nil {
log.Errorf("failure to find repo owner %s. %s", repo.User.Login, err) log.Errorf("failure to find repo owner %s. %s", repo.User.Login, err)
c.Fail(500, err) c.Fail(500, err)
@ -84,7 +84,7 @@ func PostHook(c *gin.Context) {
return return
} }
err = store.InsertBuild(repo.FullName, build) err = store.SetBuild(repo.FullName, build)
if err != nil { if err != nil {
c.Fail(500, err) c.Fail(500, err)
return return

View file

@ -51,9 +51,9 @@ func GetLogin(c *gin.Context) {
// get the user from the database // get the user from the database
login := ToUser(c) login := ToUser(c)
u, err := store.GetUser(login.Login) u, err := store.User(login.Login)
if err != nil { if err != nil {
count, err := store.GetUserCount() count, err := store.UserCount()
if err != nil { if err != nil {
log.Errorf("cannot register %s. %s", login.Login, err) log.Errorf("cannot register %s. %s", login.Login, err)
c.Redirect(303, "/login#error=internal_error") c.Redirect(303, "/login#error=internal_error")
@ -79,7 +79,7 @@ func GetLogin(c *gin.Context) {
u.Gravatar = gravatar.Generate(u.Email) u.Gravatar = gravatar.Generate(u.Email)
// insert the user into the database // insert the user into the database
if err := store.InsertUser(u); err != nil { if err := store.SetUserNotExists(u); err != nil {
log.Errorf("cannot insert %s. %s", login.Login, err) log.Errorf("cannot insert %s. %s", login.Login, err)
c.Redirect(303, "/login#error=internal_error") c.Redirect(303, "/login#error=internal_error")
return return
@ -100,7 +100,7 @@ func GetLogin(c *gin.Context) {
u.Email = login.Email u.Email = login.Email
u.Gravatar = gravatar.Generate(u.Email) u.Gravatar = gravatar.Generate(u.Email)
if err := store.UpdateUser(u); err != nil { if err := store.SetUser(u); err != nil {
log.Errorf("cannot update %s. %s", u.Login, err) log.Errorf("cannot update %s. %s", u.Login, err)
c.Redirect(303, "/login#error=internal_error") c.Redirect(303, "/login#error=internal_error")
return return

View file

@ -19,6 +19,7 @@ type repoResp struct {
*common.Repo *common.Repo
Perms *common.Perm `json:"permissions,omitempty"` Perms *common.Perm `json:"permissions,omitempty"`
Watch *common.Subscriber `json:"subscription,omitempty"` Watch *common.Subscriber `json:"subscription,omitempty"`
Keypair *common.Keypair `json:"keypair,omitempty"`
Params map[string]string `json:"params,omitempty"` Params map[string]string `json:"params,omitempty"`
} }
@ -52,11 +53,11 @@ func GetRepo(c *gin.Context) {
repo := ToRepo(c) repo := ToRepo(c)
user := ToUser(c) user := ToUser(c)
perm := ToPerm(c) perm := ToPerm(c)
data := repoResp{repo, perm, nil, nil} data := repoResp{repo, perm, nil, nil, nil}
// if the user is an administrator of the project // if the user is an administrator of the project
// we should display the private parameter data. // we should display the private parameter data.
if perm.Admin { if perm.Admin {
data.Params, _ = store.GetRepoParams(repo.FullName) data.Params, _ = store.RepoParams(repo.FullName)
} }
// if the user is authenticated, we should display // if the user is authenticated, we should display
// if she is watching the current repository. // if she is watching the current repository.
@ -66,7 +67,9 @@ func GetRepo(c *gin.Context) {
} }
// check to see if the user is subscribing to the repo // check to see if the user is subscribing to the repo
data.Watch, _ = store.GetSubscriber(user.Login, repo.FullName) data.Watch = &common.Subscriber{}
data.Watch.Subscribed, _ = store.Subscribed(user.Login, repo.FullName)
data.Keypair, _ = store.RepoKeypair(repo.FullName)
c.JSON(200, data) c.JSON(200, data)
} }
@ -89,7 +92,7 @@ func PutRepo(c *gin.Context) {
} }
if in.Params != nil { if in.Params != nil {
err := store.UpsertRepoParams(repo.FullName, *in.Params) err := store.SetRepoParams(repo.FullName, *in.Params)
if err != nil { if err != nil {
c.Fail(400, err) c.Fail(400, err)
return return
@ -111,17 +114,19 @@ func PutRepo(c *gin.Context) {
repo.Timeout = *in.Timeout repo.Timeout = *in.Timeout
} }
err := store.UpdateRepo(repo) err := store.SetRepo(repo)
if err != nil { if err != nil {
c.Fail(400, err) c.Fail(400, err)
return return
} }
data := repoResp{repo, perm, nil, nil} data := repoResp{repo, perm, nil, nil, nil}
data.Params, _ = store.GetRepoParams(repo.FullName) data.Params, _ = store.RepoParams(repo.FullName)
// check to see if the user is subscribing to the repo // check to see if the user is subscribing to the repo
data.Watch, _ = store.GetSubscriber(user.Login, repo.FullName) data.Watch = &common.Subscriber{}
data.Watch.Subscribed, _ = store.Subscribed(user.Login, repo.FullName)
data.Keypair, _ = store.RepoKeypair(repo.FullName)
c.JSON(200, data) c.JSON(200, data)
} }
@ -147,7 +152,7 @@ func DeleteRepo(c *gin.Context) {
c.Fail(400, err) c.Fail(400, err)
} }
err = ds.DeleteRepo(r) err = ds.DelRepo(r)
if err != nil { if err != nil {
c.Fail(400, err) c.Fail(400, err)
} }
@ -213,14 +218,14 @@ func PostRepo(c *gin.Context) {
println(link) println(link)
// persist the repository // persist the repository
err = store.InsertRepo(user, r) err = store.SetRepoNotExists(user, r)
if err != nil { if err != nil {
c.Fail(500, err) c.Fail(500, err)
return return
} }
// persisty the repository key pair // persisty the repository key pair
err = store.UpsertRepoKeys(r.FullName, keypair) err = store.SetRepoKeypair(r.FullName, keypair)
if err != nil { if err != nil {
c.Fail(500, err) c.Fail(500, err)
return return

View file

@ -114,7 +114,7 @@ func SetUser(s session.Session) gin.HandlerFunc {
return return
} }
u, err := ds.GetUser(token.Login) u, err := ds.User(token.Login)
if err == nil { if err == nil {
c.Set("user", u) c.Set("user", u)
} }
@ -129,7 +129,7 @@ func SetUser(s session.Session) gin.HandlerFunc {
// to verify the token we fetch from the datastore // to verify the token we fetch from the datastore
// and check to see if the token issued date matches // and check to see if the token issued date matches
// what we found in the jwt (in case the label is re-used) // what we found in the jwt (in case the label is re-used)
t, err := ds.GetToken(token.Login, token.Label) t, err := ds.Token(token.Login, token.Label)
if err != nil || t.Issued != token.Issued { if err != nil || t.Issued != token.Issued {
c.AbortWithStatus(403) c.AbortWithStatus(403)
return return
@ -145,7 +145,7 @@ func SetRepo() gin.HandlerFunc {
u := ToUser(c) u := ToUser(c)
owner := c.Params.ByName("owner") owner := c.Params.ByName("owner")
name := c.Params.ByName("name") name := c.Params.ByName("name")
r, err := ds.GetRepo(owner + "/" + name) r, err := ds.Repo(owner + "/" + name)
switch { switch {
case err != nil && u != nil: case err != nil && u != nil:
c.Fail(401, err) c.Fail(401, err)

View file

@ -14,7 +14,7 @@
* @param {string} Name of the repository. * @param {string} Name of the repository.
*/ */
this.list = function(repoName) { this.list = function(repoName) {
return $http.get('/api/builds/'+repoName); return $http.get('/api/repos/'+repoName+'/builds');
}; };
/** /**
@ -24,7 +24,7 @@
* @param {number} Number of the build. * @param {number} Number of the build.
*/ */
this.get = function(repoName, buildNumber) { this.get = function(repoName, buildNumber) {
return $http.get('/api/builds/'+repoName+'/'+buildNumber); return $http.get('/api/repos/'+repoName+'/builds/'+buildNumber);
}; };
} }

View file

@ -16,7 +16,7 @@
* @param {number} Number of the task. * @param {number} Number of the task.
*/ */
this.get = function(repoName, number, step) { this.get = function(repoName, number, step) {
return $http.get('/api/logs/'+repoName+'/'+number+'/'+step); return $http.get('/api/repos/'+repoName+'/builds/'+number+'/tasks/'+step+'/log');
}; };
} }

View file

@ -43,7 +43,7 @@
* @param {object} JSON representation of a repository. * @param {object} JSON representation of a repository.
*/ */
this.update = function(repo) { this.update = function(repo) {
return $http.put('/api/repos/'+repo.full_name, repo); return $http.patch('/api/repos/'+repo.full_name, repo);
}; };
/** /**
@ -61,7 +61,7 @@
* @param {string} Name of the repository. * @param {string} Name of the repository.
*/ */
this.watch = function(repoName) { this.watch = function(repoName) {
return $http.post('/api/subscribers/'+repoName); return $http.post('/api/repos/'+repoName+'/watch');
}; };
/** /**
@ -70,7 +70,7 @@
* @param {string} Name of the repository. * @param {string} Name of the repository.
*/ */
this.unwatch = function(repoName) { this.unwatch = function(repoName) {
return $http.delete('/api/subscribers/'+repoName); return $http.delete('/api/repos/'+repoName+'/unwatch');
}; };
} }

View file

@ -15,7 +15,7 @@
* @param {number} Number of the build. * @param {number} Number of the build.
*/ */
this.list = function(repoName, number) { this.list = function(repoName, number) {
return $http.get('/api/tasks/'+repoName+'/'+number); return $http.get('/api/repos/'+repoName+'/builds/'+number+'/tasks');
}; };
/** /**
@ -26,7 +26,7 @@
* @param {number} Number of the task. * @param {number} Number of the task.
*/ */
this.get = function(repoName, number, step) { this.get = function(repoName, number, step) {
return $http.get('/api/tasks/'+repoName+'/'+name+'/'+step); return $http.get('/api/repos/'+repoName+'/builds/'+number+'/tasks/'+step);
}; };
/** /**
@ -37,7 +37,7 @@
* @param {number} Number of the task. * @param {number} Number of the task.
*/ */
this.get = function(repoName, number, step) { this.get = function(repoName, number, step) {
return $http.get('/api/tasks/'+repoName+'/'+name+'/'+step); return $http.get('/api/repos/'+repoName+'/builds/'+number+'/tasks/'+step);
}; };
} }

View file

@ -45,7 +45,7 @@
* Updates an existing user * Updates an existing user
*/ */
this.put = function(user) { this.put = function(user) {
return $http.put('/api/users/'+user.login, user); return $http.patch('/api/users/'+user.login, user);
}; };
/** /**

View file

@ -16,12 +16,12 @@ import (
// GET /api/status/:owner/:name/:number/:context // GET /api/status/:owner/:name/:number/:context
// //
func GetStatus(c *gin.Context) { func GetStatus(c *gin.Context) {
ds := ToDatastore(c) store := ToDatastore(c)
repo := ToRepo(c) repo := ToRepo(c)
num, _ := strconv.Atoi(c.Params.ByName("number")) num, _ := strconv.Atoi(c.Params.ByName("number"))
ctx := c.Params.ByName("context") ctx := c.Params.ByName("context")
status, err := ds.GetBuildStatus(repo.FullName, num, ctx) status, err := store.Status(repo.FullName, num, ctx)
if err != nil { if err != nil {
c.Fail(404, err) c.Fail(404, err)
} else { } else {
@ -36,7 +36,7 @@ func GetStatus(c *gin.Context) {
// POST /api/status/:owner/:name/:number // POST /api/status/:owner/:name/:number
// //
func PostStatus(c *gin.Context) { func PostStatus(c *gin.Context) {
ds := ToDatastore(c) store := ToDatastore(c)
repo := ToRepo(c) repo := ToRepo(c)
num, err := strconv.Atoi(c.Params.ByName("number")) num, err := strconv.Atoi(c.Params.ByName("number"))
if err != nil { if err != nil {
@ -48,7 +48,7 @@ func PostStatus(c *gin.Context) {
c.AbortWithStatus(400) c.AbortWithStatus(400)
return return
} }
if err := ds.InsertBuildStatus(repo.Name, num, in); err != nil { if err := store.SetStatus(repo.Name, num, in); err != nil {
c.Fail(400, err) c.Fail(400, err)
} else { } else {
c.JSON(201, in) c.JSON(201, in)
@ -62,11 +62,11 @@ func PostStatus(c *gin.Context) {
// GET /api/status/:owner/:name/:number/:context // GET /api/status/:owner/:name/:number/:context
// //
func GetStatusList(c *gin.Context) { func GetStatusList(c *gin.Context) {
ds := ToDatastore(c) store := ToDatastore(c)
repo := ToRepo(c) repo := ToRepo(c)
num, _ := strconv.Atoi(c.Params.ByName("number")) num, _ := strconv.Atoi(c.Params.ByName("number"))
list, err := ds.GetBuildStatusList(repo.FullName, num) list, err := store.StatusList(repo.FullName, num)
if err != nil { if err != nil {
c.Fail(404, err) c.Fail(404, err)
} else { } else {

View file

@ -15,7 +15,7 @@ func Unsubscribe(c *gin.Context) {
repo := ToRepo(c) repo := ToRepo(c)
user := ToUser(c) user := ToUser(c)
err := store.DeleteSubscriber(user.Login, repo.FullName) err := store.DelSubscriber(user.Login, repo.FullName)
if err != nil { if err != nil {
c.Fail(400, err) c.Fail(400, err)
} else { } else {
@ -33,7 +33,7 @@ func Subscribe(c *gin.Context) {
repo := ToRepo(c) repo := ToRepo(c)
user := ToUser(c) user := ToUser(c)
err := store.InsertSubscriber(user.Login, repo.FullName) err := store.SetSubscriber(user.Login, repo.FullName)
if err != nil { if err != nil {
c.Fail(400, err) c.Fail(400, err)
} else { } else {

View file

@ -14,12 +14,12 @@ import (
// GET /api/tasks/:owner/:name/:number/:task // GET /api/tasks/:owner/:name/:number/:task
// //
func GetTask(c *gin.Context) { func GetTask(c *gin.Context) {
ds := ToDatastore(c) store := ToDatastore(c)
repo := ToRepo(c) repo := ToRepo(c)
b, _ := strconv.Atoi(c.Params.ByName("number")) b, _ := strconv.Atoi(c.Params.ByName("number"))
t, _ := strconv.Atoi(c.Params.ByName("task")) t, _ := strconv.Atoi(c.Params.ByName("task"))
task, err := ds.GetTask(repo.FullName, b, t) task, err := store.Task(repo.FullName, b, t)
if err != nil { if err != nil {
c.Fail(404, err) c.Fail(404, err)
} else { } else {
@ -34,11 +34,11 @@ func GetTask(c *gin.Context) {
// GET /api/tasks/:owner/:name/:number // GET /api/tasks/:owner/:name/:number
// //
func GetTasks(c *gin.Context) { func GetTasks(c *gin.Context) {
ds := ToDatastore(c) store := ToDatastore(c)
repo := ToRepo(c) repo := ToRepo(c)
num, _ := strconv.Atoi(c.Params.ByName("number")) num, _ := strconv.Atoi(c.Params.ByName("number"))
tasks, err := ds.GetTaskList(repo.FullName, num) tasks, err := store.TaskList(repo.FullName, num)
if err != nil { if err != nil {
c.Fail(404, err) c.Fail(404, err)
} else { } else {
@ -53,18 +53,18 @@ func GetTasks(c *gin.Context) {
// GET /api/logs/:owner/:name/:number/:task // GET /api/logs/:owner/:name/:number/:task
// //
func GetTaskLogs(c *gin.Context) { func GetTaskLogs(c *gin.Context) {
ds := ToDatastore(c) store := ToDatastore(c)
repo := ToRepo(c) repo := ToRepo(c)
full, _ := strconv.ParseBool(c.Params.ByName("full")) full, _ := strconv.ParseBool(c.Params.ByName("full"))
build, _ := strconv.Atoi(c.Params.ByName("number")) build, _ := strconv.Atoi(c.Params.ByName("number"))
task, _ := strconv.Atoi(c.Params.ByName("task")) task, _ := strconv.Atoi(c.Params.ByName("task"))
logs, err := ds.GetTaskLogs(repo.FullName, build, task) r, err := store.LogReader(repo.FullName, build, task)
if err != nil { if err != nil {
c.Fail(404, err) c.Fail(404, err)
} else if full { } else if full {
io.Copy(c.Writer, logs) io.Copy(c.Writer, r)
} else { } else {
io.Copy(c.Writer, io.LimitReader(logs, 2000000)) io.Copy(c.Writer, io.LimitReader(r, 2000000))
} }
} }

View file

@ -36,7 +36,7 @@ func PostToken(c *gin.Context) {
token.Kind = common.TokenUser token.Kind = common.TokenUser
token.Issued = time.Now().UTC().Unix() token.Issued = time.Now().UTC().Unix()
err := store.InsertToken(token) err := store.SetToken(token)
if err != nil { if err != nil {
c.Fail(400, err) c.Fail(400, err)
} }
@ -57,11 +57,11 @@ func DelToken(c *gin.Context) {
user := ToUser(c) user := ToUser(c)
label := c.Params.ByName("label") label := c.Params.ByName("label")
token, err := store.GetToken(user.Login, label) token, err := store.Token(user.Login, label)
if err != nil { if err != nil {
c.Fail(404, err) c.Fail(404, err)
} }
err = store.DeleteToken(token) err = store.DelToken(token)
if err != nil { if err != nil {
c.Fail(400, err) c.Fail(400, err)
} }

View file

@ -24,20 +24,20 @@ func GetUserCurr(c *gin.Context) {
// PUT /api/user // PUT /api/user
// //
func PutUserCurr(c *gin.Context) { func PutUserCurr(c *gin.Context) {
ds := ToDatastore(c) store := ToDatastore(c)
me := ToUser(c) user := ToUser(c)
in := &common.User{} in := &common.User{}
if !c.BindWith(in, binding.JSON) { if !c.BindWith(in, binding.JSON) {
return return
} }
me.Email = in.Email user.Email = in.Email
me.Gravatar = gravatar.Generate(in.Email) user.Gravatar = gravatar.Generate(in.Email)
err := ds.UpdateUser(me) err := store.SetUser(user)
if err != nil { if err != nil {
c.Fail(400, err) c.Fail(400, err)
} else { } else {
c.JSON(200, me) c.JSON(200, user)
} }
} }
@ -48,9 +48,9 @@ func PutUserCurr(c *gin.Context) {
// GET /api/user/repos // GET /api/user/repos
// //
func GetUserRepos(c *gin.Context) { func GetUserRepos(c *gin.Context) {
ds := ToDatastore(c) store := ToDatastore(c)
me := ToUser(c) user := ToUser(c)
repos, err := ds.GetUserRepos(me.Login) repos, err := store.RepoList(user.Login)
if err != nil { if err != nil {
c.Fail(400, err) c.Fail(400, err)
} else { } else {
@ -65,9 +65,9 @@ func GetUserRepos(c *gin.Context) {
// GET /api/user/tokens // GET /api/user/tokens
// //
func GetUserTokens(c *gin.Context) { func GetUserTokens(c *gin.Context) {
ds := ToDatastore(c) store := ToDatastore(c)
me := ToUser(c) user := ToUser(c)
tokens, err := ds.GetUserTokens(me.Login) tokens, err := store.TokenList(user.Login)
if err != nil { if err != nil {
c.Fail(400, err) c.Fail(400, err)
} else { } else {

View file

@ -14,8 +14,8 @@ import (
// GET /api/users // GET /api/users
// //
func GetUsers(c *gin.Context) { func GetUsers(c *gin.Context) {
ds := ToDatastore(c) store := ToDatastore(c)
users, err := ds.GetUserList() users, err := store.UserList()
if err != nil { if err != nil {
c.Fail(400, err) c.Fail(400, err)
} else { } else {
@ -30,12 +30,12 @@ func GetUsers(c *gin.Context) {
// POST /api/users // POST /api/users
// //
func PostUser(c *gin.Context) { func PostUser(c *gin.Context) {
ds := ToDatastore(c) store := ToDatastore(c)
name := c.Params.ByName("name") name := c.Params.ByName("name")
user := &common.User{Login: name, Name: name} user := &common.User{Login: name, Name: name}
user.Token = c.Request.FormValue("token") user.Token = c.Request.FormValue("token")
user.Secret = c.Request.FormValue("secret") user.Secret = c.Request.FormValue("secret")
if err := ds.InsertUser(user); err != nil { if err := store.SetUserNotExists(user); err != nil {
c.Fail(400, err) c.Fail(400, err)
} else { } else {
c.JSON(201, user) c.JSON(201, user)
@ -49,9 +49,9 @@ func PostUser(c *gin.Context) {
// GET /api/users/:name // GET /api/users/:name
// //
func GetUser(c *gin.Context) { func GetUser(c *gin.Context) {
ds := ToDatastore(c) store := ToDatastore(c)
name := c.Params.ByName("name") name := c.Params.ByName("name")
user, err := ds.GetUser(name) user, err := store.User(name)
if err != nil { if err != nil {
c.Fail(404, err) c.Fail(404, err)
} else { } else {
@ -66,10 +66,10 @@ func GetUser(c *gin.Context) {
// PUT /api/users/:name // PUT /api/users/:name
// //
func PutUser(c *gin.Context) { func PutUser(c *gin.Context) {
ds := ToDatastore(c) store := ToDatastore(c)
me := ToUser(c) me := ToUser(c)
name := c.Params.ByName("name") name := c.Params.ByName("name")
user, err := ds.GetUser(name) user, err := store.User(name)
if err != nil { if err != nil {
c.Fail(404, err) c.Fail(404, err)
return return
@ -88,7 +88,7 @@ func PutUser(c *gin.Context) {
user.Admin = in.Admin user.Admin = in.Admin
} }
err = ds.UpdateUser(user) err = store.SetUser(user)
if err != nil { if err != nil {
c.Fail(400, err) c.Fail(400, err)
} else { } else {
@ -103,10 +103,10 @@ func PutUser(c *gin.Context) {
// DELETE /api/users/:name // DELETE /api/users/:name
// //
func DeleteUser(c *gin.Context) { func DeleteUser(c *gin.Context) {
ds := ToDatastore(c) store := ToDatastore(c)
me := ToUser(c) me := ToUser(c)
name := c.Params.ByName("name") name := c.Params.ByName("name")
user, err := ds.GetUser(name) user, err := store.User(name)
if err != nil { if err != nil {
c.Fail(404, err) c.Fail(404, err)
return return
@ -119,7 +119,7 @@ func DeleteUser(c *gin.Context) {
return return
} }
if err := ds.DeleteUser(user); err != nil { if err := store.DelUser(user); err != nil {
c.Fail(400, err) c.Fail(400, err)
} else { } else {
c.Writer.WriteHeader(204) c.Writer.WriteHeader(204)