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

20
f3/ci.go Normal file
View file

@ -0,0 +1,20 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// Copyright twenty-panda <twenty-panda@posteo.com>
// SPDX-License-Identifier: MIT
package f3
type CI struct {
Common
}
func (o CI) Equal(other CI) bool {
return o.Common.Equal(other.Common)
}
func (o *CI) Clone() Interface {
clone := &CI{}
*clone = *o
return clone
}

35
f3/comment.go Normal file
View file

@ -0,0 +1,35 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package f3
import "time"
type Comment struct {
Common
PosterID *Reference `json:"poster_id"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
Content string `json:"content"`
}
func (o *Comment) GetReferences() References {
references := o.Common.GetReferences()
if !o.PosterID.IsNil() {
references = append(references, o.PosterID)
}
return references
}
func (o Comment) Equal(other Comment) bool {
return o.Common.Equal(other.Common) &&
nilOrEqual(o.PosterID, other.PosterID) &&
o.Content == other.Content
}
func (o *Comment) Clone() Interface {
clone := &Comment{}
*clone = *o
return clone
}

37
f3/equal.go Normal file
View file

@ -0,0 +1,37 @@
// Copyright limiting-factor <limiting-factor@posteo.com>
// SPDX-License-Identifier: MIT
package f3
import (
"time"
)
type equalConstraint[T any] interface {
Equal(T) bool
*T
}
func nilOrEqual[P any, T equalConstraint[P]](a, b T) bool {
return (a == nil && b == nil) ||
(a != nil && b != nil && a.Equal(*b))
}
func arrayEqual[P any, T equalConstraint[P]](a, b []T) bool {
if len(a) != len(b) {
return false
}
for i := 0; i < len(a); i++ {
if !nilOrEqual(a[i], b[i]) {
return false
}
}
return true
}
func nilOrEqualTimeToDate(a, b *time.Time) bool {
return (a == nil && b == nil) ||
(a != nil && b != nil && a.Format(time.DateOnly) == b.Format(time.DateOnly))
}

53
f3/equal_test.go Normal file
View file

@ -0,0 +1,53 @@
// Copyright limiting-factor <limiting-factor@posteo.com>
// SPDX-License-Identifier: MIT
package f3
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
type s struct {
v int
}
func (o s) Equal(other s) bool {
return o.v == other.v
}
func TestNilOrEqual(t *testing.T) {
s1 := &s{1}
s2 := &s{1}
s3 := &s{2}
assert.True(t, nilOrEqual[s](nil, nil))
assert.False(t, nilOrEqual(s1, nil))
assert.False(t, nilOrEqual(nil, s2))
assert.True(t, nilOrEqual(s1, s2))
assert.False(t, nilOrEqual(s1, s3))
}
func TestArrayEqual(t *testing.T) {
s1 := []*s{{1}, {2}}
s2 := []*s{{1}, {2}}
s3 := []*s{{1}, {2}, {3}}
assert.True(t, arrayEqual(s1, s2))
assert.False(t, arrayEqual(s1, s3))
}
func TestNilOrEqualTimeToDate(t *testing.T) {
t1, err := time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
require.NoError(t, err)
t2, err := time.Parse(time.RFC3339, "2006-01-02T00:01:00Z")
require.NoError(t, err)
t3, err := time.Parse(time.RFC3339, "2026-01-02T11:01:00Z")
require.NoError(t, err)
assert.True(t, nilOrEqualTimeToDate(nil, nil))
assert.False(t, nilOrEqualTimeToDate(&t1, nil))
assert.False(t, nilOrEqualTimeToDate(nil, &t2))
assert.True(t, nilOrEqualTimeToDate(&t1, &t2))
assert.False(t, nilOrEqualTimeToDate(&t1, &t3))
}

109
f3/file_format.go Normal file
View file

@ -0,0 +1,109 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package f3
import (
"encoding/json"
"fmt"
"os"
"github.com/santhosh-tekuri/jsonschema/v6"
)
// Load project data from file, with optional validation
func Load(filename string, data any, validation bool) error {
bs, err := os.ReadFile(filename)
if err != nil {
return err
}
if validation {
err := validate(bs, data)
if err != nil {
return err
}
}
return unmarshal(bs, data)
}
func Store(filename string, data any) error {
f, err := os.Create(filename)
if err != nil {
return err
}
defer f.Close()
bs, err := json.MarshalIndent(data, "", " ")
if err != nil {
return err
}
if _, err := f.Write(bs); err != nil {
return err
}
if _, err := f.Write([]byte("\n")); err != nil {
return err
}
return nil
}
func unmarshal(bs []byte, data any) error {
return json.Unmarshal(bs, data)
}
func getSchema(filename string) (*jsonschema.Schema, error) {
c := jsonschema.NewCompiler()
return c.Compile(filename)
}
func validate(bs []byte, datatype any) error {
var v any
err := unmarshal(bs, &v)
if err != nil {
return err
}
var schemaFilename string
switch datatype := datatype.(type) {
case *User:
schemaFilename = "schemas/user.json"
case *Organization:
schemaFilename = "schemas/organization.json"
case *Project:
schemaFilename = "schemas/project.json"
case *Topic:
schemaFilename = "schemas/topic.json"
case *Issue:
schemaFilename = "schemas/issue.json"
case *PullRequest:
schemaFilename = "schemas/pullrequest.json"
case *Label:
schemaFilename = "schemas/label.json"
case *Milestone:
schemaFilename = "schemas/milestone.json"
case *Release:
schemaFilename = "schemas/release.json"
case *ReleaseAsset:
schemaFilename = "schemas/releaseasset.json"
case *Comment:
schemaFilename = "schemas/comment.json"
case *Reaction:
schemaFilename = "schemas/reaction.json"
case *Repository:
schemaFilename = "schemas/repository.json"
case *Review:
schemaFilename = "schemas/review.json"
case *ReviewComment:
schemaFilename = "schemas/reviewcomment.json"
case *CI:
schemaFilename = "schemas/ci.json"
default:
return fmt.Errorf("file_format:validate: %T does not have a schema that could be used for validation", datatype)
}
sch, err := getSchema(schemaFilename)
if err != nil {
return err
}
return sch.Validate(v)
}

166
f3/file_format_test.go Normal file
View file

@ -0,0 +1,166 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package f3
import (
"path/filepath"
"strings"
"testing"
"github.com/santhosh-tekuri/jsonschema/v6"
"github.com/stretchr/testify/assert"
)
func TestStoreLoad(t *testing.T) {
tmpDir := t.TempDir()
type S struct {
A int
B string
}
original := S{A: 1, B: "B"}
p := filepath.Join(tmpDir, "s.json")
assert.NoError(t, Store(p, original))
var loaded S
assert.NoError(t, Load(p, &loaded, false))
assert.EqualValues(t, original, loaded)
}
func TestF3_CI(t *testing.T) {
var ci CI
err := Load("file_format_testdata/ci/good.json", &ci, true)
assert.NoError(t, err)
err = Load("file_format_testdata/ci/bad.json", &ci, true)
assert.ErrorContains(t, err, "'/index': value must be one of")
}
func TestF3_User(t *testing.T) {
var user User
err := Load("file_format_testdata/user/good.json", &user, true)
assert.NoError(t, err)
err = Load("file_format_testdata/user/bad.json", &user, true)
assert.ErrorContains(t, err, "missing properties 'index'")
}
func TestF3_Organization(t *testing.T) {
var organization Organization
err := Load("file_format_testdata/organization/good.json", &organization, true)
assert.NoError(t, err)
err = Load("file_format_testdata/organization/bad.json", &organization, true)
assert.ErrorContains(t, err, "missing properties 'index'")
}
func TestF3_Project(t *testing.T) {
var project Project
err := Load("file_format_testdata/project/good.json", &project, true)
assert.NoError(t, err)
err = Load("file_format_testdata/project/bad.json", &project, true)
assert.ErrorContains(t, err, "'/stars': got string, want number")
}
func TestF3_Issue(t *testing.T) {
var issue Issue
err := Load("file_format_testdata/issue/good.json", &issue, true)
assert.NoError(t, err)
err = Load("file_format_testdata/issue/bad.json", &issue, true)
assert.ErrorContains(t, err, "missing property 'index'")
}
func TestF3_PullRequest(t *testing.T) {
var pullRequest PullRequest
err := Load("file_format_testdata/pullrequest/good.json", &pullRequest, true)
assert.NoError(t, err)
err = Load("file_format_testdata/pullrequest/bad.json", &pullRequest, true)
assert.ErrorContains(t, err, "missing properties 'index'")
}
func TestF3_Release(t *testing.T) {
var release Release
err := Load("file_format_testdata/release/good.json", &release, true)
assert.NoError(t, err)
err = Load("file_format_testdata/release/bad.json", &release, true)
assert.ErrorContains(t, err, "missing properties 'index'")
}
func TestF3_ReleaseAsset(t *testing.T) {
var releaseAsset ReleaseAsset
err := Load("file_format_testdata/releaseasset/good.json", &releaseAsset, true)
assert.NoError(t, err)
err = Load("file_format_testdata/releaseasset/bad.json", &releaseAsset, true)
assert.ErrorContains(t, err, "missing properties 'index'")
}
func TestF3_Comment(t *testing.T) {
var comment Comment
err := Load("file_format_testdata/comment/good.json", &comment, true)
assert.NoError(t, err)
err = Load("file_format_testdata/comment/bad.json", &comment, true)
assert.ErrorContains(t, err, "'/created': 'AAAAAAAAA' is not valid date-time")
}
func TestF3_Label(t *testing.T) {
var label Label
err := Load("file_format_testdata/label/good.json", &label, true)
assert.NoError(t, err)
err = Load("file_format_testdata/label/bad.json", &label, true)
assert.ErrorContains(t, err, "'/exclusive': got string, want boolean")
}
func TestF3_Milestone(t *testing.T) {
var milestone Milestone
err := Load("file_format_testdata/milestone/good.json", &milestone, true)
assert.NoError(t, err)
err = Load("file_format_testdata/milestone/bad.json", &milestone, true)
assert.ErrorContains(t, err, "missing properties 'index'")
}
func TestF3_Review(t *testing.T) {
var review Review
err := Load("file_format_testdata/review/good.json", &review, true)
assert.NoError(t, err)
err = Load("file_format_testdata/review/bad.json", &review, true)
assert.ErrorContains(t, err, "missing properties 'index'")
}
func TestF3_Reaction(t *testing.T) {
var reaction Reaction
err := Load("file_format_testdata/reaction/good.json", &reaction, true)
assert.NoError(t, err)
err = Load("file_format_testdata/reaction/bad.json", &reaction, true)
assert.ErrorContains(t, err, "missing properties 'index'")
}
func TestF3_Repository(t *testing.T) {
var repository Repository
err := Load("file_format_testdata/repository/good.json", &repository, true)
assert.NoError(t, err)
err = Load("file_format_testdata/repository/bad.json", &repository, true)
assert.ErrorContains(t, err, "missing property 'name'")
}
func TestF3_ReviewComment(t *testing.T) {
var reviewComment ReviewComment
err := Load("file_format_testdata/reviewcomment/good.json", &reviewComment, true)
assert.NoError(t, err)
err = Load("file_format_testdata/reviewcomment/bad.json", &reviewComment, true)
assert.ErrorContains(t, err, "missing properties 'index'")
}
func TestF3_Topic(t *testing.T) {
var topic Topic
err := Load("file_format_testdata/topic.json", &topic, true)
assert.NoError(t, err)
}
func TestF3_ValidationFail(t *testing.T) {
var issue Issue
err := Load("file_format_testdata/issue/bad.json", &issue, true)
if _, ok := err.(*jsonschema.ValidationError); ok {
errors := strings.Split(err.(*jsonschema.ValidationError).GoString(), "\n")
assert.Contains(t, errors[1], "missing property")
} else {
t.Fatalf("got: type %T with value %s, want: *jsonschema.ValidationError", err, err)
}
}

View file

@ -0,0 +1,3 @@
{
"index": "Unknown"
}

View file

@ -0,0 +1,3 @@
{
"index": "Forgejo Actions"
}

View file

@ -0,0 +1,7 @@
{
"index": "5",
"poster_id": "1",
"created": "AAAAAAAAA",
"updated": "1986-04-12T23:20:50.52Z",
"content": "comment_content_5"
}

View file

@ -0,0 +1,14 @@
{
"index": "5",
"poster_id": "/user/1",
"created": "1985-04-12T23:20:50.52Z",
"updated": "1986-04-12T23:20:50.52Z",
"content": "comment_content_5",
"reactions": [
{
"index": "8",
"user_id": "/user/23",
"content": "laugh"
}
]
}

View file

@ -0,0 +1,20 @@
{
"poster_id": "/forge/users/1",
"title": "title_a",
"content": "content_a",
"milestone": "../../milestones/23",
"state": "closed",
"is_locked": false,
"created": "1985-04-12T23:20:50.52Z",
"updated": "1986-04-12T23:20:50.52Z",
"closed": null,
"due": "1986-04-12",
"labels": [
"../../labels/435"
],
"reactions": null,
"assignees": [
"/forge/users/1",
"/forge/users/2"
]
}

View file

@ -0,0 +1,21 @@
{
"index": "1",
"poster_id": "/forge/users/1",
"title": "title_a",
"content": "content_a",
"milestone": "../../milestones/23",
"state": "closed",
"is_locked": false,
"created": "1985-04-12T23:20:50.52Z",
"updated": "1986-04-12T23:20:50.52Z",
"closed": "1986-04-12T23:20:50.52Z",
"due": "1986-04-12",
"labels": [
"../../labels/435"
],
"reactions": [],
"assignees": [
"/forge/users/1",
"/forge/users/2"
]
}

View file

@ -0,0 +1,7 @@
{
"index": "1",
"name": "label1",
"description": "label1 description",
"color": "ffffff",
"exclusive": "CCCCCCCC"
}

View file

@ -0,0 +1,7 @@
{
"index": "1",
"name": "label1",
"description": "label1 description",
"color": "ffffff",
"exclusive": false
}

View file

@ -0,0 +1,2 @@
{
}

View file

@ -0,0 +1,10 @@
{
"index": "1",
"title": "title_a",
"description": "description_a",
"deadline": "1988-04-12T23:20:50.52Z",
"created": "1985-04-12T23:20:50.52Z",
"updated": "1986-04-12T23:20:50.52Z",
"closed": "1987-04-12T23:20:50.52Z",
"state": "closed"
}

View file

@ -0,0 +1,2 @@
{
}

View file

@ -0,0 +1,5 @@
{
"index": "9",
"name": "orgunique",
"full_name": "Org Unique"
}

View file

@ -0,0 +1,28 @@
{
"index": "1",
"name": "projectname",
"is_private": false,
"is_mirror": false,
"description": "project description",
"default_branch": "main",
"repositories": [
{
"name": "vcs",
"vcs": "hg"
},
{
"name": "vcs.wiki"
}
],
"archived": true,
"archived_at": "1987-04-12T23:20:50.52Z",
"created": "1985-04-12T23:20:50.52Z",
"updated": "1986-04-12T23:20:50.52Z",
"url": "https://example.com",
"stars": "BBBBBB",
"has_ci": true,
"has_issues": true,
"has_packages": true,
"has_pull_requests": true,
"has_wiki": true
}

View file

@ -0,0 +1,28 @@
{
"index": "1",
"name": "projectname",
"is_private": false,
"is_mirror": false,
"description": "project description",
"default_branch": "main",
"repositories": [
{
"name": "vcs",
"vcs": "hg"
},
{
"name": "vcs.wiki"
}
],
"archived": true,
"archived_at": "1987-04-12T23:20:50.52Z",
"created": "1985-04-12T23:20:50.52Z",
"updated": "1986-04-12T23:20:50.52Z",
"url": "https://example.com",
"stars": 20,
"has_ci": true,
"has_issues": true,
"has_packages": true,
"has_pull_requests": true,
"has_wiki": true
}

View file

@ -0,0 +1,2 @@
{
}

View file

@ -0,0 +1,32 @@
{
"index": "1",
"poster_id": "/forgejo/users/1",
"title": "title_a",
"content": "content_a",
"milestone": "../../milestones/5",
"state": "closed",
"is_locked": false,
"created": "1985-04-12T23:20:50.52Z",
"updated": "1986-04-12T23:20:50.52Z",
"closed": "1986-04-12T23:20:50.52Z",
"labels": [
"../../labels/435"
],
"reactions": [],
"assignees": [],
"merged": false,
"merged_time": "1986-04-12T23:20:50.52Z",
"merged_commit_sha": "shashasha",
"head": {
"clone_url": "head_clone_url",
"ref": "head_branch",
"sha": "head_sha",
"repository": "/forge/user/1/projects/2/repositories/vcs"
},
"base": {
"clone_url": "base_clone_url",
"ref": "base_branch",
"sha": "base _sha",
"repository": "/forge/user/3/projects/4/repositories/vcs"
}
}

View file

@ -0,0 +1,2 @@
{
}

View file

@ -0,0 +1,5 @@
{
"index": "8",
"user_id": "/forge/users/912",
"content": "laugh"
}

View file

@ -0,0 +1,2 @@
{
}

View file

@ -0,0 +1,11 @@
{
"index": "123",
"tag_name": "v12",
"target_commitish": "stable",
"name": "v12 name",
"body": "v12 body",
"draft": false,
"prerelease": false,
"publisher_id": "/forgejo/user/1",
"created": "1985-04-12T23:20:50.52Z"
}

View file

@ -0,0 +1,2 @@
{
}

View file

@ -0,0 +1,11 @@
{
"index": "5",
"name": "asset_5",
"content_type": "application/zip",
"size": 50,
"download_count": 10,
"download_url": "http://example.com/something",
"created": "1985-04-12T23:20:50.52Z",
"updated": "1986-04-12T23:20:50.52Z",
"sha256": "4c5b2f412017de78124ae3a063d08e76566eea0cba6deb2533fb176d816a54fc"
}

View file

@ -0,0 +1,2 @@
{
}

View file

@ -0,0 +1,4 @@
{
"name": "vcs.wiki",
"vcs": "fossil"
}

View file

@ -0,0 +1,3 @@
{
}

View file

@ -0,0 +1,12 @@
{
"index": "1",
"reviewer_id": "/forge/user/50",
"official": false,
"commit_id": "shashashasha",
"content": "cover review comment",
"created_at": "1985-04-12T23:20:50.52Z",
"state": "PENDING",
"dissmissed": false,
"stale": false
}

View file

@ -0,0 +1,2 @@
{
}

View file

@ -0,0 +1,14 @@
{
"index": "100",
"content": "review comment",
"tree_path": "dir/file1.txt",
"diff_hunk": "@@hunkhunk",
"line": 1,
"lines_count": 1,
"commit_id": "shashashasha",
"poster_id": "/forge/users/10",
"reactions": [],
"created_at": "1985-04-12T23:20:50.52Z",
"updated_at": "1985-04-12T23:20:50.52Z",
"resolver": "/forge/users/10"
}

View file

@ -0,0 +1,4 @@
{
"index": "1",
"name": "category1"
}

View file

@ -0,0 +1,2 @@
{
}

View file

@ -0,0 +1,8 @@
{
"index": "7",
"name": "User Name One",
"email": "user1@example.com",
"username": "user1",
"password": "gloxKainlo",
"admin": false
}

20
f3/forge.go Normal file
View file

@ -0,0 +1,20 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package f3
type Forge struct {
Common
URL string `json:"url"`
}
func (o Forge) Equal(other Forge) bool {
return o.Common.Equal(other.Common)
}
func (o *Forge) Clone() Interface {
clone := &Forge{}
*clone = *o
return clone
}

99
f3/formatbase.go Normal file
View file

@ -0,0 +1,99 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package f3
import (
"encoding/json"
"strings"
"code.forgejo.org/f3/gof3/v3/util"
)
type Interface interface {
GetID() string
GetName() string
SetID(id string)
IsNil() bool
GetReferences() References
ToReference() *Reference
Clone() Interface
}
type ReferenceInterface interface {
Get() string
Set(reference string)
GetIDAsString() string
GetIDAsInt() int64
}
type Reference struct {
ID string
}
func (r *Reference) Get() string {
return r.ID
}
func (r *Reference) Set(reference string) {
r.ID = reference
}
func (r *Reference) GetIDAsInt() int64 {
return util.ParseInt(r.GetIDAsString())
}
func (r *Reference) GetIDAsString() string {
s := strings.Split(r.ID, "/")
return s[len(s)-1]
}
type References []ReferenceInterface
func (r *Reference) UnmarshalJSON(b []byte) error {
return json.Unmarshal(b, &r.ID)
}
func (r Reference) MarshalJSON() ([]byte, error) {
return json.Marshal(r.ID)
}
func (r *Reference) GetID() string { return r.ID }
func (r *Reference) SetID(id string) { r.ID = id }
func (r *Reference) IsNil() bool { return r == nil || r.ID == "0" || r.ID == "" }
func (r Reference) Equal(other Reference) bool { return r.ID == other.ID }
func NewReferences() References {
return make([]ReferenceInterface, 0, 1)
}
func NewReference(id string) *Reference {
r := &Reference{}
r.SetID(id)
return r
}
type Common struct {
Index Reference `json:"index"`
}
func (c *Common) GetID() string { return c.Index.GetID() }
func (c *Common) GetName() string { return c.GetID() }
func (c *Common) SetID(id string) { c.Index.SetID(id) }
func (c *Common) IsNil() bool { return c == nil || c.Index.IsNil() }
func (c *Common) GetReferences() References { return NewReferences() }
func (c *Common) ToReference() *Reference { return &c.Index }
func (c Common) Equal(other Common) bool { return true }
var Nil = &Common{}
func NewCommon(id string) Common {
return Common{Index: *NewReference(id)}
}
func (c *Common) Clone() Interface {
clone := &Common{}
*clone = *c
return clone
}

57
f3/formatbase_test.go Normal file
View file

@ -0,0 +1,57 @@
// Copyright limiting-factor <limiting-factor@posteo.com>
// SPDX-License-Identifier: MIT
package f3
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestF3Reference(t *testing.T) {
ref := "reference"
r := NewReference(ref)
assert.Equal(t, ref, r.GetID())
otherRef := "other"
r.SetID(otherRef)
assert.Equal(t, otherRef, r.GetID())
r.Set(otherRef)
assert.Equal(t, otherRef, r.Get())
assert.True(t, r.Equal(*r))
m, err := r.MarshalJSON()
require.NoError(t, err)
u := NewReference("???")
require.NoError(t, u.UnmarshalJSON(m))
assert.True(t, r.Equal(*u))
assert.False(t, r.IsNil())
r.SetID("")
assert.True(t, r.IsNil())
r.SetID("0")
assert.True(t, r.IsNil())
var nilRef *Reference
assert.True(t, nilRef.IsNil())
}
func TestF3Common(t *testing.T) {
id := "ID"
c := NewCommon(id)
assert.Equal(t, id, c.GetID())
assert.Equal(t, id, c.GetName())
otherID := "otherID"
c.SetID(otherID)
assert.Equal(t, otherID, c.GetID())
assert.False(t, c.IsNil())
c.SetID("")
assert.True(t, c.IsNil())
c.SetID("0")
assert.True(t, c.IsNil())
var nilCommon *Common
assert.True(t, nilCommon.IsNil())
}

58
f3/issue.go Normal file
View file

@ -0,0 +1,58 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package f3
import "time"
const (
IssueStateOpen = "open"
IssueStateClosed = "closed"
)
type Issue struct {
Common
PosterID *Reference `json:"poster_id"`
Assignees []*Reference `json:"assignees"`
Labels []*Reference `json:"labels"`
Title string `json:"title"`
Content string `json:"content"`
Milestone *Reference `json:"milestone"`
State string `json:"state"` // open, closed
IsLocked bool `json:"is_locked"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
Closed *time.Time `json:"closed"`
}
func (o *Issue) GetReferences() References {
references := o.Common.GetReferences()
for _, assignee := range o.Assignees {
references = append(references, assignee)
}
for _, label := range o.Labels {
references = append(references, label)
}
if !o.Milestone.IsNil() {
references = append(references, o.Milestone)
}
return append(references, o.PosterID)
}
func (o Issue) Equal(other Issue) bool {
return o.Common.Equal(other.Common) &&
nilOrEqual(o.PosterID, other.PosterID) &&
arrayEqual(o.Assignees, other.Assignees) &&
arrayEqual(o.Labels, other.Labels) &&
o.Title == other.Title &&
nilOrEqual(o.Milestone, other.Milestone) &&
o.State == other.State &&
o.IsLocked == other.IsLocked
}
func (o *Issue) Clone() Interface {
clone := &Issue{}
*clone = *o
return clone
}

