mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-03 22:02:24 -06:00 
			
		
		
		
	* Add Swagger spec test script * Fix Swagger spec errors not related to statuses with polls * Add API tests that post a status with a poll * Fix creating a status with a poll from form params * Fix Swagger spec errors related to statuses with polls (this is the last error) * Fix Swagger spec warnings not related to unused definitions * Suppress a duplicate list update params definition that was somehow causing wrong param names * Add Swagger test to CI - updates Drone config - vendorizes go-swagger - fixes a file extension issue that caused the test script to generate JSON instead of YAML with the vendorized version * Put `Sample: ` on its own line everywhere * Remove unused id param from emojiCategoriesGet * Add 5 more pairs of profile fields to account update API Swagger * Remove Swagger prefix from dummy fields It makes the generated code look weird * Manually annotate params for statusCreate operation * Fix all remaining Swagger spec warnings - Change some models into operation parameters - Ignore models that already correspond to manually documented operation parameters but can't be trivially changed (those with file fields) * Documented that creating a status with scheduled_at isn't implemented yet * sign drone.yml * Fix filter API Swagger errors * fixup! Fix filter API Swagger errors --------- Co-authored-by: tobi <tobi.smethurst@protonmail.com>
		
			
				
	
	
		
			250 lines
		
	
	
	
		
			8.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			250 lines
		
	
	
	
		
			8.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2018 The Go Authors. All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
// Pseudo-versions
 | 
						|
//
 | 
						|
// Code authors are expected to tag the revisions they want users to use,
 | 
						|
// including prereleases. However, not all authors tag versions at all,
 | 
						|
// and not all commits a user might want to try will have tags.
 | 
						|
// A pseudo-version is a version with a special form that allows us to
 | 
						|
// address an untagged commit and order that version with respect to
 | 
						|
// other versions we might encounter.
 | 
						|
//
 | 
						|
// A pseudo-version takes one of the general forms:
 | 
						|
//
 | 
						|
//	(1) vX.0.0-yyyymmddhhmmss-abcdef123456
 | 
						|
//	(2) vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdef123456
 | 
						|
//	(3) vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdef123456+incompatible
 | 
						|
//	(4) vX.Y.Z-pre.0.yyyymmddhhmmss-abcdef123456
 | 
						|
//	(5) vX.Y.Z-pre.0.yyyymmddhhmmss-abcdef123456+incompatible
 | 
						|
//
 | 
						|
// If there is no recently tagged version with the right major version vX,
 | 
						|
// then form (1) is used, creating a space of pseudo-versions at the bottom
 | 
						|
// of the vX version range, less than any tagged version, including the unlikely v0.0.0.
 | 
						|
//
 | 
						|
// If the most recent tagged version before the target commit is vX.Y.Z or vX.Y.Z+incompatible,
 | 
						|
// then the pseudo-version uses form (2) or (3), making it a prerelease for the next
 | 
						|
// possible semantic version after vX.Y.Z. The leading 0 segment in the prerelease string
 | 
						|
// ensures that the pseudo-version compares less than possible future explicit prereleases
 | 
						|
// like vX.Y.(Z+1)-rc1 or vX.Y.(Z+1)-1.
 | 
						|
//
 | 
						|
// If the most recent tagged version before the target commit is vX.Y.Z-pre or vX.Y.Z-pre+incompatible,
 | 
						|
// then the pseudo-version uses form (4) or (5), making it a slightly later prerelease.
 | 
						|
 | 
						|
package module
 | 
						|
 | 
						|
import (
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"strings"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"golang.org/x/mod/internal/lazyregexp"
 | 
						|
	"golang.org/x/mod/semver"
 | 
						|
)
 | 
						|
 | 
						|
var pseudoVersionRE = lazyregexp.New(`^v[0-9]+\.(0\.0-|\d+\.\d+-([^+]*\.)?0\.)\d{14}-[A-Za-z0-9]+(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$`)
 | 
						|
 | 
						|
const PseudoVersionTimestampFormat = "20060102150405"
 | 
						|
 | 
						|
// PseudoVersion returns a pseudo-version for the given major version ("v1")
 | 
						|
// preexisting older tagged version ("" or "v1.2.3" or "v1.2.3-pre"), revision time,
 | 
						|
// and revision identifier (usually a 12-byte commit hash prefix).
 | 
						|
func PseudoVersion(major, older string, t time.Time, rev string) string {
 | 
						|
	if major == "" {
 | 
						|
		major = "v0"
 | 
						|
	}
 | 
						|
	segment := fmt.Sprintf("%s-%s", t.UTC().Format(PseudoVersionTimestampFormat), rev)
 | 
						|
	build := semver.Build(older)
 | 
						|
	older = semver.Canonical(older)
 | 
						|
	if older == "" {
 | 
						|
		return major + ".0.0-" + segment // form (1)
 | 
						|
	}
 | 
						|
	if semver.Prerelease(older) != "" {
 | 
						|
		return older + ".0." + segment + build // form (4), (5)
 | 
						|
	}
 | 
						|
 | 
						|
	// Form (2), (3).
 | 
						|
	// Extract patch from vMAJOR.MINOR.PATCH
 | 
						|
	i := strings.LastIndex(older, ".") + 1
 | 
						|
	v, patch := older[:i], older[i:]
 | 
						|
 | 
						|
	// Reassemble.
 | 
						|
	return v + incDecimal(patch) + "-0." + segment + build
 | 
						|
}
 | 
						|
 | 
						|
