Compare commits
28 commits
8c2c776833
...
0766fa4d93
| Author | SHA1 | Date | |
|---|---|---|---|
| 0766fa4d93 | |||
| 3bb63651ee | |||
| e85bc74328 | |||
| bd73caef15 | |||
| c78d690ffc | |||
| 15d0212084 | |||
| 80216f7dbb | |||
| b50bd0f835 | |||
| e27fea23b5 | |||
| 5c502de95d | |||
| 851fa99b4b | |||
| 5c0cc8631f | |||
| 5e1133b97e | |||
| a3e995c75e | |||
| 28944e0dca | |||
| f71db5044e | |||
| c865dcc8bc | |||
| 3e08a81fa2 | |||
| ea227d0968 | |||
| c8eb857ad7 | |||
| 5422888cf8 | |||
| 9608b31425 | |||
| 27c27c9791 | |||
| fa11abf29a | |||
| 553d9a9eeb | |||
| f9c831d756 | |||
| 79a6d17044 | |||
| 7d5812277c |
42 changed files with 906 additions and 300 deletions
74
.deadcode-out
Normal file
74
.deadcode-out
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
code.forgejo.org/f3/gof3/v3/api
|
||||
TreeMirror
|
||||
|
||||
code.forgejo.org/f3/gof3/v3/f3
|
||||
RepositoryDirname
|
||||
|
||||
code.forgejo.org/f3/gof3/v3/forges/forgejo
|
||||
common.isContainer
|
||||
webClients.impersonate
|
||||
treeDriver.getWebClient
|
||||
|
||||
code.forgejo.org/f3/gof3/v3/forges/forgejo/sdk
|
||||
hasAgent
|
||||
GetAgent
|
||||
Version
|
||||
NewClientWithHTTP
|
||||
SetHTTPClient
|
||||
UseSSHCert
|
||||
UseSSHPubkey
|
||||
SetOTP
|
||||
SetContext
|
||||
SetSudo
|
||||
SetUserAgent
|
||||
SetDebugMode
|
||||
OptionalBool
|
||||
OptionalString
|
||||
OptionalInt64
|
||||
VerifyWebhookSignature
|
||||
VerifyWebhookSignatureMiddleware
|
||||
NewHTTPSignWithPubkey
|
||||
NewHTTPSignWithCert
|
||||
newHTTPSign
|
||||
findCertSigner
|
||||
findPubkeySigner
|
||||
SetGiteaVersion
|
||||
|
||||
code.forgejo.org/f3/gof3/v3/forges/helpers/tests/repository
|
||||
TestHelper.GetNode
|
||||
TestHelper.RevList
|
||||
TestHelper.AssertRepositoryNotFileExists
|
||||
TestHelper.BranchRepositoryFeature
|
||||
|
||||
code.forgejo.org/f3/gof3/v3/options/cli
|
||||
OptionsCLI.FromFlags
|
||||
OptionsCLI.GetFlags
|
||||
|
||||
code.forgejo.org/f3/gof3/v3/tree/f3
|
||||
NewLabelReference
|
||||
NewPullRequestLabelReference
|
||||
NewMilestoneReference
|
||||
NewPath
|
||||
pullRequestNode.GetPullRequestHead
|
||||
pullRequestNode.GetPullRequestRef
|
||||
pullRequestNode.GetPullRequestPushRefs
|
||||
newPullRequestNode
|
||||
NewRepositoryPath
|
||||
NewTopicPath
|
||||
NewTopicPathString
|
||||
NewTopicReference
|
||||
|
||||
code.forgejo.org/f3/gof3/v3/tree/f3/objects
|
||||
FuncReadURLAndSetSHA
|
||||
|
||||
code.forgejo.org/f3/gof3/v3/tree/generic
|
||||
MirrorOptions.SetNoRemap
|
||||
TreePartialMirror
|
||||
|
||||
code.forgejo.org/f3/gof3/v3/tree/tests/f3
|
||||
Creator.GetDirectory
|
||||
Creator.Generate
|
||||
|
||||
code.forgejo.org/f3/gof3/v3/util/tests
|
||||
CompareEqualValues
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -4,3 +4,4 @@ coverage.out
|
|||
coverage.html
|
||||
tests/*.out
|
||||
format/schemas/.gitignore
|
||||
.cur-deadcode-out
|
||||
|
|
|
|||
|
|
@ -27,9 +27,11 @@ linters:
|
|||
fast: false
|
||||
|
||||
run:
|
||||
go: 1.21
|
||||
go: 1.22
|
||||
timeout: 10m
|
||||
skip-dirs:
|
||||
|
||||
issues:
|
||||
exclude-dirs:
|
||||
- forges/forgejo/sdk
|
||||
|
||||
linters-settings:
|
||||
|
|
@ -69,8 +71,6 @@ linters-settings:
|
|||
- name: errorf
|
||||
- name: duplicated-imports
|
||||
- name: modifies-value-receiver
|
||||
gofumpt:
|
||||
lang-version: "1.21"
|
||||
depguard:
|
||||
#list-type: denylist
|
||||
# Check the list against standard lib.
|
||||
|
|
|
|||
42
Makefile
42
Makefile
|
|
@ -3,12 +3,16 @@ GO ?= go
|
|||
BINDATA_DEST := format/bindata.go
|
||||
BINDATA_HASH := $(addsuffix .hash,$(BINDATA_DEST))
|
||||
|
||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.7.0
|
||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.5.0
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.56.1
|
||||
GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.10
|
||||
DIFF ?= diff --unified
|
||||
|
||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v2/cmd/editorconfig-checker@2.8.0 # renovate: datasource=go
|
||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.6.0 # renovate: datasource=go
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.57.2 # renovate: datasource=go
|
||||
UNCOVER_PACKAGE ?= github.com/gregoryv/uncover/cmd/uncover@latest
|
||||
MISSPELL_PACKAGE ?= github.com/client9/misspell/cmd/misspell@v0.3.4
|
||||
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.4.1 # renovate: datasource=go
|
||||
DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.21.0 # renovate: datasource=go
|
||||
|
||||
DEADCODE_ARGS ?= -generated=false -test -f='{{println .Path}}{{range .Funcs}}{{printf "\t%s\n" .Name}}{{end}}{{println}}' code.forgejo.org/f3/gof3/v3/...
|
||||
|
||||
VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//')
|
||||
|
||||
|
|
@ -33,14 +37,36 @@ deps-backend:
|
|||
$(GO) mod download
|
||||
$(GO) install $(GOFUMPT_PACKAGE)
|
||||
$(GO) install $(GOLANGCI_LINT_PACKAGE)
|
||||
$(GO) install $(GXZ_PAGAGE)
|
||||
$(GO) install $(UNCOVER_PACKAGE)
|
||||
$(GO) install $(MISSPELL_PACKAGE)
|
||||
$(GO) install $(DEADCODE_PACKAGE)
|
||||
|
||||
.PHONY: lint
|
||||
lint:
|
||||
$(GO) run $(GOLANGCI_LINT_PACKAGE) run
|
||||
@if ! $(MAKE) lint-run ; then echo "Please run 'make lint-fix' and commit the result" ; exit 1 ; fi
|
||||
|
||||
.PHONY: lint-run
|
||||
lint-run:
|
||||
$(GO) run $(GOLANGCI_LINT_PACKAGE) run $(GOLANGCI_LINT_ARGS)
|
||||
$(GO) run $(DEADCODE_PACKAGE) $(DEADCODE_ARGS) > .cur-deadcode-out
|
||||
$(DIFF) .deadcode-out .cur-deadcode-out
|
||||
|
||||
.PHONY: lint-fix
|
||||
lint-fix:
|
||||
$(GO) run $(GOLANGCI_LINT_PACKAGE) run $(GOLANGCI_LINT_ARGS) --fix
|
||||
$(GO) run $(DEADCODE_PACKAGE) $(DEADCODE_ARGS) > .deadcode-out
|
||||
|
||||
.PHONY: fmt
|
||||
fmt:
|
||||
MISSPELL_PACKAGE=$(MISSPELL_PACKAGE) GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) gofumpt -extra -w .
|
||||
GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) gofumpt -extra -w .
|
||||
|
||||
SPELLCHECK_FILES = $(GO_DIRS)
|
||||
|
||||
.PHONY: lint-spell
|
||||
lint-spell:
|
||||
@go run $(MISSPELL_PACKAGE) -error $(SPELLCHECK_FILES)
|
||||
|
||||
.PHONY: lint-spell-fix
|
||||
lint-spell-fix:
|
||||
@go run $(MISSPELL_PACKAGE) -w $(SPELLCHECK_FILES)
|
||||
|
||||
|
|
|
|||
|
|
@ -13,15 +13,13 @@
|
|||
"clone_url": "head_clone_url",
|
||||
"ref": "head_branch",
|
||||
"sha": "head_sha",
|
||||
"repo_name": "repo_a",
|
||||
"owner_name": "owner_a"
|
||||
"repository": "/forge/user/1/projects/2/repositories/vcs"
|
||||
},
|
||||
"base": {
|
||||
"clone_url": "base_clone_url",
|
||||
"ref": "base_branch",
|
||||
"sha": "base _sha",
|
||||
"repo_name": "repo_b",
|
||||
"owner_name": "owner_b"
|
||||
"repository": "/forge/user/3/projects/4/repositories/vcs"
|
||||
},
|
||||
"labels": ["label1"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ func (c *Common) ToReference() *Reference { return &c.Index }
|
|||
func (c *Common) GetCmpIgnoreFields() []string { return []string{".Index"} }
|
||||
func (c *Common) GetComparers() []Comparer { return []Comparer{} }
|
||||
|
||||
func NewCmpCompareOptions(f Interface) cmp.Options {
|
||||
func newCmpCompareOptions(f Interface) cmp.Options {
|
||||
options := make(cmp.Options, 0, 5)
|
||||
for _, comparer := range f.GetComparers() {
|
||||
options = append(options, cmp.Comparer(comparer))
|
||||
|
|
@ -110,7 +110,7 @@ func NewCmpOptions(f Interface) cmp.Options {
|
|||
},
|
||||
cmp.Ignore()),
|
||||
}
|
||||
return append(options, NewCmpCompareOptions(f)...)
|
||||
return append(options, newCmpCompareOptions(f)...)
|
||||
}
|
||||
|
||||
var Nil = &Common{}
|
||||
|
|
|
|||
|
|
@ -42,15 +42,17 @@ func (o *PullRequest) GetReferences() References {
|
|||
if o.Milestone != nil {
|
||||
references = append(references, o.Milestone)
|
||||
}
|
||||
references = append(references, o.Base.GetReferences()...)
|
||||
references = append(references, o.Head.GetReferences()...)
|
||||
return append(references, o.PosterID)
|
||||
}
|
||||
|
||||
func (o *PullRequest) IsForkPullRequest() bool {
|
||||
return o.Head.RepoPath() != o.Base.RepoPath()
|
||||
return o.Head.Repository != o.Base.Repository
|
||||
}
|
||||
|
||||
func (o PullRequest) GetCmpIgnoreFields() []string {
|
||||
return append(o.Common.GetCmpIgnoreFields(), ".FetchFunc", ".Updated", ".Created", ".Closed")
|
||||
return append(o.Common.GetCmpIgnoreFields(), ".FetchFunc", ".Updated", ".Created", ".Closed", ".Repository")
|
||||
}
|
||||
|
||||
func (o *PullRequest) Clone() Interface {
|
||||
|
|
|
|||
|
|
@ -4,17 +4,12 @@
|
|||
|
||||
package f3
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type PullRequestBranch struct {
|
||||
Ref string `json:"ref"`
|
||||
SHA string `json:"sha"`
|
||||
OwnerName string `json:"owner_name"`
|
||||
RepoName string `json:"repo_name"`
|
||||
Ref string `json:"ref"`
|
||||
SHA string `json:"sha"`
|
||||
Repository *Reference `json:"repository"`
|
||||
}
|
||||
|
||||
func (o PullRequestBranch) RepoPath() string {
|
||||
return fmt.Sprintf("%s/%s", o.OwnerName, o.RepoName)
|
||||
func (o *PullRequestBranch) GetReferences() References {
|
||||
return References{o.Repository}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@
|
|||
]
|
||||
},
|
||||
"labels": {
|
||||
"description": "List of labels.",
|
||||
"description": "List of label unique identifiers.",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
"type": "string"
|
||||
},
|
||||
"milestone": {
|
||||
"description": "Name of the milestone.",
|
||||
"description": "Unique identifier of the milestone.",
|
||||
"type": "string"
|
||||
},
|
||||
"state": {
|
||||
|
|
@ -59,7 +59,7 @@
|
|||
]
|
||||
},
|
||||
"labels": {
|
||||
"description": "List of labels.",
|
||||
"description": "List of labels unique identifiers.",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
|
|
|
|||
|
|
@ -13,20 +13,15 @@
|
|||
"description": "SHA of the commit.",
|
||||
"type": "string"
|
||||
},
|
||||
"repo_name": {
|
||||
"description": "Name of the project that contains the repository.",
|
||||
"type": "string"
|
||||
},
|
||||
"owner_name": {
|
||||
"description": "Name of the user or organization that contains the project.",
|
||||
"repository": {
|
||||
"description": "Unique identifier of the repository.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"ref",
|
||||
"sha",
|
||||
"repo_name",
|
||||
"owner_name"
|
||||
"repository"
|
||||
],
|
||||
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
"type": "string"
|
||||
},
|
||||
"reviewer_id": {
|
||||
"description": "Unique identifer of review author.",
|
||||
"description": "Unique identifier of review author.",
|
||||
"type": "string"
|
||||
},
|
||||
"official": {
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ func (o *nodeDriver) IsNull() bool { return false }
|
|||
|
||||
func (o *nodeDriver) GetIDFromName(ctx context.Context, name string) generic.NodeID {
|
||||
switch o.getKind() {
|
||||
case generic.KindRoot, f3_tree.KindProjects, f3_tree.KindUsers, f3_tree.KindOrganizations:
|
||||
case generic.KindRoot, f3_tree.KindProjects, f3_tree.KindUsers, f3_tree.KindOrganizations, f3_tree.KindRepositories:
|
||||
default:
|
||||
panic(fmt.Errorf("unxpected kind %s", o.getKind()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,10 @@ func (o *common) getKind() generic.Kind {
|
|||
return o.GetNode().GetKind()
|
||||
}
|
||||
|
||||
func (o *common) getChildDriver(kind generic.Kind) generic.NodeDriverInterface {
|
||||
return o.GetNode().GetChild(generic.NodeID(kind)).GetDriver()
|
||||
}
|
||||
|
||||
func (o *common) isContainer() bool {
|
||||
return o.getF3Tree().IsContainer(o.getKind())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,17 +6,52 @@ package forgejo
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
"code.forgejo.org/f3/gof3/v3/util"
|
||||
)
|
||||
|
||||
type forge struct {
|
||||
generic.NullDriver
|
||||
common
|
||||
|
||||
ownersKind map[string]generic.Kind
|
||||
}
|
||||
|
||||
func newForge() generic.NodeDriverInterface {
|
||||
return &forge{}
|
||||
return &forge{
|
||||
ownersKind: make(map[string]generic.Kind),
|
||||
}
|
||||
}
|
||||
|
||||
func (o *forge) getOwnersKind(ctx context.Context, id string) generic.Kind {
|
||||
kind, ok := o.ownersKind[id]
|
||||
if !ok {
|
||||
_, _, err := o.getClient().GetUserByID(util.ParseInt(id))
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "user not found") {
|
||||
organizations := o.getChildDriver(f3_tree.KindOrganizations).(*organizations)
|
||||
if organizations.getNameFromID(ctx, util.ParseInt(id)) != "" {
|
||||
kind = f3_tree.KindOrganizations
|
||||
} else {
|
||||
panic(fmt.Errorf("%v does not match any user or organization", id))
|
||||
}
|
||||
} else {
|
||||
panic(fmt.Errorf("GetUserByID(%s) failed %w", id, err))
|
||||
}
|
||||
} else {
|
||||
kind = f3_tree.KindUsers
|
||||
}
|
||||
o.ownersKind[id] = kind
|
||||
}
|
||||
return kind
|
||||
}
|
||||
|
||||
func (o *forge) getOwnersPath(ctx context.Context, id string) f3_tree.Path {
|
||||
return f3_tree.NewPathFromString("/").SetForge().SetOwners(o.getOwnersKind(ctx, id))
|
||||
}
|
||||
|
||||
func (o *forge) Equals(context.Context, generic.NodeInterface) bool { return true }
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ type pullRequest struct {
|
|||
common
|
||||
|
||||
forgejoPullRequest *forgejo_sdk.PullRequest
|
||||
headRepository *f3.Reference
|
||||
baseRepository *f3.Reference
|
||||
fetchFunc f3.PullRequestFetchFunc
|
||||
}
|
||||
|
||||
|
|
@ -43,6 +45,33 @@ func (o *pullRequest) NewFormat() f3.Interface {
|
|||
return node.GetTree().(f3_tree.TreeInterface).NewFormat(node.GetKind())
|
||||
}
|
||||
|
||||
func (o *pullRequest) repositoryToReference(ctx context.Context, repository *forgejo_sdk.Repository) *f3.Reference {
|
||||
if repository == nil {
|
||||
panic("unexpected nil repository")
|
||||
}
|
||||
forge := o.getTree().GetRoot().GetChild(f3_tree.KindForge).GetDriver().(*forge)
|
||||
owners := forge.getOwnersPath(ctx, fmt.Sprintf("%d", repository.Owner.ID))
|
||||
return f3_tree.NewRepositoryReference(owners.String(), repository.Owner.ID, repository.ID)
|
||||
}
|
||||
|
||||
func (o *pullRequest) referenceToRepository(reference *f3.Reference) *forgejo_sdk.Repository {
|
||||
var owner, project int64
|
||||
if reference.Get() == "../../repository/vcs" {
|
||||
project = f3_tree.GetProjectID(o.GetNode())
|
||||
owner = f3_tree.GetOwnerID(o.GetNode())
|
||||
} else {
|
||||
p := f3_tree.ToPath(generic.PathAbsolute(o.GetNode().GetCurrentPath().String(), reference.Get()))
|
||||
o.Trace("%v %v", o.GetNode().GetCurrentPath().String(), p)
|
||||
owner, project = p.OwnerAndProjectID()
|
||||
}
|
||||
return &forgejo_sdk.Repository{
|
||||
ID: project,
|
||||
Owner: &forgejo_sdk.User{
|
||||
ID: owner,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (o *pullRequest) ToFormat() f3.Interface {
|
||||
if o.forgejoPullRequest == nil {
|
||||
return o.NewFormat()
|
||||
|
|
@ -63,31 +92,19 @@ func (o *pullRequest) ToFormat() f3.Interface {
|
|||
}
|
||||
|
||||
var (
|
||||
headUserName string
|
||||
headRepoName string
|
||||
headRef string
|
||||
headSHA string
|
||||
headRef string
|
||||
headSHA string
|
||||
)
|
||||
if o.forgejoPullRequest.Head != nil {
|
||||
if o.forgejoPullRequest.Head.Repository != nil {
|
||||
headUserName = o.forgejoPullRequest.Head.Repository.Owner.UserName
|
||||
headRepoName = o.forgejoPullRequest.Head.Repository.Name
|
||||
}
|
||||
headSHA = o.forgejoPullRequest.Head.Sha
|
||||
headRef = o.forgejoPullRequest.Head.Ref
|
||||
}
|
||||
|
||||
var (
|
||||
baseUserName string
|
||||
baseRepoName string
|
||||
baseRef string
|
||||
baseSHA string
|
||||
baseRef string
|
||||
baseSHA string
|
||||
)
|
||||
if o.forgejoPullRequest.Base != nil {
|
||||
if o.forgejoPullRequest.Base.Repository != nil {
|
||||
baseUserName = o.forgejoPullRequest.Base.Repository.Owner.UserName
|
||||
baseRepoName = o.forgejoPullRequest.Base.Repository.Name
|
||||
}
|
||||
baseSHA = o.forgejoPullRequest.Base.Sha
|
||||
baseRef = o.forgejoPullRequest.Base.Ref
|
||||
}
|
||||
|
|
@ -117,16 +134,14 @@ func (o *pullRequest) ToFormat() f3.Interface {
|
|||
MergeCommitSHA: mergeCommitSHA,
|
||||
IsLocked: o.forgejoPullRequest.IsLocked,
|
||||
Head: f3.PullRequestBranch{
|
||||
Ref: headRef,
|
||||
SHA: headSHA,
|
||||
RepoName: headRepoName,
|
||||
OwnerName: headUserName,
|
||||
Ref: headRef,
|
||||
SHA: headSHA,
|
||||
Repository: o.headRepository,
|
||||
},
|
||||
Base: f3.PullRequestBranch{
|
||||
Ref: baseRef,
|
||||
SHA: baseSHA,
|
||||
RepoName: baseRepoName,
|
||||
OwnerName: baseUserName,
|
||||
Ref: baseRef,
|
||||
SHA: baseSHA,
|
||||
Repository: o.baseRepository,
|
||||
},
|
||||
FetchFunc: o.fetchFunc,
|
||||
}
|
||||
|
|
@ -156,24 +171,14 @@ func (o *pullRequest) FromFormat(content f3.Interface) {
|
|||
Merged: pullRequest.MergedTime,
|
||||
MergedCommitID: &pullRequest.MergeCommitSHA,
|
||||
Base: &forgejo_sdk.PRBranchInfo{
|
||||
Ref: pullRequest.Base.Ref,
|
||||
Sha: pullRequest.Base.SHA,
|
||||
Repository: &forgejo_sdk.Repository{
|
||||
Name: pullRequest.Base.RepoName,
|
||||
Owner: &forgejo_sdk.User{
|
||||
UserName: pullRequest.Base.OwnerName,
|
||||
},
|
||||
},
|
||||
Ref: pullRequest.Base.Ref,
|
||||
Sha: pullRequest.Base.SHA,
|
||||
Repository: o.referenceToRepository(pullRequest.Base.Repository),
|
||||
},
|
||||
Head: &forgejo_sdk.PRBranchInfo{
|
||||
Ref: pullRequest.Head.Ref,
|
||||
Sha: pullRequest.Head.SHA,
|
||||
Repository: &forgejo_sdk.Repository{
|
||||
Name: pullRequest.Head.RepoName,
|
||||
Owner: &forgejo_sdk.User{
|
||||
UserName: pullRequest.Head.OwnerName,
|
||||
},
|
||||
},
|
||||
Ref: pullRequest.Head.Ref,
|
||||
Sha: pullRequest.Head.SHA,
|
||||
Repository: o.referenceToRepository(pullRequest.Head.Repository),
|
||||
},
|
||||
Created: &pullRequest.Created,
|
||||
Updated: &pullRequest.Updated,
|
||||
|
|
@ -186,16 +191,19 @@ func (o *pullRequest) Get(ctx context.Context) bool {
|
|||
node := o.GetNode()
|
||||
o.Trace("%s", node.GetID())
|
||||
|
||||
owner := f3_tree.GetOwnerName(o.GetNode())
|
||||
project := f3_tree.GetProjectName(o.GetNode())
|
||||
ownerName := f3_tree.GetOwnerName(o.GetNode())
|
||||
projectName := f3_tree.GetProjectName(o.GetNode())
|
||||
|
||||
pr, resp, err := o.getClient().GetPullRequest(owner, project, util.ParseInt(string(node.GetID())))
|
||||
pr, resp, err := o.getClient().GetPullRequest(ownerName, projectName, util.ParseInt(string(node.GetID())))
|
||||
if resp.StatusCode == 404 {
|
||||
return false
|
||||
}
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("pullRequest %v %w", o, err))
|
||||
}
|
||||
|
||||
o.headRepository = o.repositoryToReference(ctx, o.forgejoPullRequest.Head.Repository)
|
||||
o.baseRepository = o.repositoryToReference(ctx, o.forgejoPullRequest.Base.Repository)
|
||||
o.forgejoPullRequest = pr
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,8 +60,7 @@ func (o *treeF3) CreateChild(ctx context.Context, pathString string, set setFunc
|
|||
o.Trace("%s %s | %T %s", parent.String(), node.GetID(), node, node.GetKind())
|
||||
child := o.Factory(ctx, o.GetChildrenKind(node.GetKind()))
|
||||
child.SetParent(node)
|
||||
childParentPath := parent.Clone()
|
||||
childParentPath = childParentPath.Append(node)
|
||||
childParentPath := parent.Append(node)
|
||||
if set != nil {
|
||||
set(childParentPath, child)
|
||||
}
|
||||
|
|
@ -91,7 +90,7 @@ func newTreeF3(ctx context.Context, opts options.Interface) generic.TreeInterfac
|
|||
return newFixedChildrenNode(ctx, tree, []generic.Kind{KindProjects})
|
||||
})
|
||||
tree.Register(KindProject, func(ctx context.Context, kind generic.Kind) generic.NodeInterface {
|
||||
return newFixedChildrenNode(ctx, tree, []generic.Kind{KindRepositories, KindIssues, KindLabels, KindMilestones, KindPullRequests, KindReleases})
|
||||
return newFixedChildrenNode(ctx, tree, []generic.Kind{KindRepositories, KindLabels, KindMilestones, KindIssues, KindPullRequests, KindReleases})
|
||||
})
|
||||
tree.Register(KindIssue, func(ctx context.Context, kind generic.Kind) generic.NodeInterface {
|
||||
return newFixedChildrenNode(ctx, tree, []generic.Kind{KindComments, KindReactions})
|
||||
|
|
|
|||
|
|
@ -9,11 +9,12 @@ import (
|
|||
"slices"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
"code.forgejo.org/f3/gof3/v3/util"
|
||||
)
|
||||
|
||||
type Path interface {
|
||||
NodeIDs() []generic.NodeID
|
||||
OwnerAndProject() (owner, project generic.NodeID)
|
||||
OwnerAndProjectID() (owner, project int64)
|
||||
|
||||
AppendID(id string) Path
|
||||
Ignore() Path
|
||||
|
|
@ -39,6 +40,9 @@ type Path interface {
|
|||
Milestones() Path
|
||||
SetMilestones() Path
|
||||
|
||||
Owners() Path
|
||||
SetOwners(owners generic.Kind) Path
|
||||
|
||||
Organizations() Path
|
||||
SetOrganizations() Path
|
||||
|
||||
|
|
@ -103,9 +107,9 @@ func (o path) NodeIDs() []generic.NodeID {
|
|||
return nodeIDs
|
||||
}
|
||||
|
||||
func (o path) OwnerAndProject() (owner, project generic.NodeID) {
|
||||
func (o path) OwnerAndProjectID() (owner, project int64) {
|
||||
nodeIDs := o.NodeIDs()
|
||||
return nodeIDs[0], nodeIDs[1]
|
||||
return util.ParseInt(string(nodeIDs[0])), util.ParseInt(string(nodeIDs[1]))
|
||||
}
|
||||
|
||||
func (o path) Root() Path { return o.popKind(generic.Kind("")) }
|
||||
|
|
@ -158,7 +162,8 @@ func (o path) SetTopics() Path { return o.appendKind(KindTopics) }
|
|||
func (o path) Users() Path { return o.popKind(KindUsers) }
|
||||
func (o path) SetUsers() Path { return o.appendKind(KindUsers) }
|
||||
|
||||
func (o path) Owners() Path { return o.popKind(KindUsers, KindOrganizations) }
|
||||
func (o path) Owners() Path { return o.popKind(KindUsers, KindOrganizations) }
|
||||
func (o path) SetOwners(owners generic.Kind) Path { return o.appendKind(owners) }
|
||||
|
||||
func (o path) AppendID(id string) Path {
|
||||
return ToPath(o.Append(generic.NewNodeFromID(id)))
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
"code.forgejo.org/f3/gof3/v3/util"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
|
@ -20,8 +21,9 @@ func TestF3Path(t *testing.T) {
|
|||
}
|
||||
nodeIDs := make([]generic.NodeID, 0, 10)
|
||||
{
|
||||
p := p.SetUsers()
|
||||
id := "user1"
|
||||
p := p.SetOwners(KindUsers)
|
||||
id := "1"
|
||||
ownerID := util.ParseInt(id)
|
||||
nodeIDs := append(nodeIDs, generic.NodeID(id))
|
||||
p = p.AppendID(id)
|
||||
assert.EqualValues(t, generic.NodeID(id), p.Root().Forge().Users().First().GetID())
|
||||
|
|
@ -29,14 +31,15 @@ func TestF3Path(t *testing.T) {
|
|||
|
||||
{
|
||||
p := p.SetProjects()
|
||||
id := "project1"
|
||||
id := "2"
|
||||
projectID := util.ParseInt(id)
|
||||
nodeIDs := append(nodeIDs, generic.NodeID(id))
|
||||
p = p.AppendID(id)
|
||||
assert.EqualValues(t, generic.NodeID(id), p.Root().Forge().Users().Ignore().Projects().First().GetID())
|
||||
assert.EqualValues(t, nodeIDs, p.NodeIDs())
|
||||
owner, project := p.OwnerAndProject()
|
||||
assert.EqualValues(t, nodeIDs[0], owner)
|
||||
assert.EqualValues(t, nodeIDs[1], project)
|
||||
owner, project := p.OwnerAndProjectID()
|
||||
assert.EqualValues(t, ownerID, owner)
|
||||
assert.EqualValues(t, projectID, project)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ package f3
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
)
|
||||
|
||||
|
|
@ -40,3 +42,19 @@ func newRepositoryNode(ctx context.Context, tree generic.TreeInterface) generic.
|
|||
node := &repositoryNode{}
|
||||
return node.Init(node)
|
||||
}
|
||||
|
||||
func NewRepositoryPath[T, U any](owners string, owner T, project U) generic.Path {
|
||||
return generic.NewPathFromString(NewRepositoryPathString(owners, owner, project))
|
||||
}
|
||||
|
||||
func NewRepositoryPathString[T, U any](owners string, owner T, project U) string {
|
||||
return fmt.Sprintf("%s/%v/projects/%v/repositories/vcs", owners, owner, project)
|
||||
}
|
||||
|
||||
func NewRepositoryReference[T, U any](owners string, owner T, project U) *f3.Reference {
|
||||
return f3.NewReference(NewRepositoryPathString(owners, owner, project))
|
||||
}
|
||||
|
||||
func NewPullRequestSameRepositoryReference() *f3.Reference {
|
||||
return f3.NewReference("../../repositories/vcs")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,13 +8,7 @@ import (
|
|||
"context"
|
||||
)
|
||||
|
||||
type CompareOptions struct{}
|
||||
|
||||
func NewCompareOptions() *CompareOptions {
|
||||
return &CompareOptions{}
|
||||
}
|
||||
|
||||
func NodeCompare(ctx context.Context, a, b NodeInterface, options *CompareOptions) bool {
|
||||
func NodeCompare(ctx context.Context, a, b NodeInterface) bool {
|
||||
a.Trace("a '%s' | b '%s'", a.GetCurrentPath(), b.GetCurrentPath())
|
||||
|
||||
if a.GetKind() != b.GetKind() {
|
||||
|
|
@ -48,7 +42,7 @@ func NodeCompare(ctx context.Context, a, b NodeInterface, options *CompareOption
|
|||
return false
|
||||
}
|
||||
|
||||
if !NodeCompare(ctx, aChild, bChild, options) {
|
||||
if !NodeCompare(ctx, aChild, bChild) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
@ -56,7 +50,7 @@ func NodeCompare(ctx context.Context, a, b NodeInterface, options *CompareOption
|
|||
return true
|
||||
}
|
||||
|
||||
func TreeCompare(ctx context.Context, aTree TreeInterface, aPath Path, bTree TreeInterface, bPath Path, options *CompareOptions) bool {
|
||||
func TreeCompare(ctx context.Context, aTree TreeInterface, aPath Path, bTree TreeInterface, bPath Path) bool {
|
||||
aTree.Trace("'%s' => '%s'", aPath, bPath)
|
||||
|
||||
a := aTree.Find(aPath)
|
||||
|
|
@ -71,5 +65,5 @@ func TreeCompare(ctx context.Context, aTree TreeInterface, aPath Path, bTree Tre
|
|||
return false
|
||||
}
|
||||
|
||||
return NodeCompare(ctx, a, b, options)
|
||||
return NodeCompare(ctx, a, b)
|
||||
}
|
||||
|
|
|
|||
223
tree/generic/compare_test.go
Normal file
223
tree/generic/compare_test.go
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
// Copyright Earl Warren <contact@earl-warren.org>
|
||||
// Copyright Loïc Dachary <loic@dachary.org>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package generic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/logger"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type compareFormat struct {
|
||||
f3.Common
|
||||
V int
|
||||
}
|
||||
|
||||
func (o *compareFormat) Clone() f3.Interface {
|
||||
clone := &compareFormat{}
|
||||
*clone = *o
|
||||
return clone
|
||||
}
|
||||
|
||||
type compareNodeDriver struct {
|
||||
NullDriver
|
||||
v int
|
||||
ID string
|
||||
}
|
||||
|
||||
func (o *compareNodeDriver) NewFormat() f3.Interface {
|
||||
return &compareFormat{
|
||||
Common: f3.NewCommon(o.ID),
|
||||
}
|
||||
}
|
||||
|
||||
func (o *compareNodeDriver) ToFormat() f3.Interface {
|
||||
f := o.NewFormat().(*compareFormat)
|
||||
f.V = o.v
|
||||
return f
|
||||
}
|
||||
|
||||
func (o *compareNodeDriver) FromFormat(f f3.Interface) {
|
||||
fc := f.(*compareFormat)
|
||||
o.v = fc.V
|
||||
o.ID = fc.GetID()
|
||||
}
|
||||
|
||||
func newCompareNodeDriver() NodeDriverInterface {
|
||||
return &compareNodeDriver{}
|
||||
}
|
||||
|
||||
type compareTreeDriver struct {
|
||||
NullTreeDriver
|
||||
}
|
||||
|
||||
func newCompareTreeDriver() TreeDriverInterface {
|
||||
return &compareTreeDriver{}
|
||||
}
|
||||
|
||||
func (o *compareTreeDriver) Factory(ctx context.Context, kind Kind) NodeDriverInterface {
|
||||
d := newCompareNodeDriver()
|
||||
d.SetTreeDriver(o)
|
||||
return d
|
||||
}
|
||||
|
||||
func newCompareTree() TreeInterface {
|
||||
tree := &testTree{}
|
||||
tree.Init(tree, newTestOptions())
|
||||
tree.Trace("init done")
|
||||
tree.SetDriver(newCompareTreeDriver())
|
||||
tree.Register(kindCompareNode, func(ctx context.Context, kind Kind) NodeInterface {
|
||||
node := &compareNode{}
|
||||
return node.Init(node)
|
||||
})
|
||||
return tree
|
||||
}
|
||||
|
||||
var kindCompareNode = Kind("compare")
|
||||
|
||||
type compareNode struct {
|
||||
Node
|
||||
}
|
||||
|
||||
func TestTreeCompare(t *testing.T) {
|
||||
tree := newTestTree()
|
||||
log := logger.NewCaptureLogger()
|
||||
log.SetLevel(logger.Trace)
|
||||
tree.SetLogger(log)
|
||||
|
||||
root := tree.Factory(context.Background(), kindTestNodeLevelOne)
|
||||
tree.SetRoot(root)
|
||||
assert.True(t, TreeCompare(context.Background(), tree, NewPathFromString(""), tree, NewPathFromString("")))
|
||||
|
||||
log.Reset()
|
||||
assert.False(t, TreeCompare(context.Background(), tree, NewPathFromString("/notfound"), tree, NewPathFromString("")))
|
||||
assert.Contains(t, log.String(), "a does not have /notfound")
|
||||
|
||||
log.Reset()
|
||||
assert.False(t, TreeCompare(context.Background(), tree, NewPathFromString("/"), tree, NewPathFromString("/notfound")))
|
||||
assert.Contains(t, log.String(), "b does not have /notfound")
|
||||
}
|
||||
|
||||
func TestNodeCompare(t *testing.T) {
|
||||
log := logger.NewCaptureLogger()
|
||||
log.SetLevel(logger.Trace)
|
||||
|
||||
treeA := newCompareTree()
|
||||
treeA.SetLogger(log)
|
||||
|
||||
treeB := newCompareTree()
|
||||
treeB.SetLogger(log)
|
||||
|
||||
nodeA := treeA.Factory(context.Background(), kindCompareNode)
|
||||
nodeA.SetID("root")
|
||||
assert.True(t, NodeCompare(context.Background(), nodeA, nodeA))
|
||||
|
||||
t.Run("different kind", func(t *testing.T) {
|
||||
log.Reset()
|
||||
other := treeB.Factory(context.Background(), kindCompareNode)
|
||||
other.SetKind("other")
|
||||
assert.False(t, NodeCompare(context.Background(), nodeA, other))
|
||||
assert.Contains(t, log.String(), "kind is different")
|
||||
})
|
||||
|
||||
t.Run("difference", func(t *testing.T) {
|
||||
log.Reset()
|
||||
other := treeB.Factory(context.Background(), kindCompareNode)
|
||||
other.FromFormat(&compareFormat{V: 123456})
|
||||
|
||||
assert.False(t, NodeCompare(context.Background(), nodeA, other))
|
||||
assert.Contains(t, log.String(), "difference")
|
||||
assert.Contains(t, log.String(), "123456")
|
||||
})
|
||||
|
||||
t.Run("children count", func(t *testing.T) {
|
||||
log.Reset()
|
||||
other := treeB.Factory(context.Background(), kindCompareNode)
|
||||
other.SetChild(treeB.Factory(context.Background(), kindCompareNode))
|
||||
|
||||
assert.False(t, NodeCompare(context.Background(), nodeA, other))
|
||||
assert.Contains(t, log.String(), "children count")
|
||||
})
|
||||
|
||||
nodeAA := treeA.Factory(context.Background(), kindCompareNode)
|
||||
nodeAA.SetID("levelone")
|
||||
nodeA.SetChild(nodeAA)
|
||||
|
||||
nodeB := treeB.Factory(context.Background(), kindCompareNode)
|
||||
nodeB.SetID("root")
|
||||
|
||||
t.Run("children are the same", func(t *testing.T) {
|
||||
nodeBB := treeB.Factory(context.Background(), kindCompareNode)
|
||||
nodeBB.SetID("levelone")
|
||||
nodeB.SetChild(nodeBB)
|
||||
|
||||
assert.True(t, NodeCompare(context.Background(), nodeA, nodeB))
|
||||
|
||||
nodeB.DeleteChild(nodeBB.GetID())
|
||||
})
|
||||
|
||||
t.Run("children have different IDs", func(t *testing.T) {
|
||||
log.Reset()
|
||||
|
||||
nodeBB := treeB.Factory(context.Background(), kindCompareNode)
|
||||
nodeBB.SetID("SOMETHINGELSE")
|
||||
nodeB.SetChild(nodeBB)
|
||||
|
||||
assert.False(t, NodeCompare(context.Background(), nodeA, nodeB))
|
||||
assert.Contains(t, log.String(), "id levelone matching the child")
|
||||
|
||||
nodeB.DeleteChild(nodeBB.GetID())
|
||||
})
|
||||
|
||||
t.Run("children have different content", func(t *testing.T) {
|
||||
log.Reset()
|
||||
|
||||
nodeBB := treeB.Factory(context.Background(), kindCompareNode)
|
||||
nodeBB.FromFormat(&compareFormat{V: 12345678})
|
||||
nodeBB.SetID("levelone")
|
||||
nodeB.SetChild(nodeBB)
|
||||
|
||||
assert.False(t, NodeCompare(context.Background(), nodeA, nodeB))
|
||||
assert.Contains(t, log.String(), "difference")
|
||||
assert.Contains(t, log.String(), "12345678")
|
||||
|
||||
nodeB.DeleteChild(nodeBB.GetID())
|
||||
})
|
||||
|
||||
t.Run("children are the same because of their mapped ID", func(t *testing.T) {
|
||||
log.Reset()
|
||||
|
||||
nodeBB := treeB.Factory(context.Background(), kindCompareNode)
|
||||
nodeBB.SetID("REMAPPEDID")
|
||||
nodeB.SetChild(nodeBB)
|
||||
|
||||
nodeAA.SetMappedID("REMAPPEDID")
|
||||
|
||||
assert.True(t, NodeCompare(context.Background(), nodeA, nodeB))
|
||||
|
||||
nodeB.DeleteChild(nodeBB.GetID())
|
||||
nodeAA.SetMappedID(NilID)
|
||||
})
|
||||
|
||||
t.Run("children are different because of their mapped ID", func(t *testing.T) {
|
||||
log.Reset()
|
||||
|
||||
nodeBB := treeB.Factory(context.Background(), kindCompareNode)
|
||||
nodeBB.SetID("levelone")
|
||||
nodeB.SetChild(nodeBB)
|
||||
|
||||
nodeAA.SetMappedID("REMAPPEDID")
|
||||
|
||||
assert.False(t, NodeCompare(context.Background(), nodeA, nodeB))
|
||||
assert.Contains(t, log.String(), "id REMAPPEDID matching the child")
|
||||
|
||||
nodeB.DeleteChild(nodeBB.GetID())
|
||||
nodeAA.SetMappedID(NilID)
|
||||
})
|
||||
}
|
||||
|
|
@ -70,7 +70,7 @@ func (o *noopNodeDriver) FromFormat(f f3.Interface) {
|
|||
o.GetNode().SetID(NodeID(f.GetID()))
|
||||
}
|
||||
|
||||
func newNoopNodeDriver() NodeDriverInterface {
|
||||
func newTestNodeDriver() NodeDriverInterface {
|
||||
return &noopNodeDriver{}
|
||||
}
|
||||
|
||||
|
|
@ -83,22 +83,22 @@ func newTestTreeDriver() TreeDriverInterface {
|
|||
}
|
||||
|
||||
func (o *testTreeDriver) Factory(ctx context.Context, kind Kind) NodeDriverInterface {
|
||||
d := newNoopNodeDriver()
|
||||
d := newTestNodeDriver()
|
||||
d.SetTreeDriver(o)
|
||||
return d
|
||||
}
|
||||
|
||||
func NewTestTree() TreeInterface {
|
||||
func newTestTree() TreeInterface {
|
||||
tree := &testTree{}
|
||||
tree.Init(tree, newTestOptions())
|
||||
tree.Trace("init done")
|
||||
tree.SetDriver(newTestTreeDriver())
|
||||
tree.Register(KindTestNodeLevelOne, func(ctx context.Context, kind Kind) NodeInterface {
|
||||
node := &TestNodeLevelOne{}
|
||||
tree.Register(kindTestNodeLevelOne, func(ctx context.Context, kind Kind) NodeInterface {
|
||||
node := &testNodeLevelOne{}
|
||||
return node.Init(node)
|
||||
})
|
||||
tree.Register(KindTestNodeLevelTwo, func(ctx context.Context, kind Kind) NodeInterface {
|
||||
node := &TestNodeLevelTwo{}
|
||||
tree.Register(kindTestNodeLevelTwo, func(ctx context.Context, kind Kind) NodeInterface {
|
||||
node := &testNodeLevelTwo{}
|
||||
return node.Init(node)
|
||||
})
|
||||
return tree
|
||||
|
|
@ -124,19 +124,14 @@ func (o *testNode) Equals(ctx context.Context, other NodeInterface) bool {
|
|||
return o.GetV() == other.(testNodeInterface).GetV()
|
||||
}
|
||||
|
||||
func NewTestNode(v int) NodeInterface {
|
||||
node := &testNode{v: v}
|
||||
return node.Init(node)
|
||||
}
|
||||
var kindTestNodeLevelOne = Kind("levelone")
|
||||
|
||||
var KindTestNodeLevelOne = Kind("levelone")
|
||||
|
||||
type TestNodeLevelOne struct {
|
||||
type testNodeLevelOne struct {
|
||||
testNode
|
||||
}
|
||||
|
||||
var KindTestNodeLevelTwo = Kind("leveltwo")
|
||||
var kindTestNodeLevelTwo = Kind("leveltwo")
|
||||
|
||||
type TestNodeLevelTwo struct {
|
||||
type testNodeLevelTwo struct {
|
||||
testNode
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,14 +41,14 @@ func TestNodeIsNil(t *testing.T) {
|
|||
assert.True(t, node.GetIsNil())
|
||||
}
|
||||
|
||||
func TestNodeCompare(t *testing.T) {
|
||||
func TestNodeEquals(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
tree := NewTestTree()
|
||||
one := tree.Factory(ctx, KindTestNodeLevelOne)
|
||||
one.(*TestNodeLevelOne).v = 1
|
||||
tree := newTestTree()
|
||||
one := tree.Factory(ctx, kindTestNodeLevelOne)
|
||||
one.(*testNodeLevelOne).v = 1
|
||||
assert.True(t, one.Equals(ctx, one))
|
||||
two := tree.Factory(ctx, KindTestNodeLevelOne)
|
||||
two.(*TestNodeLevelOne).v = 2
|
||||
two := tree.Factory(ctx, kindTestNodeLevelOne)
|
||||
two.(*testNodeLevelOne).v = 2
|
||||
assert.False(t, one.Equals(ctx, two))
|
||||
}
|
||||
|
||||
|
|
@ -77,6 +77,40 @@ func TestNodeMappedID(t *testing.T) {
|
|||
assert.True(t, mapped == node.GetMappedID())
|
||||
}
|
||||
|
||||
func TestNodeNewFormat(t *testing.T) {
|
||||
node := NewNode()
|
||||
node.SetDriver(NewNullDriver())
|
||||
|
||||
assert.Panics(t, func() { node.NewFormat() })
|
||||
}
|
||||
|
||||
func TestChildren(t *testing.T) {
|
||||
parent := NewNode()
|
||||
assert.Empty(t, parent.GetChildren())
|
||||
|
||||
id1 := NodeID("one")
|
||||
child1 := NewNode()
|
||||
child1.SetID(id1)
|
||||
parent.SetChild(child1)
|
||||
|
||||
id2 := NodeID("two")
|
||||
child2 := NewNode()
|
||||
child2.SetID(id2)
|
||||
parent.SetChild(child2)
|
||||
|
||||
children := parent.GetChildren()
|
||||
assert.Len(t, children, 2)
|
||||
assert.Equal(t, children[0].GetID(), id1)
|
||||
assert.Equal(t, children[1].GetID(), id2)
|
||||
|
||||
nodeChildren := parent.GetNodeChildren()
|
||||
assert.Len(t, nodeChildren, 2)
|
||||
delete(nodeChildren, id1)
|
||||
parent.SetChildren(nodeChildren)
|
||||
nodeChildren = parent.GetNodeChildren()
|
||||
assert.Len(t, nodeChildren, 1)
|
||||
}
|
||||
|
||||
func TestNodeID(t *testing.T) {
|
||||
node := NewNode()
|
||||
assert.EqualValues(t, NilID, node.GetID())
|
||||
|
|
@ -128,7 +162,7 @@ type treeChildren struct {
|
|||
Tree
|
||||
}
|
||||
|
||||
func NewTreeChildren() TreeInterface {
|
||||
func newTreeChildren() TreeInterface {
|
||||
tree := &treeChildren{}
|
||||
tree.Init(tree, newTestOptions())
|
||||
treeDriver := &driverTreeChildren{}
|
||||
|
|
@ -143,7 +177,7 @@ func NewTreeChildren() TreeInterface {
|
|||
}
|
||||
|
||||
func TestNodeListPage(t *testing.T) {
|
||||
tree := NewTreeChildren()
|
||||
tree := newTreeChildren()
|
||||
|
||||
ctx := context.Background()
|
||||
node := tree.Factory(ctx, KindNil)
|
||||
|
|
@ -158,7 +192,7 @@ func TestNodeListPage(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestNodeList(t *testing.T) {
|
||||
tree := NewTreeChildren()
|
||||
tree := newTreeChildren()
|
||||
|
||||
ctx := context.Background()
|
||||
node := tree.Factory(ctx, KindNil)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import (
|
|||
)
|
||||
|
||||
type Path interface {
|
||||
Clone() Path
|
||||
Length() int
|
||||
PathString() PathString
|
||||
PathMappedString() PathString
|
||||
|
|
@ -19,6 +18,7 @@ type Path interface {
|
|||
RemoveFirst() Path
|
||||
PopFirst() (NodeInterface, Path)
|
||||
Pop() (NodeInterface, Path)
|
||||
RemoveLast() Path
|
||||
Empty() bool
|
||||
First() NodeInterface
|
||||
Last() NodeInterface
|
||||
|
|
@ -29,16 +29,16 @@ type PathImplementation []NodeInterface
|
|||
|
||||
func PathAbsoluteString(current, destination string) string {
|
||||
if !strings.HasPrefix(destination, "/") {
|
||||
return current + "/" + destination
|
||||
return filepath.Clean(current + "/" + destination)
|
||||
}
|
||||
return destination
|
||||
return filepath.Clean(destination)
|
||||
}
|
||||
|
||||
func PathAbsolute(current, destination string) Path {
|
||||
return NewPathFromString(PathAbsoluteString(current, destination))
|
||||
}
|
||||
|
||||
func PathStringRelative(current, destination string) string {
|
||||
func PathRelativeString(current, destination string) string {
|
||||
r, err := filepath.Rel(current, destination)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
@ -75,8 +75,14 @@ func NewPath(nodes ...NodeInterface) Path {
|
|||
|
||||
func (o PathImplementation) PathString() PathString {
|
||||
elements := make([]string, 0, 10)
|
||||
for _, node := range o {
|
||||
elements = append(elements, string(node.GetID()))
|
||||
for i, node := range o {
|
||||
id := node.GetID()
|
||||
element := string(id)
|
||||
// i == 0 is root and intentionally empty
|
||||
if i > 0 && id == NilID {
|
||||
element = "nothing"
|
||||
}
|
||||
elements = append(elements, element)
|
||||
}
|
||||
return elements
|
||||
}
|
||||
|
|
@ -97,10 +103,6 @@ func (o PathImplementation) Length() int {
|
|||
return len(o)
|
||||
}
|
||||
|
||||
func (o PathImplementation) Clone() Path {
|
||||
return o[:]
|
||||
}
|
||||
|
||||
func (o PathImplementation) Append(child NodeInterface) Path {
|
||||
return append(o, child)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,3 +104,62 @@ func TestNodePath(t *testing.T) {
|
|||
assert.EqualValues(t, "/1/2", pathString.Join())
|
||||
}
|
||||
}
|
||||
|
||||
func TestPathAbsoluteString(t *testing.T) {
|
||||
assert.Equal(t, "/c", PathAbsoluteString("/a/b", "/c/d/.."))
|
||||
assert.Equal(t, "/a/b/c", PathAbsoluteString("/a/b", "c"))
|
||||
assert.Equal(t, "/a/b/c", PathAbsoluteString("/a/./b", "c/d/.."))
|
||||
}
|
||||
|
||||
func TestPathAbsolute(t *testing.T) {
|
||||
assert.Equal(t, "/a/b/c", PathAbsolute("/a/b", "c").String())
|
||||
}
|
||||
|
||||
func TestPathRelativeString(t *testing.T) {
|
||||
assert.Equal(t, "../c", PathRelativeString("/a/b/d", "/a/b/c"))
|
||||
assert.Panics(t, func() { PathRelativeString("/a/b/d", "") })
|
||||
}
|
||||
|
||||
func TestPathString(t *testing.T) {
|
||||
path := NewPathFromString("/a/b/c")
|
||||
assert.Equal(t, "/a/b/c", path.PathString().Join())
|
||||
last, path := path.Pop()
|
||||
path = path.Append(NewNode())
|
||||
path = path.Append(last)
|
||||
assert.Equal(t, "/a/b/nothing/c", path.PathString().Join())
|
||||
}
|
||||
|
||||
func TestPathMappedString(t *testing.T) {
|
||||
path := NewPathFromString("/a/b")
|
||||
for _, node := range path.All() {
|
||||
node.SetDriver(NewNullDriver())
|
||||
node.SetMappedID(node.GetID() + "M")
|
||||
}
|
||||
assert.Equal(t, "M/aM/bM", path.PathMappedString().Join())
|
||||
}
|
||||
|
||||
func TestPathMethods(t *testing.T) {
|
||||
path := NewPathFromString("/a/b/c")
|
||||
assert.Equal(t, "/a/b/c", path.String())
|
||||
assert.Equal(t, 4, path.Length())
|
||||
assert.Len(t, path.All(), 4)
|
||||
assert.False(t, path.Empty())
|
||||
|
||||
first, path := path.PopFirst()
|
||||
assert.Equal(t, "", string(first.GetID()))
|
||||
assert.Equal(t, "a/b/c", path.String())
|
||||
|
||||
assert.Equal(t, "a", string(path.First().GetID()))
|
||||
|
||||
assert.Equal(t, "c", string(path.Last().GetID()))
|
||||
|
||||
firstRemoved := path.RemoveFirst()
|
||||
assert.Equal(t, "b/c", firstRemoved.String())
|
||||
|
||||
last, lastRemoved := path.Pop()
|
||||
assert.Equal(t, "c", string(last.GetID()))
|
||||
assert.Equal(t, "a/b", lastRemoved.String())
|
||||
|
||||
lastRemoved = path.RemoveLast()
|
||||
assert.Equal(t, "a/b", lastRemoved.String())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,10 +6,49 @@ package generic
|
|||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/util"
|
||||
)
|
||||
|
||||
type ErrorRemapReferencesRelative error
|
||||
|
||||
func RemapReferences(ctx context.Context, node NodeInterface, f f3.Interface) {
|
||||
for _, reference := range f.GetReferences() {
|
||||
toPath := NewPath()
|
||||
collectTo := func(ctx context.Context, parent, path Path, node NodeInterface) {
|
||||
element := NewNode()
|
||||
mappedID := node.GetMappedID()
|
||||
if mappedID == "" {
|
||||
node.Trace("mapped ID for %s is not defined", path)
|
||||
}
|
||||
element.SetID(mappedID)
|
||||
toPath = toPath.Append(element)
|
||||
}
|
||||
from := reference.Get()
|
||||
isRelative := !strings.HasPrefix(from, "/")
|
||||
if isRelative && !strings.HasPrefix(from, "..") {
|
||||
panic(NewError[ErrorRemapReferencesRelative]("relative references that do not start with .. are not supported %s", from))
|
||||
}
|
||||
current := node.GetCurrentPath().String()
|
||||
fromPath := PathAbsolute(current, from)
|
||||
node.GetTree().Apply(ctx, fromPath, NewApplyOptions(collectTo).SetWhere(ApplyEachNode))
|
||||
to := toPath.String()
|
||||
node.Trace("from '%s' to '%s'", fromPath, to)
|
||||
if isRelative {
|
||||
currentMapped := node.GetParent().GetCurrentPath().PathMappedString().Join()
|
||||
// because the mapped ID of the current node has not been allocated yet
|
||||
// and it does not matter as long as it is replaced with ..
|
||||
// it will not work at all if a relative reference does not start with ..
|
||||
currentMapped += "/PLACEHODLER"
|
||||
to = PathRelativeString(currentMapped, to)
|
||||
}
|
||||
node.Trace("convert reference %s => %s", reference.Get(), to)
|
||||
reference.Set(to)
|
||||
}
|
||||
}
|
||||
|
||||
func NodeCollectReferences(ctx context.Context, node NodeInterface) []Path {
|
||||
pathToReferences := make(map[string]Path, 5)
|
||||
|
||||
|
|
@ -23,15 +62,9 @@ func NodeCollectReferences(ctx context.Context, node NodeInterface) []Path {
|
|||
if _, ok := pathToReferences[absoluteReference]; ok {
|
||||
continue
|
||||
}
|
||||
found := tree.ApplyAndGet(ctx, NewPathFromString(absoluteReference), NewApplyOptions(func(ctx context.Context, parent, path Path, node NodeInterface) {
|
||||
if !node.GetIsSync() {
|
||||
node.Get(ctx)
|
||||
}
|
||||
tree.ApplyAndGet(ctx, NewPathFromString(absoluteReference), NewApplyOptions(func(ctx context.Context, parent, path Path, node NodeInterface) {
|
||||
pathToReferences[absoluteReference] = node.GetCurrentPath()
|
||||
}))
|
||||
if !found {
|
||||
panic(NewError[ErrorNodeNotFound]("reference %s is not found in %s", reference.Get(), node.GetCurrentPath()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
163
tree/generic/references_test.go
Normal file
163
tree/generic/references_test.go
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
// Copyright Earl Warren <contact@earl-warren.org>
|
||||
// Copyright Loïc Dachary <loic@dachary.org>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package generic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type referenceFormat struct {
|
||||
f3.Common
|
||||
R *f3.Reference
|
||||
}
|
||||
|
||||
func (o *referenceFormat) Clone() f3.Interface {
|
||||
clone := &referenceFormat{}
|
||||
*clone = *o
|
||||
return clone
|
||||
}
|
||||
|
||||
func (o *referenceFormat) GetReferences() f3.References {
|
||||
references := o.Common.GetReferences()
|
||||
if o.R != nil {
|
||||
references = append(references, o.R)
|
||||
}
|
||||
return references
|
||||
}
|
||||
|
||||
type referencesNodeDriver struct {
|
||||
NullDriver
|
||||
|
||||
f referenceFormat
|
||||
}
|
||||
|
||||
func (o *referencesNodeDriver) GetIDFromName(ctx context.Context, name string) NodeID {
|
||||
return NilID
|
||||
}
|
||||
|
||||
func (o *referencesNodeDriver) Get(context.Context) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *referencesNodeDriver) NewFormat() f3.Interface {
|
||||
return &referenceFormat{}
|
||||
}
|
||||
|
||||
func (o *referencesNodeDriver) ToFormat() f3.Interface {
|
||||
return &o.f
|
||||
}
|
||||
|
||||
func (o *referencesNodeDriver) FromFormat(f f3.Interface) {
|
||||
o.f = *f.(*referenceFormat)
|
||||
}
|
||||
|
||||
func newReferencesNodeDriver() NodeDriverInterface {
|
||||
return &referencesNodeDriver{}
|
||||
}
|
||||
|
||||
type testTreeReferencesDriver struct {
|
||||
NullTreeDriver
|
||||
}
|
||||
|
||||
func newTestTreeReferencesDriver() TreeDriverInterface {
|
||||
return &testTreeReferencesDriver{}
|
||||
}
|
||||
|
||||
func (o *testTreeReferencesDriver) Factory(ctx context.Context, kind Kind) NodeDriverInterface {
|
||||
d := newReferencesNodeDriver()
|
||||
d.SetTreeDriver(o)
|
||||
return d
|
||||
}
|
||||
|
||||
var kindTestNodeReferences = Kind("references")
|
||||
|
||||
type testNodeReferences struct {
|
||||
testNode
|
||||
}
|
||||
|
||||
func newTestTreeReferences() TreeInterface {
|
||||
tree := &testTree{}
|
||||
tree.Init(tree, newTestOptions())
|
||||
tree.SetDriver(newTestTreeReferencesDriver())
|
||||
tree.Register(kindTestNodeReferences, func(ctx context.Context, kind Kind) NodeInterface {
|
||||
node := &testNodeReferences{}
|
||||
return node.Init(node)
|
||||
})
|
||||
return tree
|
||||
}
|
||||
|
||||
func TestTreeCollectReferences(t *testing.T) {
|
||||
tree := newTestTreeReferences()
|
||||
root := tree.Factory(context.Background(), kindTestNodeReferences)
|
||||
tree.SetRoot(root)
|
||||
|
||||
one := tree.Factory(context.Background(), kindTestNodeReferences)
|
||||
one.FromFormat(&referenceFormat{R: f3.NewReference("/somewhere")})
|
||||
one.SetID("one")
|
||||
root.SetChild(one)
|
||||
|
||||
// the second node that has the same reference is here to ensure
|
||||
// they are deduplicated
|
||||
two := tree.Factory(context.Background(), kindTestNodeReferences)
|
||||
two.FromFormat(&referenceFormat{R: f3.NewReference("/somewhere")})
|
||||
two.SetID("two")
|
||||
root.SetChild(two)
|
||||
|
||||
references := TreeCollectReferences(context.Background(), tree, NewPathFromString("/"))
|
||||
assert.Len(t, references, 1)
|
||||
assert.EqualValues(t, "/somewhere", references[0].String())
|
||||
}
|
||||
|
||||
func TestRemapReferences(t *testing.T) {
|
||||
tree := newTestTreeReferences()
|
||||
|
||||
root := tree.Factory(context.Background(), kindTestNodeReferences)
|
||||
tree.SetRoot(root)
|
||||
|
||||
one := tree.Factory(context.Background(), kindTestNodeReferences)
|
||||
one.SetID("one")
|
||||
one.SetMappedID("remappedone")
|
||||
one.SetParent(root)
|
||||
root.SetChild(one)
|
||||
|
||||
two := tree.Factory(context.Background(), kindTestNodeReferences)
|
||||
two.FromFormat(&referenceFormat{R: f3.NewReference("/one")})
|
||||
two.SetID("two")
|
||||
two.SetMappedID("two")
|
||||
two.SetParent(root)
|
||||
root.SetChild(two)
|
||||
|
||||
{
|
||||
f := two.ToFormat()
|
||||
RemapReferences(context.Background(), two, f)
|
||||
r := f.GetReferences()
|
||||
if assert.Len(t, r, 1) {
|
||||
assert.Equal(t, "/remappedone", r[0].Get())
|
||||
}
|
||||
}
|
||||
|
||||
three := tree.Factory(context.Background(), kindTestNodeReferences)
|
||||
three.FromFormat(&referenceFormat{R: f3.NewReference("../../one")})
|
||||
three.SetID("three")
|
||||
three.SetMappedID("three")
|
||||
three.SetParent(two)
|
||||
two.SetChild(three)
|
||||
|
||||
{
|
||||
f := three.ToFormat()
|
||||
RemapReferences(context.Background(), three, f)
|
||||
r := f.GetReferences()
|
||||
if assert.Len(t, r, 1) {
|
||||
assert.Equal(t, "../../remappedone", r[0].Get())
|
||||
}
|
||||
}
|
||||
|
||||
assert.Panics(t, func() { RemapReferences(context.Background(), three, &referenceFormat{R: f3.NewReference("./one")}) })
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestTreeInit(t *testing.T) {
|
||||
|
|
@ -40,17 +41,48 @@ func TestTreePageSize(t *testing.T) {
|
|||
assert.EqualValues(t, pageSize, tree.GetPageSize())
|
||||
}
|
||||
|
||||
func TestTreeAllocateID(t *testing.T) {
|
||||
tree := NewTree(newTestOptions())
|
||||
assert.True(t, tree.AllocateID())
|
||||
}
|
||||
|
||||
func TestTreeFactoryDerived(t *testing.T) {
|
||||
tree := NewTestTree()
|
||||
root := tree.Factory(context.Background(), KindTestNodeLevelOne)
|
||||
tree := newTestTree()
|
||||
root := tree.Factory(context.Background(), kindTestNodeLevelOne)
|
||||
tree.SetRoot(root)
|
||||
assert.True(t, root == tree.GetRoot())
|
||||
assert.True(t, KindTestNodeLevelOne == root.GetKind())
|
||||
assert.True(t, kindTestNodeLevelOne == root.GetKind())
|
||||
assert.True(t, tree.GetSelf() == root.GetTree().GetSelf())
|
||||
|
||||
leveltwo := tree.Factory(context.Background(), KindTestNodeLevelTwo)
|
||||
leveltwo := tree.Factory(context.Background(), kindTestNodeLevelTwo)
|
||||
leveltwo.SetParent(root)
|
||||
assert.True(t, root == leveltwo.GetParent())
|
||||
assert.True(t, KindTestNodeLevelTwo == leveltwo.GetKind())
|
||||
assert.True(t, kindTestNodeLevelTwo == leveltwo.GetKind())
|
||||
assert.True(t, tree.GetSelf() == leveltwo.GetTree().GetSelf())
|
||||
}
|
||||
|
||||
func TestTreeApply(t *testing.T) {
|
||||
tree := newTestTree()
|
||||
root := tree.Factory(context.Background(), kindTestNodeLevelOne)
|
||||
tree.SetRoot(root)
|
||||
|
||||
assert.True(t, tree.Apply(context.Background(), NewPath(), nil))
|
||||
assert.True(t, tree.Apply(context.Background(), NewPathFromString("/"),
|
||||
NewApplyOptions(func(ctx context.Context, parent, path Path, node NodeInterface) {
|
||||
require.Equal(t, root, node)
|
||||
})),
|
||||
)
|
||||
}
|
||||
|
||||
func TestTreeApplyAndGet(t *testing.T) {
|
||||
tree := newTestTree()
|
||||
root := tree.Factory(context.Background(), kindTestNodeLevelOne)
|
||||
tree.SetRoot(root)
|
||||
|
||||
assert.True(t, tree.ApplyAndGet(context.Background(), NewPath(), nil))
|
||||
assert.True(t, tree.ApplyAndGet(context.Background(), NewPathFromString("/"),
|
||||
NewApplyOptions(func(ctx context.Context, parent, path Path, node NodeInterface) {
|
||||
require.Equal(t, root, node)
|
||||
})),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,10 +6,7 @@ package generic
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/util"
|
||||
)
|
||||
|
||||
|
|
@ -91,37 +88,6 @@ func TreeUnify(ctx context.Context, origin, destination TreeInterface, options *
|
|||
NodeUnify(ctx, originRoot, NewPath(), destinationRoot, NewPath(), options)
|
||||
}
|
||||
|
||||
func RemapReferences(ctx context.Context, node NodeInterface, f f3.Interface) {
|
||||
for _, reference := range f.GetReferences() {
|
||||
toPath := NewPath()
|
||||
collectTo := func(ctx context.Context, parent, path Path, node NodeInterface) {
|
||||
element := NewNode()
|
||||
element.SetID(node.GetMappedID())
|
||||
toPath = toPath.Append(element)
|
||||
}
|
||||
from := reference.Get()
|
||||
isRelative := !strings.HasPrefix(from, "/")
|
||||
if isRelative && !strings.HasPrefix(from, "..") {
|
||||
panic(fmt.Errorf("relative references that do not start with .. are not supported %s", from))
|
||||
}
|
||||
current := node.GetCurrentPath().String()
|
||||
fromPath := PathAbsolute(current, from)
|
||||
node.Trace("collectTo %s", from)
|
||||
node.GetTree().Apply(ctx, fromPath, NewApplyOptions(collectTo).SetWhere(ApplyEachNode))
|
||||
to := toPath.String()
|
||||
if isRelative {
|
||||
currentMapped := node.GetParent().GetCurrentPath().PathMappedString().Join()
|
||||
// because the mapped ID of the current node has not been allocated yet
|
||||
// and it does not matter as long as it is replaced with ..
|
||||
// it will not work at all if a relative reference does not start with ..
|
||||
currentMapped += "/PLACEHODLER"
|
||||
to = PathStringRelative(currentMapped, to)
|
||||
}
|
||||
node.Trace("convert reference %s => %s", reference.Get(), to)
|
||||
reference.Set(to)
|
||||
}
|
||||
}
|
||||
|
||||
func NodeCopy(ctx context.Context, origin, destination NodeInterface, destinationID NodeID, options *UnifyOptions) {
|
||||
f := origin.GetSelf().ToFormat()
|
||||
if options.noremap {
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ import (
|
|||
func TestUnifyNilRootOrigin(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
origin := NewTestTree()
|
||||
destination := NewTestTree()
|
||||
origin := newTestTree()
|
||||
destination := newTestTree()
|
||||
destinationRoot := NewNode()
|
||||
destination.SetRoot(destinationRoot)
|
||||
assert.Equal(t, destinationRoot, destination.GetRoot())
|
||||
|
|
@ -26,10 +26,10 @@ func TestUnifyNilRootOrigin(t *testing.T) {
|
|||
func TestUnifyNilRootDestination(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
origin := NewTestTree()
|
||||
originRoot := origin.Factory(ctx, KindTestNodeLevelOne)
|
||||
origin := newTestTree()
|
||||
originRoot := origin.Factory(ctx, kindTestNodeLevelOne)
|
||||
origin.SetRoot(originRoot)
|
||||
destination := NewTestTree()
|
||||
destination := newTestTree()
|
||||
TreeUnify(ctx, origin, destination, NewUnifyOptions(destination))
|
||||
assert.EqualValues(t, KindTestNodeLevelOne, destination.GetRoot().GetKind())
|
||||
assert.EqualValues(t, kindTestNodeLevelOne, destination.GetRoot().GetKind())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -179,7 +179,6 @@ func (f *Creator) GenerateMilestone() *f3.Milestone {
|
|||
|
||||
func (f *Creator) GeneratePullRequest(parent generic.Path) *f3.PullRequest {
|
||||
user := f3_tree.GetFirstFormat[*f3.User](parent.Last())
|
||||
project := f3_tree.GetFirstFormat[*f3.Project](parent.Last())
|
||||
projectNode := f3_tree.GetFirstNodeKind(parent.Last(), f3_tree.KindProject)
|
||||
repositoryNode := projectNode.Find(generic.NewPathFromString("repositories/vcs"))
|
||||
repositoryNode.Get(context.Background())
|
||||
|
|
@ -210,16 +209,14 @@ func (f *Creator) GeneratePullRequest(parent generic.Path) *f3.PullRequest {
|
|||
MergedTime: nil,
|
||||
MergeCommitSHA: "",
|
||||
Head: f3.PullRequestBranch{
|
||||
Ref: featureRef,
|
||||
SHA: featureSha,
|
||||
RepoName: project.Name,
|
||||
OwnerName: user.UserName,
|
||||
Ref: featureRef,
|
||||
SHA: featureSha,
|
||||
Repository: f3_tree.NewPullRequestSameRepositoryReference(),
|
||||
},
|
||||
Base: f3.PullRequestBranch{
|
||||
Ref: mainRef,
|
||||
SHA: mainSha,
|
||||
RepoName: project.Name,
|
||||
OwnerName: user.UserName,
|
||||
Ref: mainRef,
|
||||
SHA: mainSha,
|
||||
Repository: f3_tree.NewPullRequestSameRepositoryReference(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ func TestF3Mirror(t *testing.T) {
|
|||
|
||||
fixtureTree.Trace("======= compare fixture with forge mirrored to filesystem")
|
||||
for _, pathPair := range pathPairs {
|
||||
assert.True(t, generic.TreeCompare(ctx, fixtureTree, pathPair[0], verificationTree, pathPair[1], generic.NewCompareOptions()))
|
||||
assert.True(t, generic.TreeCompare(ctx, fixtureTree, pathPair[0], verificationTree, pathPair[1]))
|
||||
}
|
||||
|
||||
TreeDelete(t, testForge.GetNonTestUsers(), forgeWriteOptions, forgeWriteTree)
|
||||
|
|
@ -175,7 +175,7 @@ func TestF3Tree(t *testing.T) {
|
|||
otherTree := generic.GetFactory("f3")(ctx, tests_forge.GetFactory(filesystem_options.Name)().NewOptions(t))
|
||||
otherTree.GetOptions().(options.URLInterface).SetURL(tree.GetOptions().(options.URLInterface).GetURL())
|
||||
otherTree.WalkAndGet(ctx, generic.NewWalkOptions(nil))
|
||||
assert.True(t, generic.TreeCompare(ctx, tree, generic.NewPathFromString(""), otherTree, generic.NewPathFromString(""), generic.NewCompareOptions()))
|
||||
assert.True(t, generic.TreeCompare(ctx, tree, generic.NewPathFromString(""), otherTree, generic.NewPathFromString("")))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ func TestF3FilesystemMappedID(t *testing.T) {
|
|||
|
||||
generic.TreeMirror(ctx, aTree, bTree, rootPath, generic.NewMirrorOptions())
|
||||
|
||||
assert.True(t, generic.TreeCompare(ctx, aTree, rootPath, bTree, rootPath, generic.NewCompareOptions()))
|
||||
assert.True(t, generic.TreeCompare(ctx, aTree, rootPath, bTree, rootPath))
|
||||
|
||||
//
|
||||
// aTree maps user id 10111 to 10111.mapped
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ func ComplianceTests(t *testing.T, tree f3_tree.TreeInterface, kindToFixturePath
|
|||
tree.Trace("about to insert child %s", id)
|
||||
assert.EqualValues(t, generic.NilNode, parent.GetChild(child.GetID()))
|
||||
} else {
|
||||
tree.Trace("about insert child with nil ID")
|
||||
tree.Trace("about to insert child with nil ID")
|
||||
}
|
||||
if child.GetDriver().IsNull() {
|
||||
t.Skip("no driver, skipping")
|
||||
|
|
@ -107,7 +107,7 @@ func ComplianceTests(t *testing.T, tree f3_tree.TreeInterface, kindToFixturePath
|
|||
}
|
||||
child.FromFormat(a)
|
||||
b := child.ToFormat()
|
||||
cmpOptions := f3.NewCmpCompareOptions(a)
|
||||
cmpOptions := f3.NewCmpOptions(a)
|
||||
require.True(t, cmp.Equal(a, b, cmpOptions), cmp.Diff(a, b, cmpOptions))
|
||||
|
||||
child.FromFormat(saved)
|
||||
|
|
|
|||
|
|
@ -318,7 +318,6 @@ func GeneratorModifyReleaseAsset(asset *f3.ReleaseAsset, parent generic.Path) *f
|
|||
|
||||
func GeneratorSetRandomPullRequest(t *testing.T, pullRequest *f3.PullRequest, parent generic.Path) *f3.PullRequest {
|
||||
user := f3_tree.GetFirstFormat[*f3.User](parent.Last())
|
||||
project := f3_tree.GetFirstFormat[*f3.Project](parent.Last())
|
||||
projectNode := f3_tree.GetFirstNodeKind(parent.Last(), f3_tree.KindProject)
|
||||
repositoryNode := projectNode.Find(generic.NewPathFromString("repositories/vcs"))
|
||||
repositoryNode.Get(context.Background())
|
||||
|
|
@ -348,16 +347,14 @@ func GeneratorSetRandomPullRequest(t *testing.T, pullRequest *f3.PullRequest, pa
|
|||
pullRequest.MergedTime = nil
|
||||
pullRequest.MergeCommitSHA = ""
|
||||
pullRequest.Head = f3.PullRequestBranch{
|
||||
Ref: featureRef,
|
||||
SHA: featureSha,
|
||||
RepoName: project.Name,
|
||||
OwnerName: user.UserName,
|
||||
Ref: featureRef,
|
||||
SHA: featureSha,
|
||||
Repository: f3.NewReference("../../repository/vcs"),
|
||||
}
|
||||
pullRequest.Base = f3.PullRequestBranch{
|
||||
Ref: mainRef,
|
||||
SHA: mainSha,
|
||||
RepoName: project.Name,
|
||||
OwnerName: user.UserName,
|
||||
Ref: mainRef,
|
||||
SHA: mainSha,
|
||||
Repository: f3.NewReference("../../repository/vcs"),
|
||||
}
|
||||
return pullRequest
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,8 @@ func TestF3PullRequest(t *testing.T) {
|
|||
|
||||
fixtureTree.Trace("======= compare fixture with forge mirrored to filesystem")
|
||||
for _, pathPair := range pathPairs {
|
||||
assert.True(t, generic.TreeCompare(ctx, fixtureTree, pathPair[0], verificationTree, pathPair[1], generic.NewCompareOptions()))
|
||||
fixtureTree.Trace("======= compare %s with %s", pathPair[0], pathPair[1])
|
||||
assert.True(t, generic.TreeCompare(ctx, fixtureTree, pathPair[0], verificationTree, pathPair[1]))
|
||||
}
|
||||
|
||||
TreeDelete(t, testForge.GetNonTestUsers(), forgeWriteOptions, forgeWriteTree)
|
||||
|
|
|
|||
|
|
@ -22,16 +22,16 @@ func TestCompare(t *testing.T) {
|
|||
bTree := NewMemoryTree(ctx, "O")
|
||||
testTreeBuild(t, bTree, 2)
|
||||
|
||||
assert.True(t, generic.TreeCompare(ctx, aTree, generic.NewPathFromString(""), bTree, generic.NewPathFromString(""), generic.NewCompareOptions()))
|
||||
assert.True(t, generic.TreeCompare(ctx, aTree, generic.NewPathFromString(""), bTree, generic.NewPathFromString("")))
|
||||
|
||||
{
|
||||
toDelete := generic.NewPathFromString("/O-A/O-B")
|
||||
|
||||
aTree.Find(toDelete).Delete(ctx)
|
||||
assert.False(t, generic.TreeCompare(ctx, aTree, generic.NewPathFromString(""), bTree, generic.NewPathFromString(""), generic.NewCompareOptions()))
|
||||
assert.False(t, generic.TreeCompare(ctx, aTree, generic.NewPathFromString(""), bTree, generic.NewPathFromString("")))
|
||||
|
||||
bTree.Find(toDelete).Delete(ctx)
|
||||
assert.True(t, generic.TreeCompare(ctx, aTree, generic.NewPathFromString(""), bTree, generic.NewPathFromString(""), generic.NewCompareOptions()))
|
||||
assert.True(t, generic.TreeCompare(ctx, aTree, generic.NewPathFromString(""), bTree, generic.NewPathFromString("")))
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -40,33 +40,33 @@ func TestCompare(t *testing.T) {
|
|||
aNode := aTree.Find(toModify)
|
||||
memory.SetContent(aNode, content)
|
||||
aNode.Upsert(ctx)
|
||||
assert.False(t, generic.TreeCompare(ctx, aTree, generic.NewPathFromString(""), bTree, generic.NewPathFromString(""), generic.NewCompareOptions()))
|
||||
assert.False(t, generic.TreeCompare(ctx, aTree, generic.NewPathFromString(""), bTree, generic.NewPathFromString("")))
|
||||
|
||||
bNode := bTree.Find(toModify)
|
||||
memory.SetContent(bNode, content)
|
||||
bNode.Upsert(ctx)
|
||||
|
||||
assert.True(t, generic.TreeCompare(ctx, aTree, generic.NewPathFromString(""), bTree, generic.NewPathFromString(""), generic.NewCompareOptions()))
|
||||
assert.True(t, generic.TreeCompare(ctx, aTree, generic.NewPathFromString(""), bTree, generic.NewPathFromString("")))
|
||||
}
|
||||
|
||||
{
|
||||
toModify := generic.NewPathFromString("/O-A/O-F")
|
||||
aTree.Find(toModify).SetKind(generic.Kind("???"))
|
||||
assert.False(t, generic.TreeCompare(ctx, aTree, generic.NewPathFromString(""), bTree, generic.NewPathFromString(""), generic.NewCompareOptions()))
|
||||
assert.False(t, generic.TreeCompare(ctx, aTree, generic.NewPathFromString(""), bTree, generic.NewPathFromString("")))
|
||||
bTree.Find(toModify).SetKind(generic.Kind("???"))
|
||||
assert.True(t, generic.TreeCompare(ctx, aTree, generic.NewPathFromString(""), bTree, generic.NewPathFromString(""), generic.NewCompareOptions()))
|
||||
assert.True(t, generic.TreeCompare(ctx, aTree, generic.NewPathFromString(""), bTree, generic.NewPathFromString("")))
|
||||
}
|
||||
|
||||
{
|
||||
pathToMap := generic.NewPathFromString("/O-A/O-J/O-M")
|
||||
mappedID := generic.NodeID("MAPPED")
|
||||
aTree.Find(pathToMap).SetMappedID(mappedID)
|
||||
assert.False(t, generic.TreeCompare(ctx, aTree, generic.NewPathFromString(""), bTree, generic.NewPathFromString(""), generic.NewCompareOptions()))
|
||||
assert.False(t, generic.TreeCompare(ctx, aTree, generic.NewPathFromString(""), bTree, generic.NewPathFromString("")))
|
||||
|
||||
bNode := bTree.Find(pathToMap).Delete(ctx)
|
||||
bNode.SetID(mappedID)
|
||||
parentPathToMap := generic.NewPathFromString("/O-A/O-J")
|
||||
bTree.Find(parentPathToMap).SetChild(bNode)
|
||||
assert.True(t, generic.TreeCompare(ctx, aTree, generic.NewPathFromString(""), bTree, generic.NewPathFromString(""), generic.NewCompareOptions()))
|
||||
assert.True(t, generic.TreeCompare(ctx, aTree, generic.NewPathFromString(""), bTree, generic.NewPathFromString("")))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,3 @@ func RandSeq(n int) string {
|
|||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func RandInt64() int64 {
|
||||
return random.Int63()
|
||||
}
|
||||
|
|
|
|||
16
util/rand_test.go
Normal file
16
util/rand_test.go
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright Earl Warren <contact@earl-warren.org>
|
||||
// Copyright Loïc Dachary <loic@dachary.org>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRandSeq(t *testing.T) {
|
||||
l := 23
|
||||
assert.Len(t, RandSeq(l), l)
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
// Copyright Earl Warren <contact@earl-warren.org>
|
||||
// Copyright Loïc Dachary <loic@dachary.org>
|
||||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package uri
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ErrURISchemeNotSupported represents a scheme error
|
||||
type ErrURISchemeNotSupported struct {
|
||||
Scheme string
|
||||
}
|
||||
|
||||
func (e ErrURISchemeNotSupported) Error() string {
|
||||
return fmt.Sprintf("Unsupported scheme: %v", e.Scheme)
|
||||
}
|
||||
|
||||
// Open open a local file or a remote file
|
||||
func Open(uriStr string) (io.ReadCloser, error) {
|
||||
u, err := url.Parse(uriStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch strings.ToLower(u.Scheme) {
|
||||
case "http", "https":
|
||||
f, err := http.Get(uriStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return f.Body, nil
|
||||
case "file":
|
||||
return os.Open(u.Path)
|
||||
default:
|
||||
return nil, ErrURISchemeNotSupported{Scheme: u.Scheme}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
// Copyright Earl Warren <contact@earl-warren.org>
|
||||
// Copyright Loïc Dachary <loic@dachary.org>
|
||||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package uri
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestReadURI(t *testing.T) {
|
||||
p, err := filepath.Abs("./uri.go")
|
||||
assert.NoError(t, err)
|
||||
f, err := Open("file://" + p)
|
||||
assert.NoError(t, err)
|
||||
defer f.Close()
|
||||
}
|
||||
Loading…
Reference in a new issue