25
f3/label.go Normal file
View file

@ -0,0 +1,25 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package f3
type Label struct {
Common
Name string `json:"name"`
Color string `json:"color"`
Description string `json:"description"`
}
func (o Label) Equal(other Label) bool {
return o.Common.Equal(other.Common) &&
o.Name == other.Name &&
o.Color == other.Color &&
o.Description == other.Description
}
func (o *Label) Clone() Interface {
clone := &Label{}
*clone = *o
return clone
}

37
f3/milestone.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 f3
import "time"
const (
MilestoneStateOpen = "open"
MilestoneStateClosed = "closed"
)
type Milestone struct {
Common
Title string `json:"title"`
Description string `json:"description"`
Deadline *time.Time `json:"deadline"`
Created time.Time `json:"created"`
Updated *time.Time `json:"updated"`
Closed *time.Time `json:"closed"`
State string `json:"state"` // open, closed
}
func (o Milestone) Equal(other Milestone) bool {
return o.Common.Equal(other.Common) &&
o.Title == other.Title &&
o.Description == other.Description &&
nilOrEqualTimeToDate(o.Deadline, other.Deadline) &&
o.State == other.State
}
func (o *Milestone) Clone() Interface {
clone := &Milestone{}
*clone = *o
return clone
}

81
f3/new.go Normal file
View file