// ZeroPseudoVersion returns a pseudo-version with a zero timestamp and
 | 
						|
// revision, which may be used as a placeholder.
 | 
						|
func ZeroPseudoVersion(major string) string {
 | 
						|
	return PseudoVersion(major, "", time.Time{}, "000000000000")
 | 
						|
}
 | 
						|
 | 
						|
// incDecimal returns the decimal string incremented by 1.
 | 
						|
func incDecimal(decimal string) string {
 | 
						|
	// Scan right to left turning 9s to 0s until you find a digit to increment.
 | 
						|
	digits := []byte(decimal)
 | 
						|
	i := len(digits) - 1
 | 
						|
	for ; i >= 0 && digits[i] == '9'; i-- {
 | 
						|
		digits[i] = '0'
 | 
						|
	}
 | 
						|
	if i >= 0 {
 | 
						|
		digits[i]++
 | 
						|
	} else {
 | 
						|
		// digits is all zeros
 | 
						|
		digits[0] = '1'
 | 
						|
		digits = append(digits, '0')
 | 
						|
	}
 | 
						|
	return string(digits)
 | 
						|
}
 | 
						|
 | 
						|
// decDecimal returns the decimal string decremented by 1, or the empty string
 | 
						|
// if the decimal is all zeroes.
 | 
						|
func decDecimal(decimal string) string {
 | 
						|
	// Scan right to left turning 0s to 9s until you find a digit to decrement.
 | 
						|
	digits := []byte(decimal)
 | 
						|
	i := len(digits) - 1
 | 
						|
	for ; i >= 0 && digits[i] == '0'; i-- {
 | 
						|
		digits[i] = '9'
 | 
						|
	}
 | 
						|
	if i < 0 {
 | 
						|
		// decimal is all zeros
 | 
						|
		return ""
 | 
						|
	}
 | 
						|
	if i == 0 && digits[i] == '1' && len(digits) > 1 {
 | 
						|
		digits = digits[1:]
 | 
						|
	} else {
 | 
						|
		digits[i]--
 | 
						|
	}
 | 
						|
	return string(digits)
 | 
						|
}
 | 
						|
 | 
						|
// IsPseudoVersion reports whether v is a pseudo-version.
 | 
						|
func IsPseudoVersion(v string) bool {
 | 
						|
	return strings.Count(v, "-") >= 2 && semver.IsValid(v) && pseudoVersionRE.MatchString(v)
 | 
						|
}
 | 
						|
 | 
						|
// IsZeroPseudoVersion returns whether v is a pseudo-version with a zero base,
 | 
						|
// timestamp, and revision, as returned by [ZeroPseudoVersion].
 | 
						|
func IsZeroPseudoVersion(v string) bool {
 | 
						|
	return v == ZeroPseudoVersion(semver.Major(v))
 | 
						|
}
 | 
						|
 | 
						|
// PseudoVersionTime returns the time stamp of the pseudo-version v.
 | 
						|
// It returns an error if v is not a pseudo-version or if the time stamp
 | 
						|
// embedded in the pseudo-version is not a valid time.
 | 
						|
