~sircmpwn/sr.ht-dev

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch

[PATCH v2 git.sr.ht] api/graph: Add cloneUrl argument to createRepository

Details
Message ID
<20220117164309.16311-1-me@adnano.co>
DKIM signature
pass
Download raw message
Patch: +46 -12
The optional cloneUrl argument allows the client to specify an optional
Url from which the repository will be cloned.

This paves the way for future improvements such as the ability to clone
third-party repositories from the web UI.

In order to prevent users from cloning private repositories on the
filesystem, the "file" protocol transport has been disabled.
---
It might be somewhat difficult to conditionally enable the "file"
transport since it is a global configuration option. It would be nice if
we could pass the list of allowed transports to go-git's clone
function. This may need some more thought.

Instead of a cloneId parameter, we could have some code that parses URLs
like https://git.sr.ht/~user/repo and determines if it is a local
repository. We'll probably need that code anyways even if we add a
cloneId parameter.

 api/graph/api/generated.go    | 23 +++++++++++++++++------
 api/graph/resolver.go         |  7 +++++++
 api/graph/schema.graphqls     |  6 ++++--
 api/graph/schema.resolvers.go | 22 ++++++++++++++++++----
 4 files changed, 46 insertions(+), 12 deletions(-)

diff --git a/api/graph/api/generated.go b/api/graph/api/generated.go
index fab27d7..1ed4254 100644
--- a/api/graph/api/generated.go
+++ b/api/graph/api/generated.go
@@ -116,7 +116,7 @@ type ComplexityRoot struct {
	}

	Mutation struct {
		CreateRepository func(childComplexity int, name string, visibility model.Visibility, description *string) int
		CreateRepository func(childComplexity int, name string, visibility model.Visibility, description *string, cloneURL *string) int
		CreateWebhook    func(childComplexity int, config model.UserWebhookInput) int
		DeleteACL        func(childComplexity int, id int) int
		DeleteArtifact   func(childComplexity int, id int) int
@@ -302,7 +302,7 @@ type CommitResolver interface {
	Diff(ctx context.Context, obj *model.Commit) (string, error)
}
type MutationResolver interface {
	CreateRepository(ctx context.Context, name string, visibility model.Visibility, description *string) (*model.Repository, error)
	CreateRepository(ctx context.Context, name string, visibility model.Visibility, description *string, cloneURL *string) (*model.Repository, error)
	UpdateRepository(ctx context.Context, id int, input map[string]interface{}) (*model.Repository, error)
	DeleteRepository(ctx context.Context, id int) (*model.Repository, error)
	UpdateACL(ctx context.Context, repoID int, mode model.AccessMode, entity string) (*model.ACL, error)
@@ -609,7 +609,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
			return 0, false
		}

		return e.complexity.Mutation.CreateRepository(childComplexity, args["name"].(string), args["visibility"].(model.Visibility), args["description"].(*string)), true
		return e.complexity.Mutation.CreateRepository(childComplexity, args["name"].(string), args["visibility"].(model.Visibility), args["description"].(*string), args["cloneUrl"].(*string)), true

	case "Mutation.createWebhook":
		if e.complexity.Mutation.CreateWebhook == nil {
@@ -2114,8 +2114,10 @@ input UserWebhookInput {
}

type Mutation {
  "Creates a new git repository"
  createRepository(name: String!, visibility: Visibility!, description: String): Repository @access(scope: REPOSITORIES, kind: RW)
  """
  Creates a new git repository.
  """
  createRepository(name: String!, visibility: Visibility!, description: String, cloneUrl: String): Repository @access(scope: REPOSITORIES, kind: RW)

  "Updates the metadata for a git repository"
  updateRepository(id: Int!, input: RepoInput!): Repository @access(scope: REPOSITORIES, kind: RW)
@@ -2238,6 +2240,15 @@ func (ec *executionContext) field_Mutation_createRepository_args(ctx context.Con
		}
	}
	args["description"] = arg2
	var arg3 *string
	if tmp, ok := rawArgs["cloneUrl"]; ok {
		ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("cloneUrl"))
		arg3, err = ec.unmarshalOString2ᚖstring(ctx, tmp)
		if err != nil {
			return nil, err
		}
	}
	args["cloneUrl"] = arg3
	return args, nil
}