@ -0,0 +1,81 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package f3
import (
"fmt"
)
func New(name string) Interface {
common := NewCommon(name)
switch name {
case "<root>":
return &common
case ResourceAsset:
return &ReleaseAsset{}
case ResourceAssets:
return &common
case ResourceComment:
return &Comment{}
case ResourceComments:
return &common
case ResourceIssue:
return &Issue{}
case ResourceIssues:
return &common
case ResourceLabel:
return &Label{}
case ResourceLabels:
return &common
case ResourceMilestone:
return &Milestone{}
case ResourceMilestones:
return &common
case ResourceOrganization:
return &Organization{}
case ResourceOrganizations:
return &common
case ResourceProject:
return &Project{}
case ResourceProjects:
return &common
case ResourcePullRequest:
return &PullRequest{}
case ResourcePullRequests:
return &common
case ResourceReaction:
return &Reaction{}
case ResourceReactions:
return &common
case ResourceRelease:
return &Release{}
case ResourceReleases:
return &common
case ResourceRepository:
return &Repository{}
case ResourceRepositories:
return &common
case ResourceReview:
return &Review{}
case ResourceReviews:
return &common
case ResourceReviewComment:
return &ReviewComment{}
case ResourceReviewComments:
return &common
case ResourceTopic:
return &Topic{}
case ResourceTopics:
return &common
case ResourceUser:
return &User{}
case ResourceUsers:
return &common
case ResourceForge:
return &Forge{}
default:
panic(fmt.Errorf("unknown %s", name))
}
}

