~edwargix/git.sr.ht

a5cc164fecf4896eb52fe06e5b11bf6f94de3027 — Drew DeVault 3 years ago e784cfd
API: implement repository renames
3 files changed, 61 insertions(+), 10 deletions(-)

M api/go.mod
M api/go.sum
M api/graph/schema.resolvers.go
M api/go.mod => api/go.mod +1 -1
@@ 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

M api/go.sum => api/go.sum +2 -0
@@ 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=

M api/graph/schema.resolvers.go => api/graph/schema.resolvers.go +58 -9
@@ 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
	}