b3d5ce8d2fd901817c26eaf95cf050b3beb4eb31

Author
Ayman Bagabas <ayman.bagabas@gmail.com>
Committer
Ayman Bagabas <ayman.bagabas@gmail.com>
Date

Message

refactor: combine migrations into one

Diff

This diff is truncated to protect this page.

  1diff --git a/server/backend/repo.go b/server/backend/repo.go
  2index b31484ba66eae1bc987d7d312445f085bc08f749..119de3c92d4196267760222487b21545500d04ff 100644
  3--- a/server/backend/repo.go
  4+++ b/server/backend/repo.go
  5@@ -7,7 +7,6 @@ import (
  6 	"fmt"
  7 	"io/fs"
  8 	"os"
  9-	"os/exec"
 10 	"path"
 11 	"path/filepath"
 12 	"strconv"
 13@@ -105,19 +104,23 @@ func (d *Backend) ImportRepository(ctx context.Context, name string, user proto.
 14 		return nil, proto.ErrRepoExist
 15 	}
 16 
 17-	if err := os.MkdirAll(rp, fs.ModePerm); err != nil {
 18-		return nil, err
 19+	copts := git.CloneOptions{
 20+		Bare:   true,
 21+		Mirror: opts.Mirror,
 22+		Quiet:  true,
 23+		CommandOptions: git.CommandOptions{
 24+			Timeout: -1,
 25+			Context: ctx,
 26+			Envs: []string{
 27+				fmt.Sprintf(`GIT_SSH_COMMAND=ssh -o UserKnownHostsFile="%s" -o StrictHostKeyChecking=no -i "%s"`,
 28+					filepath.Join(d.cfg.DataPath, "ssh", "known_hosts"),
 29+					d.cfg.SSH.ClientKeyPath,
 30+				),
 31+			},
 32+		},
 33 	}
 34 
 35-	cmd := exec.CommandContext(ctx, "git", "clone", "--bare", "--mirror", remote, ".")
 36-	cmd.Env = append(cmd.Env,
 37-		fmt.Sprintf(`GIT_SSH_COMMAND=ssh -o UserKnownHostsFile="%s" -o StrictHostKeyChecking=no -i "%s"`,
 38-			filepath.Join(d.cfg.DataPath, "ssh", "known_hosts"),
 39-			d.cfg.SSH.ClientKeyPath,
 40-		),
 41-	)
 42-	cmd.Dir = rp
 43-	if err := cmd.Run(); err != nil {
 44+	if err := git.Clone(remote, rp, copts); err != nil {
 45 		d.logger.Error("failed to clone repository", "err", err, "mirror", opts.Mirror, "remote", remote, "path", rp)
 46 		// Cleanup the mess!
 47 		if rerr := os.RemoveAll(rp); rerr != nil {
 48@@ -135,7 +138,7 @@ func (d *Backend) ImportRepository(ctx context.Context, name string, user proto.
 49 
 50 	defer func() {
 51 		if err != nil {
 52-			if rerr := d.DeleteRepository(ctx, name, opts.LFS); rerr != nil {
 53+			if rerr := d.DeleteRepository(ctx, name); rerr != nil {
 54 				d.logger.Error("failed to delete repository", "err", rerr, "name", name)
 55 			}
 56 		}
 57@@ -187,51 +190,54 @@ func (d *Backend) ImportRepository(ctx context.Context, name string, user proto.
 58 // DeleteRepository deletes a repository.
 59 //
 60 // It implements backend.Backend.
 61-func (d *Backend) DeleteRepository(ctx context.Context, name string, deleteLFS bool) error {
 62+func (d *Backend) DeleteRepository(ctx context.Context, name string) error {
 63 	name = utils.SanitizeRepo(name)
 64 	repo := name + ".git"
 65 	rp := filepath.Join(d.reposPath(), repo)
 66 
 67-	return d.db.TransactionContext(ctx, func(tx *db.Tx) error {
 68+	err := d.db.TransactionContext(ctx, func(tx *db.Tx) error {
 69 		// Delete repo from cache
 70 		defer d.cache.Delete(name)
 71 
 72-		if deleteLFS {
 73-			repom, err := d.store.GetRepoByName(ctx, tx, name)
 74-			if err != nil {
 75-				return err
 76-			}
 77+		repom, err := d.store.GetRepoByName(ctx, tx, name)
 78+		if err != nil {
 79+			return db.WrapError(err)
 80+		}
 81 
 82-			repoID := strconv.FormatInt(repom.ID, 10)
 83-			strg := storage.NewLocalStorage(filepath.Join(d.cfg.DataPath, "lfs", repoID))
 84-			objs, err := d.store.GetLFSObjectsByName(ctx, tx, name)
 85-			if err != nil {
 86-				return err
 87-			}
 88+		repoID := strconv.FormatInt(repom.ID, 10)
 89+		strg := storage.NewLocalStorage(filepath.Join(d.cfg.DataPath, "lfs", repoID))
 90+		objs, err := d.store.GetLFSObjectsByName(ctx, tx, name)
 91+		if err != nil {
 92+			return db.WrapError(err)
 93+		}
 94 
 95-			for _, obj := range objs {
 96-				p := lfs.Pointer{
 97-					Oid:  obj.Oid,
 98-					Size: obj.Size,
 99-				}
100+		for _, obj := range objs {
101+			p := lfs.Pointer{
102+				Oid:  obj.Oid,
103+				Size: obj.Size,
104+			}
105diff --git a/server/db/logger.go b/server/db/logger.go
106index bf3d932b24c2f57330a3d7d3e7ca0181c8869d24..821576d11990ebb4b14f76c2015d2a6a8c794f5d 100644
107--- a/server/db/logger.go
108+++ b/server/db/logger.go
109@@ -3,6 +3,7 @@ package db
110 import (
111 	"context"
112 	"database/sql"
113+	"strings"
114 
115 	"github.com/charmbracelet/log"
116 	"github.com/jmoiron/sqlx"
117@@ -10,6 +11,9 @@ import (
118 
119 func trace(l *log.Logger, query string, args ...interface{}) {
120 	if l != nil {
121+		// Remove newlines and tabs
122+		query = strings.ReplaceAll(query, "\t", "")
123+		query = strings.TrimSpace(query)
124 		l.Debug("trace", "query", query, "args", args)
125 	}
126 }
127diff --git a/server/db/migrate/0001_create_tables.go b/server/db/migrate/0001_create_tables.go
128index b6cf1c85a95cebbcc52d43f4546f14dc6e150db3..6df595cb29583a83667b809089cfb1c58c7114be 100644
129--- a/server/db/migrate/0001_create_tables.go
130+++ b/server/db/migrate/0001_create_tables.go
131@@ -25,65 +25,110 @@ var createTables = Migration{
132 		insert := "INSERT "
133 
134 		// Alter old tables (if exist)
135-		// This is to support prior versions of Soft Serve
136+		// This is to support prior versions of Soft Serve v0.6
137 		switch tx.DriverName() {
138 		case "sqlite3", "sqlite":
139 			insert += "OR IGNORE "
140 
141 			hasUserTable := hasTable(tx, "user")
142 			if hasUserTable {
143-				if _, err := tx.ExecContext(ctx, "ALTER TABLE user RENAME TO users"); err != nil {
144+				if _, err := tx.ExecContext(ctx, "ALTER TABLE user RENAME TO user_old"); err != nil {
145 					return err
146 				}
147 			}
148 
149 			if hasTable(tx, "public_key") {
150-				if _, err := tx.ExecContext(ctx, "ALTER TABLE public_key RENAME TO public_keys"); err != nil {
151+				if _, err := tx.ExecContext(ctx, "ALTER TABLE public_key RENAME TO public_key_old"); err != nil {
152 					return err
153 				}
154 			}
155 
156 			if hasTable(tx, "collab") {
157-				if _, err := tx.ExecContext(ctx, "ALTER TABLE collab RENAME TO collabs"); err != nil {
158+				if _, err := tx.ExecContext(ctx, "ALTER TABLE collab RENAME TO collab_old"); err != nil {
159 					return err
160 				}
161 			}
162 
163 			if hasTable(tx, "repo") {
164-				if _, err := tx.ExecContext(ctx, "ALTER TABLE repo RENAME TO repos"); err != nil {
165+				if _, err := tx.ExecContext(ctx, "ALTER TABLE repo RENAME TO repo_old"); err != nil {
166 					return err
167 				}
168 			}
169+		}
170 
171-			// Fix username being nullable
172-			if hasUserTable {
173+		if err := migrateUp(ctx, tx, createTablesVersion, createTablesName); err != nil {
174+			return err
175+		}
176+
177+		switch tx.DriverName() {
178+		case "sqlite3", "sqlite":
179+
180+			if _, err := tx.ExecContext(ctx, "PRAGMA foreign_keys = OFF"); err != nil {
181+				return err
182+			}
183+
184+			if hasTable(tx, "user_old") {
185 				sqlm := `
186-				PRAGMA foreign_keys = OFF;
187+				INSERT INTO users (id, username, admin, updated_at)
188+					SELECT id, username, admin, updated_at FROM user_old;
189+				`
190+				if _, err := tx.ExecContext(ctx, sqlm); err != nil {
191+					return err
192+				}
193+			}
194 
195-				CREATE TABLE users_new (
196-					id INTEGER PRIMARY KEY AUTOINCREMENT,
197-					username TEXT NOT NULL UNIQUE,
198-					admin BOOLEAN NOT NULL,
199-					created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
200-					updated_at DATETIME NOT NULL
201-				);
202+			if hasTable(tx, "public_key_old") {
203+				// Check duplicate keys
204+				pks := []struct {
205+					ID        string `db:"id"`
206+					PublicKey string `db:"public_key"`
207+				}{}
208+				if err := tx.SelectContext(ctx, &pks, "SELECT id, public_key FROM public_key_old"); err != nil {
209+					return err
210+				}
211 
212-				INSERT INTO users_new (username, admin, updated_at)
213-					SELECT username, admin, updated_at FROM users;
214+				pkss := map[string]struct{}{}
215+				for _, pk := range pks {
216+					if _, ok := pkss[pk.PublicKey]; ok {
217+						return fmt.Errorf("duplicate public key: %q, please remove the duplicate key and try again", pk.PublicKey)
218+					}
219+					pkss[pk.PublicKey] = struct{}{}
220+				}
221 
222-				DROP TABLE users;
223-				ALTER TABLE users_new RENAME TO users;
224+				sqlm := `
225+				INSERT INTO public_keys (id, user_id, public_key, created_at, updated_at)
226+					SELECT id, user_id, public_key, created_at, updated_at FROM public_key_old;
227+				`
228+				if _, err := tx.ExecContext(ctx, sqlm); err != nil {
229+					return err
230+				}
231diff --git a/server/db/migrate/0001_create_tables_postgres.up.sql b/server/db/migrate/0001_create_tables_postgres.up.sql
232index 29a8e0bacc3af6cd5419c701a996d2b29c0d762b..59cf16a58e550ddcab0066203f3166d0fa01175c 100644
233--- a/server/db/migrate/0001_create_tables_postgres.up.sql
234+++ b/server/db/migrate/0001_create_tables_postgres.up.sql
235@@ -1,59 +1,109 @@
236 CREATE TABLE IF NOT EXISTS settings (
237-    id SERIAL PRIMARY KEY,
238-    key TEXT NOT NULL UNIQUE,
239-    value TEXT NOT NULL,
240-    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
241-    updated_at TIMESTAMP NOT NULL
242+  id SERIAL PRIMARY KEY,
243+  key TEXT NOT NULL UNIQUE,
244+  value TEXT NOT NULL,
245+  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
246+  updated_at TIMESTAMP NOT NULL
247 );
248 
249 CREATE TABLE IF NOT EXISTS users (
250-    id SERIAL PRIMARY KEY,
251-    username TEXT NOT NULL UNIQUE,
252-    admin BOOLEAN NOT NULL,
253-    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
254-    updated_at TIMESTAMP NOT NULL
255+  id SERIAL PRIMARY KEY,
256+  username TEXT NOT NULL UNIQUE,
257+  admin BOOLEAN NOT NULL,
258+  password TEXT,
259+  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
260+  updated_at TIMESTAMP NOT NULL
261 );
262 
263 CREATE TABLE IF NOT EXISTS public_keys (
264-    id SERIAL PRIMARY KEY,
265-    user_id INTEGER NOT NULL,
266-    public_key TEXT NOT NULL UNIQUE,
267-    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
268-    updated_at TIMESTAMP NOT NULL,
269-    UNIQUE (user_id, public_key),
270-    CONSTRAINT user_id_fk
271-    FOREIGN KEY(user_id) REFERENCES users(id)
272-    ON DELETE CASCADE
273-    ON UPDATE CASCADE
274+  id SERIAL PRIMARY KEY,
275+  user_id INTEGER NOT NULL,
276+  public_key TEXT NOT NULL UNIQUE,
277+  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
278+  updated_at TIMESTAMP NOT NULL,
279+  CONSTRAINT user_id_fk
280+  FOREIGN KEY(user_id) REFERENCES users(id)
281+  ON DELETE CASCADE
282+  ON UPDATE CASCADE
283 );
284 
285 CREATE TABLE IF NOT EXISTS repos (
286-    id SERIAL PRIMARY KEY,
287-    name TEXT NOT NULL UNIQUE,
288-    project_name TEXT NOT NULL,
289-    description TEXT NOT NULL,
290-    private BOOLEAN NOT NULL,
291-    mirror BOOLEAN NOT NULL,
292-    hidden BOOLEAN NOT NULL,
293-    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
294-    updated_at TIMESTAMP NOT NULL
295+  id SERIAL PRIMARY KEY,
296+  name TEXT NOT NULL UNIQUE,
297+  project_name TEXT NOT NULL,
298+  description TEXT NOT NULL,
299+  private BOOLEAN NOT NULL,
300+  mirror BOOLEAN NOT NULL,
301+  hidden BOOLEAN NOT NULL,
302+  user_id INTEGER NOT NULL,
303+  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
304+  updated_at TIMESTAMP NOT NULL,
305+  CONSTRAINT user_id_fk
306+  FOREIGN KEY(user_id) REFERENCES users(id)
307+  ON DELETE CASCADE
308+  ON UPDATE CASCADE
309 );
310 
311 CREATE TABLE IF NOT EXISTS collabs (
312-    id SERIAL PRIMARY KEY,
313-    user_id INTEGER NOT NULL,
314-    repo_id INTEGER NOT NULL,
315-    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
316-    updated_at TIMESTAMP NOT NULL,
317-    UNIQUE (user_id, repo_id),
318-    CONSTRAINT user_id_fk
319-    FOREIGN KEY(user_id) REFERENCES users(id)
320-    ON DELETE CASCADE
321-    ON UPDATE CASCADE,
322-    CONSTRAINT repo_id_fk
323-    FOREIGN KEY(repo_id) REFERENCES repos(id)
324-    ON DELETE CASCADE
325-    ON UPDATE CASCADE
326+  id SERIAL PRIMARY KEY,
327+  user_id INTEGER NOT NULL,
328+  repo_id INTEGER NOT NULL,
329+  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
330+  updated_at TIMESTAMP NOT NULL,
331+  UNIQUE (user_id, repo_id),
332+  CONSTRAINT user_id_fk
333+  FOREIGN KEY(user_id) REFERENCES users(id)
334+  ON DELETE CASCADE
335diff --git a/server/db/migrate/0001_create_tables_sqlite.up.sql b/server/db/migrate/0001_create_tables_sqlite.up.sql
336index 0880f464fd1a854399ad525cda016e90ea583a4f..dad8d3f05dc281f8db440479250749d3fabf042e 100644
337--- a/server/db/migrate/0001_create_tables_sqlite.up.sql
338+++ b/server/db/migrate/0001_create_tables_sqlite.up.sql
339@@ -10,6 +10,7 @@ CREATE TABLE IF NOT EXISTS users (
340   id INTEGER PRIMARY KEY AUTOINCREMENT,
341   username TEXT NOT NULL UNIQUE,
342   admin BOOLEAN NOT NULL,
343+  password TEXT,
344   created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
345   updated_at DATETIME NOT NULL
346 );
347@@ -20,7 +21,6 @@ CREATE TABLE IF NOT EXISTS public_keys (
348   public_key TEXT NOT NULL UNIQUE,
349   created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
350   updated_at DATETIME NOT NULL,
351-  UNIQUE (user_id, public_key),
352   CONSTRAINT user_id_fk
353   FOREIGN KEY(user_id) REFERENCES users(id)
354   ON DELETE CASCADE
355@@ -35,8 +35,13 @@ CREATE TABLE IF NOT EXISTS repos (
356   private BOOLEAN NOT NULL,
357   mirror BOOLEAN NOT NULL,
358   hidden BOOLEAN NOT NULL,
359+  user_id INTEGER NOT NULL,
360   created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
361-  updated_at DATETIME NOT NULL
362+  updated_at DATETIME NOT NULL,
363+  CONSTRAINT user_id_fk
364+  FOREIGN KEY(user_id) REFERENCES users(id)
365+  ON DELETE CASCADE
366+  ON UPDATE CASCADE
367 );
368 
369 CREATE TABLE IF NOT EXISTS collabs (
370@@ -56,3 +61,49 @@ CREATE TABLE IF NOT EXISTS collabs (
371   ON UPDATE CASCADE
372 );
373 
374+CREATE TABLE IF NOT EXISTS lfs_objects (
375+  id INTEGER PRIMARY KEY AUTOINCREMENT,
376+  oid TEXT NOT NULL,
377+  size INTEGER NOT NULL,
378+  repo_id INTEGER NOT NULL,
379+  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
380+  updated_at DATETIME NOT NULL,
381+  UNIQUE (oid, repo_id),
382+  CONSTRAINT repo_id_fk
383+  FOREIGN KEY(repo_id) REFERENCES repos(id)
384+  ON DELETE CASCADE
385+  ON UPDATE CASCADE
386+);
387+
388+CREATE TABLE IF NOT EXISTS lfs_locks (
389+  id INTEGER PRIMARY KEY AUTOINCREMENT,
390+  repo_id INTEGER NOT NULL,
391+  user_id INTEGER NOT NULL,
392+  path TEXT NOT NULL,
393+  refname TEXT,
394+  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
395+  updated_at DATETIME NOT NULL,
396+  UNIQUE (repo_id, path),
397+  CONSTRAINT repo_id_fk
398+  FOREIGN KEY(repo_id) REFERENCES repos(id)
399+  ON DELETE CASCADE
400+  ON UPDATE CASCADE,
401+  CONSTRAINT user_id_fk
402+  FOREIGN KEY(user_id) REFERENCES users(id)
403+  ON DELETE CASCADE
404+  ON UPDATE CASCADE
405+);
406+
407+CREATE TABLE IF NOT EXISTS access_tokens (
408+  id INTEGER primary key autoincrement,
409+  token text NOT NULL UNIQUE,
410+  name text NOT NULL,
411+  user_id INTEGER NOT NULL,
412+  expires_at DATETIME,
413+  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
414+  updated_at DATETIME NOT NULL,
415+  CONSTRAINT user_id_fk
416+  FOREIGN KEY (user_id) REFERENCES users(id)
417+  ON DELETE CASCADE
418+  ON UPDATE CASCADE
419+);
420diff --git a/server/db/migrate/0002_create_lfs_tables.go b/server/db/migrate/0002_create_lfs_tables.go
421deleted file mode 100644
422index 8d4ace82c1f425cdf77e0a06059485589e1fba29..0000000000000000000000000000000000000000
423--- a/server/db/migrate/0002_create_lfs_tables.go
424+++ /dev/null
425@@ -1,23 +0,0 @@
426-package migrate
427-
428-import (
429-	"context"
430-
431-	"github.com/charmbracelet/soft-serve/server/db"
432-)
433-
434-const (
435-	createLFSTablesName    = "create lfs tables"
436-	createLFSTablesVersion = 2
437-)
438-
439-var createLFSTables = Migration{
440-	Version: createLFSTablesVersion,
441-	Name:    createLFSTablesName,
442-	Migrate: func(ctx context.Context, tx *db.Tx) error {
443-		return migrateUp(ctx, tx, createLFSTablesVersion, createLFSTablesName)
444-	},
445-	Rollback: func(ctx context.Context, tx *db.Tx) error {
446-		return migrateDown(ctx, tx, createLFSTablesVersion, createLFSTablesName)
447-	},
448-}
449diff --git a/server/db/migrate/0002_create_lfs_tables_postgres.down.sql b/server/db/migrate/0002_create_lfs_tables_postgres.down.sql
450deleted file mode 100644
451index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
452--- a/server/db/migrate/0002_create_lfs_tables_postgres.down.sql
453+++ /dev/null
454diff --git a/server/db/migrate/0002_create_lfs_tables_postgres.up.sql b/server/db/migrate/0002_create_lfs_tables_postgres.up.sql
455deleted file mode 100644
456index 36391d30a3add57cd9c666cfa8e52135797ae8f3..0000000000000000000000000000000000000000
457--- a/server/db/migrate/0002_create_lfs_tables_postgres.up.sql
458+++ /dev/null
459@@ -1,32 +0,0 @@
460-CREATE TABLE IF NOT EXISTS lfs_objects (
461-  id SERIAL PRIMARY KEY,
462-  oid TEXT NOT NULL,
463-  size INTEGER NOT NULL,
464-  repo_id INTEGER NOT NULL,
465-  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
466-  updated_at TIMESTAMP NOT NULL,
467-  UNIQUE (oid, repo_id),
468-  CONSTRAINT repo_id_fk
469-  FOREIGN KEY(repo_id) REFERENCES repos(id)
470-  ON DELETE CASCADE
471-  ON UPDATE CASCADE
472-);
473-
474-CREATE TABLE IF NOT EXISTS lfs_locks (
475-  id SERIAL PRIMARY KEY,
476-  repo_id INTEGER NOT NULL,
477-  user_id INTEGER NOT NULL,
478-  path TEXT NOT NULL,
479-  refname TEXT,
480-  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
481-  updated_at TIMESTAMP NOT NULL,
482-  UNIQUE (repo_id, path),
483-  CONSTRAINT repo_id_fk
484-  FOREIGN KEY(repo_id) REFERENCES repos(id)
485-  ON DELETE CASCADE
486-  ON UPDATE CASCADE,
487-  CONSTRAINT user_id_fk
488-  FOREIGN KEY(user_id) REFERENCES users(id)
489-  ON DELETE CASCADE
490-  ON UPDATE CASCADE
491-);
492diff --git a/server/db/migrate/0002_create_lfs_tables_sqlite.down.sql b/server/db/migrate/0002_create_lfs_tables_sqlite.down.sql
493deleted file mode 100644
494index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
495--- a/server/db/migrate/0002_create_lfs_tables_sqlite.down.sql
496+++ /dev/null
497diff --git a/server/db/migrate/0002_create_lfs_tables_sqlite.up.sql b/server/db/migrate/0002_create_lfs_tables_sqlite.up.sql
498deleted file mode 100644
499index 0fdf70151afc1b4fe083c96c229ac83591dbf215..0000000000000000000000000000000000000000
500--- a/server/db/migrate/0002_create_lfs_tables_sqlite.up.sql
501+++ /dev/null
502@@ -1,32 +0,0 @@
503-CREATE TABLE IF NOT EXISTS lfs_objects (
504-  id INTEGER PRIMARY KEY AUTOINCREMENT,
505-  oid TEXT NOT NULL,
506-  size INTEGER NOT NULL,
507-  repo_id INTEGER NOT NULL,
508-  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
509-  updated_at DATETIME NOT NULL,
510-  UNIQUE (oid, repo_id),
511-  CONSTRAINT repo_id_fk
512-  FOREIGN KEY(repo_id) REFERENCES repos(id)
513-  ON DELETE CASCADE
514-  ON UPDATE CASCADE
515-);
516-
517-CREATE TABLE IF NOT EXISTS lfs_locks (
518-  id INTEGER PRIMARY KEY AUTOINCREMENT,
519-  repo_id INTEGER NOT NULL,
520-  user_id INTEGER NOT NULL,
521-  path TEXT NOT NULL,
522-  refname TEXT,
523-  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
524-  updated_at DATETIME NOT NULL,
525-  UNIQUE (repo_id, path),
526-  CONSTRAINT repo_id_fk
527-  FOREIGN KEY(repo_id) REFERENCES repos(id)
528-  ON DELETE CASCADE
529-  ON UPDATE CASCADE,
530-  CONSTRAINT user_id_fk
531-  FOREIGN KEY(user_id) REFERENCES users(id)
532-  ON DELETE CASCADE
533-  ON UPDATE CASCADE
534-);
535diff --git a/server/db/migrate/0003_password_tokens.go b/server/db/migrate/0003_password_tokens.go
536deleted file mode 100644
537index 2bafd57823490d225a3c394d06cbb08daade9b7f..0000000000000000000000000000000000000000
538--- a/server/db/migrate/0003_password_tokens.go
539+++ /dev/null
540@@ -1,23 +0,0 @@
541-package migrate
542-
543-import (
544-	"context"
545-
546-	"github.com/charmbracelet/soft-serve/server/db"
547-)
548-
549-const (
550-	passwordTokensName    = "password tokens"
551-	passwordTokensVersion = 3
552-)
553-
554-var passwordTokens = Migration{
555-	Version: passwordTokensVersion,
556-	Name:    passwordTokensName,
557-	Migrate: func(ctx context.Context, tx *db.Tx) error {
558-		return migrateUp(ctx, tx, passwordTokensVersion, passwordTokensName)
559-	},
560-	Rollback: func(ctx context.Context, tx *db.Tx) error {
561-		return migrateDown(ctx, tx, passwordTokensVersion, passwordTokensName)
562-	},
563-}
564diff --git a/server/db/migrate/0003_password_tokens_postgres.down.sql b/server/db/migrate/0003_password_tokens_postgres.down.sql
565deleted file mode 100644
566index e9e9b5362eac0c0902f547ebaa41b7f8877a6834..0000000000000000000000000000000000000000
567--- a/server/db/migrate/0003_password_tokens_postgres.down.sql
568+++ /dev/null
569@@ -1,2 +0,0 @@
570-ALTER TABLE users DROP COLUMN password;
571-
572diff --git a/server/db/migrate/0003_password_tokens_postgres.up.sql b/server/db/migrate/0003_password_tokens_postgres.up.sql
573deleted file mode 100644
574index 41e772b38f5a0bcced886a07e259263001a8db8b..0000000000000000000000000000000000000000
575--- a/server/db/migrate/0003_password_tokens_postgres.up.sql
576+++ /dev/null
577@@ -1,15 +0,0 @@
578-ALTER TABLE users ADD COLUMN password TEXT;
579-
580-CREATE TABLE IF NOT EXISTS access_tokens (
581-  id SERIAL PRIMARY KEY,
582-  name text NOT NULL,
583-  token TEXT NOT NULL UNIQUE,
584-  user_id INTEGER NOT NULL,
585-  expires_at TIMESTAMP,
586-  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
587-  updated_at TIMESTAMP NOT NULL,
588-  CONSTRAINT user_id_fk
589-  FOREIGN KEY (user_id) REFERENCES users(id)
590-  ON DELETE CASCADE
591-  ON UPDATE CASCADE
592-);
593diff --git a/server/db/migrate/0003_password_tokens_sqlite.down.sql b/server/db/migrate/0003_password_tokens_sqlite.down.sql
594deleted file mode 100644
595index aa2562cc04f86147ca60f82aae4e5734f9cd4443..0000000000000000000000000000000000000000
596--- a/server/db/migrate/0003_password_tokens_sqlite.down.sql
597+++ /dev/null
598@@ -1 +0,0 @@
599-ALTER TABLE users DROP COLUMN password;
600diff --git a/server/db/migrate/0003_password_tokens_sqlite.up.sql b/server/db/migrate/0003_password_tokens_sqlite.up.sql
601deleted file mode 100644
602index 56f2707fa61723d498a5cf54a6d7eb6c688f90ef..0000000000000000000000000000000000000000
603--- a/server/db/migrate/0003_password_tokens_sqlite.up.sql
604+++ /dev/null
605@@ -1,15 +0,0 @@
606-ALTER TABLE users ADD COLUMN password TEXT;
607-
608-CREATE TABLE IF NOT EXISTS access_tokens (
609-  id INTEGER primary key autoincrement,
610-  token text NOT NULL UNIQUE,
611-  name text NOT NULL,
612-  user_id INTEGER NOT NULL,
613-  expires_at DATETIME,
614-  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
615-  updated_at DATETIME NOT NULL,
616-  CONSTRAINT user_id_fk
617-  FOREIGN KEY (user_id) REFERENCES users(id)
618-  ON DELETE CASCADE
619-  ON UPDATE CASCADE
620-);
621diff --git a/server/db/migrate/0004_repo_owner.go b/server/db/migrate/0004_repo_owner.go
622deleted file mode 100644
623index 07ab4598b3baba6e0dfecd6f0ce329508ca3ee90..0000000000000000000000000000000000000000
624--- a/server/db/migrate/0004_repo_owner.go
625+++ /dev/null
626@@ -1,23 +0,0 @@
627-package migrate
628-
629-import (
630-	"context"
631-
632-	"github.com/charmbracelet/soft-serve/server/db"
633-)
634-
635-const (
636-	repoOwnerName    = "repo owner"
637-	repoOwnerVersion = 4
638-)
639-
640-var repoOwner = Migration{
641-	Version: repoOwnerVersion,
642-	Name:    repoOwnerName,
643-	Migrate: func(ctx context.Context, tx *db.Tx) error {
644-		return migrateUp(ctx, tx, repoOwnerVersion, repoOwnerName)
645-	},
646-	Rollback: func(ctx context.Context, tx *db.Tx) error {
647-		return migrateDown(ctx, tx, repoOwnerVersion, repoOwnerName)
648-	},
649-}
650diff --git a/server/db/migrate/0004_repo_owner_postgres.down.sql b/server/db/migrate/0004_repo_owner_postgres.down.sql
651deleted file mode 100644
652index cefbad5d53b9330bd98291c2f0853ff5a3b7a5ce..0000000000000000000000000000000000000000
653--- a/server/db/migrate/0004_repo_owner_postgres.down.sql
654+++ /dev/null
655@@ -1 +0,0 @@
656-ALTER TABLE repos DROP COLUMN user_id;
657diff --git a/server/db/migrate/0004_repo_owner_postgres.up.sql b/server/db/migrate/0004_repo_owner_postgres.up.sql
658deleted file mode 100644
659index c0a73d252849562eb111a90fb74a27e6954a1179..0000000000000000000000000000000000000000
660--- a/server/db/migrate/0004_repo_owner_postgres.up.sql
661+++ /dev/null
662@@ -1,14 +0,0 @@
663-ALTER TABLE repos ADD COLUMN user_id INTEGER;
664-
665-UPDATE repos SET user_id = (
666-  SELECT id FROM users WHERE admin = true ORDER BY id LIMIT 1
667-);
668-
669-ALTER TABLE repos
670-ALTER COLUMN user_id SET NOT NULL;
671-
672-ALTER TABLE repos
673-ADD CONSTRAINT user_id_fk
674-FOREIGN KEY(user_id) REFERENCES users(id)
675-ON DELETE CASCADE
676-ON UPDATE CASCADE;
677diff --git a/server/db/migrate/0004_repo_owner_sqlite.down.sql b/server/db/migrate/0004_repo_owner_sqlite.down.sql
678deleted file mode 100644
679index 785e28f6188b03635cf9ba6ae0c84e118a0c81eb..0000000000000000000000000000000000000000
680--- a/server/db/migrate/0004_repo_owner_sqlite.down.sql
681+++ /dev/null
682@@ -1 +0,0 @@
683-DROP TABLE IF EXISTS repos_old;
684diff --git a/server/db/migrate/0004_repo_owner_sqlite.up.sql b/server/db/migrate/0004_repo_owner_sqlite.up.sql
685deleted file mode 100644
686index 453dbe85ca9f5fc76a7772629031a1eeb25eebeb..0000000000000000000000000000000000000000
687--- a/server/db/migrate/0004_repo_owner_sqlite.up.sql
688+++ /dev/null
689@@ -1,25 +0,0 @@
690-ALTER TABLE repos RENAME TO repos_old;
691-
692-CREATE TABLE repos (
693-  id INTEGER PRIMARY KEY AUTOINCREMENT,
694-  name TEXT NOT NULL UNIQUE,
695-  project_name TEXT NOT NULL,
696-  description TEXT NOT NULL,
697-  private BOOLEAN NOT NULL,
698-  mirror BOOLEAN NOT NULL,
699-  hidden BOOLEAN NOT NULL,
700-  user_id INTEGER NOT NULL,
701-  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
702-  updated_at DATETIME NOT NULL,
703-  CONSTRAINT user_id_fk
704-  FOREIGN KEY(user_id) REFERENCES users(id)
705-  ON DELETE CASCADE
706-  ON UPDATE CASCADE
707-);
708-
709-INSERT INTO repos (id, name, project_name, description, private, mirror, hidden, user_id, created_at, updated_at)
710-SELECT id, name, project_name, description, private, mirror, hidden, (
711-  SELECT id FROM users WHERE admin = true ORDER BY id LIMIT 1
712-), created_at, updated_at
713-FROM repos_old;
714-
715diff --git a/server/db/migrate/migrations.go b/server/db/migrate/migrations.go
716index 482d61cad2b3e1e5a12e341264cbe43fc621d04a..88a9e434696ecdfe5ccb58d844d1f244d3bbfce5 100644
717--- a/server/db/migrate/migrations.go
718+++ b/server/db/migrate/migrations.go
719@@ -16,9 +16,6 @@ var sqls embed.FS
720 // Keep this in order of execution, oldest to newest.
721 var migrations = []Migration{
722 	createTables,
723-	createLFSTables,
724-	passwordTokens,
725-	repoOwner,
726 }
727 
728 func execMigration(ctx context.Context, tx *db.Tx, version int, name string, down bool) error {
729diff --git a/server/ssh/cmd/delete.go b/server/ssh/cmd/delete.go
730index b719ff53721f6cdd4a4cce0d3a4aab17ff8c99d5..7dad3d3f163f8371ea7061f2560392b2e32c1a14 100644
731--- a/server/ssh/cmd/delete.go
732+++ b/server/ssh/cmd/delete.go
733@@ -6,8 +6,6 @@ import (
734 )
735 
736 func deleteCommand() *cobra.Command {
737-	var lfs bool
738-
739 	cmd := &cobra.Command{
740 		Use:               "delete REPOSITORY",
741 		Aliases:           []string{"del", "remove", "rm"},
742@@ -19,11 +17,9 @@ func deleteCommand() *cobra.Command {
743 			be := backend.FromContext(ctx)
744 			name := args[0]
745 
746-			return be.DeleteRepository(ctx, name, lfs)
747+			return be.DeleteRepository(ctx, name)
748 		},
749 	}
750 
751-	cmd.Flags().BoolVarP(&lfs, "lfs", "", false, "Delete LFS objects")
752-
753 	return cmd
754 }
755diff --git a/testscript/testdata/repo-delete.txtar b/testscript/testdata/repo-delete.txtar
756index 55d41cd9cb96ce8ce3eff9798fc2493ed21efcee..2941dd48c252029887d21f7c81570b2968d6f1c8 100644
757--- a/testscript/testdata/repo-delete.txtar
758+++ b/testscript/testdata/repo-delete.txtar
759@@ -3,6 +3,7 @@
760 soft repo create repo1
761 soft repo create repo-to-delete
762 soft repo delete repo-to-delete
763-soft repo delete nope # repo delete never fails
764+! soft repo delete nope
765+stderr '.*not found.*'
766 soft repo list
767 stdout 'repo1'