27
f3/organization.go Normal file
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 f3
type Organization struct {
Common
FullName string `json:"full_name"`
Name string `json:"name"`
}
func (o Organization) Equal(other Organization) bool {
return o.Common.Equal(other.Common) &&
o.FullName == other.FullName &&
o.Name == other.Name
}
func (o *Organization) GetName() string {
return o.Name
}
func (o *Organization) Clone() Interface {
clone := &Organization{}
*clone = *o
return clone
}

50
f3/project.go Normal file
View file

@ -0,0 +1,50 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package f3
type Project struct {
Common
Name string `json:"name"`
IsPrivate bool `json:"is_private"`
IsMirror bool `json:"is_mirror"`
Description string `json:"description"`
DefaultBranch string `json:"default_branch"`
Forked *Reference `json:"forked"`
HasWiki bool `json:"has_wiki"`
Topics []*Reference `json:"topics"`
}
func (o Project) Project(other Project) bool {
return o.Common.Equal(other.Common) &&
o.Name == other.Name &&
o.IsPrivate == other.IsPrivate &&
o.IsMirror == other.IsMirror &&
o.Description == other.Description &&
o.DefaultBranch == other.DefaultBranch &&
nilOrEqual(o.Forked, other.Forked) &&
o.HasWiki == other.HasWiki &&
arrayEqual(o.Topics, other.Topics)
}
func (o *Project) GetName() string {
return o.Name
}
func (o *Project) GetReferences() References {
references := o.Common.GetReferences()
if !o.Forked.IsNil() {
references = append(references, o.Forked)
}
for _, topic := range o.Topics {
references = append(references, topic)
}
return references
}
func (o *Project) Clone() Interface {
clone := &Project{}
*clone = *o
return clone
}

72
f3/pullrequest.go Normal file
View file

