refactor(cmd, db, git, project, ws): expando variable nameo

Amolith created

Change summary

cmd/willow.go      |   6 +-
db/migrations.go   |  32 +++++-----
db/posthooks.go    |  14 ++--
db/project.go      |  22 +++---
db/release.go      |  16 ++--
git/git.go         |  26 ++++----
project/project.go |  82 ++++++++++++++--------------
ws/ws.go           | 134 ++++++++++++++++++++++++------------------------
8 files changed, 166 insertions(+), 166 deletions(-)

Detailed changes

cmd/willow.go 🔗

@@ -99,17 +99,17 @@ func main() {
 		os.Exit(0)
 	}
 
-	mu := sync.Mutex{}
+	mutex := sync.Mutex{}
 
 	fmt.Println("Starting refresh loop")
-	go project.RefreshLoop(dbConn, &mu, config.FetchInterval, &manualRefresh, &req, &res)
+	go project.RefreshLoop(dbConn, &mutex, config.FetchInterval, &manualRefresh, &req, &res)
 
 	wsHandler := ws.Handler{
 		DbConn:        dbConn,
 		Req:           &req,
 		Res:           &res,
 		ManualRefresh: &manualRefresh,
-		Mu:            &mu,
+		Mu:            &mutex,
 		Version:       &version,
 	}
 

db/migrations.go 🔗

@@ -49,13 +49,13 @@ var migrations = [...]migration{
 }
 
 // Migrate runs all pending migrations.