func PseudoVersionTime(v string) (time.Time, error) {
 | 
						|
	_, timestamp, _, _, err := parsePseudoVersion(v)
 | 
						|
	if err != nil {
 | 
						|
		return time.Time{}, err
 | 
						|
	}
 | 
						|
	t, err := time.Parse("20060102150405", timestamp)
 | 
						|
	if err != nil {
 | 
						|
		return time.Time{}, &InvalidVersionError{
 | 
						|
			Version: v,
 | 
						|
			Pseudo:  true,
 | 
						|
			Err:     fmt.Errorf("malformed time %q", timestamp),
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return t, nil
 | 
						|
}
 | 
						|
 | 
						|
// PseudoVersionRev returns the revision identifier of the pseudo-version v.
 | 
						|
// It returns an error if v is not a pseudo-version.
 | 
						|
func PseudoVersionRev(v string) (rev string, err error) {
 | 
						|
	_, _, rev, _, err = parsePseudoVersion(v)
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
// PseudoVersionBase returns the canonical parent version, if any, upon which
 | 
						|
// the pseudo-version v is based.
 | 
						|
//
 | 
						|
// If v has no parent version (that is, if it is "vX.0.0-[…]"),
 | 
						|
// PseudoVersionBase returns the empty string and a nil error.
 | 
						|
func PseudoVersionBase(v string) (string, error) {
 | 
						|
	base, _, _, build, err := parsePseudoVersion(v)
 | 
						|
	if err != nil {
 | 
						|
		return "", err
 | 
						|
	}
 | 
						|
 | 
						|
	switch pre := semver.Prerelease(base); pre {
 | 
						|
	case "":
 | 
						|
		// vX.0.0-yyyymmddhhmmss-abcdef123456 → ""
 | 
						|
		if build != "" {
 | 
						|
			// Pseudo-versions of the form vX.0.0-yyyymmddhhmmss-abcdef123456+incompatible
 | 
						|
			// are nonsensical: the "vX.0.0-" prefix implies that there is no parent tag,
 | 
						|
			// but the "+incompatible" suffix implies that the major version of
 | 
						|
			// the parent tag is not compatible with the module's import path.
 | 
						|
			//
 | 
						|
			// There are a few such entries in the index generated by proxy.golang.org,
 | 
						|
			// but we believe those entries were generated by the proxy itself.
 | 
						|
			return "", &InvalidVersionError{
 | 
						|
				Version: v,
 | 
						|
				Pseudo:  true,
 | 
						|
				Err:     fmt.Errorf("lacks base version, but has build metadata %q", build),
 | 
						|
			}
 | 
						|
		}
 | 
						|
		return "", nil
 | 
						|
 | 
						|
	case "-0":
 | 
						|
		// vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdef123456 → vX.Y.Z
 | 
						|
		// vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdef123456+incompatible → vX.Y.Z+incompatible
 | 
						|
		base = strings.TrimSuffix(base, pre)
 | 
						|
		i := strings.LastIndexByte(base, '.')
 | 
						|
		if i < 0 {
 | 
						|
			panic("base from parsePseudoVersion missing patch number: " + base)
 | 
						|
		}
 | 
						|
		patch := decDecimal(base[i+1:])
 | 
						|
		if patch == "" {
 | 
						|
			// vX.0.0-0 is invalid, but has been observed in the wild in the index
 | 
						|
			// generated by requests to proxy.golang.org.
 | 
						|
			//
 | 
						|
			// NOTE(bcmills): I cannot find a historical bug that accounts for
 | 
						|
			// pseudo-versions of this form, nor have I seen such versions in any
 | 
						|
			// actual go.mod files. If we find actual examples of this form and a
 | 
						|
			// reasonable theory of how they came into existence, it seems fine to
 | 
						|
			// treat them as equivalent to vX.0.0 (especially since the invalid
 | 
						|
			// pseudo-versions have lower precedence than the real ones). For now, we
 | 
						|
			// reject them.
 | 
						|
			return "", &InvalidVersionError{
 | 
						|
				Version: v,
 | 
						|
				Pseudo:  true,
 | 
						|
				Err:     fmt.Errorf("version before %s would have negative patch number", base),
 | 
						|
			}
 | 
						|
		}
 | 
						|
		return base[:i+1] + patch + build, nil
 | 
						|
 | 
						|
	default:
 | 
						|
		// vX.Y.Z-pre.0.yyyymmddhhmmss-abcdef123456 → vX.Y.Z-pre
 | 
						|
		// vX.Y.Z-pre.0.yyyymmddhhmmss-abcdef123456+incompatible → vX.Y.Z-pre+incompatible
 | 
						|
		if !strings.HasSuffix(base, ".0") {
 | 
						|
			panic(`base from parsePseudoVersion missing ".0" before date: ` + base)
 | 
						|
		}
 | 
						|
		return strings.TrimSuffix(base, ".0") + build, nil
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
var errPseudoSyntax = errors.New("syntax error")
 | 
						|
 | 
						|
func parsePseudoVersion(v string) (base, timestamp, rev, build string, err error) {
 | 
						|
	if !IsPseudoVersion(v) {
 | 
						|
		return "", "", "", "", &InvalidVersionError{
 | 
						|
			Version: v,
 | 
						|
			Pseudo:  true,
 | 
						|
			Err:     errPseudoSyntax,
 | 
						|
		}
 | 
						|
	}
 | 
						|
	build = semver.Build(v)
 | 
						|
	v = strings.TrimSuffix(v, build)
 | 
						|
	j := strings.LastIndex(v, "-")
 | 
						|
	v, rev = v[:j], v[j+1:]
 | 
						|
	i := strings.LastIndex(v, "-")
 | 
						|
	if j := strings.LastIndex(v, "."); j > i {
 | 
						|
		base = v[:j] // "vX.Y.Z-pre.0" or "vX.Y.(Z+1)-0"
 | 
						|
		timestamp = v[j+1:]
 | 
						|
	} else {
 | 
						|
		base = v[:i] // "vX.0.0"
 | 
						|
		timestamp = v[i+1:]
 | 
						|
	}
 | 
						|
	return base, timestamp, rev, build, nil
 | 
						|
}
 |