@ -0,0 +1,72 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package f3
import (
"context"
"time"
)
type PullRequestFetchFunc func(ctx context.Context, url, ref string)
const (
PullRequestStateOpen = "open"
PullRequestStateClosed = "closed"
)
type PullRequest struct {
Common
PosterID *Reference `json:"poster_id"`
Title string `json:"title"`
Content string `json:"content"`
Milestone *Reference `json:"milestone"`
State string `json:"state"` // open, closed
IsLocked bool `json:"is_locked"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
Closed *time.Time `json:"closed"`
Merged bool `json:"merged"`
MergedTime *time.Time `json:"merged_time"`
MergeCommitSHA string `json:"merged_commit_sha"`
Head PullRequestBranch `json:"head"`
Base PullRequestBranch `json:"base"`
FetchFunc PullRequestFetchFunc `json:"-"`
}
func (o PullRequest) Equal(other PullRequest) bool {
return o.Common.Equal(other.Common) &&
nilOrEqual(o.PosterID, other.PosterID) &&
o.Title == other.Title &&
o.Content == other.Content &&
nilOrEqual(o.Milestone, other.Milestone) &&
o.State == other.State &&
o.IsLocked == other.IsLocked &&
o.Merged == other.Merged &&
nilOrEqual(o.MergedTime, other.MergedTime) &&
o.MergeCommitSHA == other.MergeCommitSHA &&
o.Head.Equal(other.Head) &&
o.Base.Equal(other.Base)
}
func (o *PullRequest) GetReferences() References {
references := o.Common.GetReferences()
if !o.Milestone.IsNil() {
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.Repository != o.Base.Repository
}
func (o *PullRequest) Clone() Interface {
clone := &PullRequest{}
*clone = *o
return clone
}

20
f3/pullrequestbranch.go Normal file
View file

@ -0,0 +1,20 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package f3
type PullRequestBranch struct {
Ref string `json:"ref"`
SHA string `json:"sha"`
Repository *Reference `json:"repository"`
}
func (o PullRequestBranch) Equal(other PullRequestBranch) bool {
return o.Ref == other.Ref &&
o.SHA == other.SHA
}
func (o *PullRequestBranch) GetReferences() References {
return References{o.Repository}
}

31
f3/reaction.go Normal file
View file

@ -0,0 +1,31 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package f3
type Reaction struct {
Common
UserID *Reference `json:"user_id"`
Content string `json:"content"`
}
func (o Reaction) Equal(other Reaction) bool {
return o.Common.Equal(other.Common) &&
nilOrEqual(o.UserID, other.UserID) &&
o.Content == other.Content
}
func (o *Reaction) GetReferences() References {
references := o.Common.GetReferences()
if !o.UserID.IsNil() {
references = append(references, o.UserID)
}
return references
}
func (o *Reaction) Clone() Interface {
clone := &Reaction{}
*clone = *o
return clone
}

48
f3/release.go Normal file
View file

@ -0,0 +1,48 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package f3
import (
"time"
)
type Release struct {
Common
TagName string `json:"tag_name"`
TargetCommitish string `json:"target_commitish"`
Name string `json:"name"`
Body string `json:"body"`
Draft bool `json:"draft"`
Prerelease bool `json:"prerelease"`
PublisherID *Reference `json:"publisher_id"`
Assets []*ReleaseAsset `json:"assets"`
Created time.Time `json:"created"`
}
func (o Release) Equal(other Release) bool {
return o.Common.Equal(other.Common) &&
o.TagName == other.TagName &&
o.TargetCommitish == other.TargetCommitish &&
o.Name == other.Name &&
o.Body == other.Body &&
o.Draft == other.Draft &&
o.Prerelease == other.Prerelease &&
nilOrEqual(o.PublisherID, other.PublisherID) &&
arrayEqual(o.Assets, other.Assets)
}
func (o *Release) GetReferences() References {
references := o.Common.GetReferences()
if !o.PublisherID.IsNil() {
references = append(references, o.PublisherID)
}
return references
}
func (o *Release) Clone() Interface {
clone := &Release{}
*clone = *o
return clone
}

38
f3/releaseasset.go Normal file
View file

@ -0,0 +1,38 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package f3
import (
"io"
"time"
)
type DownloadFuncType func() io.ReadCloser
type ReleaseAsset struct {
Common
Name string `json:"name"`
ContentType string `json:"content_type"`
Size int64 `json:"size"`
DownloadCount int64 `json:"download_count"`
Created time.Time `json:"created"`
SHA256 string `json:"sha256"`
DownloadURL string `json:"download_url"`
DownloadFunc DownloadFuncType `json:"-"`
}
func (o ReleaseAsset) Equal(other ReleaseAsset) bool {
return o.Common.Equal(other.Common) &&
o.Name == other.Name &&
o.ContentType == other.ContentType &&
o.Size == other.Size &&
o.SHA256 == other.SHA256
}
func (o *ReleaseAsset) Clone() Interface {
clone := &ReleaseAsset{}
*clone = *o
return clone
}

45
f3/repository.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 f3
import (
"context"
)
const (
RepositoryNameDefault = "vcs"
RepositoryNameWiki = "vcs.wiki"
)
var nameToID = map[string]int64{
RepositoryNameDefault: 1,
RepositoryNameWiki: 2,
}
// var RepositoryNames = []string{RepositoryNameDefault, RepositoryNameWiki}
var RepositoryNames = []string{RepositoryNameDefault}
type Repository struct {
Common
Name string
FetchFunc func(ctx context.Context, destination string, internalRefs []string) `json:"-"`
}
func (o Repository) Equal(other Repository) bool {
return o.Common.Equal(other.Common) &&
o.Name == other.Name
}
func (o *Repository) Clone() Interface {
clone := &Repository{}
*clone = *o
return clone
}
func RepositoryDirname(name string) string {
return "git" + name
}

39
f3/resources.go Normal file
View file

@ -0,0 +1,39 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package f3
const (
ResourceAsset = "asset"
ResourceAssets = "assets"
ResourceComment = "comment"
ResourceComments = "comments"
ResourceIssue = "issue"
ResourceIssues = "issues"
ResourceLabel = "label"
ResourceLabels = "labels"
ResourceMilestone = "milestone"
ResourceMilestones = "milestones"
ResourceOrganization = "organization"
ResourceOrganizations = "organizations"
ResourceProject = "project"
ResourceProjects = "projects"
ResourcePullRequest = "pull_request"
ResourcePullRequests = "pull_requests"
ResourceReaction = "reaction"
ResourceReactions = "reactions"
ResourceRelease = "release"
ResourceReleases = "releases"
ResourceRepository = "repository"
ResourceRepositories = "repositories"
ResourceReview = "review"
ResourceReviews = "reviews"
ResourceReviewComment = "reviewcomment"
ResourceReviewComments = "reviewcomments"
ResourceTopic = "topic"
ResourceTopics = "topics"
ResourceUser = "user"
ResourceUsers = "users"
ResourceForge = "forge"
)

48
f3/review.go Normal file
View file

@ -0,0 +1,48 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package f3
import "time"
const (
ReviewStatePending = "PENDING"
ReviewStateApproved = "APPROVED"
ReviewStateChangesRequested = "CHANGES_REQUESTED"
ReviewStateCommented = "COMMENTED"
ReviewStateRequestReview = "REQUEST_REVIEW"
ReviewStateUnknown = ""
)
type Review struct {
Common
ReviewerID *Reference `json:"reviewer_id"`
Official bool `json:"official"`
CommitID string `json:"commit_id"`
Content string `json:"content"`
CreatedAt time.Time `json:"created_at"`
State string `json:"state"`
}
func (o Review) Equal(other Review) bool {
return o.Common.Equal(other.Common) &&
nilOrEqual(o.ReviewerID, other.ReviewerID) &&
o.CommitID == other.CommitID &&
o.Content == other.Content &&
o.State == other.State
}
func (o *Review) GetReferences() References {
references := o.Common.GetReferences()
if !o.ReviewerID.IsNil() {
references = append(references, o.ReviewerID)
}
return references
}
func (o *Review) Clone() Interface {
clone := &Review{}
*clone = *o
return clone
}

46
f3/reviewcomment.go Normal file
View file

@ -0,0 +1,46 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package f3
import (
"time"
)
type ReviewComment struct {
Common
Content string `json:"content"`
TreePath string `json:"tree_path"`
DiffHunk string `json:"diff_hunk"`
Line int `json:"line"`
LinesCount int `json:"lines_count"`
CommitID string `json:"commit_id"`
PosterID *Reference `json:"poster_id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func (o ReviewComment) Equal(other ReviewComment) bool {
return o.Common.Equal(other.Common) &&
o.Content == other.Content &&
o.TreePath == other.TreePath &&
o.Line == other.Line &&
o.LinesCount == other.LinesCount &&
o.CommitID == other.CommitID &&
nilOrEqual(o.PosterID, other.PosterID)
}
func (o *ReviewComment) GetReferences() References {
references := o.Common.GetReferences()
if !o.PosterID.IsNil() {
references = append(references, o.PosterID)
}
return references
}
func (o *ReviewComment) Clone() Interface {
clone := &ReviewComment{}
*clone = *o
return clone
}

