| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 | package migrationsimport (	"errors"	"strconv"	"strings"	"time"	"github.com/go-xorm/xorm")type migration func(*xorm.Engine) error// The version table. Should have only one row with id==1type Version struct {	Id      int64	Version int64}// This is a sequence of migrations. Add new migrations to the bottom of the list.// If you want to "retire" a migration, replace it with "expiredMigration"var migrations = []migration{	accessToCollaboration,}// Migrate database to current versionfunc Migrate(x *xorm.Engine) error {	if err := x.Sync(new(Version)); err != nil {		return err	}	currentVersion := &Version{Id: 1}	has, err := x.Get(currentVersion)	if err != nil {		return err	} else if !has {		needsMigration, err := x.IsTableExist("user")		if err != nil {			return err		}		if needsMigration {			isEmpty, err := x.IsTableEmpty("user")			if err != nil {				return err			}			needsMigration = !isEmpty		}		if !needsMigration {			currentVersion.Version = int64(len(migrations))		}		if _, err = x.InsertOne(currentVersion); err != nil {			return err		}	}	v := currentVersion.Version	for i, migration := range migrations[v:] {		if err = migration(x); err != nil {			return err		}		currentVersion.Version = v + int64(i) + 1		if _, err = x.Id(1).Update(currentVersion); err != nil {			return err		}	}	return nil}func expiredMigration(x *xorm.Engine) error {	return errors.New("You are migrating from a too old gogs version")}func mustParseInt64(in []byte) int64 {	i, err := strconv.ParseInt(string(in), 10, 64)	if err != nil {		i = 0	}	return i}func accessToCollaboration(x *xorm.Engine) error {	type Collaboration struct {		ID      int64     `xorm:"pk autoincr"`		RepoID  int64     `xorm:"UNIQUE(s) INDEX NOT NULL"`		UserID  int64     `xorm:"UNIQUE(s) INDEX NOT NULL"`		Created time.Time `xorm:"CREATED"`	}	x.Sync(new(Collaboration))	sql := `SELECT u.id AS uid, a.repo_name AS repo, a.mode AS mode FROM access a JOIN user u ON a.user_name=u.lower_name`	results, err := x.Query(sql)	if err != nil {		return err	}	for _, result := range results {		userID := mustParseInt64(result["uid"])		repoRefName := string(result["repo"])		mode := mustParseInt64(result["mode"])		//Collaborators must have write access		if mode < 2 {			continue		}		parts := strings.SplitN(repoRefName, "/", 2)		ownerName := parts[0]		repoName := parts[1]		sql = `SELECT u.id as uid, ou.uid as memberid FROM user u LEFT JOIN org_user ou ON ou.org_id=u.id WHERE u.lower_name=?`		results, err := x.Query(sql, ownerName)		if err != nil {			return err		}		if len(results) < 1 {			continue		}		ownerID := mustParseInt64(results[0]["uid"])		for _, member := range results {			memberID := mustParseInt64(member["memberid"])			// We can skip all cases that a user is member of the owning organization			if memberID == userID {				continue			}		}		sql = `SELECT id FROM repository WHERE owner_id=? AND lower_name=?`		results, err = x.Query(sql, ownerID, repoName)		if err != nil {			return err		}		if len(results) < 1 {			continue		}		repoID := results[0]["id"]		sql = `INSERT INTO collaboration (user_id, repo_id) VALUES (?,?)`		_, err = x.Exec(sql, userID, repoID)		if err != nil {			return err		}	}	return nil}
 |