mirror of
				https://github.com/go-gitea/gitea
				synced 2025-11-04 05:18:25 +00:00 
			
		
		
		
	* update github.com/blevesearch/bleve v2.0.2 -> v2.0.3 * github.com/denisenkom/go-mssqldb v0.9.0 -> v0.10.0 * github.com/editorconfig/editorconfig-core-go v2.4.1 -> v2.4.2 * github.com/go-chi/cors v1.1.1 -> v1.2.0 * github.com/go-git/go-billy v5.0.0 -> v5.1.0 * github.com/go-git/go-git v5.2.0 -> v5.3.0 * github.com/go-ldap/ldap v3.2.4 -> v3.3.0 * github.com/go-redis/redis v8.6.0 -> v8.8.2 * github.com/go-sql-driver/mysql v1.5.0 -> v1.6.0 * github.com/go-swagger/go-swagger v0.26.1 -> v0.27.0 * github.com/lib/pq v1.9.0 -> v1.10.1 * github.com/mattn/go-sqlite3 v1.14.6 -> v1.14.7 * github.com/go-testfixtures/testfixtures v3.5.0 -> v3.6.0 * github.com/issue9/identicon v1.0.1 -> v1.2.0 * github.com/klauspost/compress v1.11.8 -> v1.12.1 * github.com/mgechev/revive v1.0.3 -> v1.0.6 * github.com/microcosm-cc/bluemonday v1.0.7 -> v1.0.8 * github.com/niklasfasching/go-org v1.4.0 -> v1.5.0 * github.com/olivere/elastic v7.0.22 -> v7.0.24 * github.com/pelletier/go-toml v1.8.1 -> v1.9.0 * github.com/prometheus/client_golang v1.9.0 -> v1.10.0 * github.com/xanzy/go-gitlab v0.44.0 -> v0.48.0 * github.com/yuin/goldmark v1.3.3 -> v1.3.5 * github.com/6543/go-version v1.2.4 -> v1.3.1 * do github.com/lib/pq v1.10.0 -> v1.10.1 again ...
		
			
				
	
	
		
			515 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			515 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
// Copyright 2012 Jesse van den Kieboom. All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
package flags
 | 
						|
 | 
						|
import (
 | 
						|
	"bufio"
 | 
						|
	"bytes"
 | 
						|
	"fmt"
 | 
						|
	"io"
 | 
						|
	"runtime"
 | 
						|
	"strings"
 | 
						|
	"unicode/utf8"
 | 
						|
)
 | 
						|
 | 
						|
type alignmentInfo struct {
 | 
						|
	maxLongLen      int
 | 
						|
	hasShort        bool
 | 
						|
	hasValueName    bool
 | 
						|
	terminalColumns int
 | 
						|
	indent          bool
 | 
						|
}
 | 
						|
 | 
						|
const (
 | 
						|
	paddingBeforeOption                 = 2
 | 
						|
	distanceBetweenOptionAndDescription = 2
 | 
						|
)
 | 
						|
 | 
						|
func (a *alignmentInfo) descriptionStart() int {
 | 
						|
	ret := a.maxLongLen + distanceBetweenOptionAndDescription
 | 
						|
 | 
						|
	if a.hasShort {
 | 
						|
		ret += 2
 | 
						|
	}
 | 
						|
 | 
						|
	if a.maxLongLen > 0 {
 | 
						|
		ret += 4
 | 
						|
	}
 | 
						|
 | 
						|
	if a.hasValueName {
 | 
						|
		ret += 3
 | 
						|
	}
 | 
						|
 | 
						|
	return ret
 | 
						|
}
 | 
						|
 | 
						|
