PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/p/moul/forge/v0

Package
Open in gnoweb ↗

Overview

Kind
Pure package
Name
v0
Namespace
moul / forge
Files
14 (README)(gnomod.toml)
Exported functions
n/a — not supported for pure packages by the node (vm/qfuncs)
Module
gno.land/p/moul/forge/v0
gno
0.9

Files (14)

  • README.mdmarkdown
  • gnomod.tomltoml
  • change.gnogno
  • errors.gnogno
  • forge.gnogno
  • issue.gnogno
  • ref.gnogno
  • validate.gnogno
  • change_test.gnogno
  • forge_test.gnogno
  • helpers_test.gnogno
  • issue_test.gnogno
  • ref_test.gnogno
  • validate_test.gnogno
  • issue.gnogno
    1package forge23import "gno.land/p/nt/avl/v0"45// Issue is a discussion thread bound to a repo. Anyone with an address may open6// one: the spam gate is not a moderator, it is that the author pays gas and7// locks the storage deposit for every byte they write.

    Functions

    not supported for pure packages by the node (vm/qfuncs)

    Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

    8
    type Issue struct {
    9 ID int64
    10 Title string
    11 Body string
    12 Author address
    13 Open bool
    14 Labels []string
    15 CreatedAt int64
    16 UpdatedAt int64
    17
    18 comments *avl.Tree // padded id -> *Comment
    19 nextComment int64
    20}
    21
    22// Comment is one reply, on an issue or on a change request.
    23type Comment struct {
    24 ID int64
    25 Author address
    26 Body string
    27 CreatedAt int64
    28}
    29
    30// OpenIssue files an issue. Permissionless by design.
    31func (r *Repo) OpenIssue(actor address, height int64, title, body string, labels []string) (*Issue, error) {
    32 if r.Archived {
    33 return nil, ErrRepoArchived
    34 }
    35 if title == "" || !ValidLine(title, MaxTitleLen) {
    36 return nil, ErrInvalidText
    37 }
    38 if !ValidText(body, MaxBodyLen) {
    39 return nil, ErrInvalidText
    40 }
    41 if err := checkLabels(labels); err != nil {
    42 return nil, err
    43 }
    44 i := &Issue{
    45 ID: r.nextIssue,
    46 Title: title,
    47 Body: body,
    48 Author: actor,
    49 Open: true,
    50 Labels: append([]string{}, labels...),
    51 CreatedAt: height,
    52 UpdatedAt: height,
    53 comments: avl.NewTree(),
    54 }
    55 r.issues.Set(seqKey(i.ID), i)
    56 r.nextIssue++
    57 return i, nil
    58}
    59
    60// CommentIssue appends a reply. Closed issues still take comments (closing is a
    61// triage state, not a gag); an archived repo takes none.
    62func (r *Repo) CommentIssue(actor address, height, id int64, body string) (*Comment, error) {
    63 if r.Archived {
    64 return nil, ErrRepoArchived
    65 }
    66 i := r.Issue(id)
    67 if i == nil {
    68 return nil, ErrIssueNotFound
    69 }
    70 if body == "" || !ValidText(body, MaxCommentLen) {
    71 return nil, ErrInvalidText
    72 }
    73 c := &Comment{ID: i.nextComment, Author: actor, Body: body, CreatedAt: height}
    74 i.comments.Set(seqKey(c.ID), c)
    75 i.nextComment++
    76 i.UpdatedAt = height
    77 return c, nil
    78}
    79
    80// SetIssueOpen closes or reopens an issue. The author can always close their
    81// own; maintainers can close anyone's.
    82func (r *Repo) SetIssueOpen(actor address, height, id int64, open bool) error {
    83 if r.Archived {
    84 return ErrRepoArchived
    85 }
    86 i := r.Issue(id)
    87 if i == nil {
    88 return ErrIssueNotFound
    89 }
    90 if i.Author != actor && !r.Can(actor, RoleMaintainer) {
    91 return ErrUnauthorized
    92 }
    93 i.Open = open
    94 i.UpdatedAt = height
    95 return nil
    96}
    97
    98// SetIssueLabels replaces an issue's labels. Triage is a maintainer action.
    99func (r *Repo) SetIssueLabels(actor address, height, id int64, labels []string) error {
    100 if r.Archived {
    101 return ErrRepoArchived
    102 }
    103 i := r.Issue(id)
    104 if i == nil {
    105 return ErrIssueNotFound
    106 }
    107 if !r.Can(actor, RoleMaintainer) {
    108 return ErrUnauthorized
    109 }
    110 if err := checkLabels(labels); err != nil {
    111 return err
    112 }
    113 i.Labels = append([]string{}, labels...)
    114 i.UpdatedAt = height
    115 return nil
    116}
    117
    118// Issue returns an issue by id, or nil.
    119func (r *Repo) Issue(id int64) *Issue {
    120 v := r.issues.Get(seqKey(id))
    121 if v == nil {
    122 return nil
    123 }
    124 return v.(*Issue)
    125}
    126
    127// IterateIssues walks issues newest-first.
    128func (r *Repo) IterateIssues(offset, count int, cb func(*Issue) bool) {
    129 if count <= 0 {
    130 count = r.issues.Size()
    131 }
    132 r.issues.ReverseIterateByOffset(offset, count, func(_ string, value any) bool {
    133 return cb(value.(*Issue))
    134 })
    135}
    136
    137// OpenIssueCount counts issues still open.
    138func (r *Repo) OpenIssueCount() int {
    139 n := 0
    140 r.issues.Iterate("", "", func(_ string, value any) bool {
    141 if value.(*Issue).Open {
    142 n++
    143 }
    144 return false
    145 })
    146 return n
    147}
    148
    149// CommentCount is the number of replies on the issue.
    150func (i *Issue) CommentCount() int { return i.comments.Size() }
    151
    152// IterateComments walks replies oldest-first.
    153func (i *Issue) IterateComments(offset, count int, cb func(*Comment) bool) {
    154 if count <= 0 {
    155 count = i.comments.Size()
    156 }
    157 i.comments.IterateByOffset(offset, count, func(_ string, value any) bool {
    158 return cb(value.(*Comment))
    159 })
    160}
    161
    162func checkLabels(labels []string) error {
    163 if len(labels) > MaxLabels {
    164 return ErrTooMany
    165 }
    166 for _, l := range labels {
    167 if !ValidLabel(l) {
    168 return ErrInvalidText
    169 }
    170 }
    171 return nil
    172}
    173