42
f3/schemas/ci.json Normal file
View file

@ -0,0 +1,42 @@
{
"title": "CI",
"description": "The Continuous Integration supported by the project. The configuration files are found in the repository itself, under a path that depends on the CI system.",
"type": "object",
"additionalProperties": false,
"properties": {
"index": {
"description": "The type of continuous integration",
"enum": [
"Apache Gump",
"Azure DevOps Server",
"Bamboo",
"Buddy",
"Buildbot",
"BuildMaster",
"CircleCI",
"Drone",
"Forgejo Actions",
"Gitea Actions",
"GitHub Actions",
"GitLab",
"GoCD",
"Jenkins",
"OpenMake",
"Semaphore",
"TeamCity",
"tekton",
"Travis CI",
"Vexor",
"Woodpecker CI"
]
}
},
"required": [
"index"
],
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://code.forgejo.org/f3/f3-schemas/src/branch/main/ci.json",
"$$target": "ci.json"
}

49
f3/schemas/comment.json Normal file
View file

@ -0,0 +1,49 @@
{
"title": "Comment",
"description": "Comment associated to a commentable object (i.e. issue, review, etc.). Forge users add a comment to an object to create a non-threaded conversation.",
"type": "object",
"additionalProperties": false,
"properties": {
"index": {
"description": "Unique identifier of the comment.",
"type": "string"
},
"poster_id": {
"description": "Unique identifier of the comment author.",
"type": "string"
},
"created": {
"description": "Creation time.",
"type": "string",
"format": "date-time"
},
"updated": {
"description": "Last update time.",
"type": "string",
"format": "date-time"
},
"content": {
"description": "Markdown content of the comment.",
"type": "string"
},
"reactions": {
"description": "List of reactions.",
"type": "array",
"items": {
"$ref": "reaction.json"
}
}
},
"required": [
"index",
"poster_id",
"created",
"updated",
"content"
],
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://code.forgejo.org/f3/f3-schemas/src/branch/main/comment.json",
"$$target": "comment.json"
}

22
f3/schemas/index.rst Normal file
View file

@ -0,0 +1,22 @@
.. toctree::
:maxdepth: 2
.. jsonschema:: ci.json
.. jsonschema:: comment.json
.. jsonschema:: issue.json
.. jsonschema:: label.json
.. jsonschema:: milestone.json
.. jsonschema:: object.json
.. jsonschema:: organization.json
.. jsonschema:: project.json
.. jsonschema:: pullrequest.json
.. jsonschema:: pullrequestbranch.json
.. jsonschema:: reaction.json
.. jsonschema:: release.json
.. jsonschema:: releaseasset.json
.. jsonschema:: repository.json
.. jsonschema:: review.json
.. jsonschema:: reviewcomment.json
.. jsonschema:: topic.json
.. jsonschema:: user.json

96
f3/schemas/issue.json Normal file
View file

@ -0,0 +1,96 @@
{
"title": "Issue",
"description": "An issue within an issue tracking system, relative to a project.",
"type": "object",
"additionalProperties": false,
"properties": {
"index": {
"description": "Unique identifier of the issue.",
"type": "string"
},
"poster_id": {
"description": "Unique identifier of the user who authored the issue.",
"type": "string"
},
"title": {
"description": "Short description displayed as the title.",
"type": "string"
},
"content": {
"description": "Description of the issue.",
"type": "string"
},
"milestone": {
"description": "Unique identifier of the milestone.",
"type": "string"
},
"state": {
"description": "An issue is 'closed' when it is resolved, 'open' otherwise. Issues that do not relate to a topic that needs to be resolved, such as an open conversation, may never be closed.",
"enum": [
"closed",
"open"
]
},
"is_locked": {
"description": "A locked issue can only be modified by privileged users. It is commonly used for moderation purposes when comments associated with the issue are too heated.",
"type": "boolean"
},
"created": {
"description": "Creation time.",
"type": "string",
"format": "date-time"
},
"updated": {
"description": "Last update time.",
"type": "string",
"format": "date-time"
},
"closed": {
"description": "The last time 'state' changed to 'closed'.",
"type": "string",
"format": "date-time"
},
"due": {
"description": "Due date.",
"type": "string",
"format": "date"
},
"labels": {
"description": "List of label unique identifiers.",
"type": "array",
"items": {
"type": "string"
}
},
"reactions": {
"description": "List of reactions.",
"type": "array",
"items": {
"$ref": "reaction.json"
}
},
"assignees": {
"description": "List of assignees.",
"type": "array",
"items": {
"description": "Name of a user assigned to the issue.",
"type": "string"
}
}
},
"required": [
"index",
"poster_id",
"title",
"content",
"state",
"is_locked",
"created",
"updated"
],
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://code.forgejo.org/f3/f3-schemas/src/branch/main/issue.json",
"$$target": "issue.json"
}

37
f3/schemas/label.json Normal file
View file

@ -0,0 +1,37 @@
{
"title": "Label",
"description": "Label associated to an issue.",
"type": "object",
"additionalProperties": false,
"properties": {
"index": {
"description": "Unique identifier.",
"type": "string"
},
"name": {
"description": "Name of the label, unique within the repository.",
"type": "string"
},
"color": {
"description": "Color code of the label in RGB notation 'xxx' or 'xxxxxx'.",
"type": "string"
},
"description": {
"description": "Long description.",
"type": "string"
},
"exclusive": {
"description": "There can only be one label with the prefix found before the first slash (/).",
"type": "boolean"
}
},
"required": [
"index",
"name"
],
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://code.forgejo.org/f3/f3-schemas/src/branch/main/label.json",
"$$target": "label.json"
}

62
f3/schemas/milestone.json Normal file
View file

@ -0,0 +1,62 @@
{
"title": "Milestone",
"description": "Milestone relative to a project, for the purpose of grouping objects due to a given date (issues, etc.).",
"type": "object",
"additionalProperties": false,
"properties": {
"index": {
"description": "Unique identifier.",
"type": "string"
},
"title": {
"description": "Short description.",
"type": "string"
},
"description": {
"description": "Long description.",
"type": "string"
},
"deadline": {
"description": "Deadline after which the milestone is overdue.",
"type": "string",
"format": "date-time"
},
"created": {
"description": "Creation time.",
"type": "string",
"format": "date-time"
},
"updated": {
"description": "Last update time.",
"type": "string",
"format": "date-time"
},
"closed": {
"description": "The last time 'state' changed to 'closed'.",
"type": "string",
"format": "date-time"
},
"state": {
"description": "A 'closed' milestone will not see any activity in the future, otherwise it is 'open'.",
"enum": [
"closed",
"open"
]
}
},
"required": [
"index",
"title",
"description",
"deadline",
"created",
"updated",
"closed",
"state"
],
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://code.forgejo.org/f3/f3-schemas/src/branch/main/milestone.json",
"$$target": "milestone.json"
}

35
f3/schemas/object.json Normal file
View file

@ -0,0 +1,35 @@
{
"title": "Object",
"description": "Meta information and reference to an opaque content such as an image. The unique identifier is the SHA-256 of the content of the object.",
"type": "object",
"additionalProperties": false,
"properties": {
"index": {
"description": "Unique identifier.",
"type": "string"
},
"mime": {
"description": "Mime type of the object.",
"type": "string"
},
"name": {
"description": "Human readable file name.",
"type": "string"
},
"description": {
"description": "Description.",
"type": "string"
}
},
"required": [
"index",
"mime",
"name",
"description"
],
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://code.forgejo.org/f3/f3-schemas/src/branch/main/object.json",
"$$target": "object.json"
}

View file

