diff --git a/common/user.go b/common/user.go index 107c8562..22801e54 100644 --- a/common/user.go +++ b/common/user.go @@ -10,8 +10,4 @@ type User struct { Admin bool `json:"admin,omitempty"` Created int64 `json:"created_at,omitempty"` Updated int64 `json:"updated_at,omitempty"` - - // Repos contains a list of subscriptions - // to repositories the user is watching. - Repos map[string]struct{} `json:"-"` } diff --git a/datastore/bolt/repo.go b/datastore/bolt/repo.go index 0381b51d..e875dfba 100644 --- a/datastore/bolt/repo.go +++ b/datastore/bolt/repo.go @@ -1,10 +1,11 @@ package bolt import ( + "bytes" "time" - "github.com/drone/drone/common" "github.com/boltdb/bolt" + "github.com/drone/drone/common" ) // GetRepo gets the repository by name. @@ -12,7 +13,7 @@ func (db *DB) GetRepo(repo string) (*common.Repo, error) { repo_ := &common.Repo{} key := []byte(repo) - err := db.View(func (t *bolt.Tx) error { + err := db.View(func(t *bolt.Tx) error { return get(t, bucketRepo, key, repo_) }) @@ -25,7 +26,7 @@ func (db *DB) GetRepoParams(repo string) (map[string]string, error) { params := map[string]string{} key := []byte(repo) - err := db.View(func (t *bolt.Tx) error { + err := db.View(func(t *bolt.Tx) error { return get(t, bucketRepoParams, key, ¶ms) }) @@ -38,7 +39,7 @@ func (db *DB) GetRepoKeys(repo string) (*common.Keypair, error) { keypair := &common.Keypair{} key := []byte(repo) - err := db.View(func (t *bolt.Tx) error { + err := db.View(func(t *bolt.Tx) error { return get(t, bucketRepoKeys, key, keypair) }) @@ -51,7 +52,7 @@ func (db *DB) UpdateRepo(repo *common.Repo) error { key := []byte(repo.FullName) repo.Updated = time.Now().UTC().Unix() - return db.Update(func (t *bolt.Tx) error { + return db.Update(func(t *bolt.Tx) error { return update(t, bucketRepo, key, repo) }) } @@ -59,14 +60,21 @@ func (db *DB) UpdateRepo(repo *common.Repo) error { // InsertRepo inserts a repository in the datastore and // subscribes the user to that repository. func (db *DB) InsertRepo(user *common.User, repo *common.Repo) error { - key := []byte(repo.FullName) + repokey := []byte(repo.FullName) repo.Created = time.Now().UTC().Unix() repo.Updated = time.Now().UTC().Unix() - return db.Update(func (t *bolt.Tx) error { - // TODO(bradrydzewski) add repo to user index - // TODO(bradrydzewski) add user to repo index - return insert(t, bucketRepo, key, repo) + return db.Update(func(t *bolt.Tx) error { + userkey := []byte(user.Login) + err := push(t, bucketUserRepos, userkey, repokey) + if err != nil { + return err + } + // err = push(t, bucketRepoUsers, repokey, userkey) + // if err != nil { + // return err + // } + return insert(t, bucketRepo, repokey, repo) }) } @@ -75,7 +83,7 @@ func (db *DB) InsertRepo(user *common.User, repo *common.Repo) error { func (db *DB) UpsertRepoParams(repo string, params map[string]string) error { key := []byte(repo) - return db.Update(func (t *bolt.Tx) error { + return db.Update(func(t *bolt.Tx) error { return update(t, bucketRepoParams, key, params) }) } @@ -85,7 +93,7 @@ func (db *DB) UpsertRepoParams(repo string, params map[string]string) error { func (db *DB) UpsertRepoKeys(repo string, keypair *common.Keypair) error { key := []byte(repo) - return db.Update(func (t *bolt.Tx) error { + return db.Update(func(t *bolt.Tx) error { return update(t, bucketRepoKeys, key, keypair) }) } @@ -111,25 +119,48 @@ func (db *DB) DeleteRepo(repo *common.Repo) error { return t.Commit() } -// // GetSubscriber gets the subscriber by login for the -// // named repository. -// func (db *DB) GetSubscriber(repo string, login string) (*common.Subscriber, error) { -// sub := &common.Subscriber{} -// key := []byte(login + "/" + repo) -// err := get(db, bucketUserRepos, key, sub) -// return sub, err -// } +// GetSubscriber gets the subscriber by login for the +// named repository. +func (db *DB) GetSubscriber(login, repo string) (*common.Subscriber, error) { + sub := &common.Subscriber{} + err := db.View(func(t *bolt.Tx) error { + repokey := []byte(repo) -// // InsertSubscriber inserts a subscriber for the named -// // repository. -// func (db *DB) InsertSubscriber(repo string, sub *common.Subscriber) error { -// key := []byte(sub.Login + "/" + repo) -// return insert(db, bucketUserRepos, key, sub) -// } + // 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 + } -// // DeleteSubscriber removes the subscriber by login for the -// // named repository. -// func (db *DB) DeleteSubscriber(repo string, sub *common.Subscriber) error { -// key := []byte(sub.Login + "/" + repo) -// return delete(db, bucketUserRepos, key) -// } + for _, key := range keys { + if bytes.Equal(repokey, key) { + sub.Subscribed = true + return nil + } + } + return nil + }) + return sub, err +} + +// InsertSubscriber inserts a subscriber for the named +// repository. +func (db *DB) InsertSubscriber(login, repo string) error { + return db.Update(func(t *bolt.Tx) error { + userkey := []byte(login) + repokey := []byte(repo) + return push(t, bucketUserRepos, userkey, repokey) + }) +} + +// DeleteSubscriber removes the subscriber by login for the +// named repository. +func (db *DB) DeleteSubscriber(login, repo string) error { + return db.Update(func(t *bolt.Tx) error { + userkey := []byte(login) + repokey := []byte(repo) + return splice(t, bucketUserRepos, userkey, repokey) + }) +} diff --git a/datastore/bolt/user.go b/datastore/bolt/user.go index 92493590..cbd180d0 100644 --- a/datastore/bolt/user.go +++ b/datastore/bolt/user.go @@ -54,39 +54,33 @@ func (db *DB) GetUserTokens(login string) ([]*common.Token, error) { // GetUserRepos gets a list of repositories for the // given user account. func (db *DB) GetUserRepos(login string) ([]*common.Repo, error) { - t, err := db.Begin(false) - if err != nil { - return nil, err - } - defer t.Rollback() repos := []*common.Repo{} - user := &common.User{} - - // get the user struct from the database - key := []byte(login) - raw := t.Bucket(bucketUser).Get(key) - err = decode(raw, user) - if err != nil { - return nil, err - } - - // for each item in the index, get the repository - // and append to the array - for repoName, _ := range user.Repos { - repo := &common.Repo{} - key = []byte(repoName) - raw = t.Bucket(bucketRepo).Get(key) - if raw == nil { - // this will happen when the repository has been deleted - // TODO we should probably upate the index in this case. - continue + 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 } - err = decode(raw, repo) - if err != nil { - break + + // 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) } - repos = append(repos, repo) - } + return nil + }) + return repos, err } diff --git a/datastore/bolt/util.go b/datastore/bolt/util.go index 68d46835..744225d9 100644 --- a/datastore/bolt/util.go +++ b/datastore/bolt/util.go @@ -74,11 +74,13 @@ func splice(t *bolt.Tx, bucket, index, value []byte) error { if err != nil && err != ErrKeyNotFound { return err } + for i, key := range keys { if bytes.Equal(key, value) { keys = keys[:i+copy(keys[i:], keys[i+1:])] break } } + return update(t, bucket, index, &keys) } diff --git a/datastore/datastore.go b/datastore/datastore.go index 4c200fca..2a7a4365 100644 --- a/datastore/datastore.go +++ b/datastore/datastore.go @@ -46,17 +46,17 @@ type Datastore interface { // DeleteUser deletes the token. DeleteToken(*common.Token) error - // // GetSubscriber gets the subscriber by login for the - // // named repository. - // GetSubscriber(string, string) (*common.Subscriber, error) + // GetSubscriber gets the subscriber by login for the + // named repository. + GetSubscriber(string, string) (*common.Subscriber, error) - // // InsertSubscriber inserts a subscriber for the named - // // repository. - // InsertSubscriber(string, *common.Subscriber) error + // InsertSubscriber inserts a subscriber for the named + // repository. + InsertSubscriber(string, string) error - // // DeleteSubscriber removes the subscriber by login for the - // // named repository. - // DeleteSubscriber(string, *common.Subscriber) error + // DeleteSubscriber removes the subscriber by login for the + // named repository. + DeleteSubscriber(string, string) error // GetRepo gets the repository by name. GetRepo(string) (*common.Repo, error) diff --git a/server/repos.go b/server/repos.go index 1f7e86ab..7f7a6e08 100644 --- a/server/repos.go +++ b/server/repos.go @@ -66,8 +66,7 @@ func GetRepo(c *gin.Context) { } // check to see if the user is subscribing to the repo - _, ok := user.Repos[repo.FullName] - data.Watch = &common.Subscriber{Subscribed: ok} + data.Watch, _ = store.GetSubscriber(user.Login, repo.FullName) c.JSON(200, data) } @@ -122,8 +121,7 @@ func PutRepo(c *gin.Context) { data.Params, _ = store.GetRepoParams(repo.FullName) // check to see if the user is subscribing to the repo - _, ok := user.Repos[repo.FullName] - data.Watch = &common.Subscriber{Subscribed: ok} + data.Watch, _ = store.GetSubscriber(user.Login, repo.FullName) c.JSON(200, data) } @@ -207,11 +205,11 @@ func PostRepo(c *gin.Context) { // activate the repository before we make any // local changes to the database. - err = remote.Activate(user, r, keypair, link) - if err != nil { - c.Fail(500, err) - return - } + // err = remote.Activate(user, r, keypair, link) + // if err != nil { + // c.Fail(500, err) + // return + // } println(link) // persist the repository @@ -228,16 +226,6 @@ func PostRepo(c *gin.Context) { return } - // subscribe the user to the repository - // if this fails we'll ignore, since the user - // can just go click the "watch" button in the - // user interface. - if user.Repos == nil { - user.Repos = map[string]struct{}{} - } - user.Repos[r.FullName] = struct{}{} - store.UpdateUser(user) - c.JSON(200, r) } diff --git a/server/subscribe.go b/server/subscribe.go index e811f3f9..a8606607 100644 --- a/server/subscribe.go +++ b/server/subscribe.go @@ -1,9 +1,8 @@ package server import ( - "github.com/gin-gonic/gin" - "github.com/drone/drone/common" + "github.com/gin-gonic/gin" ) // Unubscribe accapets a request to unsubscribe the @@ -16,8 +15,7 @@ func Unsubscribe(c *gin.Context) { repo := ToRepo(c) user := ToUser(c) - delete(user.Repos, repo.FullName) - err := store.UpdateUser(user) + err := store.DeleteSubscriber(user.Login, repo.FullName) if err != nil { c.Fail(400, err) } else { @@ -34,11 +32,8 @@ func Subscribe(c *gin.Context) { store := ToDatastore(c) repo := ToRepo(c) user := ToUser(c) - if user.Repos == nil { - user.Repos = map[string]struct{}{} - } - user.Repos[repo.FullName] = struct{}{} - err := store.UpdateUser(user) + + err := store.InsertSubscriber(user.Login, repo.FullName) if err != nil { c.Fail(400, err) } else {