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/v1

Package
Open in gnoweb ↗

Overview

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

Files (18)

  • README.mdmarkdown
  • gnomod.tomltoml
  • change.gnogno
  • errors.gnogno
  • forge.gnogno
  • issue.gnogno
  • pkg.gnogno
  • ref.gnogno
  • release.gnogno
  • validate.gnogno
  • change_test.gnogno
  • forge_test.gnogno
  • helpers_test.gnogno
  • issue_test.gnogno
  • pkg_test.gnogno
  • ref_test.gnogno
  • release_test.gnogno
  • validate_test.gnogno
  • validate.gnogno
    1package forge23import "strings"45// Size caps. Every string the chain stores is bounded: an unbounded field is an6// unbounded storage deposit, and on gno.land the deposit is paid per byte by7// whoever writes it (100ugnot/byte at the time of writing).

    Functions

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

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

    8
    const (
    9 MaxRepoPartLen = 39 // per side of "<namespace>/<name>"
    10 MaxRefNameLen = 255 // git's own limit for a single ref name
    11 MaxTitleLen = 200 // issue / change title
    12 MaxBodyLen = 8192 // issue / change body
    13 MaxCommentLen = 4096
    14 MaxDescLen = 512
    15 MaxNoteLen = 140 // single-line note attached to a log entry
    16 MaxMirrorLen = 512
    17 MaxMirrors = 8
    18 MaxLabels = 10
    19 MaxLabelLen = 32
    20)
    21
    22// ValidOID reports whether s is a git object id: 40 (SHA-1) or 64 (SHA-256)
    23// lowercase hex characters. Case is fixed so the same object always has the
    24// same on-chain key and the same digest-chain input.
    25func ValidOID(s string) bool {
    26 if len(s) != 40 && len(s) != 64 {
    27 return false
    28 }
    29 for i := 0; i < len(s); i++ {
    30 c := s[i]
    31 if (c < '0' || c > '9') && (c < 'a' || c > 'f') {
    32 return false
    33 }
    34 }
    35 return true
    36}
    37
    38// ValidRefName reports whether s is a fully-qualified ref name this forge
    39// accepts: a "refs/"-rooted subset of git-check-ref-format(1).
    40//
    41// Deliberately stricter than git: the name must be fully qualified, so there is
    42// never an ambiguity between "main" the branch and "main" the tag, and a client
    43// can map an on-chain name onto a local ref without a lookup table.
    44func ValidRefName(s string) bool {
    45 if s == "" || len(s) > MaxRefNameLen {
    46 return false
    47 }
    48 if !strings.HasPrefix(s, "refs/") {
    49 return false
    50 }
    51 if strings.Contains(s, "..") || strings.Contains(s, "@{") {
    52 return false
    53 }
    54 if strings.HasSuffix(s, "/") || strings.HasSuffix(s, ".") {
    55 return false
    56 }
    57 parts := strings.Split(s, "/")
    58 if len(parts) < 2 {
    59 return false
    60 }
    61 for _, p := range parts {
    62 if p == "" || p == "@" {
    63 return false
    64 }
    65 if strings.HasPrefix(p, ".") || strings.HasSuffix(p, ".lock") {
    66 return false
    67 }
    68 for i := 0; i < len(p); i++ {
    69 if !refByteOK(p[i]) {
    70 return false
    71 }
    72 }
    73 }
    74 return true
    75}
    76
    77// refByteOK rejects the bytes git itself rejects in a ref component: ASCII
    78// control characters, space, DEL, and the pathspec/revision metacharacters.
    79func refByteOK(c byte) bool {
    80 if c <= 0x20 || c == 0x7f {
    81 return false
    82 }
    83 switch c {
    84 case '~', '^', ':', '?', '*', '[', '\\':
    85 return false
    86 }
    87 return true
    88}
    89
    90// ValidRepoID reports whether s is "<namespace>/<name>". The name is always a
    91// lowercase slug; the namespace is either a slug (a claimed user name) or a
    92// bech32 address (the caller's own). The two shapes cannot collide: an address
    93// is 40 characters and a slug caps at MaxRepoPartLen, which is 39.
    94//
    95// This layer validates the SHAPE only. Whether the caller may claim a given
    96// namespace is an ownership question that needs a chain, so it belongs to the
    97// realm (see the realm's README).
    98func ValidRepoID(s string) bool {
    99 ns, name, ok := SplitRepoID(s)
    100 if !ok {
    101 return false
    102 }
    103 return (validSlug(ns) || AddressNamespace(ns)) && validSlug(name)
    104}
    105
    106// SplitRepoID splits "<namespace>/<name>" into its two halves. It does not
    107// validate either half; ok is false only when the id is not two slash-separated
    108// non-empty parts.
    109func SplitRepoID(s string) (ns, name string, ok bool) {
    110 i := strings.Index(s, "/")
    111 if i <= 0 || i == len(s)-1 || strings.Count(s, "/") != 1 {
    112 return "", "", false
    113 }
    114 return s[:i], s[i+1:], true
    115}
    116
    117// AddressNamespace reports whether ns is shaped like a gno bech32 address, the
    118// namespace every account owns without registering anything. The realm still
    119// checks that it is the CALLER's address; this only says which of the two
    120// ownership rules applies.
    121func AddressNamespace(ns string) bool {
    122 if len(ns) != 40 || !strings.HasPrefix(ns, "g1") {
    123 return false
    124 }
    125 for i := 2; i < len(ns); i++ {
    126 if !strings.ContainsRune(bech32Charset, rune(ns[i])) {
    127 return false
    128 }
    129 }
    130 return true
    131}
    132
    133// bech32Charset is bech32's data alphabet: lowercase alphanumerics minus the
    134// four characters it drops to avoid transcription errors (1, b, i, o).
    135const bech32Charset = "023456789acdefghjklmnpqrstuvwxyz"
    136
    137// validSlug: 1..MaxRepoPartLen chars, [a-z0-9] at both ends, [a-z0-9-_.] inside,
    138// no "..", no "--". Mixed case is rejected rather than folded: two ids that
    139// differ only in case would be two avl keys and one human-visible name.
    140func validSlug(s string) bool {
    141 if s == "" || len(s) > MaxRepoPartLen {
    142 return false
    143 }
    144 if !alnum(s[0]) || !alnum(s[len(s)-1]) {
    145 return false
    146 }
    147 if strings.Contains(s, "..") || strings.Contains(s, "--") {
    148 return false
    149 }
    150 for i := 0; i < len(s); i++ {
    151 c := s[i]
    152 if alnum(c) || c == '-' || c == '_' || c == '.' {
    153 continue
    154 }
    155 return false
    156 }
    157 return true
    158}
    159
    160func alnum(c byte) bool {
    161 return (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')
    162}
    163
    164// ValidText reports whether s fits in max bytes and carries no control
    165// characters other than newline and tab. Render output is markdown served by
    166// gnoweb, so a stray control byte is a rendering bug for every reader forever.
    167func ValidText(s string, max int) bool {
    168 if len(s) > max {
    169 return false
    170 }
    171 for i := 0; i < len(s); i++ {
    172 c := s[i]
    173 if c == '\n' || c == '\t' {
    174 continue
    175 }
    176 if c < 0x20 || c == 0x7f {
    177 return false
    178 }
    179 }
    180 return true
    181}
    182
    183// ValidLine reports whether s is single-line text within max bytes. Used for
    184// titles and for log-entry notes, which are fields of the digest chain: a
    185// newline there would let one note impersonate two.
    186func ValidLine(s string, max int) bool {
    187 if strings.ContainsAny(s, "\n\t") {
    188 return false
    189 }
    190 return ValidText(s, max)
    191}
    192
    193// ValidMirror reports whether s looks like a fetch locator. The chain does not
    194// resolve it: it only records where the maintainers say the objects are: so
    195// the check is a shape check, not a promise that anything is reachable.
    196func ValidMirror(s string) bool {
    197 if !ValidLine(s, MaxMirrorLen) || s == "" {
    198 return false
    199 }
    200 for _, p := range []string{"https://", "http://", "git://", "ssh://", "ipfs://", "ipns://", "ar://", "rad://", "git@"} {
    201 if strings.HasPrefix(s, p) {
    202 return true
    203 }
    204 }
    205 return false
    206}
    207
    208// ValidLabel reports whether s is an issue label.
    209func ValidLabel(s string) bool {
    210 return s != "" && ValidLine(s, MaxLabelLen) && !strings.Contains(s, ",")
    211}
    212