1
0
Fork 0

Adding upstream version 3.10.8.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-05-18 09:37:23 +02:00
parent 37e9b6d587
commit 03bfe4079e
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
356 changed files with 28857 additions and 0 deletions

View file

@ -0,0 +1,85 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package filesystem
import (
"context"
"io"
"os"
"path/filepath"
"code.forgejo.org/f3/gof3/v3/f3"
"code.forgejo.org/f3/gof3/v3/id"
"code.forgejo.org/f3/gof3/v3/tree/generic"
)
type assetDriver struct {
nodeDriver
}
func newAssetDriver(content f3.Interface) generic.NodeDriverInterface {
n := newNodeDriver(content).(*nodeDriver)
a := &assetDriver{
nodeDriver: *n,
}
return a
}
func (o *assetDriver) getPath() string {
f := o.nodeDriver.content.(*f3.ReleaseAsset)
options := o.GetTreeDriver().(*treeDriver).options
return filepath.Join(options.Directory, "objects", f.SHA256[0:2], f.SHA256[2:4], f.SHA256)
}
func (o *assetDriver) save(ctx context.Context) {
assetFormat := o.nodeDriver.content.(*f3.ReleaseAsset)
objectsHelper := o.getF3Tree().GetObjectsHelper()
sha, tmpPath := objectsHelper.Save(assetFormat.DownloadFunc())
assetFormat.SHA256 = sha
path := o.getPath()
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
panic(err)
}
if err := os.Rename(tmpPath, path); err != nil {
panic(err)
}
o.GetNode().Trace("%s %s", assetFormat.SHA256, path)
}
func (o *assetDriver) setDownloadFunc() {
f := o.nodeDriver.content.(*f3.ReleaseAsset)
f.DownloadFunc = func() io.ReadCloser {
f, err := os.Open(o.getPath())
if err != nil {
panic(err)
}
return f
}
}
func (o *assetDriver) Put(ctx context.Context) id.NodeID {
return o.upsert(ctx)
}
func (o *assetDriver) Patch(ctx context.Context) {
o.upsert(ctx)
}
func (o *assetDriver) upsert(ctx context.Context) id.NodeID {
assetFormat := o.nodeDriver.content.(*f3.ReleaseAsset)
if assetFormat.SHA256 != "" {
o.save(ctx)
}
o.setDownloadFunc()
return o.nodeDriver.upsert(ctx)
}
func (o *assetDriver) Get(ctx context.Context) bool {
if o.nodeDriver.Get(ctx) {
o.setDownloadFunc()
return true
}
return false
}

37
forges/filesystem/json.go Normal file
View file

@ -0,0 +1,37 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package filesystem
import (
"encoding/json"
"fmt"
"os"
)
func loadJSON(filename string, data any) {
bs, err := os.ReadFile(filename)
if err != nil {
panic(fmt.Errorf("ReadFile %w", err))
}
if err := json.Unmarshal(bs, data); err != nil {
panic(fmt.Errorf("Unmarshal %s %s %w", filename, string(bs), err))
}
}
func saveJSON(filename string, data any) {
f, err := os.Create(filename)
if err != nil {
panic(fmt.Errorf("Create %w", err))
}
defer f.Close()
bs, err := json.MarshalIndent(data, "", " ")
if err != nil {
panic(fmt.Errorf("MarshalIndent %w", err))
}
if _, err := f.Write(bs); err != nil {
panic(fmt.Errorf("Write %w", err))
}
}

16
forges/filesystem/main.go Normal file
View file

@ -0,0 +1,16 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package filesystem
import (
filesystem_options "code.forgejo.org/f3/gof3/v3/forges/filesystem/options"
"code.forgejo.org/f3/gof3/v3/options"
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
)
func init() {
f3_tree.RegisterForgeFactory(filesystem_options.Name, newTreeDriver)
options.RegisterFactory(filesystem_options.Name, newOptions)
}

249
forges/filesystem/node.go Normal file
View file