-func Migrate(db *sql.DB) error {
-	version := getSchemaVersion(db)
+func Migrate(database *sql.DB) error {
+	version := getSchemaVersion(database)
 	for nextMigration := version + 1; nextMigration < len(migrations); nextMigration++ {
-		if err := runMigration(db, nextMigration); err != nil {
+		if err := runMigration(database, nextMigration); err != nil {
 			return fmt.Errorf("migrations failed: %w", err)
 		}
-		if version := getSchemaVersion(db); version != nextMigration {
+		if version := getSchemaVersion(database); version != nextMigration {
 			return fmt.Errorf("migration did not update version (expected %d, got %d)", nextMigration, version)
 		}
 	}
@@ -67,31 +67,31 @@ func Migrate(db *sql.DB) error {
 // transaction if unsuccessful.
 func runMigration(db *sql.DB, migrationIdx int) (err error) {
 	current := migrations[migrationIdx]
-	tx, err := db.BeginTx(context.Background(), &sql.TxOptions{})
+	transaction, err := db.BeginTx(context.Background(), &sql.TxOptions{})
 	if err != nil {
 		return fmt.Errorf("failed opening transaction for migration %d: %w", migrationIdx, err)
 	}
 	defer func() {
 		if err == nil {
-			err = tx.Commit()
+			err = transaction.Commit()
 		}
 		if err != nil {
-			if rbErr := tx.Rollback(); rbErr != nil {
+			if rbErr := transaction.Rollback(); rbErr != nil {
 				err = fmt.Errorf("failed rolling back: %w due to: %w", rbErr, err)
 			}
 		}
 	}()
 	if len(current.upQuery) > 0 {
-		if _, err := tx.Exec(current.upQuery); err != nil {
+		if _, err := transaction.Exec(current.upQuery); err != nil {
 			return fmt.Errorf("failed running migration %d: %w", migrationIdx, err)
 		}
 	}
 	if current.postHook != nil {
-		if err := current.postHook(tx); err != nil {
+		if err := current.postHook(transaction); err != nil {
 			return fmt.Errorf("failed running posthook for migration %d: %w", migrationIdx, err)
 		}
 	}
-	return updateSchemaVersion(tx, migrationIdx)
+	return updateSchemaVersion(transaction, migrationIdx)
 }
 
 // undoMigration rolls the single most recent migration back inside a
@@ -99,28 +99,28 @@ func runMigration(db *sql.DB, migrationIdx int) (err error) {
 // successful, and rolls back the transaction if unsuccessful.
 //
 //lint:ignore U1000 Will be used when #34 is implemented (https://todo.sr.ht/~amolith/willow/34)
-func undoMigration(db *sql.DB, migrationIdx int) (err error) {
+func undoMigration(database *sql.DB, migrationIdx int) (err error) {
 	current := migrations[migrationIdx]
-	tx, err := db.BeginTx(context.Background(), &sql.TxOptions{})
+	transaction, err := database.BeginTx(context.Background(), &sql.TxOptions{})
 	if err != nil {
 		return fmt.Errorf("failed opening undo transaction for migration %d: %w", migrationIdx, err)
 	}
 	defer func() {
 		if err == nil {
-			err = tx.Commit()
+			err = transaction.Commit()
 		}
 		if err != nil {
-			if rbErr := tx.Rollback(); rbErr != nil {
+			if rbErr := transaction.Rollback(); rbErr != nil {
 				err = fmt.Errorf("failed rolling back: %w due to: %w", rbErr, err)
 			}
 		}
 	}()
 	if len(current.downQuery) > 0 {
-		if _, err := tx.Exec(current.downQuery); err != nil {
+		if _, err := transaction.Exec(current.downQuery); err != nil {
 			return fmt.Errorf("failed undoing migration %d: %w", migrationIdx, err)
 		}
 	}
-	return updateSchemaVersion(tx, migrationIdx-1)
+	return updateSchemaVersion(transaction, migrationIdx-1)
 }
 
 // getSchemaVersion returns the schema version from the database.

db/posthooks.go 🔗

@@ -14,10 +14,10 @@ import (
 // projects_tmp, loops through the rows generating a repeatable ID for each
 // project, and inserting it into the new table along with the data from the old
 // table.
-func generateAndInsertProjectIDs(tx *sql.Tx) error {
+func generateAndInsertProjectIDs(transaction *sql.Tx) error {
 	// Loop through projects_tmp, generate a project_id for each, and insert
 	// into projects
-	rows, err := tx.Query("SELECT url, name, forge, version, created_at FROM projects_tmp")
+	rows, err := transaction.Query("SELECT url, name, forge, version, created_at FROM projects_tmp")
 	if err != nil {
 		return fmt.Errorf("failed to list projects in projects_tmp: %w", err)
 	}
@@ -35,7 +35,7 @@ func generateAndInsertProjectIDs(tx *sql.Tx) error {
 			return fmt.Errorf("failed to scan row from projects_tmp: %w", err)
 		}
 		id := fmt.Sprintf("%x", sha256.Sum256([]byte(url+name+forge+created_at)))
-		_, err = tx.Exec(
+		_, err = transaction.Exec(
 			"INSERT INTO projects (id, url, name, forge, version, created_at) VALUES (@id, @url, @name, @forge, @version, @created_at)",
 			sql.Named("id", id),
 			sql.Named("url", url),
@@ -49,7 +49,7 @@ func generateAndInsertProjectIDs(tx *sql.Tx) error {
 		}
 	}
 
-	if _, err := tx.Exec("DROP TABLE projects_tmp"); err != nil {
+	if _, err := transaction.Exec("DROP TABLE projects_tmp"); err != nil {
 		return fmt.Errorf("failed to drop projects_tmp: %w", err)
 	}
 
@@ -61,8 +61,8 @@ func generateAndInsertProjectIDs(tx *sql.Tx) error {
 }
 
 // Basing the project's ID on when it was created (L37) was a bad idea.
-func correctProjectIDs(tx *sql.Tx) error {
-	rows, err := tx.Query("SELECT id, url, name, forge FROM projects")
+func correctProjectIDs(transaction *sql.Tx) error {
+	rows, err := transaction.Query("SELECT id, url, name, forge FROM projects")
 	if err != nil {
 		return fmt.Errorf("failed to list projects in projects_tmp: %w", err)
 	}
@@ -79,7 +79,7 @@ func correctProjectIDs(tx *sql.Tx) error {
 			return fmt.Errorf("failed to scan row from projects_tmp: %w", err)
 		}
 		id := fmt.Sprintf("%x", sha256.Sum256([]byte(url+name+forge)))
-		_, err = tx.Exec(
+		_, err = transaction.Exec(
 			"UPDATE projects SET id = @id WHERE id = @old_id",
 			sql.Named("id", id),
 			sql.Named("old_id", old_id),

db/project.go 🔗

@@ -11,26 +11,26 @@ import (
 )
 
 // DeleteProject deletes a project from the database.
-func DeleteProject(db *sql.DB, mu *sync.Mutex, id string) error {
+func DeleteProject(database *sql.DB, mu *sync.Mutex, projID string) error {
 	mu.Lock()
 	defer mu.Unlock()
-	_, err := db.Exec("DELETE FROM projects WHERE id = ?", id)
+	_, err := database.Exec("DELETE FROM projects WHERE id = ?", projID)
 	if err != nil {
 		return err
 	}
-	_, err = db.Exec("DELETE FROM releases WHERE project_id = ?", id)
+	_, err = database.Exec("DELETE FROM releases WHERE project_id = ?", projID)
 	return err
 }
 
 // GetProject returns a project from the database.
-func GetProject(db *sql.DB, id string) (map[string]string, error) {
+func GetProject(db *sql.DB, projID string) (map[string]string, error) {
 	var name, forge, url, version string
-	err := db.QueryRow("SELECT name, forge, url, version FROM projects WHERE id = ?", id).Scan(&name, &forge, &url, &version)
+	err := db.QueryRow("SELECT name, forge, url, version FROM projects WHERE id = ?", projID).Scan(&name, &forge, &url, &version)
 	if err != nil {
 		return nil, err
 	}
 	project := map[string]string{
-		"id":      id,
+		"id":      projID,
 		"name":    name,
 		"url":     url,
 		"forge":   forge,
@@ -40,7 +40,7 @@ func GetProject(db *sql.DB, id string) (map[string]string, error) {
 }
 
 // UpsertProject adds or updates a project in the database.
-func UpsertProject(db *sql.DB, mu *sync.Mutex, id, url, name, forge, running string) error {
+func UpsertProject(db *sql.DB, mu *sync.Mutex, projID, url, name, forge, running string) error {
 	mu.Lock()
 	defer mu.Unlock()
 	_, err := db.Exec(`INSERT INTO projects (id, url, name, forge, version)
@@ -49,7 +49,7 @@ func UpsertProject(db *sql.DB, mu *sync.Mutex, id, url, name, forge, running str
 			UPDATE SET
 				name = excluded.name,
 				forge = excluded.forge,
-				version = excluded.version;`, id, url, name, forge, running)
+				version = excluded.version;`, projID, url, name, forge, running)
 	return err
 }
 
@@ -63,13 +63,13 @@ func GetProjects(db *sql.DB) ([]map[string]string, error) {
 
 	var projects []map[string]string
 	for rows.Next() {
-		var id, name, url, forge, version string
-		err = rows.Scan(&id, &name, &url, &forge, &version)
+		var projID, name, url, forge, version string
+		err = rows.Scan(&projID, &name, &url, &forge, &version)
 		if err != nil {
 			return nil, err
 		}
 		project := map[string]string{
-			"id":      id,
+			"id":      projID,
 			"name":    name,
 			"url":     url,
 			"forge":   forge,

db/release.go 🔗

@@ -12,7 +12,7 @@ import (
 
 // UpsertRelease adds or updates a release for a project with a given ID in the
 // database.
-func UpsertRelease(db *sql.DB, mu *sync.Mutex, id, projectID, url, tag, content, date string) error {
+func UpsertRelease(db *sql.DB, mu *sync.Mutex, relID, projID, url, tag, content, date string) error {
 	mu.Lock()
 	defer mu.Unlock()
 	_, err := db.Exec(`INSERT INTO releases (id, project_id, url, tag, content, date)
@@ -23,13 +23,13 @@ func UpsertRelease(db *sql.DB, mu *sync.Mutex, id, projectID, url, tag, content,
 				content = excluded.content,
 				tag = excluded.tag,
 				content = excluded.content,
-				date = excluded.date;`, id, projectID, url, tag, content, date)
+				date = excluded.date;`, relID, projID, url, tag, content, date)
 	return err
 }
 
 // GetReleases returns all releases for a project with a given id from the database.
-func GetReleases(db *sql.DB, projectID string) ([]map[string]string, error) {
-	rows, err := db.Query(`SELECT id, url, tag, content, date FROM releases WHERE project_id = ?`, projectID)
+func GetReleases(db *sql.DB, projID string) ([]map[string]string, error) {
+	rows, err := db.Query(`SELECT id, url, tag, content, date FROM releases WHERE project_id = ?`, projID)
 	if err != nil {
 		return nil, err
 	}
@@ -38,19 +38,19 @@ func GetReleases(db *sql.DB, projectID string) ([]map[string]string, error) {
 	releases := make([]map[string]string, 0)
 	for rows.Next() {
 		var (
-			id      string
+			relID   string
 			url     string
 			tag     string
 			content string
 			date    string
 		)
-		err := rows.Scan(&id, &url, &tag, &content, &date)
+		err := rows.Scan(&relID, &url, &tag, &content, &date)
 		if err != nil {
 			return nil, err
 		}
 		releases = append(releases, map[string]string{
-			"id":         id,
-			"project_id": projectID,
+			"id":         relID,
+			"project_id": projID,
 			"url":        url,
 			"tag":        tag,
 			"content":    content,

git/git.go 🔗

@@ -41,11 +41,11 @@ var (
 // GetReleases fetches all releases in a remote repository, whether HTTP(S) or
 // SSH.
 func GetReleases(gitURI, forge string) ([]Release, error) {
-	r, err := minimalClone(gitURI)
+	repo, err := minimalClone(gitURI)
 	if err != nil {
 		return nil, err
 	}
-	tagRefs, err := r.Tags()
+	tagRefs, err := repo.Tags()
 	if err != nil {
 		return nil, err
 	}
@@ -63,12 +63,12 @@ func GetReleases(gitURI, forge string) ([]Release, error) {
 	releases := make([]Release, 0)
 
 	err = tagRefs.ForEach(func(tagRef *plumbing.Reference) error {
-		tagObj, err := r.TagObject(tagRef.Hash())
+		tagObj, err := repo.TagObject(tagRef.Hash())
 
 		var message string
 		var date time.Time
 		if errors.Is(err, plumbing.ErrObjectNotFound) {
-			commitTag, err := r.CommitObject(tagRef.Hash())
+			commitTag, err := repo.CommitObject(tagRef.Hash())
 			if err != nil {
 				return err
 			}
@@ -112,28 +112,28 @@ func minimalClone(url string) (*git.Repository, error) {
 		return nil, err
 	}
 
-	r, err := git.PlainOpen(path)
+	repo, err := git.PlainOpen(path)
 	if err == nil {
-		err = r.Fetch(&git.FetchOptions{
+		err = repo.Fetch(&git.FetchOptions{
 			RemoteName: "origin",
 			Depth:      1,
 			Tags:       git.AllTags,
 		})
 		if errors.Is(err, git.NoErrAlreadyUpToDate) {
-			return r, nil
+			return repo, nil
 		}
-		return r, err
+		return repo, err
 	} else if !errors.Is(err, git.ErrRepositoryNotExists) {
 		return nil, err
 	}
 
-	r, err = git.PlainClone(path, false, &git.CloneOptions{
+	repo, err = git.PlainClone(path, false, &git.CloneOptions{
 		URL:          url,
 		SingleBranch: true,
 		NoCheckout:   true,
 		Depth:        1,
 	})
-	return r, err
+	return repo, err
 }
 
 // RemoveRepo removes a repository from the local filesystem.
@@ -173,16 +173,16 @@ func stringifyRepo(url string) (string, error) {
 	url = strings.TrimSuffix(url, ".git")
 	url = strings.TrimSuffix(url, "/")
 
-	ep, err := transport.NewEndpoint(url)
+	endpoint, err := transport.NewEndpoint(url)
 	if err != nil {
 		return "", err
 	}
 
-	switch ep.Protocol {
+	switch endpoint.Protocol {
 	case "http", "https":
 		return "data/" + strings.Split(url, "://")[1], nil
 	case "ssh":
-		return "data/" + ep.Host + "/" + ep.Path, nil
+		return "data/" + endpoint.Host + "/" + endpoint.Path, nil
 	default:
 		return "", errors.New("unsupported protocol")
 	}

project/project.go 🔗

@@ -41,7 +41,7 @@ type Release struct {
 }
 
 // GetReleases returns a list of all releases for a project from the database.
-func GetReleases(dbConn *sql.DB, mu *sync.Mutex, proj Project) (Project, error) {
+func GetReleases(dbConn *sql.DB, mutex *sync.Mutex, proj Project) (Project, error) {
 	proj.ID = GenProjectID(proj.URL, proj.Name, proj.Forge)
 
 	ret, err := db.GetReleases(dbConn, proj.ID)
@@ -50,7 +50,7 @@ func GetReleases(dbConn *sql.DB, mu *sync.Mutex, proj Project) (Project, error)
 	}
 
 	if len(ret) == 0 {
-		return fetchReleases(dbConn, mu, proj)
+		return fetchReleases(dbConn, mutex, proj)
 	}
 
 	for _, row := range ret {
@@ -68,51 +68,51 @@ func GetReleases(dbConn *sql.DB, mu *sync.Mutex, proj Project) (Project, error)
 }
 
 // fetchReleases fetches releases from a project's forge given its URI.
-func fetchReleases(dbConn *sql.DB, mu *sync.Mutex, p Project) (Project, error) {
+func fetchReleases(dbConn *sql.DB, mutex *sync.Mutex, project Project) (Project, error) {
 	var err error
-	switch p.Forge {
+	switch project.Forge {
 	case "github", "gitea", "forgejo":
-		rssReleases, err := rss.GetReleases(p.URL)
+		rssReleases, err := rss.GetReleases(project.URL)
 		if err != nil {
 			fmt.Println("Error getting RSS releases:", err)
-			return p, err
+			return project, err
 		}
 		for _, release := range rssReleases {
-			p.Releases = append(p.Releases, Release{
-				ID:      GenReleaseID(p.URL, release.URL, release.Tag),
+			project.Releases = append(project.Releases, Release{
+				ID:      GenReleaseID(project.URL, release.URL, release.Tag),
 				Tag:     release.Tag,
 				Content: release.Content,
 				URL:     release.URL,
 				Date:    release.Date,
 			})
-			err = upsertReleases(dbConn, mu, p.ID, p.Releases)
+			err = upsertReleases(dbConn, mutex, project.ID, project.Releases)
 			if err != nil {
 				log.Printf("Error upserting release: %v", err)
-				return p, err
+				return project, err
 			}
 		}
 	default:
-		gitReleases, err := git.GetReleases(p.URL, p.Forge)
+		gitReleases, err := git.GetReleases(project.URL, project.Forge)
 		if err != nil {
-			return p, err
+			return project, err
 		}
 		for _, release := range gitReleases {
-			p.Releases = append(p.Releases, Release{
-				ID:      GenReleaseID(p.URL, release.URL, release.Tag),
+			project.Releases = append(project.Releases, Release{
+				ID:      GenReleaseID(project.URL, release.URL, release.Tag),
 				Tag:     release.Tag,
 				Content: release.Content,
 				URL:     release.URL,
 				Date:    release.Date,
 			})
-			err = upsertReleases(dbConn, mu, p.ID, p.Releases)
+			err = upsertReleases(dbConn, mutex, project.ID, project.Releases)
 			if err != nil {
 				log.Printf("Error upserting release: %v", err)
-				return p, err
+				return project, err
 			}
 		}
 	}
-	p.Releases = SortReleases(p.Releases)
-	return p, err
+	project.Releases = SortReleases(project.Releases)
+	return project, err
 }
 
 func SortReleases(releases []Release) []Release {
@@ -130,10 +130,10 @@ func SortProjects(projects []Project) []Project {
 }
 
 // upsertReleases updates or inserts a release in the database.
-func upsertReleases(dbConn *sql.DB, mu *sync.Mutex, projID string, releases []Release) error {
+func upsertReleases(dbConn *sql.DB, mutex *sync.Mutex, projID string, releases []Release) error {
 	for _, release := range releases {
 		date := release.Date.Format("2006-01-02 15:04:05")
-		err := db.UpsertRelease(dbConn, mu, release.ID, projID, release.URL, release.Tag, release.Content, date)
+		err := db.UpsertRelease(dbConn, mutex, release.ID, projID, release.URL, release.Tag, release.Content, date)
 		if err != nil {
 			log.Printf("Error upserting release: %v", err)
 			return err
@@ -154,22 +154,22 @@ func GenProjectID(url, name, forge string) string {
 	return fmt.Sprintf("%x", idByte)
 }
 
-func Track(dbConn *sql.DB, mu *sync.Mutex, manualRefresh *chan struct{}, name, url, forge, release string) {
+func Track(dbConn *sql.DB, mutex *sync.Mutex, manualRefresh *chan struct{}, name, url, forge, release string) {
 	id := GenProjectID(url, name, forge)
-	err := db.UpsertProject(dbConn, mu, id, url, name, forge, release)
+	err := db.UpsertProject(dbConn, mutex, id, url, name, forge, release)
 	if err != nil {
 		fmt.Println("Error upserting project:", err)
 	}
 	*manualRefresh <- struct{}{}
 }
 
-func Untrack(dbConn *sql.DB, mu *sync.Mutex, id string) {
+func Untrack(dbConn *sql.DB, mutex *sync.Mutex, id string) {
 	proj, err := db.GetProject(dbConn, id)
 	if err != nil {
 		fmt.Println("Error getting project:", err)
 	}
 
-	err = db.DeleteProject(dbConn, mu, proj["id"])
+	err = db.DeleteProject(dbConn, mutex, proj["id"])
 	if err != nil {
 		fmt.Println("Error deleting project:", err)
 	}
@@ -182,7 +182,7 @@ func Untrack(dbConn *sql.DB, mu *sync.Mutex, id string) {
 	}
 }
 
-func RefreshLoop(dbConn *sql.DB, mu *sync.Mutex, interval int, manualRefresh, req *chan struct{}, res *chan []Project) {
+func RefreshLoop(dbConn *sql.DB, mutex *sync.Mutex, interval int, manualRefresh, req *chan struct{}, res *chan []Project) {
 	ticker := time.NewTicker(time.Second * time.Duration(interval))
 
 	fetch := func() []Project {
@@ -190,19 +190,19 @@ func RefreshLoop(dbConn *sql.DB, mu *sync.Mutex, interval int, manualRefresh, re
 		if err != nil {
 			fmt.Println("Error getting projects:", err)
 		}
-		for i, p := range projectsList {
-			p, err := fetchReleases(dbConn, mu, p)
+		for idx, project := range projectsList {
+			p, err := fetchReleases(dbConn, mutex, project)
 			if err != nil {
 				fmt.Println(err)
 				continue
 			}
-			projectsList[i] = p
+			projectsList[idx] = p
 		}
 		sort.Slice(projectsList, func(i, j int) bool {
 			return strings.ToLower(projectsList[i].Name) < strings.ToLower(projectsList[j].Name)
 		})
 		for i := range projectsList {
-			err = upsertReleases(dbConn, mu, projectsList[i].ID, projectsList[i].Releases)
+			err = upsertReleases(dbConn, mutex, projectsList[i].ID, projectsList[i].Releases)
 			if err != nil {
 				fmt.Println("Error upserting release:", err)
 				continue
@@ -236,24 +236,24 @@ func GetProject(dbConn *sql.DB, proj Project) (Project, error) {
 	} else if err != nil {
 		return proj, err
 	}
-	p := Project{
+	project := Project{
 		ID:      proj.ID,
 		URL:     proj.URL,
 		Name:    proj.Name,
 		Forge:   proj.Forge,
 		Running: projectDB["version"],
 	}
-	return p, err
+	return project, err
 }
 
 // GetProjectWithReleases returns a single project from the database along with its releases.
-func GetProjectWithReleases(dbConn *sql.DB, mu *sync.Mutex, proj Project) (Project, error) {
+func GetProjectWithReleases(dbConn *sql.DB, mutex *sync.Mutex, proj Project) (Project, error) {
 	project, err := GetProject(dbConn, proj)
 	if err != nil {
 		return Project{}, err
 	}
 
-	return GetReleases(dbConn, mu, project)
+	return GetReleases(dbConn, mutex, project)
 }
 
 // GetProjects returns a list of all projects from the database.
@@ -264,13 +264,13 @@ func GetProjects(dbConn *sql.DB) ([]Project, error) {
 	}
 
 	projects := make([]Project, len(projectsDB))
-	for i, p := range projectsDB {
+	for i, project := range projectsDB {
 		projects[i] = Project{
-			ID:      p["id"],
-			URL:     p["url"],
-			Name:    p["name"],
-			Forge:   p["forge"],
-			Running: p["version"],
+			ID:      project["id"],
+			URL:     project["url"],
+			Name:    project["name"],
+			Forge:   project["forge"],
+			Running: project["version"],
 		}
 	}
 
@@ -279,14 +279,14 @@ func GetProjects(dbConn *sql.DB) ([]Project, error) {
 
 // GetProjectsWithReleases returns a list of all projects and all their releases
 // from the database.
-func GetProjectsWithReleases(dbConn *sql.DB, mu *sync.Mutex) ([]Project, error) {
+func GetProjectsWithReleases(dbConn *sql.DB, mutex *sync.Mutex) ([]Project, error) {
 	projects, err := GetProjects(dbConn)
 	if err != nil {
 		return nil, err
 	}
 
 	for i := range projects {
-		projects[i], err = GetReleases(dbConn, mu, projects[i])
+		projects[i], err = GetReleases(dbConn, mutex, projects[i])
 		if err != nil {
 			return nil, err
 		}

ws/ws.go 🔗

@@ -32,20 +32,20 @@ type Handler struct {
 }
 
 //go:embed static
-var fs embed.FS
+var staticFSEmbed embed.FS
 
 var bmStrict = bluemonday.StrictPolicy()
 
-func (h Handler) RootHandler(w http.ResponseWriter, r *http.Request) {
-	if !h.isAuthorised(r) {
-		http.Redirect(w, r, "/login", http.StatusSeeOther)
+func (h Handler) RootHandler(writer http.ResponseWriter, request *http.Request) {
+	if !h.isAuthorised(request) {
+		http.Redirect(writer, request, "/login", http.StatusSeeOther)
 		return
 	}
 	projectsWithReleases, err := project.GetProjectsWithReleases(h.DbConn, h.Mu)
 	if err != nil {
 		fmt.Println(err)
-		w.WriteHeader(http.StatusInternalServerError)
-		_, err := w.Write([]byte("Internal Server Error"))
+		writer.WriteHeader(http.StatusInternalServerError)
+		_, err := writer.Write([]byte("Internal Server Error"))
 		if err != nil {
 			fmt.Println(err)
 		}
@@ -62,32 +62,32 @@ func (h Handler) RootHandler(w http.ResponseWriter, r *http.Request) {
 		IsDashboard: true,
 	}
 
-	tmpl := template.Must(template.ParseFS(fs, "static/dashboard.html.tmpl", "static/head.html.tmpl", "static/header.html.tmpl", "static/footer.html.tmpl"))
-	if err := tmpl.Execute(w, data); err != nil {
+	tmpl := template.Must(template.ParseFS(staticFSEmbed, "static/dashboard.html.tmpl", "static/head.html.tmpl", "static/header.html.tmpl", "static/footer.html.tmpl"))
+	if err := tmpl.Execute(writer, data); err != nil {
 		fmt.Println(err)
 	}
 }
 
-func (h Handler) NewHandler(w http.ResponseWriter, r *http.Request) {
-	if !h.isAuthorised(r) {
-		http.Redirect(w, r, "/login", http.StatusSeeOther)
+func (h Handler) NewHandler(writer http.ResponseWriter, request *http.Request) {
+	if !h.isAuthorised(request) {
+		http.Redirect(writer, request, "/login", http.StatusSeeOther)
 		return
 	}
-	params := r.URL.Query()
+	params := request.URL.Query()
 	action := bmStrict.Sanitize(params.Get("action"))
-	if r.Method == http.MethodGet {
+	if request.Method == http.MethodGet {
 		switch action {
 		case "":
 			data := struct{ Version string }{Version: *h.Version}
-			tmpl := template.Must(template.ParseFS(fs, "static/new.html.tmpl", "static/head.html.tmpl", "static/header.html.tmpl", "static/footer.html.tmpl"))
-			if err := tmpl.Execute(w, data); err != nil {
+			tmpl := template.Must(template.ParseFS(staticFSEmbed, "static/new.html.tmpl", "static/head.html.tmpl", "static/header.html.tmpl", "static/footer.html.tmpl"))
+			if err := tmpl.Execute(writer, data); err != nil {
 				fmt.Println(err)
 			}
 		case "delete":
 			submittedID := params.Get("id")
 			if submittedID == "" {
-				w.WriteHeader(http.StatusBadRequest)
-				_, err := w.Write([]byte("No URL provided"))
+				writer.WriteHeader(http.StatusBadRequest)
+				_, err := writer.Write([]byte("No URL provided"))
 				if err != nil {
 					fmt.Println(err)
 				}
@@ -95,12 +95,12 @@ func (h Handler) NewHandler(w http.ResponseWriter, r *http.Request) {
 			}
 
 			project.Untrack(h.DbConn, h.Mu, submittedID)
-			http.Redirect(w, r, "/", http.StatusSeeOther)
+			http.Redirect(writer, request, "/", http.StatusSeeOther)
 		default:
 			submittedURL := bmStrict.Sanitize(params.Get("url"))
 			if submittedURL == "" {
-				w.WriteHeader(http.StatusBadRequest)
-				_, err := w.Write([]byte("No URL provided"))
+				writer.WriteHeader(http.StatusBadRequest)
+				_, err := writer.Write([]byte("No URL provided"))
 				if err != nil {
 					fmt.Println(err)
 				}
@@ -109,8 +109,8 @@ func (h Handler) NewHandler(w http.ResponseWriter, r *http.Request) {
 
 			forge := bmStrict.Sanitize(params.Get("forge"))
 			if forge == "" {
-				w.WriteHeader(http.StatusBadRequest)
-				_, err := w.Write([]byte("No forge provided"))
+				writer.WriteHeader(http.StatusBadRequest)
+				_, err := writer.Write([]byte("No forge provided"))
 				if err != nil {
 					fmt.Println(err)
 				}
@@ -119,8 +119,8 @@ func (h Handler) NewHandler(w http.ResponseWriter, r *http.Request) {
 
 			name := bmStrict.Sanitize(params.Get("name"))
 			if name == "" {
-				w.WriteHeader(http.StatusBadRequest)
-				_, err := w.Write([]byte("No name provided"))
+				writer.WriteHeader(http.StatusBadRequest)
+				_, err := writer.Write([]byte("No name provided"))
 				if err != nil {
 					fmt.Println(err)
 				}
@@ -136,8 +136,8 @@ func (h Handler) NewHandler(w http.ResponseWriter, r *http.Request) {
 
 			proj, err := project.GetProject(h.DbConn, proj)
 			if err != nil && !errors.Is(err, sql.ErrNoRows) {
-				w.WriteHeader(http.StatusBadRequest)
-				_, err := w.Write(fmt.Appendf(nil, "Error getting project: %s", err))
+				writer.WriteHeader(http.StatusBadRequest)
+				_, err := writer.Write(fmt.Appendf(nil, "Error getting project: %s", err))
 				if err != nil {
 					fmt.Println(err)
 				}
@@ -146,8 +146,8 @@ func (h Handler) NewHandler(w http.ResponseWriter, r *http.Request) {
 
 			proj, err = project.GetReleases(h.DbConn, h.Mu, proj)
 			if err != nil {
-				w.WriteHeader(http.StatusBadRequest)
-				_, err := w.Write(fmt.Appendf(nil, "Error getting releases: %s", err))
+				writer.WriteHeader(http.StatusBadRequest)
+				_, err := writer.Write(fmt.Appendf(nil, "Error getting releases: %s", err))
 				if err != nil {
 					fmt.Println(err)
 				}
@@ -162,49 +162,49 @@ func (h Handler) NewHandler(w http.ResponseWriter, r *http.Request) {
 				Project: proj,
 			}
 
-			tmpl := template.Must(template.ParseFS(fs, "static/select-release.html.tmpl", "static/head.html.tmpl", "static/header.html.tmpl", "static/footer.html.tmpl"))
-			if err := tmpl.Execute(w, data); err != nil {
+			tmpl := template.Must(template.ParseFS(staticFSEmbed, "static/select-release.html.tmpl", "static/head.html.tmpl", "static/header.html.tmpl", "static/footer.html.tmpl"))
+			if err := tmpl.Execute(writer, data); err != nil {
 				fmt.Println(err)
 			}
 		}
 	}
 
-	if r.Method == http.MethodPost {
-		err := r.ParseForm()
+	if request.Method == http.MethodPost {
+		err := request.ParseForm()
 		if err != nil {
 			fmt.Println(err)
 		}
-		idValue := bmStrict.Sanitize(r.FormValue("id"))
-		nameValue := bmStrict.Sanitize(r.FormValue("name"))
-		urlValue := bmStrict.Sanitize(r.FormValue("url"))
-		forgeValue := bmStrict.Sanitize(r.FormValue("forge"))
-		releaseValue := bmStrict.Sanitize(r.FormValue("release"))
+		idValue := bmStrict.Sanitize(request.FormValue("id"))
+		nameValue := bmStrict.Sanitize(request.FormValue("name"))
+		urlValue := bmStrict.Sanitize(request.FormValue("url"))
+		forgeValue := bmStrict.Sanitize(request.FormValue("forge"))
+		releaseValue := bmStrict.Sanitize(request.FormValue("release"))
 
 		// If releaseValue is not empty, we're updating an existing project
 		if idValue != "" && nameValue != "" && urlValue != "" && forgeValue != "" && releaseValue != "" {
 			project.Track(h.DbConn, h.Mu, h.ManualRefresh, nameValue, urlValue, forgeValue, releaseValue)
-			http.Redirect(w, r, "/", http.StatusSeeOther)
+			http.Redirect(writer, request, "/", http.StatusSeeOther)
 			return
 		}
 
 		// If releaseValue is empty, we're creating a new project
 		if idValue == "" && nameValue != "" && urlValue != "" && forgeValue != "" && releaseValue == "" {
-			http.Redirect(w, r, "/new?action=yoink&name="+url.QueryEscape(nameValue)+"&url="+url.QueryEscape(urlValue)+"&forge="+url.QueryEscape(forgeValue), http.StatusSeeOther)
+			http.Redirect(writer, request, "/new?action=yoink&name="+url.QueryEscape(nameValue)+"&url="+url.QueryEscape(urlValue)+"&forge="+url.QueryEscape(forgeValue), http.StatusSeeOther)
 			return
 		}
 
-		w.WriteHeader(http.StatusBadRequest)
-		_, err = w.Write([]byte("No data provided"))
+		writer.WriteHeader(http.StatusBadRequest)
+		_, err = writer.Write([]byte("No data provided"))
 		if err != nil {
 			fmt.Println(err)
 		}
 	}
 }
 
-func (h Handler) LoginHandler(w http.ResponseWriter, r *http.Request) {
-	if r.Method == http.MethodGet {
-		if h.isAuthorised(r) {
-			http.Redirect(w, r, "/", http.StatusSeeOther)
+func (h Handler) LoginHandler(writer http.ResponseWriter, request *http.Request) {
+	if request.Method == http.MethodGet {
+		if h.isAuthorised(request) {
+			http.Redirect(writer, request, "/", http.StatusSeeOther)
 			return
 		}
 
@@ -213,23 +213,23 @@ func (h Handler) LoginHandler(w http.ResponseWriter, r *http.Request) {
 		}{
 			Version: *h.Version,
 		}
-		tmpl := template.Must(template.ParseFS(fs, "static/login.html.tmpl", "static/head.html.tmpl", "static/footer.html.tmpl"))
-		if err := tmpl.Execute(w, data); err != nil {
+		tmpl := template.Must(template.ParseFS(staticFSEmbed, "static/login.html.tmpl", "static/head.html.tmpl", "static/footer.html.tmpl"))
+		if err := tmpl.Execute(writer, data); err != nil {
 			fmt.Println(err)
 		}
 	}
 
-	if r.Method == http.MethodPost {
-		err := r.ParseForm()
+	if request.Method == http.MethodPost {
+		err := request.ParseForm()
 		if err != nil {
 			fmt.Println(err)
 		}
-		username := bmStrict.Sanitize(r.FormValue("username"))
-		password := bmStrict.Sanitize(r.FormValue("password"))
+		username := bmStrict.Sanitize(request.FormValue("username"))
+		password := bmStrict.Sanitize(request.FormValue("password"))
 
 		if username == "" || password == "" {
-			w.WriteHeader(http.StatusBadRequest)
-			_, err := w.Write([]byte("No data provided"))
+			writer.WriteHeader(http.StatusBadRequest)
+			_, err := writer.Write([]byte("No data provided"))
 			if err != nil {
 				fmt.Println(err)
 			}
@@ -238,8 +238,8 @@ func (h Handler) LoginHandler(w http.ResponseWriter, r *http.Request) {
 
 		authorised, err := users.UserAuthorised(h.DbConn, username, password)
 		if err != nil {
-			w.WriteHeader(http.StatusBadRequest)
-			_, err := w.Write(fmt.Appendf(nil, "Error logging in: %s", err))
+			writer.WriteHeader(http.StatusBadRequest)
+			_, err := writer.Write(fmt.Appendf(nil, "Error logging in: %s", err))
 			if err != nil {
 				fmt.Println(err)
 			}
@@ -247,8 +247,8 @@ func (h Handler) LoginHandler(w http.ResponseWriter, r *http.Request) {
 		}
 
 		if !authorised {
-			w.WriteHeader(http.StatusUnauthorized)
-			_, err := w.Write([]byte("Incorrect username or password"))
+			writer.WriteHeader(http.StatusUnauthorized)
+			_, err := writer.Write([]byte("Incorrect username or password"))
 			if err != nil {
 				fmt.Println(err)
 			}
@@ -257,8 +257,8 @@ func (h Handler) LoginHandler(w http.ResponseWriter, r *http.Request) {
 
 		session, expiry, err := users.CreateSession(h.DbConn, username)
 		if err != nil {
-			w.WriteHeader(http.StatusBadRequest)
-			_, err := w.Write(fmt.Appendf(nil, "Error creating session: %s", err))
+			writer.WriteHeader(http.StatusBadRequest)
+			_, err := writer.Write(fmt.Appendf(nil, "Error creating session: %s", err))
 			if err != nil {
 				fmt.Println(err)
 			}
@@ -276,13 +276,13 @@ func (h Handler) LoginHandler(w http.ResponseWriter, r *http.Request) {
 			Secure:   true,
 		}
 
-		http.SetCookie(w, &cookie)
-		http.Redirect(w, r, "/", http.StatusSeeOther)
+		http.SetCookie(writer, &cookie)
+		http.Redirect(writer, request, "/", http.StatusSeeOther)
 	}
 }
 
-func (h Handler) LogoutHandler(w http.ResponseWriter, r *http.Request) {
-	cookie, err := r.Cookie("id")
+func (h Handler) LogoutHandler(writer http.ResponseWriter, request *http.Request) {
+	cookie, err := request.Cookie("id")
 	if err != nil {
 		fmt.Println(err)
 	}
@@ -290,15 +290,15 @@ func (h Handler) LogoutHandler(w http.ResponseWriter, r *http.Request) {
 	err = users.InvalidateSession(h.DbConn, cookie.Value)
 	if err != nil {
 		fmt.Println(err)
-		_, err = w.Write(fmt.Appendf(nil, "Error logging out: %s", err))
+		_, err = writer.Write(fmt.Appendf(nil, "Error logging out: %s", err))
 		if err != nil {
 			fmt.Println(err)
 		}
 		return
 	}
 	cookie.MaxAge = -1
-	http.SetCookie(w, cookie)
-	http.Redirect(w, r, "/login", http.StatusSeeOther)
+	http.SetCookie(writer, cookie)
+	http.Redirect(writer, request, "/login", http.StatusSeeOther)
 }
 
 // isAuthorised makes a database request to the sessions table to see if the
@@ -325,7 +325,7 @@ func StaticHandler(writer http.ResponseWriter, request *http.Request) {
 	} else if strings.HasSuffix(resource, ".js") {
 		writer.Header().Set("Content-Type", "text/javascript")
 	}
-	home, err := fs.ReadFile(resource)
+	home, err := staticFSEmbed.ReadFile(resource)
 	if err != nil {
 		fmt.Println(err)
 	}