func (a *alignmentInfo) updateLen(name string, indent bool) {
 | 
						|
	l := utf8.RuneCountInString(name)
 | 
						|
 | 
						|
	if indent {
 | 
						|
		l = l + 4
 | 
						|
	}
 | 
						|
 | 
						|
	if l > a.maxLongLen {
 | 
						|
		a.maxLongLen = l
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (p *Parser) getAlignmentInfo() alignmentInfo {
 | 
						|
	ret := alignmentInfo{
 | 
						|
		maxLongLen:      0,
 | 
						|
		hasShort:        false,
 | 
						|
		hasValueName:    false,
 | 
						|
		terminalColumns: getTerminalColumns(),
 | 
						|
	}
 | 
						|
 | 
						|
	if ret.terminalColumns <= 0 {
 | 
						|
		ret.terminalColumns = 80
 | 
						|
	}
 | 
						|
 | 
						|
	var prevcmd *Command
 | 
						|
 | 
						|
	p.eachActiveGroup(func(c *Command, grp *Group) {
 | 
						|
		if !grp.showInHelp() {
 | 
						|
			return
 | 
						|
		}
 | 
						|
		if c != prevcmd {
 | 
						|
			for _, arg := range c.args {
 | 
						|
				ret.updateLen(arg.Name, c != p.Command)
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		for _, info := range grp.options {
 | 
						|
			if !info.showInHelp() {
 | 
						|
				continue
 | 
						|
			}
 | 
						|
 | 
						|
			if info.ShortName != 0 {
 | 
						|
				ret.hasShort = true
 | 
						|
			}
 | 
						|
 | 
						|
			if len(info.ValueName) > 0 {
 | 
						|
				ret.hasValueName = true
 | 
						|
			}
 | 
						|
 | 
						|
			l := info.LongNameWithNamespace() + info.ValueName
 | 
						|
 | 
						|
			if len(info.Choices) != 0 {
 | 
						|
				l += "[" + strings.Join(info.Choices, "|") + "]"
 | 
						|
			}
 | 
						|
 | 
						|
			ret.updateLen(l, c != p.Command)
 | 
						|
		}
 | 
						|
	})
 | 
						|
 | 
						|
	return ret
 | 
						|
}
 | 
						|
 | 
						|
func wrapText(s string, l int, prefix string) string {
 | 
						|
	var ret string
 | 
						|
 | 
						|
	if l < 10 {
 | 
						|
		l = 10
 | 
						|
	}
 | 
						|
 | 
						|
	// Basic text wrapping of s at spaces to fit in l
 | 
						|
	lines := strings.Split(s, "\n")
 | 
						|
 | 
						|
	for _, line := range lines {
 | 
						|
		var retline string
 | 
						|
 | 
						|
		line = strings.TrimSpace(line)
 | 
						|
 | 
						|
		for len(line) > l {
 | 
						|
			// Try to split on space
 | 
						|
			suffix := ""
 | 
						|
 | 
						|
			pos := strings.LastIndex(line[:l], " ")
 | 
						|
 | 
						|
			if pos < 0 {
 | 
						|
				pos = l - 1
 | 
						|
				suffix = "-\n"
 | 
						|
			}
 | 
						|
 | 
						|
			if len(retline) != 0 {
 | 
						|
				retline += "\n" + prefix
 | 
						|
			}
 | 
						|
 | 
						|
			retline += strings.TrimSpace(line[:pos]) + suffix
 | 
						|
			line = strings.TrimSpace(line[pos:])
 | 
						|
		}
 | 
						|
 | 
						|
		if len(line) > 0 {
 | 
						|
			if len(retline) != 0 {
 | 
						|
				retline += "\n" + prefix
 | 
						|
			}
 | 
						|
 | 
						|
			retline += line
 | 
						|
		}
 | 
						|
 | 
						|
		if len(ret) > 0 {
 | 
						|
			ret += "\n"
 | 
						|
 | 
						|
			if len(retline) > 0 {
 | 
						|
				ret += prefix
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		ret += retline
 | 
						|
	}
 | 
						|
 | 
						|
	return ret
 | 
						|
}
 | 
						|
 | 
						|
func (p *Parser) writeHelpOption(writer *bufio.Writer, option *Option, info alignmentInfo) {
 | 
						|
	line := &bytes.Buffer{}
 | 
						|
 | 
						|
	prefix := paddingBeforeOption
 | 
						|
 | 
						|
	if info.indent {
 | 
						|
		prefix += 4
 | 
						|
	}
 | 
						|
 | 
						|
	if option.Hidden {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	line.WriteString(strings.Repeat(" ", prefix))
 | 
						|
 | 
						|
	if option.ShortName != 0 {
 | 
						|
		line.WriteRune(defaultShortOptDelimiter)
 | 
						|
		line.WriteRune(option.ShortName)
 | 
						|
	} else if info.hasShort {
 | 
						|
		line.WriteString("  ")
 | 
						|
	}
 | 
						|
 | 
						|
	descstart := info.descriptionStart() + paddingBeforeOption
 | 
						|
 | 
						|
	if len(option.LongName) > 0 {
 | 
						|
		if option.ShortName != 0 {
 | 
						|
			line.WriteString(", ")
 | 
						|
		} else if info.hasShort {
 | 
						|
			line.WriteString("  ")
 | 
						|
		}
 | 
						|
 | 
						|
		line.WriteString(defaultLongOptDelimiter)
 | 
						|
		line.WriteString(option.LongNameWithNamespace())
 | 
						|
	}
 | 
						|
 | 
						|
	if option.canArgument() {
 | 
						|
		line.WriteRune(defaultNameArgDelimiter)
 | 
						|
 | 
						|
		if len(option.ValueName) > 0 {
 | 
						|
			line.WriteString(option.ValueName)
 | 
						|
		}
 | 
						|
 | 
						|
		if len(option.Choices) > 0 {
 | 
						|
			line.WriteString("[" + strings.Join(option.Choices, "|") + "]")
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	written := line.Len()
 | 
						|
	line.WriteTo(writer)
 | 
						|
 | 
						|
	if option.Description != "" {
 | 
						|
		dw := descstart - written
 | 
						|
		writer.WriteString(strings.Repeat(" ", dw))
 | 
						|
 | 
						|
		var def string
 | 
						|
 | 
						|
		if len(option.DefaultMask) != 0 {
 | 
						|
			if option.DefaultMask != "-" {
 | 
						|
				def = option.DefaultMask
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			def = option.defaultLiteral
 | 
						|
		}
 | 
						|
 | 
						|
		var envDef string
 | 
						|
		if option.EnvKeyWithNamespace() != "" {
 | 
						|
			var envPrintable string
 | 
						|
			if runtime.GOOS == "windows" {
 | 
						|
				envPrintable = "%" + option.EnvKeyWithNamespace() + "%"
 | 
						|
			} else {
 | 
						|
				envPrintable = "$" + option.EnvKeyWithNamespace()
 | 
						|
			}
 | 
						|
			envDef = fmt.Sprintf(" [%s]", envPrintable)
 | 
						|
		}
 | 
						|
 | 
						|
		var desc string
 | 
						|
 | 
						|
		if def != "" {
 | 
						|
			desc = fmt.Sprintf("%s (default: %v)%s", option.Description, def, envDef)
 | 
						|
		} else {
 | 
						|
			desc = option.Description + envDef
 | 
						|
		}
 | 
						|
 | 
						|
		writer.WriteString(wrapText(desc,
 | 
						|
			info.terminalColumns-descstart,
 | 
						|
			strings.Repeat(" ", descstart)))
 | 
						|
	}
 | 
						|
 | 
						|
	writer.WriteString("\n")
 | 
						|
}
 | 
						|
 | 
						|
func maxCommandLength(s []*Command) int {
 | 
						|
	if len(s) == 0 {
 | 
						|
		return 0
 | 
						|
	}
 | 
						|
 | 
						|
	ret := len(s[0].Name)
 | 
						|
 | 
						|
	for _, v := range s[1:] {
 | 
						|
		l := len(v.Name)
 | 
						|
 | 
						|
		if l > ret {
 | 
						|
			ret = l
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return ret
 | 
						|
}
 | 
						|
 | 
						|
// WriteHelp writes a help message containing all the possible options and
 | 
						|
// their descriptions to the provided writer. Note that the HelpFlag parser
 | 
						|
// option provides a convenient way to add a -h/--help option group to the
 | 
						|
// command line parser which will automatically show the help messages using
 | 
						|
// this method.
 | 
						|
func (p *Parser) WriteHelp(writer io.Writer) {
 | 
						|
	if writer == nil {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	wr := bufio.NewWriter(writer)
 | 
						|
	aligninfo := p.getAlignmentInfo()
 | 
						|
 | 
						|
	cmd := p.Command
 | 
						|
 | 
						|
	for cmd.Active != nil {
 | 
						|
		cmd = cmd.Active
 | 
						|
	}
 | 
						|
 | 
						|
	if p.Name != "" {
 | 
						|
		wr.WriteString("Usage:\n")
 | 
						|
		wr.WriteString(" ")
 | 
						|
 | 
						|
		allcmd := p.Command
 | 
						|
 | 
						|
		for allcmd != nil {
 | 
						|
			var usage string
 | 
						|
 | 
						|
			if allcmd == p.Command {
 | 
						|
				if len(p.Usage) != 0 {
 | 
						|
					usage = p.Usage
 | 
						|
				} else if p.Options&HelpFlag != 0 {
 | 
						|
					usage = "[OPTIONS]"
 | 
						|
				}
 | 
						|
			} else if us, ok := allcmd.data.(Usage); ok {
 | 
						|
				usage = us.Usage()
 | 
						|
			} else if allcmd.hasHelpOptions() {
 | 
						|
				usage = fmt.Sprintf("[%s-OPTIONS]", allcmd.Name)
 | 
						|
			}
 | 
						|
 | 
						|
			if len(usage) != 0 {
 | 
						|
				fmt.Fprintf(wr, " %s %s", allcmd.Name, usage)
 | 
						|
			} else {
 | 
						|
				fmt.Fprintf(wr, " %s", allcmd.Name)
 | 
						|
			}
 | 
						|
 | 
						|
			if len(allcmd.args) > 0 {
 | 
						|
				fmt.Fprintf(wr, " ")
 | 
						|
			}
 | 
						|
 | 
						|
			for i, arg := range allcmd.args {
 | 
						|
				if i != 0 {
 | 
						|
					fmt.Fprintf(wr, " ")
 | 
						|
				}
 | 
						|
 | 
						|
				name := arg.Name
 | 
						|
 | 
						|
				if arg.isRemaining() {
 | 
						|
					name = name + "..."
 | 
						|
				}
 | 
						|
 | 
						|
				if !allcmd.ArgsRequired {
 | 
						|
					fmt.Fprintf(wr, "[%s]", name)
 | 
						|
				} else {
 | 
						|
					fmt.Fprintf(wr, "%s", name)
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			if allcmd.Active == nil && len(allcmd.commands) > 0 {
 | 
						|
				var co, cc string
 | 
						|
 | 
						|
				if allcmd.SubcommandsOptional {
 | 
						|
					co, cc = "[", "]"
 | 
						|
				} else {
 | 
						|
					co, cc = "<", ">"
 | 
						|
				}
 | 
						|
 | 
						|
				visibleCommands := allcmd.visibleCommands()
 | 
						|
 | 
						|
				if len(visibleCommands) > 3 {
 | 
						|
					fmt.Fprintf(wr, " %scommand%s", co, cc)
 | 
						|
				} else {
 | 
						|
					subcommands := allcmd.sortedVisibleCommands()
 | 
						|
					names := make([]string, len(subcommands))
 | 
						|
 | 
						|
					for i, subc := range subcommands {
 | 
						|
						names[i] = subc.Name
 | 
						|
					}
 | 
						|
 | 
						|
					fmt.Fprintf(wr, " %s%s%s", co, strings.Join(names, " | "), cc)
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			allcmd = allcmd.Active
 | 
						|
		}
 | 
						|
 | 
						|
		fmt.Fprintln(wr)
 | 
						|
 | 
						|
		if len(cmd.LongDescription) != 0 {
 | 
						|
			fmt.Fprintln(wr)
 | 
						|
 | 
						|
			t := wrapText(cmd.LongDescription,
 | 
						|
				aligninfo.terminalColumns,
 | 
						|
				"")
 | 
						|
 | 
						|
			fmt.Fprintln(wr, t)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	c := p.Command
 | 
						|
 | 
						|
	for c != nil {
 | 
						|
		printcmd := c != p.Command
 | 
						|
 | 
						|
		c.eachGroup(func(grp *Group) {
 | 
						|
			first := true
 | 
						|
 | 
						|
			// Skip built-in help group for all commands except the top-level
 | 
						|
			// parser
 | 
						|
			if grp.Hidden || (grp.isBuiltinHelp && c != p.Command) {
 | 
						|
				return
 | 
						|
			}
 | 
						|
 | 
						|
			for _, info := range grp.options {
 | 
						|
				if !info.showInHelp() {
 | 
						|
					continue
 | 
						|
				}
 | 
						|
 | 
						|
				if printcmd {
 | 
						|
					fmt.Fprintf(wr, "\n[%s command options]\n", c.Name)
 | 
						|
					aligninfo.indent = true
 | 
						|
					printcmd = false
 | 
						|
				}
 | 
						|
 | 
						|
				if first && cmd.Group != grp {
 | 
						|
					fmt.Fprintln(wr)
 | 
						|
 | 
						|
					if aligninfo.indent {
 | 
						|
						wr.WriteString("    ")
 | 
						|
					}
 | 
						|
 | 
						|
					fmt.Fprintf(wr, "%s:\n", grp.ShortDescription)
 | 
						|
					first = false
 | 
						|
				}
 | 
						|
 | 
						|
				p.writeHelpOption(wr, info, aligninfo)
 | 
						|
			}
 | 
						|
		})
 | 
						|
 | 
						|
		var args []*Arg
 | 
						|
		for _, arg := range c.args {
 | 
						|
			if arg.Description != "" {
 | 
						|
				args = append(args, arg)
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if len(args) > 0 {
 | 
						|
			if c == p.Command {
 | 
						|
				fmt.Fprintf(wr, "\nArguments:\n")
 | 
						|
			} else {
 | 
						|
				fmt.Fprintf(wr, "\n[%s command arguments]\n", c.Name)
 | 
						|
			}
 | 
						|
 | 
						|
			descStart := aligninfo.descriptionStart() + paddingBeforeOption
 | 
						|
 | 
						|
			for _, arg := range args {
 | 
						|
				argPrefix := strings.Repeat(" ", paddingBeforeOption)
 | 
						|
				argPrefix += arg.Name
 | 
						|
 | 
						|
				if len(arg.Description) > 0 {
 | 
						|
					argPrefix += ":"
 | 
						|
					wr.WriteString(argPrefix)
 | 
						|
 | 
						|
					// Space between "arg:" and the description start
 | 
						|
					descPadding := strings.Repeat(" ", descStart-len(argPrefix))
 | 
						|
					// How much space the description gets before wrapping
 | 
						|
					descWidth := aligninfo.terminalColumns - 1 - descStart
 | 
						|
					// Whitespace to which we can indent new description lines
 | 
						|
					descPrefix := strings.Repeat(" ", descStart)
 | 
						|
 | 
						|
					wr.WriteString(descPadding)
 | 
						|
					wr.WriteString(wrapText(arg.Description, descWidth, descPrefix))
 | 
						|
				} else {
 | 
						|
					wr.WriteString(argPrefix)
 | 
						|
				}
 | 
						|
 | 
						|
				fmt.Fprintln(wr)
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		c = c.Active
 | 
						|
	}
 | 
						|
 | 
						|
	scommands := cmd.sortedVisibleCommands()
 | 
						|
 | 
						|
	if len(scommands) > 0 {
 | 
						|
		maxnamelen := maxCommandLength(scommands)
 | 
						|
 | 
						|
		fmt.Fprintln(wr)
 | 
						|
		fmt.Fprintln(wr, "Available commands:")
 | 
						|
 | 
						|
		for _, c := range scommands {
 | 
						|
			fmt.Fprintf(wr, "  %s", c.Name)
 | 
						|
 | 
						|
			if len(c.ShortDescription) > 0 {
 | 
						|
				pad := strings.Repeat(" ", maxnamelen-len(c.Name))
 | 
						|
				fmt.Fprintf(wr, "%s  %s", pad, c.ShortDescription)
 | 
						|
 | 
						|
				if len(c.Aliases) > 0 {
 | 
						|
					fmt.Fprintf(wr, " (aliases: %s)", strings.Join(c.Aliases, ", "))
 | 
						|
				}
 | 
						|
 | 
						|
			}
 | 
						|
 | 
						|
			fmt.Fprintln(wr)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	wr.Flush()
 | 
						|
}
 | 
						|
 | 
						|
// WroteHelp is a helper to test the error from ParseArgs() to
 | 
						|
// determine if the help message was written. It is safe to
 | 
						|
// call without first checking that error is nil.
 | 
						|
func WroteHelp(err error) bool {
 | 
						|
	if err == nil { // No error
 | 
						|
		return false
 | 
						|
	}
 | 
						|
 | 
						|
	flagError, ok := err.(*Error)
 | 
						|
	if !ok { // Not a go-flag error
 | 
						|
		return false
 | 
						|
	}
 | 
						|
 | 
						|
	if flagError.Type != ErrHelp { // Did not print the help message
 | 
						|
		return false
 | 
						|
	}
 | 
						|
 | 
						|
	return true
 | 
						|
}
 |