From a5cc164fecf4896eb52fe06e5b11bf6f94de3027 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 26 Nov 2020 14:17:23 -0500 Subject: [PATCH] API: implement repository renames --- api/go.mod | 2 +- api/go.sum | 2 ++ api/graph/schema.resolvers.go | 67 ++++++++++++++++++++++++++++++----- 3 files changed, 61 insertions(+), 10 deletions(-) diff --git a/api/go.mod b/api/go.mod index ac83629..87b6421 100644 --- a/api/go.mod +++ b/api/go.mod @@ -3,7 +3,7 @@ module git.sr.ht/~sircmpwn/git.sr.ht/api go 1.14 require ( - git.sr.ht/~sircmpwn/core-go v0.0.0-20201126154911-33562018fec2 + git.sr.ht/~sircmpwn/core-go v0.0.0-20201126191555-4cc9b34f4ca8 git.sr.ht/~sircmpwn/getopt v0.0.0-20191230200459-23622cc906b3 github.com/99designs/gqlgen v0.13.0 github.com/Masterminds/squirrel v1.4.0 diff --git a/api/go.sum b/api/go.sum index c973f14..b435f6f 100644 --- a/api/go.sum +++ b/api/go.sum @@ -4,6 +4,8 @@ git.sr.ht/~sircmpwn/core-go v0.0.0-20201121171719-31fc9fce43e9 h1:w0toCjfdNh2JE4 git.sr.ht/~sircmpwn/core-go v0.0.0-20201121171719-31fc9fce43e9/go.mod h1:LLLvDJIgVgmA/sHl0fzj9UvpFiLi0v8a/aiBc3g22ik= git.sr.ht/~sircmpwn/core-go v0.0.0-20201126154911-33562018fec2 h1:qtKGxaNnO86GZtT4IYGHzQx3fN7P6NgxjhZaLeTdR84= git.sr.ht/~sircmpwn/core-go v0.0.0-20201126154911-33562018fec2/go.mod h1:LLLvDJIgVgmA/sHl0fzj9UvpFiLi0v8a/aiBc3g22ik= +git.sr.ht/~sircmpwn/core-go v0.0.0-20201126191555-4cc9b34f4ca8 h1:4Z5v+Xld0h57mHrODjdhHZrb4LbFigCCqLmJGOhQlyc= +git.sr.ht/~sircmpwn/core-go v0.0.0-20201126191555-4cc9b34f4ca8/go.mod h1:LLLvDJIgVgmA/sHl0fzj9UvpFiLi0v8a/aiBc3g22ik= git.sr.ht/~sircmpwn/dowork v0.0.0-20201013160733-35ca012e4dc8 h1:ltrdYYclC4wQEg3QdcG2hgYAFCk+6/l2vU1OXygKXVA= git.sr.ht/~sircmpwn/dowork v0.0.0-20201013160733-35ca012e4dc8/go.mod h1:8neHEO3503w/rNtttnR0JFpQgM/GFhaafVwvkPsFIDw= git.sr.ht/~sircmpwn/getopt v0.0.0-20191230200459-23622cc906b3 h1:4wDp4BKF7NQqoh73VXpZsB/t1OEhDpz/zEpmdQfbjDk= diff --git a/api/graph/schema.resolvers.go b/api/graph/schema.resolvers.go index fbf5dad..453ff15 100644 --- a/api/graph/schema.resolvers.go +++ b/api/graph/schema.resolvers.go @@ -157,21 +157,64 @@ func (r *mutationResolver) CreateRepository(ctx context.Context, name string, vi } func (r *mutationResolver) UpdateRepository(ctx context.Context, id int, input map[string]interface{}) (*model.Repository, error) { - if _, ok := input["name"]; ok { - panic(fmt.Errorf("updateRepository: rename not implemented")) // TODO - } - - var repo model.Repository + var ( + repo model.Repository + origPath string + repoPath string + moved bool + ) if err := database.WithTx(ctx, nil, func(tx *sql.Tx) error { - row := database.Apply(&repo, input). + user := auth.ForContext(ctx) + + query := database.Apply(&repo, input). Where(`id = ?`, id). Where(`owner_id = ?`, auth.ForContext(ctx).UserID). Set(`updated`, sq.Expr(`now() at time zone 'utc'`)). Suffix(`RETURNING id, created, updated, name, description, visibility, - upstream_uri, path, owner_id`). - RunWith(tx). - QueryRowContext(ctx) + upstream_uri, path, owner_id`) + + // Create redirect if updating name + if n, ok := input["name"]; ok { + name, ok := n.(string) + if !ok { + return fmt.Errorf("Invalid type for 'name' field (expected string)") + } + + var origPath string + row := tx.QueryRowContext(ctx, ` + INSERT INTO redirect ( + created, name, path, owner_id, new_repo_id + ) SELECT + NOW() at time zone 'utc', + orig.name, orig.path, orig.owner_id, orig.id + FROM repository orig + WHERE id = $1 AND owner_id = $2 + RETURNING path; + `, id, auth.ForContext(ctx).UserID) + if err := row.Scan(&origPath); err != nil { + if err == sql.ErrNoRows { + return fmt.Errorf("No repository by ID %d found for this user", id) + } + return err + } + + conf := config.ForContext(ctx) + repoStore, ok := conf.Get("git.sr.ht", "repos") + if !ok || repoStore == "" { + panic(fmt.Errorf("Configuration error: [git.sr.ht]repos is unset")) + } + + repoPath := path.Join(repoStore, "~"+user.Username, name) + err := os.Rename(origPath, repoPath) + if err != nil { + return err + } + moved = true + query = query.Set(`path`, repoPath) + } + + row := query.RunWith(tx).QueryRowContext(ctx) if err := row.Scan(&repo.ID, &repo.Created, &repo.Updated, &repo.Name, &repo.Description, &repo.Visibility, &repo.UpstreamURL, &repo.Path, &repo.OwnerID); err != nil { @@ -182,6 +225,12 @@ func (r *mutationResolver) UpdateRepository(ctx context.Context, id int, input m } return nil }); err != nil { + if moved && err != nil { + err := os.Rename(repoPath, origPath) + if err != nil { + panic(err) + } + } return nil, err } -- 2.38.4