@ -0,0 +1,29 @@
{
"title": "Organization",
"description": "A forge organization.",
"type": "object",
"additionalProperties": false,
"properties": {
"index": {
"description": "Unique identifier of the organization.",
"type": "string"
},
"name": {
"description": "Unique name of the organization.",
"type": "string"
},
"full_name": {
"description": "Readable name of the organization.",
"type": "string"
}
},
"required": [
"index",
"name"
],
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://code.forgejo.org/f3/f3-schemas/src/branch/main/organization.json",
"$$target": "organization.json"
}

117
f3/schemas/project.json Normal file
View file

@ -0,0 +1,117 @@
{
"title": "Project",
"description": "A software project contains a code repository, an issue tracker, etc.",
"type": "object",
"additionalProperties": false,
"properties": {
"index": {
"description": "Unique identifier of the project.",
"type": "string"
},
"name": {
"description": "Name of the project, relative to the owner.",
"type": "string"
},
"is_private": {
"description": "True if the visibility of the project is not public.",
"type": "boolean"
},
"is_mirror": {
"description": "True if it is a mirror of a project residing on another forge.",
"type": "boolean"
},
"description": {
"description": "Long description of the project.",
"type": "string"
},
"default_branch": {
"description": "Name of the default branch in the code repository.",
"type": "string"
},
"repositories": {
"type": "array",
"items": {
"$ref": "repository.json"
}
},
"forked": {
"description": "Unique identifier of the project from which this one was forked.",
"type": "string"
},
"ci": {
"type": "array",
"items": {
"$ref": "ci.json"
}
},
"archived": {
"description": "True if archived and read only.",
"type": "boolean"
},
"archived_at": {
"description": "Time of archival.",
"type": "string",
"format": "date-time"
},
"created": {
"description": "Creation time.",
"type": "string",
"format": "date-time"
},
"updated": {
"description": "Last update time.",
"type": "string",
"format": "date-time"
},
"url": {
"description": "URL associated with the project, for instance the project home page.",
"type": "string"
},
"stars": {
"description": "Number of stars.",
"type": "number"
},
"has_ci": {
"description": "True if CI is enabled.",
"type": "boolean"
},
"has_issues": {
"description": "True if the issue tracker is enabled.",
"type": "boolean"
},
"has_packages": {
"description": "True if the software packages are enabled.",
"type": "boolean"
},
"has_kanban": {
"description": "True if the kanban is enabled.",
"type": "boolean"
},
"has_pull_requests": {
"description": "True if pull requests are enabled.",
"type": "boolean"
},
"has_releases": {
"description": "True if releases are enabled.",
"type": "boolean"
},
"has_wiki": {
"description": "True if the wiki is enabled.",
"type": "boolean"
}
},
"required": [
"index",
"name",
"is_private",
"is_mirror",
"description",
"default_branch",
"repositories"
],
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://code.forgejo.org/f3/f3-schemas/src/branch/main/project.json",
"$$target": "project.json"
}

134
f3/schemas/pullrequest.json Normal file
View file

@ -0,0 +1,134 @@
{
"title": "Pull request",
"description": "A pull requests to merge a commit from a 'head' that may be another branch in the same repository or a branch in a forked repository.",
"type": "object",
"additionalProperties": false,
"properties": {
"index": {
"description": "Unique identifier of the pull request.",
"type": "string"
},
"poster_id": {
"description": "Unique identifier of the user who authored the pull request.",
"type": "string"
},
"title": {
"description": "Short description displayed as the title.",
"type": "string"
},
"content": {
"description": "Long description.",
"type": "string"
},
"milestone": {
"description": "Unique identifier of the milestone.",
"type": "string"
},
"state": {
"description": "A 'closed' pull request will not see any activity in the future, otherwise it is 'open'.",
"enum": [
"closed",
"open"
]
},
"is_locked": {
"description": "A locked pull request can only be modified by privileged users.",
"type": "boolean"
},
"created": {
"description": "Creation time.",
"type": "string",
"format": "date-time"
},
"updated": {
"description": "Last update time.",
"type": "string",
"format": "date-time"
},
"closed": {
"description": "The last time 'state' changed to 'closed'.",
"type": "string",
"format": "date-time"
},
"labels": {
"description": "List of labels unique identifiers.",
"type": "array",
"items": {
"type": "string"
}
},
"reactions": {
"description": "List of reactions.",
"type": "array",
"items": {
"$ref": "reaction.json"
}
},
"assignees": {
"description": "List of assignees.",
"type": "array",
"items": {
"description": "Name of a user assigned to the issue.",
"type": "string"
}
},
"merged": {
"description": "True if the pull request was merged.",
"type": "boolean"
},
"merged_time": {
"description": "The time when the pull request was merged.",
"type": "string",
"format": "date-time"
},
"merged_commit_sha": {
"description": "The SHA of the merge commit.",
"type": "string"
},
"head": {
"description": "The changes proposed in the pull request.",
"type": "object",
"items": {
"$ref": "pullrequestbranch.json"
}
},
"base": {
"description": "The branch where the pull request changes in the head are to be merged.",
"type": "object",
"items": {
"$ref": "pullrequestbranch.json"
}
},
"merged_by": {
"description": "Unique identifier of the user who merged the pull request.",
"type": "string"
},
"due": {
"description": "Due date.",
"type": "string",
"format": "date"
},
"allow_edit": {
"description": "True when the author of the pull request allows pushing new commits to its branch.",
"type": "boolean"
}
},
"required": [
"index",
"poster_id",
"title",
"content",
"state",
"is_locked",
"created",
"updated",
"merged",
"head",
"base"
],
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://code.forgejo.org/f3/f3-schemas/src/branch/main/pullrequest.json",
"$$target": "pullrequest.json"
}

View file

@ -0,0 +1,30 @@
{
"title": "Pull request reference to a commit",
"description": "The location of a commit and the repository where it can be found.",
"type": "object",
"additionalProperties": false,
"properties": {
"ref": {
"description": "Repository reference of the commit (branch, tag, etc.).",
"type": "string"
},
"sha": {
"description": "SHA of the commit.",
"type": "string"
},
"repository": {
"description": "Unique identifier of the repository.",
"type": "string"
}
},
"required": [
"ref",
"sha",
"repository"
],
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://code.forgejo.org/f3/f3-schemas/src/branch/main/pullrequestbranch.json",
"$$target": "pullrequestbranch.json"
}

30
f3/schemas/reaction.json Normal file
View file

@ -0,0 +1,30 @@
{
"title": "Reaction",
"description": "Reaction associated to a comment that is displayed as a single emoji.",
"type": "object",
"additionalProperties": false,
"properties": {
"index": {
"description": "Unique identifier of the reaction.",
"type": "string"
},
"user_id": {
"description": "Unique identifier of the user who authored the reaction.",
"type": "string"
},
"content": {
"description": "Representation of the reaction. The rendering of the reaction depends on the forge displaying it.",
"type": "string"
}
},
"required": [
"index",
"user_id",
"content"
],
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://code.forgejo.org/f3/f3-schemas/src/branch/main/reaction.json",
"$$target": "reaction.json"
}

60
f3/schemas/release.json Normal file
View file

@ -0,0 +1,60 @@
{
"title": "Release",
"description": "A release is associated with a tag in a repository and contains of a set of files (release assets).",
"type": "object",
"additionalProperties": false,
"properties": {
"index": {
"description": "Unique identifier of the release.",
"type": "string"
},
"tag_name": {
"description": "Tag name of the release.",
"type": "string"
},
"target_commitish": {
"description": "Specifies the commitish value that determines where the tag is created from. Can be any branch or commit SHA. Unused if the tag already exists.",
"type": "string"
},
"name": {
"description": "The name of the release.",
"type": "string"
},
"body": {
"description": "Text describing the contents of the release, usually the release notes.",
"type": "string"
},
"draft": {
"description": "True if the release is a draft.",
"type": "boolean"
},
"prerelease": {
"description": "True if the release is a pre-release.",
"type": "boolean"
},
"publisher_id": {
"description": "Unique identifier of the user who authored the release.",
"type": "string"
},
"created": {
"description": "Creation time.",
"type": "string",
"format": "date-time"
}
},
"required": [
"index",
"tag_name",
"name",
"body",
"draft",
"prerelease",
"publisher_id",
"created"
],
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://code.forgejo.org/f3/f3-schemas/src/branch/main/release.json",
"$$target": "release.json"
}

