Goit

Simple and lightweight Git web server
git clone http://git.omkov.net/Goit
Log | Tree | Refs | README | Download

Goit/src/goit/db.go (154 lines, 3.2 KiB) -rw-r--r-- blame download

0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
package goit

import (
	"database/sql"
	"fmt"
	"log"

	"github.com/Jamozed/Goit/src/util"
)

/*
Current database schema:
users:
	id INTEGER PRIMARY KEY AUTOINCREMENT
	name TEXT UNIQUE NOT NULL
	name_full TEXT NOT NULL
	pass BLOB NOT NULL
	pass_algo TEXT NOT NULL
	salt BLOB NOT NULL
	is_admin BOOLEAN NOT NULL

repos:
	id INTEGER PRIMARY KEY AUTOINCREMENT
	owner_id INTEGER NOT NULL
	name TEXT UNIQUE NOT NULL
	name_lower TEXT UNIQUE NOT NULL
	description TEXT NOT NULL
	default_branch TEXT NOT NULL DEFAULT 'master'
	upstream TEXT NOT NULL
	visibility INTEGER NOT NULL DEFAULT 0
	is_mirror BOOLEAN NOT NULL
*/

func updateDatabase(db *sql.DB) error {
	const LATEST_VERSION = 3

	tx, err := db.Begin()
	if err != nil {
		return err
	}
	defer tx.Rollback()

	var version int
	if err := tx.QueryRow("PRAGMA user_version").Scan(&version); err != nil {
		return err
	}

	if version > LATEST_VERSION {
		return fmt.Errorf("database version is newer than supported (%d > %d)", version, LATEST_VERSION)
	}

	logMigration := true

	if version <= 0 {
		/* Database is empty or new, initialise from scratch */
		log.Println("Initialising database at version", LATEST_VERSION)
		logMigration = false

		if _, err := tx.Exec(
			`CREATE TABLE IF NOT EXISTS users (
				id INTEGER PRIMARY KEY AUTOINCREMENT,
				name TEXT UNIQUE NOT NULL,
				name_full TEXT NOT NULL,
				pass BLOB NOT NULL,
				pass_algo TEXT NOT NULL,
				salt BLOB NOT NULL,
				is_admin BOOLEAN NOT NULL
			)`,
		); err != nil {
			return err
		}

		if _, err := tx.Exec(
			`CREATE TABLE IF NOT EXISTS repos (
				id INTEGER PRIMARY KEY AUTOINCREMENT,
				owner_id INTEGER NOT NULL,
				name TEXT UNIQUE NOT NULL,
				name_lower TEXT UNIQUE NOT NULL,
				description TEXT NOT NULL,
				upstream TEXT NOT NULL,
				is_private BOOLEAN NOT NULL,
				is_mirror BOOLEAN NOT NULL
			)`,
		); err != nil {
			return err
		}

		version = 1
	}
	if version <= 1 {
		if logMigration {
			log.Println("Migrating database from version 1 to 2")
		}

		if _, err := tx.Exec("ALTER TABLE repos ADD COLUMN default_branch TEXT NOT NULL DEFAULT 'master'"); err != nil {
			return err
		}

		version = 2
	}
	if version <= 2 {
		if logMigration {
			log.Println("Migrating database from version 2 to 3")
		}

		if _, err := tx.Exec("ALTER TABLE repos ADD COLUMN visibility INTEGER NOT NULL DEFAULT 0"); err != nil {
			return err
		}

		/* Set values for each repo according to is_private */
		var visibilities = map[int64]Visibility{}

		if rows, err := tx.Query("SELECT id, is_private FROM repos"); err != nil {
			return err
		} else {
			for rows.Next() {
				var id int64
				var isPrivate bool

				if err := rows.Scan(&id, &isPrivate); err != nil {
					return err
				}

				visibilities[id] = util.If(isPrivate, Private, Public)
			}

			rows.Close()
		}

		for id, visibility := range visibilities {
			if _, err := tx.Exec("UPDATE repos SET visibility = ? WHERE id = ?", visibility, id); err != nil {
				return err
			}
		}

		/* Remove is_private column */
		if _, err := tx.Exec("ALTER TABLE repos DROP COLUMN is_private"); err != nil {
			return err
		}

		version = 3
	}

	if _, err := tx.Exec(fmt.Sprint("PRAGMA user_version = ", version)); err != nil {
		return err
	}

	if err := tx.Commit(); err != nil {
		return err
	}

	return nil
}