@@ -3986,7 +3997,7 @@ func (ec *executionContext) _Mutation_createRepository(ctx context.Context, fiel
	resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
		directive0 := func(rctx context.Context) (interface{}, error) {
			ctx = rctx // use context from middleware stack in children
			return ec.resolvers.Mutation().CreateRepository(rctx, args["name"].(string), args["visibility"].(model.Visibility), args["description"].(*string))
			return ec.resolvers.Mutation().CreateRepository(rctx, args["name"].(string), args["visibility"].(model.Visibility), args["description"].(*string), args["cloneUrl"].(*string))
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			scope, err := ec.unmarshalNAccessScope2gitᚗsrᚗhtᚋאsircmpwnᚋgitᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "REPOSITORIES")
diff --git a/api/graph/resolver.go b/api/graph/resolver.go
index c8a657f..ede7a6d 100644
--- a/api/graph/resolver.go
+++ b/api/graph/resolver.go
@@ -2,6 +2,8 @@ package graph

import (
	"regexp"

	"github.com/go-git/go-git/v5/plumbing/transport/client"
)

type Resolver struct{}
@@ -9,3 +11,8 @@ type Resolver struct{}
var (
	repoNameRE = regexp.MustCompile(`^[A-Za-z0-9._-]+$`)
)

func init() {
	// Disable cloning of local repositories
	client.InstallProtocol("file", nil)
}
diff --git a/api/graph/schema.graphqls b/api/graph/schema.graphqls
index a75662b..8472daa 100644
--- a/api/graph/schema.graphqls
+++ b/api/graph/schema.graphqls
@@ -525,8 +525,10 @@ input UserWebhookInput {
}

type Mutation {
  "Creates a new git repository"
  createRepository(name: String!, visibility: Visibility!, description: String): Repository @access(scope: REPOSITORIES, kind: RW)
  """
  Creates a new git repository.
  """
  createRepository(name: String!, visibility: Visibility!, description: String, cloneUrl: String): Repository @access(scope: REPOSITORIES, kind: RW)

  "Updates the metadata for a git repository"
  updateRepository(id: Int!, input: RepoInput!): Repository @access(scope: REPOSITORIES, kind: RW)
diff --git a/api/graph/schema.resolvers.go b/api/graph/schema.resolvers.go
index b6f8602..9708387 100644
--- a/api/graph/schema.resolvers.go
+++ b/api/graph/schema.resolvers.go
@@ -71,7 +71,7 @@ func (r *commitResolver) Diff(ctx context.Context, obj *model.Commit) (string, e
	return obj.DiffContext(ctx), nil
}

func (r *mutationResolver) CreateRepository(ctx context.Context, name string, visibility model.Visibility, description *string) (*model.Repository, error) {
func (r *mutationResolver) CreateRepository(ctx context.Context, name string, visibility model.Visibility, description *string, cloneURL *string) (*model.Repository, error) {
	if !repoNameRE.MatchString(name) {
		return nil, fmt.Errorf("Invalid repository name '%s' (must match %s)",
			name, repoNameRE.String())
@@ -146,9 +146,23 @@ func (r *mutationResolver) CreateRepository(ctx context.Context, name string, vi
			return err
		}

		gitrepo, err := git.PlainInit(repoPath, true)
		if err != nil {
			return err
		var gitrepo *git.Repository
		if cloneURL != nil {
			// TODO: Queue clone in background?
			var err error
			gitrepo, err = git.PlainClone(repoPath, true, &git.CloneOptions{
				URL:               *cloneURL,
				RecurseSubmodules: git.NoRecurseSubmodules,
			})
			if err != nil {
				return err
			}
		} else {
			var err error
			gitrepo, err = git.PlainInit(repoPath, true)
			if err != nil {
				return err
			}
		}
		repoCreated = true
		config, err := gitrepo.Config()
-- 
2.34.1
Reply to thread Export thread (mbox)