View file

@ -0,0 +1,61 @@
{
"title": "Release asset",
"description": "A file associated with a release. The content of the file is opaque.",
"type": "object",
"additionalProperties": false,
"properties": {
"index": {
"description": "Unique identifier of the release asset.",
"type": "string"
},
"name": {
"description": "The name of the release asset.",
"type": "string"
},
"content_type": {
"description": "The content type of the release asset (application/zip, etc.).",
"type": "string"
},
"size": {
"description": "Size in bytes of the release asset.",
"type": "number"
},
"download_count": {
"description": "The number of times the release asset was downloaded.",
"type": "number"
},
"download_url": {
"description": "The URL from which the release asset can be downloaded.",
"type": "string"
},
"created": {
"description": "Creation time.",
"type": "string",
"format": "date-time"
},
"updated": {
"description": "Last update time.",
"type": "string",
"format": "date-time"
},
"sha256": {
"description": "SHA256 of the cnotent of the asset.",
"type": "string"
}
},
"required": [
"index",
"name",
"content_type",
"size",
"download_count",
"created",
"updated",
"sha256"
],
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://code.forgejo.org/f3/f3-schemas/src/branch/main/releaseasset.json",
"$$target": "releaseasset.json"
}

View file

@ -0,0 +1,31 @@
{
"title": "Repository",
"description": "VCS repository relative to a project. The actual content of the repository is found in the sibling 'repository' directory.",
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"description": "Unique name of the repository relative to the project (e.g. vcs or vcs.wiki).",
"type": "string"
},
"vcs": {
"description": "The type of the repository, defaults to 'git'",
"enum": [
"git",
"hg",
"bazaar",
"darcs",
"fossil",
"svn"
]
}
},
"required": [
"name"
],
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://code.forgejo.org/f3/f3-schemas/src/branch/main/repository.json",
"$$target": "repository.json"
}

63
f3/schemas/review.json Normal file
View file

@ -0,0 +1,63 @@
{
"title": "Review",
"description": "A set of review comments on a pull/merge request.",
"type": "object",
"additionalProperties": false,
"properties": {
"index": {
"description": "Unique identifier of the review.",
"type": "string"
},
"reviewer_id": {
"description": "Unique identifier of review author.",
"type": "string"
},
"official": {
"description": "True if a positive review counts to reach the required threshold.",
"type": "boolean"
},
"commit_id": {
"description": "SHA of the commit targeted by the review.",
"type": "string"
},
"content": {
"description": "Cover message of the review.",
"type": "string"
},
"created_at": {
"description": "Creation time.",
"type": "string",
"format": "date-time"
},
"state": {
"description": "State of the review.",
"enum": [
"PENDING",
"APPROVED",
"CHANGES_REQUESTED",
"COMMENTED"
]
},
"dissmissed": {
"description": "True if the review was dismissed.",
"type": "boolean"
},
"stale": {
"description": "True if the review is stale because the pull request content changed after it was published.",
"type": "boolean"
}
},
"required": [
"index",
"reviewer_id",
"commit_id",
"content",
"created_at",
"state"
],
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://code.forgejo.org/f3/f3-schemas/src/branch/main/review.json",
"$$target": "review.json"
}

View file

@ -0,0 +1,77 @@
{
"title": "Review comment",
"description": "A comment in the context of a review.",
"type": "object",
"additionalProperties": false,
"properties": {
"index": {
"description": "Unique identifier of the review comment.",
"type": "string"
},
"content": {
"description": "The text of the review comment.",
"type": "string"
},
"tree_path": {
"description": "The relative path to the file commented on.",
"type": "string"
},
"diff_hunk": {
"description": "The hunk commented on.",
"type": "string"
},
"line": {
"description": "The line number of the comment relative to the tree_path.",
"type": "number"
},
"lines_count": {
"description": "The range of lines that are commented on. If absent it defaults to one and is a single line comment. If specified it must be a positive number. If line is N and lines_count is C, the range of lines commented on is ]N-C,N]. In other words, the range starts lines_count before line, which is the last of the range",
"type": "number"
},
"commit_id": {
"description": "The SHA of the tree_path commented on.",
"type": "string"
},
"poster_id": {
"description": "Unique identifier of the user who authored the comment.",
"type": "string"
},
"reactions": {
"description": "List of reactions.",
"type": "array",
"items": {
"$ref": "reaction.json"
}
},
"created_at": {
"description": "Creation time.",
"type": "string",
"format": "date-time"
},
"updated_at": {
"description": "Last update time.",
"type": "string",
"format": "date-time"
},
"resolver": {
"description": "Unique identifier of the user who resolved the comment.",
"type": "string"
}
},
"required": [
"index",
"content",
"tree_path",
"diff_hunk",
"line",
"commit_id",
"poster_id",
"created_at",
"updated_at"
],
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://code.forgejo.org/f3/f3-schemas/src/branch/main/reviewcomment.json",
"$$target": "reviewcomment.json"
}

25
f3/schemas/topic.json Normal file
View file

@ -0,0 +1,25 @@
{
"title": "Topic",
"description": "A category associated with a project. There can be multiple topics/categories for a given project.",
"type": "object",
"additionalProperties": false,
"properties": {
"index": {
"description": "Unique identifier.",
"type": "string"
},
"name": {
"description": "The name of the category the project belongs to.",
"type": "string"
}
},
"required": [
"index",
"name"
],
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://code.forgejo.org/f3/f3-schemas/src/branch/main/topic.json",
"$$target": "topic.json"
}

42
f3/schemas/user.json Normal file
View file

@ -0,0 +1,42 @@
{
"title": "User",
"description": "A forge user.",
"type": "object",
"additionalProperties": false,
"properties": {
"index": {
"description": "Unique identifier of the user.",
"type": "string"
},
"name": {
"description": "User readable name of the user.",
"type": "string"
},
"email": {
"description": "Mail of the user.",
"type": "string"
},
"username": {
"description": "Unique name of the user.",
"type": "string"
},
"password": {
"description": "Password of the user.",
"type": "string"
},
"admin": {
"description": "True if the user has administrative permissions on the forge.",
"type": "boolean"
}
},
"required": [
"index",
"name",
"username"
],
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://code.forgejo.org/f3/f3-schemas/src/branch/main/user.json",
"$$target": "user.json"
}

21
f3/topic.go Normal file
View file

@ -0,0 +1,21 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package f3
type Topic struct {
Common
Name string `json:"name"`
}
func (o Topic) Equal(other Topic) bool {
return o.Common.Equal(other.Common) &&
o.Name == other.Name
}
func (o *Topic) Clone() Interface {
clone := &Topic{}
*clone = *o
return clone
}

32
f3/user.go Normal file
View file

@ -0,0 +1,32 @@
// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package f3
type User struct {
Common
Name string `json:"name"`
Email string `json:"email"`
UserName string `json:"username"`
Password string `json:"password"`
IsAdmin bool `json:"admin"`
}
func (o User) Equal(other User) bool {
return o.Common.Equal(other.Common) &&
o.Name == other.Name &&
o.Email == other.Email &&
o.UserName == other.UserName &&
o.IsAdmin == other.IsAdmin
}
func (o *User) GetName() string {
return o.UserName
}
func (o *User) Clone() Interface {
clone := &User{}
*clone = *o
return clone
}