@ -0,0 +1,249 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package filesystem
import (
"context"
"fmt"
"os"
"path/filepath"
"strings"
"code.forgejo.org/f3/gof3/v3/f3"
"code.forgejo.org/f3/gof3/v3/id"
"code.forgejo.org/f3/gof3/v3/kind"
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 nodeDriver struct {
generic.NullDriver
content f3.Interface
}
func newNodeDriver(content f3.Interface) generic.NodeDriverInterface {
return &nodeDriver{
content: content.Clone(),
}
}
func (o *nodeDriver) SetNative(any) {}
func (o *nodeDriver) GetNativeID() string {
return o.GetNode().GetID().String()
}
func (o *nodeDriver) getBasePath() string {
options := o.GetTreeDriver().(*treeDriver).options
return options.Directory + o.GetNode().GetCurrentPath().String()
}
func (o *nodeDriver) getTree() generic.TreeInterface {
return o.GetNode().GetTree()
}
func (o *nodeDriver) getF3Tree() f3_tree.TreeInterface {
return o.getTree().(f3_tree.TreeInterface)
}
func (o *nodeDriver) isContainer() bool {
return o.getF3Tree().IsContainer(o.getKind())
}
func (o *nodeDriver) getKind() kind.Kind {
return o.GetNode().GetKind()
}
func (o *nodeDriver) IsNull() bool { return false }
func (o *nodeDriver) GetIDFromName(ctx context.Context, name string) id.NodeID {
switch o.getKind() {
case kind.KindRoot, f3_tree.KindProjects, f3_tree.KindUsers, f3_tree.KindOrganizations, f3_tree.KindRepositories:
default:
panic(fmt.Errorf("unxpected kind %s", o.getKind()))
}
for _, child := range o.GetNode().List(ctx) {
child.Get(ctx)
if child.ToFormat().GetName() == name {
return child.GetID()
}
}
return id.NilID
}
func (o *nodeDriver) ListPage(ctx context.Context, page int) generic.ChildrenSlice {
node := o.GetNode()
node.Trace("%s '%s'", o.getKind(), node.GetID())
children := generic.NewChildrenSlice(0)
if o.getKind() == kind.KindRoot || page > 1 {
return children
}
basePath := o.getBasePath()
if !util.FileExists(basePath) {
return children
}
f3Tree := o.getF3Tree()
if !f3Tree.IsContainer(o.getKind()) {
return children
}
node.Trace("%d '%s'", page, basePath)
dirEntries, err := os.ReadDir(basePath)
if err != nil {
panic(fmt.Errorf("ReadDir %s %w", basePath, err))
}
for _, dirEntry := range dirEntries {
if !strings.HasSuffix(dirEntry.Name(), ".json") {
continue
}
node.Trace(" add %s", dirEntry.Name())
child := node.CreateChild(ctx)
i := strings.TrimSuffix(dirEntry.Name(), ".json")
childID := id.NewNodeID(i)
child.SetID(childID)
children = append(children, child)
}
return children
}
func (o *nodeDriver) Equals(context.Context, generic.NodeInterface) bool { panic("") }
func (o *nodeDriver) LookupMappedID(id id.NodeID) id.NodeID {
o.GetNode().Trace("%s", id)
return id
}
func (o *nodeDriver) hasJSON() bool {
kind := o.getKind()
if kind == f3_tree.KindForge {
return true
}
return !o.isContainer()
}
func (o *nodeDriver) Get(context.Context) bool {
o.GetNode().Trace("'%s' '%s'", o.getKind(), o.GetNode().GetID())
if !o.hasJSON() || o.GetNode().GetID() == id.NilID {
return true
}
filename := o.getBasePath() + ".json"
o.GetNode().Trace("'%s'", filename)
if !util.FileExists(filename) {
return false
}
f := o.NewFormat()
loadJSON(filename, f)
o.content = f
o.GetNode().Trace("%s %s id=%s", o.getKind(), filename, o.content.GetID())
idFilename := o.getBasePath() + ".id"
if !util.FileExists(idFilename) {
return true
}
mappedID, err := os.ReadFile(idFilename)
if err != nil {
panic(fmt.Errorf("Get %s %w", idFilename, err))
}
o.NullDriver.SetMappedID(id.NewNodeID(string(mappedID)))
return true
}
func (o *nodeDriver) SetMappedID(mapped id.NodeID) {
o.NullDriver.SetMappedID(mapped)
o.saveMappedID()
}
func (o *nodeDriver) saveMappedID() {
k := o.getKind()
switch k {
case kind.KindRoot, f3_tree.KindForge:
return
}
if o.isContainer() {
return
}
mappedID := o.GetMappedID()
if mappedID == id.NilID {
return
}
basePath := o.getBasePath()
idFilename := basePath + ".id"
o.Trace("%s", idFilename)
if err := os.WriteFile(idFilename, []byte(o.GetMappedID().String()), 0o644); err != nil {
panic(fmt.Errorf("%s %w", idFilename, err))
}
}
func (o *nodeDriver) Put(ctx context.Context) id.NodeID {
return o.upsert(ctx)
}
func (o *nodeDriver) Patch(ctx context.Context) {
o.upsert(ctx)
}
func (o *nodeDriver) upsert(context.Context) id.NodeID {
i := o.GetNode().GetID()
o.GetNode().Trace("%s %s", o.getKind(), i)
o.content.SetID(i.String())
if !o.hasJSON() || i == id.NilID {
return i
}
basePath := o.getBasePath()
dirname := filepath.Dir(basePath)
if !util.FileExists(dirname) {
if err := os.MkdirAll(dirname, 0o777); err != nil {
panic(fmt.Errorf("MakeDirAll %s %w", dirname, err))
}
}
saveJSON(basePath+".json", o.content)
o.saveMappedID()
return i
}
func (o *nodeDriver) Delete(context.Context) {
if o.isContainer() {
return
}
basePath := o.getBasePath()
if util.FileExists(basePath) {
if err := os.RemoveAll(basePath); err != nil {
panic(fmt.Errorf("RemoveAll %s %w", basePath, err))
}
}
for _, ext := range []string{".id", ".json"} {
jsonFilename := basePath + ext
if util.FileExists(jsonFilename) {
if err := os.Remove(jsonFilename); err != nil {
panic(fmt.Errorf("RemoveAll %s %w", basePath, err))
}
}
}
o.content = o.NewFormat()
}
func (o *nodeDriver) NewFormat() f3.Interface {
return o.getTree().(f3_tree.TreeInterface).NewFormat(o.getKind())
}
func (o *nodeDriver) FromFormat(content f3.Interface) {
o.content = content
}
func (o *nodeDriver) ToFormat() f3.Interface {
return o.content.Clone()
}
func (o *nodeDriver) String() string {
return o.content.GetID()
}

View file

@ -0,0 +1,16 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package filesystem
import (
filesystem_options "code.forgejo.org/f3/gof3/v3/forges/filesystem/options"
"code.forgejo.org/f3/gof3/v3/options"
)
func newOptions() options.Interface {
o := &filesystem_options.Options{}
o.SetName(filesystem_options.Name)
return o
}

View file

@ -0,0 +1,7 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package options
const Name = "filesystem"

View file

@ -0,0 +1,60 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package options
import (
"context"
"fmt"
"code.forgejo.org/f3/gof3/v3/options"
"code.forgejo.org/f3/gof3/v3/options/logger"
"github.com/urfave/cli/v3"
)
type Options struct {
options.Options
logger.OptionsLogger
Validation bool
Directory string
}
func (o *Options) GetURL() string { return o.Directory }
func (o *Options) SetURL(url string) { o.Directory = url }
func (o *Options) FromFlags(ctx context.Context, c *cli.Command, prefix string) {
o.Directory = c.String(forgeDirectoryOption(prefix))
if o.Directory == "" {
panic(fmt.Errorf("--%s is required", forgeDirectoryOption(prefix)))
}
o.Validation = c.Bool(forgeValidationOption(prefix))
}
func forgeValidationOption(direction string) string {
return direction + "-validation"
}
func forgeDirectoryOption(direction string) string {
return direction + "-directory"
}
func (o *Options) GetFlags(prefix, category string) []cli.Flag {
flags := make([]cli.Flag, 0, 10)
flags = append(flags, &cli.BoolFlag{
Name: forgeValidationOption(prefix),
Usage: "validate the JSON files against F3 JSON schemas",
Category: prefix,
})
flags = append(flags, &cli.StringFlag{
Name: forgeDirectoryOption(prefix),
Usage: "path to the F3 archive",
Category: prefix,
})
return flags
}

View file

@ -0,0 +1,68 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package filesystem
import (
"context"
"fmt"
"code.forgejo.org/f3/gof3/v3/f3"
helper_pullrequest "code.forgejo.org/f3/gof3/v3/forges/helpers/pullrequest"
"code.forgejo.org/f3/gof3/v3/id"
"code.forgejo.org/f3/gof3/v3/tree/generic"
)
type pullRequestDriver struct {
nodeDriver
h helper_pullrequest.Interface
}
func newPullRequestDriver(ctx context.Context, content f3.Interface) generic.NodeDriverInterface {
n := newNodeDriver(content).(*nodeDriver)
r := &pullRequestDriver{
nodeDriver: *n,
}
r.h = helper_pullrequest.NewHelper(ctx, r)
return r
}
func (o *pullRequestDriver) GetPullRequestPushRefs() []string {
return []string{fmt.Sprintf("refs/f3/%s/head", o.GetNativeID())}
}
func (o *pullRequestDriver) GetPullRequestRef() string {
return fmt.Sprintf("refs/f3/%s/head", o.GetNativeID())
}
func (o *pullRequestDriver) GetPullRequestHead() string {
f := o.nodeDriver.content.(*f3.PullRequest)
return f.Head.Ref
}
func (o *pullRequestDriver) SetFetchFunc(fetchFunc func(ctx context.Context, url, ref string)) {
f := o.nodeDriver.content.(*f3.PullRequest)
f.FetchFunc = fetchFunc
}
func (o *pullRequestDriver) Put(ctx context.Context) id.NodeID {
return o.upsert(ctx)
}
func (o *pullRequestDriver) Patch(ctx context.Context) {
o.upsert(ctx)
}
func (o *pullRequestDriver) upsert(ctx context.Context) id.NodeID {
o.nodeDriver.upsert(ctx)
return o.h.Upsert(ctx)
}
func (o *pullRequestDriver) Get(ctx context.Context) bool {
if o.nodeDriver.Get(ctx) {
o.h.Get(ctx)
return true
}
return false
}

View file

@ -0,0 +1,97 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package filesystem
import (
"context"
"os"
"code.forgejo.org/f3/gof3/v3/f3"
helpers_repository "code.forgejo.org/f3/gof3/v3/forges/helpers/repository"
"code.forgejo.org/f3/gof3/v3/id"
"code.forgejo.org/f3/gof3/v3/tree/generic"
"code.forgejo.org/f3/gof3/v3/util"
)
type repositoryDriver struct {
nodeDriver
h helpers_repository.Interface
}
func newRepositoryDriver(content f3.Interface) generic.NodeDriverInterface {
n := newNodeDriver(content).(*nodeDriver)
r := &repositoryDriver{
nodeDriver: *n,
}
r.h = helpers_repository.NewHelper(r)
return r
}
func (o *repositoryDriver) ToFormat() f3.Interface {
from := o.GetRepositoryURL()
o.Trace("%s", from)
f := o.nodeDriver.ToFormat().(*f3.Repository)
f.FetchFunc = func(ctx context.Context, destination string, internalRefs []string) {
o.Trace("git clone %s %s", from, destination)
helpers_repository.GitMirror(ctx, o, from, destination, internalRefs)
}
return f
}
func (o *repositoryDriver) GetHelper() any {
return o.h
}
func (o *repositoryDriver) SetFetchFunc(fetchFunc func(ctx context.Context, destination string, internalRefs []string)) {
f := o.nodeDriver.content.(*f3.Repository)
f.FetchFunc = fetchFunc
}
func (o *repositoryDriver) GetRepositoryURL() string {
return o.getBasePath()
}
func (o *repositoryDriver) GetRepositoryPushURL() string {
return o.getBasePath()
}
func (o *repositoryDriver) GetRepositoryInternalRefs() []string {
return []string{}
}
func (o *repositoryDriver) ensureRepository(ctx context.Context, directory string) {
if !util.FileExists(directory) {
if err := os.MkdirAll(directory, 0o700); err != nil {
panic(err)
}
util.Command(ctx, o, "git", "-C", directory, "init", "--bare")
}
}
func (o *repositoryDriver) Put(ctx context.Context) id.NodeID {
return o.upsert(ctx)
}
func (o *repositoryDriver) Patch(ctx context.Context) {
o.upsert(ctx)
}
func (o *repositoryDriver) upsert(ctx context.Context) id.NodeID {
o.nodeDriver.upsert(ctx)
repoDir := o.GetRepositoryPushURL()
o.GetNode().Trace("%s %s", repoDir, o.GetNode().GetID())
o.ensureRepository(ctx, repoDir)
return o.h.Upsert(ctx, o.content.(*f3.Repository))
}
func (o *repositoryDriver) Get(ctx context.Context) bool {
o.nodeDriver.Get(ctx)
f := o.nodeDriver.content.(*f3.Repository)
f.SetID(o.GetNode().GetID().String())
repoDir := o.GetRepositoryURL()
o.GetNode().Trace("%s", repoDir)
o.h.Get(ctx)
return true
}

View file

@ -0,0 +1,23 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package tests
import (
"testing"
filesystem_options "code.forgejo.org/f3/gof3/v3/forges/filesystem/options"
"code.forgejo.org/f3/gof3/v3/logger"
"code.forgejo.org/f3/gof3/v3/options"
)
func newTestOptions(t *testing.T) options.Interface {
t.Helper()
o := options.GetFactory(filesystem_options.Name)().(*filesystem_options.Options)
o.Directory = t.TempDir()
l := logger.NewLogger()
l.SetLevel(logger.Trace)
o.OptionsLogger.SetLogger(l)
return o
}

View file

@ -0,0 +1,14 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package tests
import (
filesystem_options "code.forgejo.org/f3/gof3/v3/forges/filesystem/options"
tests_forge "code.forgejo.org/f3/gof3/v3/tree/tests/f3/forge"
)
func init() {
tests_forge.RegisterFactory(filesystem_options.Name, newForgeTest)
}

View file

@ -0,0 +1,27 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package tests
import (
"testing"
filesystem_options "code.forgejo.org/f3/gof3/v3/forges/filesystem/options"
"code.forgejo.org/f3/gof3/v3/options"
tests_forge "code.forgejo.org/f3/gof3/v3/tree/tests/f3/forge"
)
type forgeTest struct {
tests_forge.Base
}
func (o *forgeTest) NewOptions(t *testing.T) options.Interface {
return newTestOptions(t)
}
func newForgeTest() tests_forge.Interface {
t := &forgeTest{}
t.SetName(filesystem_options.Name)
return t
}

45
forges/filesystem/tree.go Normal file
View file

@ -0,0 +1,45 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package filesystem
import (
"context"
filesystem_options "code.forgejo.org/f3/gof3/v3/forges/filesystem/options"
"code.forgejo.org/f3/gof3/v3/kind"
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
"code.forgejo.org/f3/gof3/v3/tree/generic"
)
type treeDriver struct {
generic.NullTreeDriver
options *filesystem_options.Options
}
func newTreeDriver(tree generic.TreeInterface, anyOptions any) generic.TreeDriverInterface {
driver := &treeDriver{
options: anyOptions.(*filesystem_options.Options),
}
driver.SetTree(tree)
driver.Init()
return driver
}
func (o *treeDriver) AllocateID() bool { return false }
func (o *treeDriver) Factory(ctx context.Context, k kind.Kind) generic.NodeDriverInterface {
content := o.GetTree().(f3_tree.TreeInterface).NewFormat(k)
switch k {
case f3_tree.KindRepository:
return newRepositoryDriver(content)
case f3_tree.KindAsset:
return newAssetDriver(content)
case f3_tree.KindPullRequest:
return newPullRequestDriver(ctx, content)
default:
return newNodeDriver(content)
}
}