mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2026-04-15 01:41:56 +00:00
update urfavecli and prune deps
This commit is contained in:
21
vendor/github.com/codegangsta/cli/LICENSE
generated
vendored
21
vendor/github.com/codegangsta/cli/LICENSE
generated
vendored
@@ -1,21 +0,0 @@
|
||||
Copyright (C) 2013 Jeremy Saenz
|
||||
All Rights Reserved.
|
||||
|
||||
MIT LICENSE
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
315
vendor/github.com/codegangsta/cli/README.md
generated
vendored
315
vendor/github.com/codegangsta/cli/README.md
generated
vendored
@@ -1,315 +0,0 @@
|
||||
[](http://gocover.io/github.com/codegangsta/cli)
|
||||
[](https://travis-ci.org/codegangsta/cli)
|
||||
[](https://godoc.org/github.com/codegangsta/cli)
|
||||
|
||||
# cli.go
|
||||
`cli.go` is simple, fast, and fun package for building command line apps in Go. The goal is to enable developers to write fast and distributable command line applications in an expressive way.
|
||||
|
||||
## Overview
|
||||
Command line apps are usually so tiny that there is absolutely no reason why your code should *not* be self-documenting. Things like generating help text and parsing command flags/options should not hinder productivity when writing a command line app.
|
||||
|
||||
**This is where `cli.go` comes into play.** `cli.go` makes command line programming fun, organized, and expressive!
|
||||
|
||||
## Installation
|
||||
Make sure you have a working Go environment (go 1.1+ is *required*). [See the install instructions](http://golang.org/doc/install.html).
|
||||
|
||||
To install `cli.go`, simply run:
|
||||
```
|
||||
$ go get github.com/codegangsta/cli
|
||||
```
|
||||
|
||||
Make sure your `PATH` includes to the `$GOPATH/bin` directory so your commands can be easily used:
|
||||
```
|
||||
export PATH=$PATH:$GOPATH/bin
|
||||
```
|
||||
|
||||
## Getting Started
|
||||
One of the philosophies behind `cli.go` is that an API should be playful and full of discovery. So a `cli.go` app can be as little as one line of code in `main()`.
|
||||
|
||||
``` go
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cli.NewApp().Run(os.Args)
|
||||
}
|
||||
```
|
||||
|
||||
This app will run and show help text, but is not very useful. Let's give an action to execute and some help documentation:
|
||||
|
||||
``` go
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "boom"
|
||||
app.Usage = "make an explosive entrance"
|
||||
app.Action = func(c *cli.Context) {
|
||||
println("boom! I say!")
|
||||
}
|
||||
|
||||
app.Run(os.Args)
|
||||
}
|
||||
```
|
||||
|
||||
Running this already gives you a ton of functionality, plus support for things like subcommands and flags, which are covered below.
|
||||
|
||||
## Example
|
||||
|
||||
Being a programmer can be a lonely job. Thankfully by the power of automation that is not the case! Let's create a greeter app to fend off our demons of loneliness!
|
||||
|
||||
Start by creating a directory named `greet`, and within it, add a file, `greet.go` with the following code in it:
|
||||
|
||||
``` go
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "greet"
|
||||
app.Usage = "fight the loneliness!"
|
||||
app.Action = func(c *cli.Context) {
|
||||
println("Hello friend!")
|
||||
}
|
||||
|
||||
app.Run(os.Args)
|
||||
}
|
||||
```
|
||||
|
||||
Install our command to the `$GOPATH/bin` directory:
|
||||
|
||||
```
|
||||
$ go install
|
||||
```
|
||||
|
||||
Finally run our new command:
|
||||
|
||||
```
|
||||
$ greet
|
||||
Hello friend!
|
||||
```
|
||||
|
||||
`cli.go` also generates neat help text:
|
||||
|
||||
```
|
||||
$ greet help
|
||||
NAME:
|
||||
greet - fight the loneliness!
|
||||
|
||||
USAGE:
|
||||
greet [global options] command [command options] [arguments...]
|
||||
|
||||
VERSION:
|
||||
0.0.0
|
||||
|
||||
COMMANDS:
|
||||
help, h Shows a list of commands or help for one command
|
||||
|
||||
GLOBAL OPTIONS
|
||||
--version Shows version information
|
||||
```
|
||||
|
||||
### Arguments
|
||||
You can lookup arguments by calling the `Args` function on `cli.Context`.
|
||||
|
||||
``` go
|
||||
...
|
||||
app.Action = func(c *cli.Context) {
|
||||
println("Hello", c.Args()[0])
|
||||
}
|
||||
...
|
||||
```
|
||||
|
||||
### Flags
|
||||
Setting and querying flags is simple.
|
||||
``` go
|
||||
...
|
||||
app.Flags = []cli.Flag {
|
||||
cli.StringFlag{
|
||||
Name: "lang",
|
||||
Value: "english",
|
||||
Usage: "language for the greeting",
|
||||
},
|
||||
}
|
||||
app.Action = func(c *cli.Context) {
|
||||
name := "someone"
|
||||
if len(c.Args()) > 0 {
|
||||
name = c.Args()[0]
|
||||
}
|
||||
if c.String("lang") == "spanish" {
|
||||
println("Hola", name)
|
||||
} else {
|
||||
println("Hello", name)
|
||||
}
|
||||
}
|
||||
...
|
||||
```
|
||||
|
||||
See full list of flags at http://godoc.org/github.com/codegangsta/cli
|
||||
|
||||
#### Alternate Names
|
||||
|
||||
You can set alternate (or short) names for flags by providing a comma-delimited list for the `Name`. e.g.
|
||||
|
||||
``` go
|
||||
app.Flags = []cli.Flag {
|
||||
cli.StringFlag{
|
||||
Name: "lang, l",
|
||||
Value: "english",
|
||||
Usage: "language for the greeting",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
That flag can then be set with `--lang spanish` or `-l spanish`. Note that giving two different forms of the same flag in the same command invocation is an error.
|
||||
|
||||
#### Values from the Environment
|
||||
|
||||
You can also have the default value set from the environment via `EnvVar`. e.g.
|
||||
|
||||
``` go
|
||||
app.Flags = []cli.Flag {
|
||||
cli.StringFlag{
|
||||
Name: "lang, l",
|
||||
Value: "english",
|
||||
Usage: "language for the greeting",
|
||||
EnvVar: "APP_LANG",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
The `EnvVar` may also be given as a comma-delimited "cascade", where the first environment variable that resolves is used as the default.
|
||||
|
||||
``` go
|
||||
app.Flags = []cli.Flag {
|
||||
cli.StringFlag{
|
||||
Name: "lang, l",
|
||||
Value: "english",
|
||||
Usage: "language for the greeting",
|
||||
EnvVar: "LEGACY_COMPAT_LANG,APP_LANG,LANG",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Subcommands
|
||||
|
||||
Subcommands can be defined for a more git-like command line app.
|
||||
```go
|
||||
...
|
||||
app.Commands = []cli.Command{
|
||||
{
|
||||
Name: "add",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "add a task to the list",
|
||||
Action: func(c *cli.Context) {
|
||||
println("added task: ", c.Args().First())
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "complete",
|
||||
Aliases: []string{"c"},
|
||||
Usage: "complete a task on the list",
|
||||
Action: func(c *cli.Context) {
|
||||
println("completed task: ", c.Args().First())
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "template",
|
||||
Aliases: []string{"r"},
|
||||
Usage: "options for task templates",
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "add",
|
||||
Usage: "add a new template",
|
||||
Action: func(c *cli.Context) {
|
||||
println("new task template: ", c.Args().First())
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "remove",
|
||||
Usage: "remove an existing template",
|
||||
Action: func(c *cli.Context) {
|
||||
println("removed task template: ", c.Args().First())
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
...
|
||||
```
|
||||
|
||||
### Bash Completion
|
||||
|
||||
You can enable completion commands by setting the `EnableBashCompletion`
|
||||
flag on the `App` object. By default, this setting will only auto-complete to
|
||||
show an app's subcommands, but you can write your own completion methods for
|
||||
the App or its subcommands.
|
||||
```go
|
||||
...
|
||||
var tasks = []string{"cook", "clean", "laundry", "eat", "sleep", "code"}
|
||||
app := cli.NewApp()
|
||||
app.EnableBashCompletion = true
|
||||
app.Commands = []cli.Command{
|
||||
{
|
||||
Name: "complete",
|
||||
Aliases: []string{"c"},
|
||||
Usage: "complete a task on the list",
|
||||
Action: func(c *cli.Context) {
|
||||
println("completed task: ", c.Args().First())
|
||||
},
|
||||
BashComplete: func(c *cli.Context) {
|
||||
// This will complete if no args are passed
|
||||
if len(c.Args()) > 0 {
|
||||
return
|
||||
}
|
||||
for _, t := range tasks {
|
||||
fmt.Println(t)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
...
|
||||
```
|
||||
|
||||
#### To Enable
|
||||
|
||||
Source the `autocomplete/bash_autocomplete` file in your `.bashrc` file while
|
||||
setting the `PROG` variable to the name of your program:
|
||||
|
||||
`PROG=myprogram source /.../cli/autocomplete/bash_autocomplete`
|
||||
|
||||
#### To Distribute
|
||||
|
||||
Copy `autocomplete/bash_autocomplete` into `/etc/bash_completion.d/` and rename
|
||||
it to the name of the program you wish to add autocomplete support for (or
|
||||
automatically install it there if you are distributing a package). Don't forget
|
||||
to source the file to make it active in the current shell.
|
||||
|
||||
```
|
||||
sudo cp src/bash_autocomplete /etc/bash_completion.d/<myprogram>
|
||||
source /etc/bash_completion.d/<myprogram>
|
||||
```
|
||||
|
||||
Alternatively, you can just document that users should source the generic
|
||||
`autocomplete/bash_autocomplete` in their bash configuration with `$PROG` set
|
||||
to the name of their program (as above).
|
||||
|
||||
## Contribution Guidelines
|
||||
Feel free to put up a pull request to fix a bug or maybe add a feature. I will give it a code review and make sure that it does not break backwards compatibility. If I or any other collaborators agree that it is in line with the vision of the project, we will work with you to get the code into a mergeable state and merge it into the master branch.
|
||||
|
||||
If you have contributed something significant to the project, I will most likely add you as a collaborator. As a collaborator you are given the ability to merge others pull requests. It is very important that new code does not break existing code, so be careful about what code you do choose to merge. If you have any questions feel free to link @codegangsta to the issue in question and we can review it together.
|
||||
|
||||
If you feel like you have contributed to the project but have not yet been added as a collaborator, I probably forgot to add you. Hit @codegangsta up over email and we will get it figured out.
|
||||
333
vendor/github.com/codegangsta/cli/app.go
generated
vendored
333
vendor/github.com/codegangsta/cli/app.go
generated
vendored
@@ -1,333 +0,0 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// App is the main structure of a cli application. It is recomended that
|
||||
// an app be created with the cli.NewApp() function
|
||||
type App struct {
|
||||
// The name of the program. Defaults to os.Args[0]
|
||||
Name string
|
||||
// Full name of command for help, defaults to Name
|
||||
HelpName string
|
||||
// Description of the program.
|
||||
Usage string
|
||||
// Description of the program argument format.
|
||||
ArgsUsage string
|
||||
// Version of the program
|
||||
Version string
|
||||
// List of commands to execute
|
||||
Commands []Command
|
||||
// List of flags to parse
|
||||
Flags []Flag
|
||||
// Boolean to enable bash completion commands
|
||||
EnableBashCompletion bool
|
||||
// Boolean to hide built-in help command
|
||||
HideHelp bool
|
||||
// Boolean to hide built-in version flag
|
||||
HideVersion bool
|
||||
// An action to execute when the bash-completion flag is set
|
||||
BashComplete func(context *Context)
|
||||
// An action to execute before any subcommands are run, but after the context is ready
|
||||
// If a non-nil error is returned, no subcommands are run
|
||||
Before func(context *Context) error
|
||||
// An action to execute after any subcommands are run, but after the subcommand has finished
|
||||
// It is run even if Action() panics
|
||||
After func(context *Context) error
|
||||
// The action to execute when no subcommands are specified
|
||||
Action func(context *Context)
|
||||
// Execute this function if the proper command cannot be found
|
||||
CommandNotFound func(context *Context, command string)
|
||||
// Compilation date
|
||||
Compiled time.Time
|
||||
// List of all authors who contributed
|
||||
Authors []Author
|
||||
// Copyright of the binary if any
|
||||
Copyright string
|
||||
// Name of Author (Note: Use App.Authors, this is deprecated)
|
||||
Author string
|
||||
// Email of Author (Note: Use App.Authors, this is deprecated)
|
||||
Email string
|
||||
// Writer writer to write output to
|
||||
Writer io.Writer
|
||||
}
|
||||
|
||||
// Tries to find out when this binary was compiled.
|
||||
// Returns the current time if it fails to find it.
|
||||
func compileTime() time.Time {
|
||||
info, err := os.Stat(os.Args[0])
|
||||
if err != nil {
|
||||
return time.Now()
|
||||
}
|
||||
return info.ModTime()
|
||||
}
|
||||
|
||||
// Creates a new cli Application with some reasonable defaults for Name, Usage, Version and Action.
|
||||
func NewApp() *App {
|
||||
return &App{
|
||||
Name: os.Args[0],
|
||||
HelpName: os.Args[0],
|
||||
Usage: "A new cli application",
|
||||
Version: "0.0.0",
|
||||
BashComplete: DefaultAppComplete,
|
||||
Action: helpCommand.Action,
|
||||
Compiled: compileTime(),
|
||||
Writer: os.Stdout,
|
||||
}
|
||||
}
|
||||
|
||||
// Entry point to the cli app. Parses the arguments slice and routes to the proper flag/args combination
|
||||
func (a *App) Run(arguments []string) (err error) {
|
||||
if a.Author != "" || a.Email != "" {
|
||||
a.Authors = append(a.Authors, Author{Name: a.Author, Email: a.Email})
|
||||
}
|
||||
|
||||
newCmds := []Command{}
|
||||
for _, c := range a.Commands {
|
||||
if c.HelpName == "" {
|
||||
c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name)
|
||||
}
|
||||
newCmds = append(newCmds, c)
|
||||
}
|
||||
a.Commands = newCmds
|
||||
|
||||
// append help to commands
|
||||
if a.Command(helpCommand.Name) == nil && !a.HideHelp {
|
||||
a.Commands = append(a.Commands, helpCommand)
|
||||
if (HelpFlag != BoolFlag{}) {
|
||||
a.appendFlag(HelpFlag)
|
||||
}
|
||||
}
|
||||
|
||||
//append version/help flags
|
||||
if a.EnableBashCompletion {
|
||||
a.appendFlag(BashCompletionFlag)
|
||||
}
|
||||
|
||||
if !a.HideVersion {
|
||||
a.appendFlag(VersionFlag)
|
||||
}
|
||||
|
||||
// parse flags
|
||||
set := flagSet(a.Name, a.Flags)
|
||||
set.SetOutput(ioutil.Discard)
|
||||
err = set.Parse(arguments[1:])
|
||||
nerr := normalizeFlags(a.Flags, set)
|
||||
if nerr != nil {
|
||||
fmt.Fprintln(a.Writer, nerr)
|
||||
context := NewContext(a, set, nil)
|
||||
ShowAppHelp(context)
|
||||
return nerr
|
||||
}
|
||||
context := NewContext(a, set, nil)
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintln(a.Writer, "Incorrect Usage.")
|
||||
fmt.Fprintln(a.Writer)
|
||||
ShowAppHelp(context)
|
||||
return err
|
||||
}
|
||||
|
||||
if checkCompletions(context) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !a.HideHelp && checkHelp(context) {
|
||||
ShowAppHelp(context)
|
||||
return nil
|
||||
}
|
||||
|
||||
if !a.HideVersion && checkVersion(context) {
|
||||
ShowVersion(context)
|
||||
return nil
|
||||
}
|
||||
|
||||
if a.After != nil {
|
||||
defer func() {
|
||||
afterErr := a.After(context)
|
||||
if afterErr != nil {
|
||||
if err != nil {
|
||||
err = NewMultiError(err, afterErr)
|
||||
} else {
|
||||
err = afterErr
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
if a.Before != nil {
|
||||
err := a.Before(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
args := context.Args()
|
||||
if args.Present() {
|
||||
name := args.First()
|
||||
c := a.Command(name)
|
||||
if c != nil {
|
||||
return c.Run(context)
|
||||
}
|
||||
}
|
||||
|
||||
// Run default Action
|
||||
a.Action(context)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Another entry point to the cli app, takes care of passing arguments and error handling
|
||||
func (a *App) RunAndExitOnError() {
|
||||
if err := a.Run(os.Args); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// Invokes the subcommand given the context, parses ctx.Args() to generate command-specific flags
|
||||
func (a *App) RunAsSubcommand(ctx *Context) (err error) {
|
||||
// append help to commands
|
||||
if len(a.Commands) > 0 {
|
||||
if a.Command(helpCommand.Name) == nil && !a.HideHelp {
|
||||
a.Commands = append(a.Commands, helpCommand)
|
||||
if (HelpFlag != BoolFlag{}) {
|
||||
a.appendFlag(HelpFlag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newCmds := []Command{}
|
||||
for _, c := range a.Commands {
|
||||
if c.HelpName == "" {
|
||||
c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name)
|
||||
}
|
||||
newCmds = append(newCmds, c)
|
||||
}
|
||||
a.Commands = newCmds
|
||||
|
||||
// append flags
|
||||
if a.EnableBashCompletion {
|
||||
a.appendFlag(BashCompletionFlag)
|
||||
}
|
||||
|
||||
// parse flags
|
||||
set := flagSet(a.Name, a.Flags)
|
||||
set.SetOutput(ioutil.Discard)
|
||||
err = set.Parse(ctx.Args().Tail())
|
||||
nerr := normalizeFlags(a.Flags, set)
|
||||
context := NewContext(a, set, ctx)
|
||||
|
||||
if nerr != nil {
|
||||
fmt.Fprintln(a.Writer, nerr)
|
||||
fmt.Fprintln(a.Writer)
|
||||
if len(a.Commands) > 0 {
|
||||
ShowSubcommandHelp(context)
|
||||
} else {
|
||||
ShowCommandHelp(ctx, context.Args().First())
|
||||
}
|
||||
return nerr
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintln(a.Writer, "Incorrect Usage.")
|
||||
fmt.Fprintln(a.Writer)
|
||||
ShowSubcommandHelp(context)
|
||||
return err
|
||||
}
|
||||
|
||||
if checkCompletions(context) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(a.Commands) > 0 {
|
||||
if checkSubcommandHelp(context) {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
if checkCommandHelp(ctx, context.Args().First()) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if a.After != nil {
|
||||
defer func() {
|
||||
afterErr := a.After(context)
|
||||
if afterErr != nil {
|
||||
if err != nil {
|
||||
err = NewMultiError(err, afterErr)
|
||||
} else {
|
||||
err = afterErr
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
if a.Before != nil {
|
||||
err := a.Before(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
args := context.Args()
|
||||
if args.Present() {
|
||||
name := args.First()
|
||||
c := a.Command(name)
|
||||
if c != nil {
|
||||
return c.Run(context)
|
||||
}
|
||||
}
|
||||
|
||||
// Run default Action
|
||||
a.Action(context)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Returns the named command on App. Returns nil if the command does not exist
|
||||
func (a *App) Command(name string) *Command {
|
||||
for _, c := range a.Commands {
|
||||
if c.HasName(name) {
|
||||
return &c
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) hasFlag(flag Flag) bool {
|
||||
for _, f := range a.Flags {
|
||||
if flag == f {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *App) appendFlag(flag Flag) {
|
||||
if !a.hasFlag(flag) {
|
||||
a.Flags = append(a.Flags, flag)
|
||||
}
|
||||
}
|
||||
|
||||
// Author represents someone who has contributed to a cli project.
|
||||
type Author struct {
|
||||
Name string // The Authors name
|
||||
Email string // The Authors email
|
||||
}
|
||||
|
||||
// String makes Author comply to the Stringer interface, to allow an easy print in the templating process
|
||||
func (a Author) String() string {
|
||||
e := ""
|
||||
if a.Email != "" {
|
||||
e = "<" + a.Email + "> "
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%v %v", a.Name, e)
|
||||
}
|
||||
210
vendor/github.com/codegangsta/cli/command.go
generated
vendored
210
vendor/github.com/codegangsta/cli/command.go
generated
vendored
@@ -1,210 +0,0 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Command is a subcommand for a cli.App.
|
||||
type Command struct {
|
||||
// The name of the command
|
||||
Name string
|
||||
// short name of the command. Typically one character (deprecated, use `Aliases`)
|
||||
ShortName string
|
||||
// A list of aliases for the command
|
||||
Aliases []string
|
||||
// A short description of the usage of this command
|
||||
Usage string
|
||||
// A longer explanation of how the command works
|
||||
Description string
|
||||
// A short description of the arguments of this command
|
||||
ArgsUsage string
|
||||
// The function to call when checking for bash command completions
|
||||
BashComplete func(context *Context)
|
||||
// An action to execute before any sub-subcommands are run, but after the context is ready
|
||||
// If a non-nil error is returned, no sub-subcommands are run
|
||||
Before func(context *Context) error
|
||||
// An action to execute after any subcommands are run, but after the subcommand has finished
|
||||
// It is run even if Action() panics
|
||||
After func(context *Context) error
|
||||
// The function to call when this command is invoked
|
||||
Action func(context *Context)
|
||||
// List of child commands
|
||||
Subcommands []Command
|
||||
// List of flags to parse
|
||||
Flags []Flag
|
||||
// Treat all flags as normal arguments if true
|
||||
SkipFlagParsing bool
|
||||
// Boolean to hide built-in help command
|
||||
HideHelp bool
|
||||
|
||||
// Full name of command for help, defaults to full command name, including parent commands.
|
||||
HelpName string
|
||||
commandNamePath []string
|
||||
}
|
||||
|
||||
// Returns the full name of the command.
|
||||
// For subcommands this ensures that parent commands are part of the command path
|
||||
func (c Command) FullName() string {
|
||||
if c.commandNamePath == nil {
|
||||
return c.Name
|
||||
}
|
||||
return strings.Join(c.commandNamePath, " ")
|
||||
}
|
||||
|
||||
// Invokes the command given the context, parses ctx.Args() to generate command-specific flags
|
||||
func (c Command) Run(ctx *Context) error {
|
||||
if len(c.Subcommands) > 0 || c.Before != nil || c.After != nil {
|
||||
return c.startApp(ctx)
|
||||
}
|
||||
|
||||
if !c.HideHelp && (HelpFlag != BoolFlag{}) {
|
||||
// append help to flags
|
||||
c.Flags = append(
|
||||
c.Flags,
|
||||
HelpFlag,
|
||||
)
|
||||
}
|
||||
|
||||
if ctx.App.EnableBashCompletion {
|
||||
c.Flags = append(c.Flags, BashCompletionFlag)
|
||||
}
|
||||
|
||||
set := flagSet(c.Name, c.Flags)
|
||||
set.SetOutput(ioutil.Discard)
|
||||
|
||||
firstFlagIndex := -1
|
||||
terminatorIndex := -1
|
||||
for index, arg := range ctx.Args() {
|
||||
if arg == "--" {
|
||||
terminatorIndex = index
|
||||
break
|
||||
} else if strings.HasPrefix(arg, "-") && firstFlagIndex == -1 {
|
||||
firstFlagIndex = index
|
||||
}
|
||||
}
|
||||
|
||||
var err error
|
||||
if firstFlagIndex > -1 && !c.SkipFlagParsing {
|
||||
args := ctx.Args()
|
||||
regularArgs := make([]string, len(args[1:firstFlagIndex]))
|
||||
copy(regularArgs, args[1:firstFlagIndex])
|
||||
|
||||
var flagArgs []string
|
||||
if terminatorIndex > -1 {
|
||||
flagArgs = args[firstFlagIndex:terminatorIndex]
|
||||
regularArgs = append(regularArgs, args[terminatorIndex:]...)
|
||||
} else {
|
||||
flagArgs = args[firstFlagIndex:]
|
||||
}
|
||||
|
||||
err = set.Parse(append(flagArgs, regularArgs...))
|
||||
} else {
|
||||
err = set.Parse(ctx.Args().Tail())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintln(ctx.App.Writer, "Incorrect Usage.")
|
||||
fmt.Fprintln(ctx.App.Writer)
|
||||
ShowCommandHelp(ctx, c.Name)
|
||||
return err
|
||||
}
|
||||
|
||||
nerr := normalizeFlags(c.Flags, set)
|
||||
if nerr != nil {
|
||||
fmt.Fprintln(ctx.App.Writer, nerr)
|
||||
fmt.Fprintln(ctx.App.Writer)
|
||||
ShowCommandHelp(ctx, c.Name)
|
||||
return nerr
|
||||
}
|
||||
context := NewContext(ctx.App, set, ctx)
|
||||
|
||||
if checkCommandCompletions(context, c.Name) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if checkCommandHelp(context, c.Name) {
|
||||
return nil
|
||||
}
|
||||
context.Command = c
|
||||
c.Action(context)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c Command) Names() []string {
|
||||
names := []string{c.Name}
|
||||
|
||||
if c.ShortName != "" {
|
||||
names = append(names, c.ShortName)
|
||||
}
|
||||
|
||||
return append(names, c.Aliases...)
|
||||
}
|
||||
|
||||
// Returns true if Command.Name or Command.ShortName matches given name
|
||||
func (c Command) HasName(name string) bool {
|
||||
for _, n := range c.Names() {
|
||||
if n == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c Command) startApp(ctx *Context) error {
|
||||
app := NewApp()
|
||||
|
||||
// set the name and usage
|
||||
app.Name = fmt.Sprintf("%s %s", ctx.App.Name, c.Name)
|
||||
if c.HelpName == "" {
|
||||
app.HelpName = c.HelpName
|
||||
} else {
|
||||
app.HelpName = fmt.Sprintf("%s %s", ctx.App.Name, c.Name)
|
||||
}
|
||||
|
||||
if c.Description != "" {
|
||||
app.Usage = c.Description
|
||||
} else {
|
||||
app.Usage = c.Usage
|
||||
}
|
||||
|
||||
// set CommandNotFound
|
||||
app.CommandNotFound = ctx.App.CommandNotFound
|
||||
|
||||
// set the flags and commands
|
||||
app.Commands = c.Subcommands
|
||||
app.Flags = c.Flags
|
||||
app.HideHelp = c.HideHelp
|
||||
|
||||
app.Version = ctx.App.Version
|
||||
app.HideVersion = ctx.App.HideVersion
|
||||
app.Compiled = ctx.App.Compiled
|
||||
app.Author = ctx.App.Author
|
||||
app.Email = ctx.App.Email
|
||||
app.Writer = ctx.App.Writer
|
||||
|
||||
// bash completion
|
||||
app.EnableBashCompletion = ctx.App.EnableBashCompletion
|
||||
if c.BashComplete != nil {
|
||||
app.BashComplete = c.BashComplete
|
||||
}
|
||||
|
||||
// set the actions
|
||||
app.Before = c.Before
|
||||
app.After = c.After
|
||||
if c.Action != nil {
|
||||
app.Action = c.Action
|
||||
} else {
|
||||
app.Action = helpSubcommand.Action
|
||||
}
|
||||
|
||||
var newCmds []Command
|
||||
for _, cc := range app.Commands {
|
||||
cc.commandNamePath = []string{c.Name, cc.Name}
|
||||
newCmds = append(newCmds, cc)
|
||||
}
|
||||
app.Commands = newCmds
|
||||
|
||||
return app.RunAsSubcommand(ctx)
|
||||
}
|
||||
388
vendor/github.com/codegangsta/cli/context.go
generated
vendored
388
vendor/github.com/codegangsta/cli/context.go
generated
vendored
@@ -1,388 +0,0 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Context is a type that is passed through to
|
||||
// each Handler action in a cli application. Context
|
||||
// can be used to retrieve context-specific Args and
|
||||
// parsed command-line options.
|
||||
type Context struct {
|
||||
App *App
|
||||
Command Command
|
||||
flagSet *flag.FlagSet
|
||||
setFlags map[string]bool
|
||||
globalSetFlags map[string]bool
|
||||
parentContext *Context
|
||||
}
|
||||
|
||||
// Creates a new context. For use in when invoking an App or Command action.
|
||||
func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context {
|
||||
return &Context{App: app, flagSet: set, parentContext: parentCtx}
|
||||
}
|
||||
|
||||
// Looks up the value of a local int flag, returns 0 if no int flag exists
|
||||
func (c *Context) Int(name string) int {
|
||||
return lookupInt(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Looks up the value of a local time.Duration flag, returns 0 if no time.Duration flag exists
|
||||
func (c *Context) Duration(name string) time.Duration {
|
||||
return lookupDuration(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Looks up the value of a local float64 flag, returns 0 if no float64 flag exists
|
||||
func (c *Context) Float64(name string) float64 {
|
||||
return lookupFloat64(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Looks up the value of a local bool flag, returns false if no bool flag exists
|
||||
func (c *Context) Bool(name string) bool {
|
||||
return lookupBool(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Looks up the value of a local boolT flag, returns false if no bool flag exists
|
||||
func (c *Context) BoolT(name string) bool {
|
||||
return lookupBoolT(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Looks up the value of a local string flag, returns "" if no string flag exists
|
||||
func (c *Context) String(name string) string {
|
||||
return lookupString(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Looks up the value of a local string slice flag, returns nil if no string slice flag exists
|
||||
func (c *Context) StringSlice(name string) []string {
|
||||
return lookupStringSlice(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Looks up the value of a local int slice flag, returns nil if no int slice flag exists
|
||||
func (c *Context) IntSlice(name string) []int {
|
||||
return lookupIntSlice(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Looks up the value of a local generic flag, returns nil if no generic flag exists
|
||||
func (c *Context) Generic(name string) interface{} {
|
||||
return lookupGeneric(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Looks up the value of a global int flag, returns 0 if no int flag exists
|
||||
func (c *Context) GlobalInt(name string) int {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupInt(name, fs)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Looks up the value of a global time.Duration flag, returns 0 if no time.Duration flag exists
|
||||
func (c *Context) GlobalDuration(name string) time.Duration {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupDuration(name, fs)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Looks up the value of a global bool flag, returns false if no bool flag exists
|
||||
func (c *Context) GlobalBool(name string) bool {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupBool(name, fs)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Looks up the value of a global string flag, returns "" if no string flag exists
|
||||
func (c *Context) GlobalString(name string) string {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupString(name, fs)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Looks up the value of a global string slice flag, returns nil if no string slice flag exists
|
||||
func (c *Context) GlobalStringSlice(name string) []string {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupStringSlice(name, fs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Looks up the value of a global int slice flag, returns nil if no int slice flag exists
|
||||
func (c *Context) GlobalIntSlice(name string) []int {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupIntSlice(name, fs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Looks up the value of a global generic flag, returns nil if no generic flag exists
|
||||
func (c *Context) GlobalGeneric(name string) interface{} {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupGeneric(name, fs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Returns the number of flags set
|
||||
func (c *Context) NumFlags() int {
|
||||
return c.flagSet.NFlag()
|
||||
}
|
||||
|
||||
// Determines if the flag was actually set
|
||||
func (c *Context) IsSet(name string) bool {
|
||||
if c.setFlags == nil {
|
||||
c.setFlags = make(map[string]bool)
|
||||
c.flagSet.Visit(func(f *flag.Flag) {
|
||||
c.setFlags[f.Name] = true
|
||||
})
|
||||
}
|
||||
return c.setFlags[name] == true
|
||||
}
|
||||
|
||||
// Determines if the global flag was actually set
|
||||
func (c *Context) GlobalIsSet(name string) bool {
|
||||
if c.globalSetFlags == nil {
|
||||
c.globalSetFlags = make(map[string]bool)
|
||||
ctx := c
|
||||
if ctx.parentContext != nil {
|
||||
ctx = ctx.parentContext
|
||||
}
|
||||
for ; ctx != nil && c.globalSetFlags[name] == false; ctx = ctx.parentContext {
|
||||
ctx.flagSet.Visit(func(f *flag.Flag) {
|
||||
c.globalSetFlags[f.Name] = true
|
||||
})
|
||||
}
|
||||
}
|
||||
return c.globalSetFlags[name]
|
||||
}
|
||||
|
||||
// Returns a slice of flag names used in this context.
|
||||
func (c *Context) FlagNames() (names []string) {
|
||||
for _, flag := range c.Command.Flags {
|
||||
name := strings.Split(flag.getName(), ",")[0]
|
||||
if name == "help" {
|
||||
continue
|
||||
}
|
||||
names = append(names, name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Returns a slice of global flag names used by the app.
|
||||
func (c *Context) GlobalFlagNames() (names []string) {
|
||||
for _, flag := range c.App.Flags {
|
||||
name := strings.Split(flag.getName(), ",")[0]
|
||||
if name == "help" || name == "version" {
|
||||
continue
|
||||
}
|
||||
names = append(names, name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Returns the parent context, if any
|
||||
func (c *Context) Parent() *Context {
|
||||
return c.parentContext
|
||||
}
|
||||
|
||||
type Args []string
|
||||
|
||||
// Returns the command line arguments associated with the context.
|
||||
func (c *Context) Args() Args {
|
||||
args := Args(c.flagSet.Args())
|
||||
return args
|
||||
}
|
||||
|
||||
// Returns the nth argument, or else a blank string
|
||||
func (a Args) Get(n int) string {
|
||||
if len(a) > n {
|
||||
return a[n]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Returns the first argument, or else a blank string
|
||||
func (a Args) First() string {
|
||||
return a.Get(0)
|
||||
}
|
||||
|
||||
// Return the rest of the arguments (not the first one)
|
||||
// or else an empty string slice
|
||||
func (a Args) Tail() []string {
|
||||
if len(a) >= 2 {
|
||||
return []string(a)[1:]
|
||||
}
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// Checks if there are any arguments present
|
||||
func (a Args) Present() bool {
|
||||
return len(a) != 0
|
||||
}
|
||||
|
||||
// Swaps arguments at the given indexes
|
||||
func (a Args) Swap(from, to int) error {
|
||||
if from >= len(a) || to >= len(a) {
|
||||
return errors.New("index out of range")
|
||||
}
|
||||
a[from], a[to] = a[to], a[from]
|
||||
return nil
|
||||
}
|
||||
|
||||
func lookupGlobalFlagSet(name string, ctx *Context) *flag.FlagSet {
|
||||
if ctx.parentContext != nil {
|
||||
ctx = ctx.parentContext
|
||||
}
|
||||
for ; ctx != nil; ctx = ctx.parentContext {
|
||||
if f := ctx.flagSet.Lookup(name); f != nil {
|
||||
return ctx.flagSet
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func lookupInt(name string, set *flag.FlagSet) int {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
val, err := strconv.Atoi(f.Value.String())
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func lookupDuration(name string, set *flag.FlagSet) time.Duration {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
val, err := time.ParseDuration(f.Value.String())
|
||||
if err == nil {
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func lookupFloat64(name string, set *flag.FlagSet) float64 {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
val, err := strconv.ParseFloat(f.Value.String(), 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func lookupString(name string, set *flag.FlagSet) string {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
return f.Value.String()
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func lookupStringSlice(name string, set *flag.FlagSet) []string {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
return (f.Value.(*StringSlice)).Value()
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func lookupIntSlice(name string, set *flag.FlagSet) []int {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
return (f.Value.(*IntSlice)).Value()
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func lookupGeneric(name string, set *flag.FlagSet) interface{} {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
return f.Value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func lookupBool(name string, set *flag.FlagSet) bool {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
val, err := strconv.ParseBool(f.Value.String())
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func lookupBoolT(name string, set *flag.FlagSet) bool {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
val, err := strconv.ParseBool(f.Value.String())
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
|
||||
switch ff.Value.(type) {
|
||||
case *StringSlice:
|
||||
default:
|
||||
set.Set(name, ff.Value.String())
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeFlags(flags []Flag, set *flag.FlagSet) error {
|
||||
visited := make(map[string]bool)
|
||||
set.Visit(func(f *flag.Flag) {
|
||||
visited[f.Name] = true
|
||||
})
|
||||
for _, f := range flags {
|
||||
parts := strings.Split(f.getName(), ",")
|
||||
if len(parts) == 1 {
|
||||
continue
|
||||
}
|
||||
var ff *flag.Flag
|
||||
for _, name := range parts {
|
||||
name = strings.Trim(name, " ")
|
||||
if visited[name] {
|
||||
if ff != nil {
|
||||
return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name)
|
||||
}
|
||||
ff = set.Lookup(name)
|
||||
}
|
||||
}
|
||||
if ff == nil {
|
||||
continue
|
||||
}
|
||||
for _, name := range parts {
|
||||
name = strings.Trim(name, " ")
|
||||
if !visited[name] {
|
||||
copyFlag(name, ff, set)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
497
vendor/github.com/codegangsta/cli/flag.go
generated
vendored
497
vendor/github.com/codegangsta/cli/flag.go
generated
vendored
@@ -1,497 +0,0 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// This flag enables bash-completion for all commands and subcommands
|
||||
var BashCompletionFlag = BoolFlag{
|
||||
Name: "generate-bash-completion",
|
||||
}
|
||||
|
||||
// This flag prints the version for the application
|
||||
var VersionFlag = BoolFlag{
|
||||
Name: "version, v",
|
||||
Usage: "print the version",
|
||||
}
|
||||
|
||||
// This flag prints the help for all commands and subcommands
|
||||
// Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand
|
||||
// unless HideHelp is set to true)
|
||||
var HelpFlag = BoolFlag{
|
||||
Name: "help, h",
|
||||
Usage: "show help",
|
||||
}
|
||||
|
||||
// Flag is a common interface related to parsing flags in cli.
|
||||
// For more advanced flag parsing techniques, it is recomended that
|
||||
// this interface be implemented.
|
||||
type Flag interface {
|
||||
fmt.Stringer
|
||||
// Apply Flag settings to the given flag set
|
||||
Apply(*flag.FlagSet)
|
||||
getName() string
|
||||
}
|
||||
|
||||
func flagSet(name string, flags []Flag) *flag.FlagSet {
|
||||
set := flag.NewFlagSet(name, flag.ContinueOnError)
|
||||
|
||||
for _, f := range flags {
|
||||
f.Apply(set)
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
func eachName(longName string, fn func(string)) {
|
||||
parts := strings.Split(longName, ",")
|
||||
for _, name := range parts {
|
||||
name = strings.Trim(name, " ")
|
||||
fn(name)
|
||||
}
|
||||
}
|
||||
|
||||
// Generic is a generic parseable type identified by a specific flag
|
||||
type Generic interface {
|
||||
Set(value string) error
|
||||
String() string
|
||||
}
|
||||
|
||||
// GenericFlag is the flag type for types implementing Generic
|
||||
type GenericFlag struct {
|
||||
Name string
|
||||
Value Generic
|
||||
Usage string
|
||||
EnvVar string
|
||||
}
|
||||
|
||||
// String returns the string representation of the generic flag to display the
|
||||
// help text to the user (uses the String() method of the generic flag to show
|
||||
// the value)
|
||||
func (f GenericFlag) String() string {
|
||||
return withEnvHint(f.EnvVar, fmt.Sprintf("%s%s \"%v\"\t%v", prefixFor(f.Name), f.Name, f.Value, f.Usage))
|
||||
}
|
||||
|
||||
// Apply takes the flagset and calls Set on the generic flag with the value
|
||||
// provided by the user for parsing by the flag
|
||||
func (f GenericFlag) Apply(set *flag.FlagSet) {
|
||||
val := f.Value
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
val.Set(envVal)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
set.Var(f.Value, name, f.Usage)
|
||||
})
|
||||
}
|
||||
|
||||
func (f GenericFlag) getName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// StringSlice is an opaque type for []string to satisfy flag.Value
|
||||
type StringSlice []string
|
||||
|
||||
// Set appends the string value to the list of values
|
||||
func (f *StringSlice) Set(value string) error {
|
||||
*f = append(*f, value)
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value (for usage defaults)
|
||||
func (f *StringSlice) String() string {
|
||||
return fmt.Sprintf("%s", *f)
|
||||
}
|
||||
|
||||
// Value returns the slice of strings set by this flag
|
||||
func (f *StringSlice) Value() []string {
|
||||
return *f
|
||||
}
|
||||
|
||||
// StringSlice is a string flag that can be specified multiple times on the
|
||||
// command-line
|
||||
type StringSliceFlag struct {
|
||||
Name string
|
||||
Value *StringSlice
|
||||
Usage string
|
||||
EnvVar string
|
||||
}
|
||||
|
||||
// String returns the usage
|
||||
func (f StringSliceFlag) String() string {
|
||||
firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ")
|
||||
pref := prefixFor(firstName)
|
||||
return withEnvHint(f.EnvVar, fmt.Sprintf("%s [%v]\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage))
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f StringSliceFlag) Apply(set *flag.FlagSet) {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
newVal := &StringSlice{}
|
||||
for _, s := range strings.Split(envVal, ",") {
|
||||
s = strings.TrimSpace(s)
|
||||
newVal.Set(s)
|
||||
}
|
||||
f.Value = newVal
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Value == nil {
|
||||
f.Value = &StringSlice{}
|
||||
}
|
||||
set.Var(f.Value, name, f.Usage)
|
||||
})
|
||||
}
|
||||
|
||||
func (f StringSliceFlag) getName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// StringSlice is an opaque type for []int to satisfy flag.Value
|
||||
type IntSlice []int
|
||||
|
||||
// Set parses the value into an integer and appends it to the list of values
|
||||
func (f *IntSlice) Set(value string) error {
|
||||
tmp, err := strconv.Atoi(value)
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
*f = append(*f, tmp)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value (for usage defaults)
|
||||
func (f *IntSlice) String() string {
|
||||
return fmt.Sprintf("%d", *f)
|
||||
}
|
||||
|
||||
// Value returns the slice of ints set by this flag
|
||||
func (f *IntSlice) Value() []int {
|
||||
return *f
|
||||
}
|
||||
|
||||
// IntSliceFlag is an int flag that can be specified multiple times on the
|
||||
// command-line
|
||||
type IntSliceFlag struct {
|
||||
Name string
|
||||
Value *IntSlice
|
||||
Usage string
|
||||
EnvVar string
|
||||
}
|
||||
|
||||
// String returns the usage
|
||||
func (f IntSliceFlag) String() string {
|
||||
firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ")
|
||||
pref := prefixFor(firstName)
|
||||
return withEnvHint(f.EnvVar, fmt.Sprintf("%s [%v]\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage))
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f IntSliceFlag) Apply(set *flag.FlagSet) {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
newVal := &IntSlice{}
|
||||
for _, s := range strings.Split(envVal, ",") {
|
||||
s = strings.TrimSpace(s)
|
||||
err := newVal.Set(s)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
}
|
||||
}
|
||||
f.Value = newVal
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Value == nil {
|
||||
f.Value = &IntSlice{}
|
||||
}
|
||||
set.Var(f.Value, name, f.Usage)
|
||||
})
|
||||
}
|
||||
|
||||
func (f IntSliceFlag) getName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// BoolFlag is a switch that defaults to false
|
||||
type BoolFlag struct {
|
||||
Name string
|
||||
Usage string
|
||||
EnvVar string
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value (for usage defaults)
|
||||
func (f BoolFlag) String() string {
|
||||
return withEnvHint(f.EnvVar, fmt.Sprintf("%s\t%v", prefixedNames(f.Name), f.Usage))
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f BoolFlag) Apply(set *flag.FlagSet) {
|
||||
val := false
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
envValBool, err := strconv.ParseBool(envVal)
|
||||
if err == nil {
|
||||
val = envValBool
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
set.Bool(name, val, f.Usage)
|
||||
})
|
||||
}
|
||||
|
||||
func (f BoolFlag) getName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// BoolTFlag this represents a boolean flag that is true by default, but can
|
||||
// still be set to false by --some-flag=false
|
||||
type BoolTFlag struct {
|
||||
Name string
|
||||
Usage string
|
||||
EnvVar string
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value (for usage defaults)
|
||||
func (f BoolTFlag) String() string {
|
||||
return withEnvHint(f.EnvVar, fmt.Sprintf("%s\t%v", prefixedNames(f.Name), f.Usage))
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f BoolTFlag) Apply(set *flag.FlagSet) {
|
||||
val := true
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
envValBool, err := strconv.ParseBool(envVal)
|
||||
if err == nil {
|
||||
val = envValBool
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
set.Bool(name, val, f.Usage)
|
||||
})
|
||||
}
|
||||
|
||||
func (f BoolTFlag) getName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// StringFlag represents a flag that takes as string value
|
||||
type StringFlag struct {
|
||||
Name string
|
||||
Value string
|
||||
Usage string
|
||||
EnvVar string
|
||||
}
|
||||
|
||||
// String returns the usage
|
||||
func (f StringFlag) String() string {
|
||||
var fmtString string
|
||||
fmtString = "%s %v\t%v"
|
||||
|
||||
if len(f.Value) > 0 {
|
||||
fmtString = "%s \"%v\"\t%v"
|
||||
} else {
|
||||
fmtString = "%s %v\t%v"
|
||||
}
|
||||
|
||||
return withEnvHint(f.EnvVar, fmt.Sprintf(fmtString, prefixedNames(f.Name), f.Value, f.Usage))
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f StringFlag) Apply(set *flag.FlagSet) {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
f.Value = envVal
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
set.String(name, f.Value, f.Usage)
|
||||
})
|
||||
}
|
||||
|
||||
func (f StringFlag) getName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// IntFlag is a flag that takes an integer
|
||||
// Errors if the value provided cannot be parsed
|
||||
type IntFlag struct {
|
||||
Name string
|
||||
Value int
|
||||
Usage string
|
||||
EnvVar string
|
||||
}
|
||||
|
||||
// String returns the usage
|
||||
func (f IntFlag) String() string {
|
||||
return withEnvHint(f.EnvVar, fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage))
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f IntFlag) Apply(set *flag.FlagSet) {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
envValInt, err := strconv.ParseInt(envVal, 0, 64)
|
||||
if err == nil {
|
||||
f.Value = int(envValInt)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
set.Int(name, f.Value, f.Usage)
|
||||
})
|
||||
}
|
||||
|
||||
func (f IntFlag) getName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// DurationFlag is a flag that takes a duration specified in Go's duration
|
||||
// format: https://golang.org/pkg/time/#ParseDuration
|
||||
type DurationFlag struct {
|
||||
Name string
|
||||
Value time.Duration
|
||||
Usage string
|
||||
EnvVar string
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value (for usage defaults)
|
||||
func (f DurationFlag) String() string {
|
||||
return withEnvHint(f.EnvVar, fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage))
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f DurationFlag) Apply(set *flag.FlagSet) {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
envValDuration, err := time.ParseDuration(envVal)
|
||||
if err == nil {
|
||||
f.Value = envValDuration
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
set.Duration(name, f.Value, f.Usage)
|
||||
})
|
||||
}
|
||||
|
||||
func (f DurationFlag) getName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// Float64Flag is a flag that takes an float value
|
||||
// Errors if the value provided cannot be parsed
|
||||
type Float64Flag struct {
|
||||
Name string
|
||||
Value float64
|
||||
Usage string
|
||||
EnvVar string
|
||||
}
|
||||
|
||||
// String returns the usage
|
||||
func (f Float64Flag) String() string {
|
||||
return withEnvHint(f.EnvVar, fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage))
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f Float64Flag) Apply(set *flag.FlagSet) {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
envValFloat, err := strconv.ParseFloat(envVal, 10)
|
||||
if err == nil {
|
||||
f.Value = float64(envValFloat)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
set.Float64(name, f.Value, f.Usage)
|
||||
})
|
||||
}
|
||||
|
||||
func (f Float64Flag) getName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
func prefixFor(name string) (prefix string) {
|
||||
if len(name) == 1 {
|
||||
prefix = "-"
|
||||
} else {
|
||||
prefix = "--"
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func prefixedNames(fullName string) (prefixed string) {
|
||||
parts := strings.Split(fullName, ",")
|
||||
for i, name := range parts {
|
||||
name = strings.Trim(name, " ")
|
||||
prefixed += prefixFor(name) + name
|
||||
if i < len(parts)-1 {
|
||||
prefixed += ", "
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func withEnvHint(envVar, str string) string {
|
||||
envText := ""
|
||||
if envVar != "" {
|
||||
envText = fmt.Sprintf(" [$%s]", strings.Join(strings.Split(envVar, ","), ", $"))
|
||||
}
|
||||
return str + envText
|
||||
}
|
||||
246
vendor/github.com/codegangsta/cli/help.go
generated
vendored
246
vendor/github.com/codegangsta/cli/help.go
generated
vendored
@@ -1,246 +0,0 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
// The text template for the Default help topic.
|
||||
// cli.go uses text/template to render templates. You can
|
||||
// render custom help text by setting this variable.
|
||||
var AppHelpTemplate = `NAME:
|
||||
{{.Name}} - {{.Usage}}
|
||||
|
||||
USAGE:
|
||||
{{.HelpName}} {{if .Flags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}
|
||||
{{if .Version}}
|
||||
VERSION:
|
||||
{{.Version}}
|
||||
{{end}}{{if len .Authors}}
|
||||
AUTHOR(S):
|
||||
{{range .Authors}}{{ . }}{{end}}
|
||||
{{end}}{{if .Commands}}
|
||||
COMMANDS:
|
||||
{{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}}
|
||||
{{end}}{{end}}{{if .Flags}}
|
||||
GLOBAL OPTIONS:
|
||||
{{range .Flags}}{{.}}
|
||||
{{end}}{{end}}{{if .Copyright }}
|
||||
COPYRIGHT:
|
||||
{{.Copyright}}
|
||||
{{end}}
|
||||
`
|
||||
|
||||
// The text template for the command help topic.
|
||||
// cli.go uses text/template to render templates. You can
|
||||
// render custom help text by setting this variable.
|
||||
var CommandHelpTemplate = `NAME:
|
||||
{{.HelpName}} - {{.Usage}}
|
||||
|
||||
USAGE:
|
||||
{{.HelpName}}{{if .Flags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{if .Description}}
|
||||
|
||||
DESCRIPTION:
|
||||
{{.Description}}{{end}}{{if .Flags}}
|
||||
|
||||
OPTIONS:
|
||||
{{range .Flags}}{{.}}
|
||||
{{end}}{{ end }}
|
||||
`
|
||||
|
||||
// The text template for the subcommand help topic.
|
||||
// cli.go uses text/template to render templates. You can
|
||||
// render custom help text by setting this variable.
|
||||
var SubcommandHelpTemplate = `NAME:
|
||||
{{.HelpName}} - {{.Usage}}
|
||||
|
||||
USAGE:
|
||||
{{.HelpName}} command{{if .Flags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}
|
||||
|
||||
COMMANDS:
|
||||
{{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}}
|
||||
{{end}}{{if .Flags}}
|
||||
OPTIONS:
|
||||
{{range .Flags}}{{.}}
|
||||
{{end}}{{end}}
|
||||
`
|
||||
|
||||
var helpCommand = Command{
|
||||
Name: "help",
|
||||
Aliases: []string{"h"},
|
||||
Usage: "Shows a list of commands or help for one command",
|
||||
ArgsUsage: "[command]",
|
||||
Action: func(c *Context) {
|
||||
args := c.Args()
|
||||
if args.Present() {
|
||||
ShowCommandHelp(c, args.First())
|
||||
} else {
|
||||
ShowAppHelp(c)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
var helpSubcommand = Command{
|
||||
Name: "help",
|
||||
Aliases: []string{"h"},
|
||||
Usage: "Shows a list of commands or help for one command",
|
||||
ArgsUsage: "[command]",
|
||||
Action: func(c *Context) {
|
||||
args := c.Args()
|
||||
if args.Present() {
|
||||
ShowCommandHelp(c, args.First())
|
||||
} else {
|
||||
ShowSubcommandHelp(c)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Prints help for the App or Command
|
||||
type helpPrinter func(w io.Writer, templ string, data interface{})
|
||||
|
||||
var HelpPrinter helpPrinter = printHelp
|
||||
|
||||
// Prints version for the App
|
||||
var VersionPrinter = printVersion
|
||||
|
||||
func ShowAppHelp(c *Context) {
|
||||
HelpPrinter(c.App.Writer, AppHelpTemplate, c.App)
|
||||
}
|
||||
|
||||
// Prints the list of subcommands as the default app completion method
|
||||
func DefaultAppComplete(c *Context) {
|
||||
for _, command := range c.App.Commands {
|
||||
for _, name := range command.Names() {
|
||||
fmt.Fprintln(c.App.Writer, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prints help for the given command
|
||||
func ShowCommandHelp(ctx *Context, command string) {
|
||||
// show the subcommand help for a command with subcommands
|
||||
if command == "" {
|
||||
HelpPrinter(ctx.App.Writer, SubcommandHelpTemplate, ctx.App)
|
||||
return
|
||||
}
|
||||
|
||||
for _, c := range ctx.App.Commands {
|
||||
if c.HasName(command) {
|
||||
HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.App.CommandNotFound != nil {
|
||||
ctx.App.CommandNotFound(ctx, command)
|
||||
} else {
|
||||
fmt.Fprintf(ctx.App.Writer, "No help topic for '%v'\n", command)
|
||||
}
|
||||
}
|
||||
|
||||
// Prints help for the given subcommand
|
||||
func ShowSubcommandHelp(c *Context) {
|
||||
ShowCommandHelp(c, c.Command.Name)
|
||||
}
|
||||
|
||||
// Prints the version number of the App
|
||||
func ShowVersion(c *Context) {
|
||||
VersionPrinter(c)
|
||||
}
|
||||
|
||||
func printVersion(c *Context) {
|
||||
fmt.Fprintf(c.App.Writer, "%v version %v\n", c.App.Name, c.App.Version)
|
||||
}
|
||||
|
||||
// Prints the lists of commands within a given context
|
||||
func ShowCompletions(c *Context) {
|
||||
a := c.App
|
||||
if a != nil && a.BashComplete != nil {
|
||||
a.BashComplete(c)
|
||||
}
|
||||
}
|
||||
|
||||
// Prints the custom completions for a given command
|
||||
func ShowCommandCompletions(ctx *Context, command string) {
|
||||
c := ctx.App.Command(command)
|
||||
if c != nil && c.BashComplete != nil {
|
||||
c.BashComplete(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
func printHelp(out io.Writer, templ string, data interface{}) {
|
||||
funcMap := template.FuncMap{
|
||||
"join": strings.Join,
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(out, 0, 8, 1, '\t', 0)
|
||||
t := template.Must(template.New("help").Funcs(funcMap).Parse(templ))
|
||||
err := t.Execute(w, data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
w.Flush()
|
||||
}
|
||||
|
||||
func checkVersion(c *Context) bool {
|
||||
found := false
|
||||
if VersionFlag.Name != "" {
|
||||
eachName(VersionFlag.Name, func(name string) {
|
||||
if c.GlobalBool(name) || c.Bool(name) {
|
||||
found = true
|
||||
}
|
||||
})
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
||||
func checkHelp(c *Context) bool {
|
||||
found := false
|
||||
if HelpFlag.Name != "" {
|
||||
eachName(HelpFlag.Name, func(name string) {
|
||||
if c.GlobalBool(name) || c.Bool(name) {
|
||||
found = true
|
||||
}
|
||||
})
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
||||
func checkCommandHelp(c *Context, name string) bool {
|
||||
if c.Bool("h") || c.Bool("help") {
|
||||
ShowCommandHelp(c, name)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func checkSubcommandHelp(c *Context) bool {
|
||||
if c.GlobalBool("h") || c.GlobalBool("help") {
|
||||
ShowSubcommandHelp(c)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func checkCompletions(c *Context) bool {
|
||||
if (c.GlobalBool(BashCompletionFlag.Name) || c.Bool(BashCompletionFlag.Name)) && c.App.EnableBashCompletion {
|
||||
ShowCompletions(c)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func checkCommandCompletions(c *Context, name string) bool {
|
||||
if c.Bool(BashCompletionFlag.Name) && c.App.EnableBashCompletion {
|
||||
ShowCommandCompletions(c, name)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
19
vendor/github.com/dchest/uniuri/LICENSE
generated
vendored
19
vendor/github.com/dchest/uniuri/LICENSE
generated
vendored
@@ -1,19 +0,0 @@
|
||||
Copyright (c) 2011 Dmitry Chestnykh
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
83
vendor/github.com/dchest/uniuri/README.md
generated
vendored
83
vendor/github.com/dchest/uniuri/README.md
generated
vendored
@@ -1,83 +0,0 @@
|
||||
Package uniuri
|
||||
=====================
|
||||
|
||||
[](https://travis-ci.org/dchest/uniuri)
|
||||
|
||||
```go
|
||||
import "github.com/dchest/uniuri"
|
||||
```
|
||||
|
||||
Package uniuri generates random strings good for use in URIs to identify
|
||||
unique objects.
|
||||
|
||||
Example usage:
|
||||
|
||||
```go
|
||||
s := uniuri.New() // s is now "apHCJBl7L1OmC57n"
|
||||
```
|
||||
|
||||
A standard string created by New() is 16 bytes in length and consists of
|
||||
Latin upper and lowercase letters, and numbers (from the set of 62 allowed
|
||||
characters), which means that it has ~95 bits of entropy. To get more
|
||||
entropy, you can use NewLen(UUIDLen), which returns 20-byte string, giving
|
||||
~119 bits of entropy, or any other desired length.
|
||||
|
||||
Functions read from crypto/rand random source, and panic if they fail to
|
||||
read from it.
|
||||
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
```go
|
||||
const (
|
||||
// Standard length of uniuri string to achive ~95 bits of entropy.
|
||||
StdLen = 16
|
||||
// Length of uniurl string to achive ~119 bits of entropy, closest
|
||||
// to what can be losslessly converted to UUIDv4 (122 bits).
|
||||
UUIDLen = 20
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
|
||||
Variables
|
||||
---------
|
||||
|
||||
```go
|
||||
var StdChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
|
||||
```
|
||||
|
||||
Standard characters allowed in uniuri string.
|
||||
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
### func New
|
||||
|
||||
```go
|
||||
func New() string
|
||||
```
|
||||
|
||||
New returns a new random string of the standard length, consisting of
|
||||
standard characters.
|
||||
|
||||
### func NewLen
|
||||
|
||||
```go
|
||||
func NewLen(length int) string
|
||||
```
|
||||
|
||||
NewLen returns a new random string of the provided length, consisting of
|
||||
standard characters.
|
||||
|
||||
### func NewLenChars
|
||||
|
||||
```go
|
||||
func NewLenChars(length int, chars []byte) string
|
||||
```
|
||||
|
||||
NewLenChars returns a new random string of the provided length, consisting
|
||||
of the provided byte slice of allowed characters (maximum 256).
|
||||
|
||||
71
vendor/github.com/dchest/uniuri/uniuri.go
generated
vendored
71
vendor/github.com/dchest/uniuri/uniuri.go
generated
vendored
@@ -1,71 +0,0 @@
|
||||
// Package uniuri generates random strings good for use in URIs to identify
|
||||
// unique objects.
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// s := uniuri.New() // s is now "apHCJBl7L1OmC57n"
|
||||
//
|
||||
// A standard string created by New() is 16 bytes in length and consists of
|
||||
// Latin upper and lowercase letters, and numbers (from the set of 62 allowed
|
||||
// characters), which means that it has ~95 bits of entropy. To get more
|
||||
// entropy, you can use NewLen(UUIDLen), which returns 20-byte string, giving
|
||||
// ~119 bits of entropy, or any other desired length.
|
||||
//
|
||||
// Functions read from crypto/rand random source, and panic if they fail to
|
||||
// read from it.
|
||||
package uniuri
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"io"
|
||||
)
|
||||
|
||||
const (
|
||||
// Standard length of uniuri string to achive ~95 bits of entropy.
|
||||
StdLen = 16
|
||||
// Length of uniurl string to achive ~119 bits of entropy, closest
|
||||
// to what can be losslessly converted to UUIDv4 (122 bits).
|
||||
UUIDLen = 20
|
||||
)
|
||||
|
||||
// Standard characters allowed in uniuri string.
|
||||
var StdChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
|
||||
|
||||
// New returns a new random string of the standard length, consisting of
|
||||
// standard characters.
|
||||
func New() string {
|
||||
return NewLenChars(StdLen, StdChars)
|
||||
}
|
||||
|
||||
// NewLen returns a new random string of the provided length, consisting of
|
||||
// standard characters.
|
||||
func NewLen(length int) string {
|
||||
return NewLenChars(length, StdChars)
|
||||
}
|
||||
|
||||
// NewLenChars returns a new random string of the provided length, consisting
|
||||
// of the provided byte slice of allowed characters (maximum 256).
|
||||
func NewLenChars(length int, chars []byte) string {
|
||||
b := make([]byte, length)
|
||||
r := make([]byte, length+(length/4)) // storage for random bytes.
|
||||
clen := byte(len(chars))
|
||||
maxrb := byte(256 - (256 % len(chars)))
|
||||
i := 0
|
||||
for {
|
||||
if _, err := io.ReadFull(rand.Reader, r); err != nil {
|
||||
panic("error reading from random source: " + err.Error())
|
||||
}
|
||||
for _, c := range r {
|
||||
if c >= maxrb {
|
||||
// Skip this number to avoid modulo bias.
|
||||
continue
|
||||
}
|
||||
b[i] = chars[c%clen]
|
||||
i++
|
||||
if i == length {
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
93
vendor/github.com/djherbis/fscache/README.md
generated
vendored
93
vendor/github.com/djherbis/fscache/README.md
generated
vendored
@@ -1,93 +0,0 @@
|
||||
fscache
|
||||
==========
|
||||
|
||||
[](https://godoc.org/github.com/djherbis/fscache)
|
||||
[](https://github.com/djherbis/fscache/releases/latest)
|
||||
[](LICENSE.txt)
|
||||
[](https://travis-ci.org/djherbis/fscache)
|
||||
[](https://coveralls.io/r/djherbis/fscache?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/djherbis/fscache)
|
||||
|
||||
Usage
|
||||
------------
|
||||
Streaming File Cache for #golang
|
||||
|
||||
fscache allows multiple readers to read from a cache while its being written to. [blog post](https://djherbis.github.io/post/fscache/)
|
||||
|
||||
Using the Cache directly:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"gopkg.in/djherbis/fscache.v0"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
// create the cache, keys expire after 1 hour.
|
||||
c, err := fscache.New("./cache", 0755, time.Hour)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// wipe the cache when done
|
||||
defer c.Clean()
|
||||
|
||||
// Get() and it's streams can be called concurrently but just for example:
|
||||
for i := 0; i < 3; i++ {
|
||||
r, w, err := c.Get("stream")
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if w != nil { // a new stream, write to it.
|
||||
go func(){
|
||||
w.Write([]byte("hello world\n"))
|
||||
w.Close()
|
||||
}()
|
||||
}
|
||||
|
||||
// the stream has started, read from it
|
||||
io.Copy(os.Stdout, r)
|
||||
r.Close()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
A Caching Middle-ware:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import(
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"gopkg.in/djherbis/fscache.v0"
|
||||
)
|
||||
|
||||
func main(){
|
||||
c, err := fscache.New("./cache", 0700, 0)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
handler := func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "%v: %s", time.Now(), "hello world")
|
||||
}
|
||||
|
||||
http.ListenAndServe(":8080", fscache.Handler(c, http.HandlerFunc(handler)))
|
||||
}
|
||||
```
|
||||
|
||||
Installation
|
||||
------------
|
||||
```sh
|
||||
go get gopkg.in/djherbis/fscache.v0
|
||||
```
|
||||
85
vendor/github.com/djherbis/fscache/distrib.go
generated
vendored
85
vendor/github.com/djherbis/fscache/distrib.go
generated
vendored
@@ -1,85 +0,0 @@
|
||||
package fscache
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha1"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Distributor provides a way to partition keys into Caches.
|
||||
type Distributor interface {
|
||||
|
||||
// GetCache will always return the same Cache for the same key.
|
||||
GetCache(key string) Cache
|
||||
|
||||
// Clean should wipe all the caches this Distributor manages
|
||||
Clean() error
|
||||
}
|
||||
|
||||
// stdDistribution distributes the keyspace evenly.
|
||||
func stdDistribution(key string, n uint64) uint64 {
|
||||
h := sha1.New()
|
||||
io.WriteString(h, key)
|
||||
buf := bytes.NewBuffer(h.Sum(nil)[:8])
|
||||
i, _ := binary.ReadUvarint(buf)
|
||||
return i % n
|
||||
}
|
||||
|
||||
// NewDistributor returns a Distributor which evenly distributes the keyspace
|
||||
// into the passed caches.
|
||||
func NewDistributor(caches ...Cache) Distributor {
|
||||
if len(caches) == 0 {
|
||||
return nil
|
||||
}
|
||||
return &distrib{
|
||||
distribution: stdDistribution,
|
||||
caches: caches,
|
||||
size: uint64(len(caches)),
|
||||
}
|
||||
}
|
||||
|
||||
type distrib struct {
|
||||
distribution func(key string, n uint64) uint64
|
||||
caches []Cache
|
||||
size uint64
|
||||
}
|
||||
|
||||
func (d *distrib) GetCache(key string) Cache {
|
||||
return d.caches[d.distribution(key, d.size)]
|
||||
}
|
||||
|
||||
// BUG(djherbis): Return an error if cleaning fails
|
||||
func (d *distrib) Clean() error {
|
||||
for _, c := range d.caches {
|
||||
c.Clean()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewPartition returns a Cache which uses the Caches defined by the passed Distributor.
|
||||
func NewPartition(d Distributor) Cache {
|
||||
return &partition{
|
||||
distributor: d,
|
||||
}
|
||||
}
|
||||
|
||||
type partition struct {
|
||||
distributor Distributor
|
||||
}
|
||||
|
||||
func (p *partition) Get(key string) (ReadAtCloser, io.WriteCloser, error) {
|
||||
return p.distributor.GetCache(key).Get(key)
|
||||
}
|
||||
|
||||
func (p *partition) Remove(key string) error {
|
||||
return p.distributor.GetCache(key).Remove(key)
|
||||
}
|
||||
|
||||
func (p *partition) Exists(key string) bool {
|
||||
return p.distributor.GetCache(key).Exists(key)
|
||||
}
|
||||
|
||||
func (p *partition) Clean() error {
|
||||
return p.distributor.Clean()
|
||||
}
|
||||
199
vendor/github.com/djherbis/fscache/fs.go
generated
vendored
199
vendor/github.com/djherbis/fscache/fs.go
generated
vendored
@@ -1,199 +0,0 @@
|
||||
package fscache
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gopkg.in/djherbis/atime.v1"
|
||||
"gopkg.in/djherbis/stream.v1"
|
||||
)
|
||||
|
||||
// FileSystem is used as the source for a Cache.
|
||||
type FileSystem interface {
|
||||
// Stream FileSystem
|
||||
stream.FileSystem
|
||||
|
||||
// Reload should look through the FileSystem and call the suplied fn
|
||||
// with the key/filename pairs that are found.
|
||||
Reload(func(key, name string)) error
|
||||
|
||||
// RemoveAll should empty the FileSystem of all files.
|
||||
RemoveAll() error
|
||||
|
||||
// AccessTimes takes a File.Name() and returns the last time the file was read,
|
||||
// and the last time it was written to.
|
||||
// It will be used to check expiry of a file, and must be concurrent safe
|
||||
// with modifications to the FileSystem (writes, reads etc.)
|
||||
AccessTimes(name string) (rt, wt time.Time, err error)
|
||||
}
|
||||
|
||||
type stdFs struct {
|
||||
root string
|
||||
}
|
||||
|
||||
// NewFs returns a FileSystem rooted at directory dir.
|
||||
// Dir is created with perms if it doesn't exist.
|
||||
func NewFs(dir string, mode os.FileMode) (FileSystem, error) {
|
||||
return &stdFs{root: dir}, os.MkdirAll(dir, mode)
|
||||
}
|
||||
|
||||
func (fs *stdFs) Reload(add func(key, name string)) error {
|
||||
files, err := ioutil.ReadDir(fs.root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addfiles := make(map[string]struct {
|
||||
os.FileInfo
|
||||
key string
|
||||
})
|
||||
|
||||
for _, f := range files {
|
||||
|
||||
if strings.HasSuffix(f.Name(), ".key") {
|
||||
continue
|
||||
}
|
||||
|
||||
key, err := fs.getKey(f.Name())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fi, ok := addfiles[key]
|
||||
|
||||
if !ok || fi.ModTime().Before(f.ModTime()) {
|
||||
if ok {
|
||||
fs.Remove(fi.Name())
|
||||
}
|
||||
addfiles[key] = struct {
|
||||
os.FileInfo
|
||||
key string
|
||||
}{
|
||||
FileInfo: f,
|
||||
key: key,
|
||||
}
|
||||
} else {
|
||||
fs.Remove(f.Name())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for _, f := range addfiles {
|
||||
path, err := filepath.Abs(filepath.Join(fs.root, f.Name()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
add(f.key, path)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fs *stdFs) Create(name string) (stream.File, error) {
|
||||
name, err := fs.makeName(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fs.create(name)
|
||||
}
|
||||
|
||||
func (fs *stdFs) create(name string) (stream.File, error) {
|
||||
return os.OpenFile(filepath.Join(fs.root, name), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
|
||||
}
|
||||
|
||||
func (fs *stdFs) Open(name string) (stream.File, error) {
|
||||
return os.Open(name)
|
||||
}
|
||||
|
||||
func (fs *stdFs) Remove(name string) error {
|
||||
os.Remove(fmt.Sprintf("%s.key", name))
|
||||
return os.Remove(name)
|
||||
}
|
||||
|
||||
func (fs *stdFs) RemoveAll() error {
|
||||
return os.RemoveAll(fs.root)
|
||||
}
|
||||
|
||||
func (fs *stdFs) AccessTimes(name string) (rt, wt time.Time, err error) {
|
||||
fi, err := os.Stat(name)
|
||||
if err != nil {
|
||||
return rt, wt, err
|
||||
}
|
||||
return atime.Get(fi), fi.ModTime(), nil
|
||||
}
|
||||
|
||||
const (
|
||||
saltSize = 8
|
||||
maxShort = 20
|
||||
shortPrefix = "s"
|
||||
longPrefix = "l"
|
||||
)
|
||||
|
||||
func salt() string {
|
||||
buf := bytes.NewBufferString("")
|
||||
enc := base64.NewEncoder(base64.URLEncoding, buf)
|
||||
io.CopyN(enc, rand.Reader, saltSize)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func tob64(s string) string {
|
||||
buf := bytes.NewBufferString("")
|
||||
enc := base64.NewEncoder(base64.URLEncoding, buf)
|
||||
enc.Write([]byte(s))
|
||||
enc.Close()
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func fromb64(s string) string {
|
||||
buf := bytes.NewBufferString(s)
|
||||
dec := base64.NewDecoder(base64.URLEncoding, buf)
|
||||
out := bytes.NewBufferString("")
|
||||
io.Copy(out, dec)
|
||||
return out.String()
|
||||
}
|
||||
|
||||
func (fs *stdFs) makeName(key string) (string, error) {
|
||||
b64key := tob64(key)
|
||||
// short name
|
||||
if len(b64key) < maxShort {
|
||||
return fmt.Sprintf("%s%s%s", shortPrefix, salt(), b64key), nil
|
||||
}
|
||||
|
||||
// long name
|
||||
hash := md5.Sum([]byte(key))
|
||||
name := fmt.Sprintf("%s%s%x", longPrefix, salt(), hash[:])
|
||||
f, err := fs.create(fmt.Sprintf("%s.key", name))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
_, err = f.Write([]byte(key))
|
||||
f.Close()
|
||||
return name, err
|
||||
}
|
||||
|
||||
func (fs *stdFs) getKey(name string) (string, error) {
|
||||
// short name
|
||||
if strings.HasPrefix(name, shortPrefix) {
|
||||
return fromb64(strings.TrimPrefix(name, shortPrefix)[saltSize:]), nil
|
||||
}
|
||||
|
||||
// long name
|
||||
f, err := fs.Open(filepath.Join(fs.root, fmt.Sprintf("%s.key", name)))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer f.Close()
|
||||
key, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(key), nil
|
||||
}
|
||||
303
vendor/github.com/djherbis/fscache/fscache.go
generated
vendored
303
vendor/github.com/djherbis/fscache/fscache.go
generated
vendored
@@ -1,303 +0,0 @@
|
||||
package fscache
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"gopkg.in/djherbis/stream.v1"
|
||||
)
|
||||
|
||||
// Cache works like a concurrent-safe map for streams.
|
||||
type Cache interface {
|
||||
|
||||
// Get manages access to the streams in the cache.
|
||||
// If the key does not exist, w != nil and you can start writing to the stream.
|
||||
// If the key does exist, w == nil.
|
||||
// r will always be non-nil as long as err == nil and you must close r when you're done reading.
|
||||
// Get can be called concurrently, and writing and reading is concurrent safe.
|
||||
Get(key string) (ReadAtCloser, io.WriteCloser, error)
|
||||
|
||||
// Remove deletes the stream from the cache, blocking until the underlying
|
||||
// file can be deleted (all active streams finish with it).
|
||||
// It is safe to call Remove concurrently with Get.
|
||||
Remove(key string) error
|
||||
|
||||
// Exists checks if a key is in the cache.
|
||||
// It is safe to call Exists concurrently with Get.
|
||||
Exists(key string) bool
|
||||
|
||||
// Clean will empty the cache and delete the cache folder.
|
||||
// Clean is not safe to call while streams are being read/written.
|
||||
Clean() error
|
||||
}
|
||||
|
||||
type cache struct {
|
||||
mu sync.RWMutex
|
||||
files map[string]fileStream
|
||||
grim Reaper
|
||||
fs FileSystem
|
||||
}
|
||||
|
||||
// ReadAtCloser is an io.ReadCloser, and an io.ReaderAt. It supports both so that Range
|
||||
// Requests are possible.
|
||||
type ReadAtCloser interface {
|
||||
io.ReadCloser
|
||||
io.ReaderAt
|
||||
}
|
||||
|
||||
type fileStream interface {
|
||||
next() (ReadAtCloser, error)
|
||||
inUse() bool
|
||||
io.WriteCloser
|
||||
Remove() error
|
||||
Name() string
|
||||
}
|
||||
|
||||
// New creates a new Cache using NewFs(dir, perms).
|
||||
// expiry is the duration after which an un-accessed key will be removed from
|
||||
// the cache, a zero value expiro means never expire.
|
||||
func New(dir string, perms os.FileMode, expiry time.Duration) (Cache, error) {
|
||||
fs, err := NewFs(dir, perms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var grim Reaper
|
||||
if expiry > 0 {
|
||||
grim = &reaper{
|
||||
expiry: expiry,
|
||||
period: expiry,
|
||||
}
|
||||
}
|
||||
return NewCache(fs, grim)
|
||||
}
|
||||
|
||||
// NewCache creates a new Cache based on FileSystem fs.
|
||||
// fs.Files() are loaded using the name they were created with as a key.
|
||||
// Reaper is used to determine when files expire, nil means never expire.
|
||||
func NewCache(fs FileSystem, grim Reaper) (Cache, error) {
|
||||
c := &cache{
|
||||
files: make(map[string]fileStream),
|
||||
grim: grim,
|
||||
fs: fs,
|
||||
}
|
||||
err := c.load()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if grim != nil {
|
||||
c.haunter()
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (c *cache) haunter() {
|
||||
c.haunt()
|
||||
time.AfterFunc(c.grim.Next(), c.haunter)
|
||||
}
|
||||
|
||||
func (c *cache) haunt() {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
for key, f := range c.files {
|
||||
if f.inUse() {
|
||||
continue
|
||||
}
|
||||
|
||||
lastRead, lastWrite, err := c.fs.AccessTimes(f.Name())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if c.grim.Reap(key, lastRead, lastWrite) {
|
||||
delete(c.files, key)
|
||||
c.fs.Remove(f.Name())
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *cache) load() error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
return c.fs.Reload(func(key, name string) {
|
||||
c.files[key] = c.oldFile(name)
|
||||
})
|
||||
}
|
||||
|
||||
func (c *cache) Exists(key string) bool {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
_, ok := c.files[key]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (c *cache) Get(key string) (r ReadAtCloser, w io.WriteCloser, err error) {
|
||||
c.mu.RLock()
|
||||
f, ok := c.files[key]
|
||||
if ok {
|
||||
r, err = f.next()
|
||||
c.mu.RUnlock()
|
||||
return r, nil, err
|
||||
}
|
||||
c.mu.RUnlock()
|
||||
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
f, ok = c.files[key]
|
||||
if ok {
|
||||
r, err = f.next()
|
||||
return r, nil, err
|
||||
}
|
||||
|
||||
f, err = c.newFile(key)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
r, err = f.next()
|
||||
if err != nil {
|
||||
f.Close()
|
||||
c.fs.Remove(f.Name())
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
c.files[key] = f
|
||||
|
||||
return r, f, err
|
||||
}
|
||||
|
||||
func (c *cache) Remove(key string) error {
|
||||
c.mu.Lock()
|
||||
f, ok := c.files[key]
|
||||
delete(c.files, key)
|
||||
c.mu.Unlock()
|
||||
|
||||
if ok {
|
||||
return f.Remove()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *cache) Clean() error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
c.files = make(map[string]fileStream)
|
||||
return c.fs.RemoveAll()
|
||||
}
|
||||
|
||||
type cachedFile struct {
|
||||
stream *stream.Stream
|
||||
handleCounter
|
||||
}
|
||||
|
||||
func (c *cache) newFile(name string) (fileStream, error) {
|
||||
s, err := stream.NewStream(name, c.fs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cf := &cachedFile{
|
||||
stream: s,
|
||||
}
|
||||
cf.inc()
|
||||
return cf, nil
|
||||
}
|
||||
|
||||
func (c *cache) oldFile(name string) fileStream {
|
||||
return &reloadedFile{
|
||||
fs: c.fs,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
type reloadedFile struct {
|
||||
fs FileSystem
|
||||
name string
|
||||
handleCounter
|
||||
io.WriteCloser // nop Write & Close methods. will never be called.
|
||||
}
|
||||
|
||||
func (f *reloadedFile) Name() string { return f.name }
|
||||
|
||||
func (f *reloadedFile) Remove() error {
|
||||
f.waitUntilFree()
|
||||
return f.fs.Remove(f.name)
|
||||
}
|
||||
|
||||
func (f *reloadedFile) next() (r ReadAtCloser, err error) {
|
||||
r, err = f.fs.Open(f.name)
|
||||
if err == nil {
|
||||
f.inc()
|
||||
}
|
||||
return &cacheReader{r: r, cnt: &f.handleCounter}, err
|
||||
}
|
||||
|
||||
func (f *cachedFile) Name() string { return f.stream.Name() }
|
||||
|
||||
func (f *cachedFile) Remove() error { return f.stream.Remove() }
|
||||
|
||||
func (f *cachedFile) next() (r ReadAtCloser, err error) {
|
||||
reader, err := f.stream.NextReader()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f.inc()
|
||||
return &cacheReader{
|
||||
r: reader,
|
||||
cnt: &f.handleCounter,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (f *cachedFile) Write(p []byte) (int, error) {
|
||||
return f.stream.Write(p)
|
||||
}
|
||||
|
||||
func (f *cachedFile) Close() error {
|
||||
defer f.dec()
|
||||
return f.stream.Close()
|
||||
}
|
||||
|
||||
type cacheReader struct {
|
||||
r ReadAtCloser
|
||||
cnt *handleCounter
|
||||
}
|
||||
|
||||
func (r *cacheReader) ReadAt(p []byte, off int64) (n int, err error) {
|
||||
return r.r.ReadAt(p, off)
|
||||
}
|
||||
|
||||
func (r *cacheReader) Read(p []byte) (n int, err error) {
|
||||
return r.r.Read(p)
|
||||
}
|
||||
|
||||
func (r *cacheReader) Close() error {
|
||||
defer r.cnt.dec()
|
||||
return r.r.Close()
|
||||
}
|
||||
|
||||
type handleCounter struct {
|
||||
cnt int64
|
||||
grp sync.WaitGroup
|
||||
}
|
||||
|
||||
func (h *handleCounter) inc() {
|
||||
h.grp.Add(1)
|
||||
atomic.AddInt64(&h.cnt, 1)
|
||||
}
|
||||
|
||||
func (h *handleCounter) dec() {
|
||||
atomic.AddInt64(&h.cnt, -1)
|
||||
h.grp.Done()
|
||||
}
|
||||
|
||||
func (h *handleCounter) inUse() bool {
|
||||
return atomic.LoadInt64(&h.cnt) > 0
|
||||
}
|
||||
|
||||
func (h *handleCounter) waitUntilFree() {
|
||||
h.grp.Wait()
|
||||
}
|
||||
41
vendor/github.com/djherbis/fscache/handler.go
generated
vendored
41
vendor/github.com/djherbis/fscache/handler.go
generated
vendored
@@ -1,41 +0,0 @@
|
||||
package fscache
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Handler is a caching middle-ware for http Handlers.
|
||||
// It responds to http requests via the passed http.Handler, and caches the response
|
||||
// using the passed cache. The cache key for the request is the req.URL.String().
|
||||
// Note: It does not cache http headers. It is more efficient to set them yourself.
|
||||
func Handler(c Cache, h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
url := req.URL.String()
|
||||
r, w, err := c.Get(url)
|
||||
if err != nil {
|
||||
h.ServeHTTP(rw, req)
|
||||
return
|
||||
}
|
||||
defer r.Close()
|
||||
if w != nil {
|
||||
go func() {
|
||||
defer w.Close()
|
||||
h.ServeHTTP(&respWrapper{
|
||||
ResponseWriter: rw,
|
||||
Writer: w,
|
||||
}, req)
|
||||
}()
|
||||
}
|
||||
io.Copy(rw, r)
|
||||
})
|
||||
}
|
||||
|
||||
type respWrapper struct {
|
||||
http.ResponseWriter
|
||||
io.Writer
|
||||
}
|
||||
|
||||
func (r *respWrapper) Write(p []byte) (int, error) {
|
||||
return r.Writer.Write(p)
|
||||
}
|
||||
129
vendor/github.com/djherbis/fscache/layers.go
generated
vendored
129
vendor/github.com/djherbis/fscache/layers.go
generated
vendored
@@ -1,129 +0,0 @@
|
||||
package fscache
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type layeredCache struct {
|
||||
layers []Cache
|
||||
}
|
||||
|
||||
// NewLayered returns a Cache which stores its data in all the passed
|
||||
// caches, when a key is requested it is loaded into all the caches above the first hit.
|
||||
func NewLayered(caches ...Cache) Cache {
|
||||
return &layeredCache{layers: caches}
|
||||
}
|
||||
|
||||
func (l *layeredCache) Get(key string) (r ReadAtCloser, w io.WriteCloser, err error) {
|
||||
var last ReadAtCloser
|
||||
var writers []io.WriteCloser
|
||||
|
||||
for i, layer := range l.layers {
|
||||
r, w, err = layer.Get(key)
|
||||
if err != nil {
|
||||
if len(writers) > 0 {
|
||||
last.Close()
|
||||
multiWC(writers...).Close()
|
||||
}
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// hit
|
||||
if w == nil {
|
||||
if len(writers) > 0 {
|
||||
go func(r io.ReadCloser) {
|
||||
wc := multiWC(writers...)
|
||||
defer r.Close()
|
||||
defer wc.Close()
|
||||
io.Copy(wc, r)
|
||||
}(r)
|
||||
return last, nil, nil
|
||||
}
|
||||
return r, nil, nil
|
||||
}
|
||||
|
||||
// miss
|
||||
writers = append(writers, w)
|
||||
|
||||
if i == len(l.layers)-1 {
|
||||
if last != nil {
|
||||
last.Close()
|
||||
}
|
||||
return r, multiWC(writers...), nil
|
||||
}
|
||||
|
||||
if last != nil {
|
||||
last.Close()
|
||||
}
|
||||
last = r
|
||||
}
|
||||
|
||||
return nil, nil, errors.New("no caches")
|
||||
}
|
||||
|
||||
func (l *layeredCache) Remove(key string) error {
|
||||
var grp sync.WaitGroup
|
||||
// walk upwards so that lower layers don't
|
||||
// restore upper layers on Get()
|
||||
for i := len(l.layers) - 1; i >= 0; i-- {
|
||||
grp.Add(1)
|
||||
go func(layer Cache) {
|
||||
defer grp.Done()
|
||||
layer.Remove(key)
|
||||
}(l.layers[i])
|
||||
}
|
||||
grp.Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *layeredCache) Exists(key string) bool {
|
||||
for _, layer := range l.layers {
|
||||
if layer.Exists(key) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (l *layeredCache) Clean() (err error) {
|
||||
for _, layer := range l.layers {
|
||||
er := layer.Clean()
|
||||
if er != nil {
|
||||
err = er
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func multiWC(wc ...io.WriteCloser) io.WriteCloser {
|
||||
if len(wc) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &multiWriteCloser{
|
||||
writers: wc,
|
||||
}
|
||||
}
|
||||
|
||||
type multiWriteCloser struct {
|
||||
writers []io.WriteCloser
|
||||
}
|
||||
|
||||
func (t *multiWriteCloser) Write(p []byte) (n int, err error) {
|
||||
for _, w := range t.writers {
|
||||
n, err = w.Write(p)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (t *multiWriteCloser) Close() error {
|
||||
for _, w := range t.writers {
|
||||
w.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
133
vendor/github.com/djherbis/fscache/memfs.go
generated
vendored
133
vendor/github.com/djherbis/fscache/memfs.go
generated
vendored
@@ -1,133 +0,0 @@
|
||||
package fscache
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"gopkg.in/djherbis/stream.v1"
|
||||
)
|
||||
|
||||
type memFS struct {
|
||||
mu sync.RWMutex
|
||||
files map[string]*memFile
|
||||
}
|
||||
|
||||
// NewMemFs creates an in-memory FileSystem.
|
||||
// It does not support persistence (Reload is a nop).
|
||||
func NewMemFs() FileSystem {
|
||||
return &memFS{
|
||||
files: make(map[string]*memFile),
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *memFS) Reload(add func(key, name string)) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fs *memFS) AccessTimes(name string) (rt, wt time.Time, err error) {
|
||||
fs.mu.RLock()
|
||||
defer fs.mu.RUnlock()
|
||||
f, ok := fs.files[name]
|
||||
if ok {
|
||||
return f.rt, f.wt, nil
|
||||
}
|
||||
return rt, wt, errors.New("file has not been read")
|
||||
}
|
||||
|
||||
func (fs *memFS) Create(key string) (stream.File, error) {
|
||||
fs.mu.Lock()
|
||||
defer fs.mu.Unlock()
|
||||
if _, ok := fs.files[key]; ok {
|
||||
return nil, errors.New("file exists")
|
||||
}
|
||||
file := &memFile{
|
||||
name: key,
|
||||
r: bytes.NewBuffer(nil),
|
||||
wt: time.Now(),
|
||||
}
|
||||
file.memReader.memFile = file
|
||||
fs.files[key] = file
|
||||
return file, nil
|
||||
}
|
||||
|
||||
func (fs *memFS) Open(name string) (stream.File, error) {
|
||||
fs.mu.Lock()
|
||||
defer fs.mu.Unlock()
|
||||
if f, ok := fs.files[name]; ok {
|
||||
f.rt = time.Now()
|
||||
return &memReader{memFile: f}, nil
|
||||
}
|
||||
return nil, errors.New("file does not exist")
|
||||
}
|
||||
|
||||
func (fs *memFS) Remove(key string) error {
|
||||
fs.mu.Lock()
|
||||
defer fs.mu.Unlock()
|
||||
delete(fs.files, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fs *memFS) RemoveAll() error {
|
||||
fs.mu.Lock()
|
||||
defer fs.mu.Unlock()
|
||||
fs.files = make(map[string]*memFile)
|
||||
return nil
|
||||
}
|
||||
|
||||
type memFile struct {
|
||||
mu sync.RWMutex
|
||||
name string
|
||||
r *bytes.Buffer
|
||||
memReader
|
||||
rt, wt time.Time
|
||||
}
|
||||
|
||||
func (f *memFile) Name() string {
|
||||
return f.name
|
||||
}
|
||||
|
||||
func (f *memFile) Write(p []byte) (int, error) {
|
||||
if len(p) > 0 {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
return f.r.Write(p)
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (f *memFile) Bytes() []byte {
|
||||
f.mu.RLock()
|
||||
defer f.mu.RUnlock()
|
||||
return f.r.Bytes()
|
||||
}
|
||||
|
||||
func (f *memFile) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type memReader struct {
|
||||
*memFile
|
||||
n int
|
||||
}
|
||||
|
||||
func (r *memReader) ReadAt(p []byte, off int64) (n int, err error) {
|
||||
data := r.Bytes()
|
||||
if int64(len(data)) < off {
|
||||
return 0, io.EOF
|
||||
}
|
||||
n, err = bytes.NewReader(data[off:]).ReadAt(p, 0)
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (r *memReader) Read(p []byte) (n int, err error) {
|
||||
n, err = bytes.NewReader(r.Bytes()[r.n:]).Read(p)
|
||||
r.n += n
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (r *memReader) Close() error {
|
||||
return nil
|
||||
}
|
||||
37
vendor/github.com/djherbis/fscache/reaper.go
generated
vendored
37
vendor/github.com/djherbis/fscache/reaper.go
generated
vendored
@@ -1,37 +0,0 @@
|
||||
package fscache
|
||||
|
||||
import "time"
|
||||
|
||||
// Reaper is used to control when streams expire from the cache.
|
||||
// It is called once right after loading, and then it is run
|
||||
// again after every Next() period of time.
|
||||
type Reaper interface {
|
||||
// Returns the amount of time to wait before the next scheduled Reaping.
|
||||
Next() time.Duration
|
||||
|
||||
// Given a key and the last r/w times of a file, return true
|
||||
// to remove the file from the cache, false to keep it.
|
||||
Reap(key string, lastRead, lastWrite time.Time) bool
|
||||
}
|
||||
|
||||
// NewReaper returns a simple reaper which runs every "period"
|
||||
// and reaps files which are older than "expiry".
|
||||
func NewReaper(expiry, period time.Duration) Reaper {
|
||||
return &reaper{
|
||||
expiry: expiry,
|
||||
period: period,
|
||||
}
|
||||
}
|
||||
|
||||
type reaper struct {
|
||||
period time.Duration
|
||||
expiry time.Duration
|
||||
}
|
||||
|
||||
func (g *reaper) Next() time.Duration {
|
||||
return g.period
|
||||
}
|
||||
|
||||
func (g *reaper) Reap(key string, lastRead, lastWrite time.Time) bool {
|
||||
return lastRead.Before(time.Now().Add(-g.expiry))
|
||||
}
|
||||
206
vendor/github.com/djherbis/fscache/server.go
generated
vendored
206
vendor/github.com/djherbis/fscache/server.go
generated
vendored
@@ -1,206 +0,0 @@
|
||||
package fscache
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
)
|
||||
|
||||
// ListenAndServe hosts a Cache for access via NewRemote
|
||||
func ListenAndServe(c Cache, addr string) error {
|
||||
return (&server{c: c}).ListenAndServe(addr)
|
||||
}
|
||||
|
||||
// NewRemote returns a Cache run via ListenAndServe
|
||||
func NewRemote(raddr string) Cache {
|
||||
return &remote{raddr: raddr}
|
||||
}
|
||||
|
||||
type server struct {
|
||||
c Cache
|
||||
}
|
||||
|
||||
func (s *server) ListenAndServe(addr string) error {
|
||||
l, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
c, err := l.Accept()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go s.Serve(c)
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
actionGet = iota
|
||||
actionRemove = iota
|
||||
actionExists = iota
|
||||
actionClean = iota
|
||||
)
|
||||
|
||||
func getKey(r io.Reader) string {
|
||||
dec := newDecoder(r)
|
||||
buf := bytes.NewBufferString("")
|
||||
io.Copy(buf, dec)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func sendKey(w io.Writer, key string) {
|
||||
enc := newEncoder(w)
|
||||
enc.Write([]byte(key))
|
||||
enc.Close()
|
||||
}
|
||||
|
||||
func (s *server) Serve(c net.Conn) {
|
||||
var action int
|
||||
fmt.Fscanf(c, "%d\n", &action)
|
||||
|
||||
switch action {
|
||||
case actionGet:
|
||||
s.get(c, getKey(c))
|
||||
case actionRemove:
|
||||
s.c.Remove(getKey(c))
|
||||
case actionExists:
|
||||
s.exists(c, getKey(c))
|
||||
case actionClean:
|
||||
s.c.Clean()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *server) exists(c net.Conn, key string) {
|
||||
if s.c.Exists(key) {
|
||||
fmt.Fprintf(c, "%d\n", 1)
|
||||
} else {
|
||||
fmt.Fprintf(c, "%d\n", 0)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *server) get(c net.Conn, key string) {
|
||||
r, w, err := s.c.Get(key)
|
||||
if err != nil {
|
||||
return // handle this better
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
if w != nil {
|
||||
go func() {
|
||||
fmt.Fprintf(c, "%d\n", 1)
|
||||
io.Copy(w, newDecoder(c))
|
||||
w.Close()
|
||||
}()
|
||||
} else {
|
||||
fmt.Fprintf(c, "%d\n", 0)
|
||||
}
|
||||
|
||||
enc := newEncoder(c)
|
||||
io.Copy(enc, r)
|
||||
enc.Close()
|
||||
}
|
||||
|
||||
type remote struct {
|
||||
raddr string
|
||||
}
|
||||
|
||||
func (rmt *remote) Get(key string) (r ReadAtCloser, w io.WriteCloser, err error) {
|
||||
c, err := net.Dial("tcp", rmt.raddr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
fmt.Fprintf(c, "%d\n", actionGet)
|
||||
sendKey(c, key)
|
||||
|
||||
var i int
|
||||
fmt.Fscanf(c, "%d\n", &i)
|
||||
|
||||
var ch chan struct{}
|
||||
|
||||
switch i {
|
||||
case 0:
|
||||
ch = make(chan struct{}) // close net.Conn on reader close
|
||||
case 1:
|
||||
ch = make(chan struct{}, 1) // two closes before net.Conn close
|
||||
|
||||
w = &safeCloser{
|
||||
c: c,
|
||||
ch: ch,
|
||||
w: newEncoder(c),
|
||||
}
|
||||
default:
|
||||
return nil, nil, errors.New("bad bad bad")
|
||||
}
|
||||
|
||||
r = &safeCloser{
|
||||
c: c,
|
||||
ch: ch,
|
||||
r: newDecoder(c),
|
||||
}
|
||||
|
||||
return r, w, nil
|
||||
}
|
||||
|
||||
type safeCloser struct {
|
||||
c net.Conn
|
||||
ch chan<- struct{}
|
||||
r ReadAtCloser
|
||||
w io.WriteCloser
|
||||
}
|
||||
|
||||
func (s *safeCloser) ReadAt(p []byte, off int64) (int, error) {
|
||||
return s.r.ReadAt(p, off)
|
||||
}
|
||||
func (s *safeCloser) Read(p []byte) (int, error) { return s.r.Read(p) }
|
||||
func (s *safeCloser) Write(p []byte) (int, error) { return s.w.Write(p) }
|
||||
|
||||
// Close only closes the underlying connection when ch is full.
|
||||
func (s *safeCloser) Close() (err error) {
|
||||
if s.r != nil {
|
||||
err = s.r.Close()
|
||||
} else if s.w != nil {
|
||||
err = s.w.Close()
|
||||
}
|
||||
|
||||
select {
|
||||
case s.ch <- struct{}{}:
|
||||
return err
|
||||
default:
|
||||
return s.c.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (rmt *remote) Exists(key string) bool {
|
||||
c, err := net.Dial("tcp", rmt.raddr)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
fmt.Fprintf(c, "%d\n", actionExists)
|
||||
sendKey(c, key)
|
||||
var i int
|
||||
fmt.Fscanf(c, "%d\n", &i)
|
||||
return i == 1
|
||||
}
|
||||
|
||||
func (rmt *remote) Remove(key string) error {
|
||||
c, err := net.Dial("tcp", rmt.raddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(c, "%d\n", actionRemove)
|
||||
sendKey(c, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rmt *remote) Clean() error {
|
||||
c, err := net.Dial("tcp", rmt.raddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(c, "%d\n", actionClean)
|
||||
return nil
|
||||
}
|
||||
72
vendor/github.com/djherbis/fscache/stream.go
generated
vendored
72
vendor/github.com/djherbis/fscache/stream.go
generated
vendored
@@ -1,72 +0,0 @@
|
||||
package fscache
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
type decoder interface {
|
||||
Decode(interface{}) error
|
||||
}
|
||||
|
||||
type encoder interface {
|
||||
Encode(interface{}) error
|
||||
}
|
||||
|
||||
type pktReader struct {
|
||||
dec decoder
|
||||
}
|
||||
|
||||
type pktWriter struct {
|
||||
enc encoder
|
||||
}
|
||||
|
||||
type packet struct {
|
||||
Err int
|
||||
Data []byte
|
||||
}
|
||||
|
||||
const eof = 1
|
||||
|
||||
func (t *pktReader) ReadAt(p []byte, off int64) (n int, err error) {
|
||||
// TODO not implemented
|
||||
return 0, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (t *pktReader) Read(p []byte) (int, error) {
|
||||
var pkt packet
|
||||
err := t.dec.Decode(&pkt)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if pkt.Err == eof {
|
||||
return 0, io.EOF
|
||||
}
|
||||
return copy(p, pkt.Data), nil
|
||||
}
|
||||
|
||||
func (t *pktReader) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *pktWriter) Write(p []byte) (int, error) {
|
||||
pkt := packet{Data: p}
|
||||
err := t.enc.Encode(pkt)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (t *pktWriter) Close() error {
|
||||
return t.enc.Encode(packet{Err: eof})
|
||||
}
|
||||
|
||||
func newEncoder(w io.Writer) io.WriteCloser {
|
||||
return &pktWriter{enc: json.NewEncoder(w)}
|
||||
}
|
||||
|
||||
func newDecoder(r io.Reader) ReadAtCloser {
|
||||
return &pktReader{dec: json.NewDecoder(r)}
|
||||
}
|
||||
424
vendor/github.com/eknkc/amber/README.md
generated
vendored
424
vendor/github.com/eknkc/amber/README.md
generated
vendored
@@ -1,424 +0,0 @@
|
||||
# amber
|
||||
--
|
||||
import "github.com/eknkc/amber"
|
||||
|
||||
Amber is an elegant templating engine for Go Programming Language
|
||||
It is inspired from HAML and Jade
|
||||
|
||||
### Tags
|
||||
|
||||
A tag is simply a word:
|
||||
|
||||
html
|
||||
|
||||
is converted to
|
||||
|
||||
<html></html>
|
||||
|
||||
It is possible to add ID and CLASS attributes to tags:
|
||||
|
||||
div#main
|
||||
span.time
|
||||
|
||||
are converted to
|
||||
|
||||
<div id="main"></div>
|
||||
<span class="time"></span>
|
||||
|
||||
Any arbitrary attribute name / value pair can be added this way:
|
||||
|
||||
a[href="http://www.google.com"]
|
||||
|
||||
You can mix multiple attributes together
|
||||
|
||||
a#someid[href="/"][title="Main Page"].main.link Click Link
|
||||
|
||||
gets converted to
|
||||
|
||||
<a id="someid" class="main link" href="/" title="Main Page">Click Link</a>
|
||||
|
||||
It is also possible to define these attributes within the block of a tag
|
||||
|
||||
a
|
||||
#someid
|
||||
[href="/"]
|
||||
[title="Main Page"]
|
||||
.main
|
||||
.link
|
||||
| Click Link
|
||||
|
||||
### Doctypes
|
||||
|
||||
To add a doctype, use `!!!` or `doctype` keywords:
|
||||
|
||||
!!! transitional
|
||||
// <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
or use `doctype`
|
||||
|
||||
doctype 5
|
||||
// <!DOCTYPE html>
|
||||
|
||||
Available options: `5`, `default`, `xml`, `transitional`, `strict`, `frameset`, `1.1`, `basic`, `mobile`
|
||||
|
||||
### Tag Content
|
||||
|
||||
For single line tag text, you can just append the text after tag name:
|
||||
|
||||
p Testing!
|
||||
|
||||
would yield
|
||||
|
||||
<p>Testing!</p>
|
||||
|
||||
For multi line tag text, or nested tags, use indentation:
|
||||
|
||||
html
|
||||
head
|
||||
title Page Title
|
||||
body
|
||||
div#content
|
||||
p
|
||||
| This is a long page content
|
||||
| These lines are all part of the parent p
|
||||
|
||||
a[href="/"] Go To Main Page
|
||||
|
||||
### Data
|
||||
|
||||
Input template data can be reached by key names directly. For example, assuming the template has been
|
||||
executed with following JSON data:
|
||||
|
||||
{
|
||||
"Name": "Ekin",
|
||||
"LastName": "Koc",
|
||||
"Repositories": [
|
||||
"amber",
|
||||
"dateformat"
|
||||
],
|
||||
"Avatar": "/images/ekin.jpg",
|
||||
"Friends": 17
|
||||
}
|
||||
|
||||
It is possible to interpolate fields using `#{}`
|
||||
|
||||
p Welcome #{Name}!
|
||||
|
||||
would print
|
||||
|
||||
<p>Welcome Ekin!</p>
|
||||
|
||||
Attributes can have field names as well
|
||||
|
||||
a[title=Name][href="/ekin.koc"]
|
||||
|
||||
would print
|
||||
|
||||
<a title="Ekin" href="/ekin.koc"></a>
|
||||
|
||||
### Expressions
|
||||
|
||||
Amber can expand basic expressions. For example, it is possible to concatenate strings with + operator:
|
||||
|
||||
p Welcome #{Name + " " + LastName}
|
||||
|
||||
Arithmetic expressions are also supported:
|
||||
|
||||
p You need #{50 - Friends} more friends to reach 50!
|
||||
|
||||
Expressions can be used within attributes
|
||||
|
||||
img[alt=Name + " " + LastName][src=Avatar]
|
||||
|
||||
### Variables
|
||||
|
||||
It is possible to define dynamic variables within templates,
|
||||
all variables must start with a $ character and can be assigned as in the following example:
|
||||
|
||||
div
|
||||
$fullname = Name + " " + LastName
|
||||
p Welcome #{$fullname}
|
||||
|
||||
If you need to access the supplied data itself (i.e. the object containing Name, LastName etc fields.) you can use `$` variable
|
||||
|
||||
p $.Name
|
||||
|
||||
### Conditions
|
||||
|
||||
For conditional blocks, it is possible to use `if <expression>`
|
||||
|
||||
div
|
||||
if Friends > 10
|
||||
p You have more than 10 friends
|
||||
else if Friends > 5
|
||||
p You have more than 5 friends
|
||||
else
|
||||
p You need more friends
|
||||
|
||||
Again, it is possible to use arithmetic and boolean operators
|
||||
|
||||
div
|
||||
if Name == "Ekin" && LastName == "Koc"
|
||||
p Hey! I know you..
|
||||
|
||||
There is a special syntax for conditional attributes. Only block attributes can have conditions;
|
||||
|
||||
div
|
||||
.hasfriends ? Friends > 0
|
||||
|
||||
This would yield a div with `hasfriends` class only if the `Friends > 0` condition holds. It is
|
||||
perfectly fine to use the same method for other types of attributes:
|
||||
|
||||
div
|
||||
#foo ? Name == "Ekin"
|
||||
[bar=baz] ? len(Repositories) > 0
|
||||
|
||||
### Iterations
|
||||
|
||||
It is possible to iterate over arrays and maps using `each`:
|
||||
|
||||
each $repo in Repositories
|
||||
p #{$repo}
|
||||
|
||||
would print
|
||||
|
||||
p amber
|
||||
p dateformat
|
||||
|
||||
It is also possible to iterate over values and indexes at the same time
|
||||
|
||||
each $i, $repo in Repositories
|
||||
p
|
||||
.even ? $i % 2 == 0
|
||||
.odd ? $i % 2 == 1
|
||||
|
||||
### Mixins
|
||||
|
||||
Mixins (reusable template blocks that accept arguments) can be defined:
|
||||
|
||||
mixin surprise
|
||||
span Surprise!
|
||||
mixin link($href, $title, $text)
|
||||
a[href=$href][title=$title] #{$text}
|
||||
|
||||
and then called multiple times within a template (or even within another mixin definition):
|
||||
|
||||
div
|
||||
+surprise
|
||||
+surprise
|
||||
+link("http://google.com", "Google", "Check out Google")
|
||||
|
||||
Template data, variables, expressions, etc., can all be passed as arguments:
|
||||
|
||||
+link(GoogleUrl, $googleTitle, "Check out " + $googleTitle)
|
||||
|
||||
### Imports
|
||||
|
||||
A template can import other templates using `import`:
|
||||
|
||||
a.amber
|
||||
p this is template a
|
||||
|
||||
b.amber
|
||||
p this is template b
|
||||
|
||||
c.amber
|
||||
div
|
||||
import a
|
||||
import b
|
||||
|
||||
gets compiled to
|
||||
|
||||
div
|
||||
p this is template a
|
||||
p this is template b
|
||||
|
||||
### Inheritance
|
||||
|
||||
A template can inherit other templates. In order to inherit another template, an `extends` keyword should be used.
|
||||
Parent template can define several named blocks and child template can modify the blocks.
|
||||
|
||||
master.amber
|
||||
!!! 5
|
||||
html
|
||||
head
|
||||
block meta
|
||||
meta[name="description"][content="This is a great website"]
|
||||
|
||||
title
|
||||
block title
|
||||
| Default title
|
||||
body
|
||||
block content
|
||||
|
||||
subpage.amber
|
||||
extends master
|
||||
|
||||
block title
|
||||
| Some sub page!
|
||||
|
||||
block append meta
|
||||
// This will be added after the description meta tag. It is also possible
|
||||
// to prepend someting to an existing block
|
||||
meta[name="keywords"][content="foo bar"]
|
||||
|
||||
block content
|
||||
div#main
|
||||
p Some content here
|
||||
|
||||
### License
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2012 Ekin Koc <ekin@eknkc.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
var DefaultOptions = Options{true, false}
|
||||
var DefaultDirOptions = DirOptions{".amber", true}
|
||||
```
|
||||
|
||||
#### func Compile
|
||||
|
||||
```go
|
||||
func Compile(input string, options Options) (*template.Template, error)
|
||||
```
|
||||
Parses and compiles the supplied amber template string. Returns corresponding Go
|
||||
Template (html/templates) instance. Necessary runtime functions will be injected
|
||||
and the template will be ready to be executed.
|
||||
|
||||
#### func CompileFile
|
||||
|
||||
```go
|
||||
func CompileFile(filename string, options Options) (*template.Template, error)
|
||||
```
|
||||
Parses and compiles the contents of supplied filename. Returns corresponding Go
|
||||
Template (html/templates) instance. Necessary runtime functions will be injected
|
||||
and the template will be ready to be executed.
|
||||
|
||||
#### func CompileDir
|
||||
```go
|
||||
func CompileDir(dirname string, dopt DirOptions, opt Options) (map[string]*template.Template, error)
|
||||
```
|
||||
Parses and compiles the contents of a supplied directory name. Returns a mapping of template name (extension stripped) to corresponding Go Template (html/template) instance. Necessary runtime functions will be injected and the template will be ready to be executed.
|
||||
|
||||
If there are templates in subdirectories, its key in the map will be it's path relative to `dirname`. For example:
|
||||
```
|
||||
templates/
|
||||
|-- index.amber
|
||||
|-- layouts/
|
||||
|-- base.amber
|
||||
```
|
||||
```go
|
||||
templates, err := amber.CompileDir("templates/", amber.DefaultDirOptions, amber.DefaultOptions)
|
||||
templates["index"] // index.amber Go Template
|
||||
templates["layouts/base"] // base.amber Go Template
|
||||
```
|
||||
By default, the search will be recursive and will match only files ending in ".amber". If recursive is turned off, it will only search the top level of the directory. Specified extension must start with a period.
|
||||
|
||||
#### type Compiler
|
||||
|
||||
```go
|
||||
type Compiler struct {
|
||||
// Compiler options
|
||||
Options
|
||||
}
|
||||
```
|
||||
|
||||
Compiler is the main interface of Amber Template Engine. In order to use an
|
||||
Amber template, it is required to create a Compiler and compile an Amber source
|
||||
to native Go template.
|
||||
|
||||
compiler := amber.New()
|
||||
// Parse the input file
|
||||
err := compiler.ParseFile("./input.amber")
|
||||
if err == nil {
|
||||
// Compile input file to Go template
|
||||
tpl, err := compiler.Compile()
|
||||
if err == nil {
|
||||
// Check built in html/template documentation for further details
|
||||
tpl.Execute(os.Stdout, somedata)
|
||||
}
|
||||
}
|
||||
|
||||
#### func New
|
||||
|
||||
```go
|
||||
func New() *Compiler
|
||||
```
|
||||
Create and initialize a new Compiler
|
||||
|
||||
#### func (*Compiler) Compile
|
||||
|
||||
```go
|
||||
func (c *Compiler) Compile() (*template.Template, error)
|
||||
```
|
||||
Compile amber and create a Go Template (html/templates) instance. Necessary
|
||||
runtime functions will be injected and the template will be ready to be
|
||||
executed.
|
||||
|
||||
#### func (*Compiler) CompileString
|
||||
|
||||
```go
|
||||
func (c *Compiler) CompileString() (string, error)
|
||||
```
|
||||
Compile template and return the Go Template source You would not be using this
|
||||
unless debugging / checking the output. Please use Compile method to obtain a
|
||||
template instance directly.
|
||||
|
||||
#### func (*Compiler) CompileWriter
|
||||
|
||||
```go
|
||||
func (c *Compiler) CompileWriter(out io.Writer) (err error)
|
||||
```
|
||||
Compile amber and write the Go Template source into given io.Writer instance You
|
||||
would not be using this unless debugging / checking the output. Please use
|
||||
Compile method to obtain a template instance directly.
|
||||
|
||||
#### func (*Compiler) Parse
|
||||
|
||||
```go
|
||||
func (c *Compiler) Parse(input string) (err error)
|
||||
```
|
||||
Parse given raw amber template string.
|
||||
|
||||
#### func (*Compiler) ParseFile
|
||||
|
||||
```go
|
||||
func (c *Compiler) ParseFile(filename string) (err error)
|
||||
```
|
||||
Parse the amber template file in given path
|
||||
|
||||
#### type Options
|
||||
|
||||
```go
|
||||
type Options struct {
|
||||
// Setting if pretty printing is enabled.
|
||||
// Pretty printing ensures that the output html is properly indented and in human readable form.
|
||||
// If disabled, produced HTML is compact. This might be more suitable in production environments.
|
||||
// Defaukt: true
|
||||
PrettyPrint bool
|
||||
// Setting if line number emiting is enabled
|
||||
// In this form, Amber emits line number comments in the output template. It is usable in debugging environments.
|
||||
// Default: false
|
||||
LineNumbers bool
|
||||
}
|
||||
```
|
||||
|
||||
#### type DirOptions
|
||||
|
||||
```go
|
||||
// Used to provide options to directory compilation
|
||||
type DirOptions struct {
|
||||
// File extension to match for compilation
|
||||
Ext string
|
||||
// Whether or not to walk subdirectories
|
||||
Recursive bool
|
||||
}
|
||||
```
|
||||
777
vendor/github.com/eknkc/amber/compiler.go
generated
vendored
777
vendor/github.com/eknkc/amber/compiler.go
generated
vendored
@@ -1,777 +0,0 @@
|
||||
package amber
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"container/list"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
gp "go/parser"
|
||||
gt "go/token"
|
||||
"html/template"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/eknkc/amber/parser"
|
||||
)
|
||||
|
||||
var builtinFunctions = [...]string{
|
||||
"len",
|
||||
"print",
|
||||
"printf",
|
||||
"println",
|
||||
"urlquery",
|
||||
"js",
|
||||
"json",
|
||||
"index",
|
||||
"html",
|
||||
"unescaped",
|
||||
}
|
||||
|
||||
// Compiler is the main interface of Amber Template Engine.
|
||||
// In order to use an Amber template, it is required to create a Compiler and
|
||||
// compile an Amber source to native Go template.
|
||||
// compiler := amber.New()
|
||||
// // Parse the input file
|
||||
// err := compiler.ParseFile("./input.amber")
|
||||
// if err == nil {
|
||||
// // Compile input file to Go template
|
||||
// tpl, err := compiler.Compile()
|
||||
// if err == nil {
|
||||
// // Check built in html/template documentation for further details
|
||||
// tpl.Execute(os.Stdout, somedata)
|
||||
// }
|
||||
// }
|
||||
type Compiler struct {
|
||||
// Compiler options
|
||||
Options
|
||||
filename string
|
||||
node parser.Node
|
||||
indentLevel int
|
||||
newline bool
|
||||
buffer *bytes.Buffer
|
||||
tempvarIndex int
|
||||
mixins map[string]*parser.Mixin
|
||||
}
|
||||
|
||||
// New creates and initialize a new Compiler.
|
||||
func New() *Compiler {
|
||||
compiler := new(Compiler)
|
||||
compiler.filename = ""
|
||||
compiler.tempvarIndex = 0
|
||||
compiler.PrettyPrint = true
|
||||
compiler.Options = DefaultOptions
|
||||
compiler.mixins = make(map[string]*parser.Mixin)
|
||||
|
||||
return compiler
|
||||
}
|
||||
|
||||
// Options defines template output behavior.
|
||||
type Options struct {
|
||||
// Setting if pretty printing is enabled.
|
||||
// Pretty printing ensures that the output html is properly indented and in human readable form.
|
||||
// If disabled, produced HTML is compact. This might be more suitable in production environments.
|
||||
// Default: true
|
||||
PrettyPrint bool
|
||||
// Setting if line number emitting is enabled
|
||||
// In this form, Amber emits line number comments in the output template. It is usable in debugging environments.
|
||||
// Default: false
|
||||
LineNumbers bool
|
||||
}
|
||||
|
||||
// DirOptions is used to provide options to directory compilation.
|
||||
type DirOptions struct {
|
||||
// File extension to match for compilation
|
||||
Ext string
|
||||
// Whether or not to walk subdirectories
|
||||
Recursive bool
|
||||
}
|
||||
|
||||
// DefaultOptions sets pretty-printing to true and line numbering to false.
|
||||
var DefaultOptions = Options{true, false}
|
||||
|
||||
// DefaultDirOptions sets expected file extension to ".amber" and recursive search for templates within a directory to true.
|
||||
var DefaultDirOptions = DirOptions{".amber", true}
|
||||
|
||||
// Compile parses and compiles the supplied amber template string. Returns corresponding Go Template (html/templates) instance.
|
||||
// Necessary runtime functions will be injected and the template will be ready to be executed.
|
||||
func Compile(input string, options Options) (*template.Template, error) {
|
||||
comp := New()
|
||||
comp.Options = options
|
||||
|
||||
err := comp.Parse(input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return comp.Compile()
|
||||
}
|
||||
|
||||
// Compile parses and compiles the supplied amber template []byte.
|
||||
// Returns corresponding Go Template (html/templates) instance.
|
||||
// Necessary runtime functions will be injected and the template will be ready to be executed.
|
||||
func CompileData(input []byte, filename string, options Options) (*template.Template, error) {
|
||||
comp := New()
|
||||
comp.Options = options
|
||||
|
||||
err := comp.ParseData(input, filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return comp.Compile()
|
||||
}
|
||||
|
||||
// MustCompile is the same as Compile, except the input is assumed error free. If else, panic.
|
||||
func MustCompile(input string, options Options) *template.Template {
|
||||
t, err := Compile(input, options)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// CompileFile parses and compiles the contents of supplied filename. Returns corresponding Go Template (html/templates) instance.
|
||||
// Necessary runtime functions will be injected and the template will be ready to be executed.
|
||||
func CompileFile(filename string, options Options) (*template.Template, error) {
|
||||
comp := New()
|
||||
comp.Options = options
|
||||
|
||||
err := comp.ParseFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return comp.Compile()
|
||||
}
|
||||
|
||||
// MustCompileFile is the same as CompileFile, except the input is assumed error free. If else, panic.
|
||||
func MustCompileFile(filename string, options Options) *template.Template {
|
||||
t, err := CompileFile(filename, options)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// CompileDir parses and compiles the contents of a supplied directory path, with options.
|
||||
// Returns a map of a template identifier (key) to a Go Template instance.
|
||||
// Ex: if the dirname="templates/" had a file "index.amber" the key would be "index"
|
||||
// If option for recursive is True, this parses every file of relevant extension
|
||||
// in all subdirectories. The key then is the path e.g: "layouts/layout"
|
||||
func CompileDir(dirname string, dopt DirOptions, opt Options) (map[string]*template.Template, error) {
|
||||
dir, err := os.Open(dirname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer dir.Close()
|
||||
|
||||
files, err := dir.Readdir(0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
compiled := make(map[string]*template.Template)
|
||||
for _, file := range files {
|
||||
// filename is for example "index.amber"
|
||||
filename := file.Name()
|
||||
fileext := filepath.Ext(filename)
|
||||
|
||||
// If recursive is true and there's a subdirectory, recurse
|
||||
if dopt.Recursive && file.IsDir() {
|
||||
dirpath := filepath.Join(dirname, filename)
|
||||
subcompiled, err := CompileDir(dirpath, dopt, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Copy templates from subdirectory into parent template mapping
|
||||
for k, v := range subcompiled {
|
||||
// Concat with parent directory name for unique paths
|
||||
key := filepath.Join(filename, k)
|
||||
compiled[key] = v
|
||||
}
|
||||
} else if fileext == dopt.Ext {
|
||||
// Otherwise compile the file and add to mapping
|
||||
fullpath := filepath.Join(dirname, filename)
|
||||
tmpl, err := CompileFile(fullpath, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Strip extension
|
||||
key := filename[0 : len(filename)-len(fileext)]
|
||||
compiled[key] = tmpl
|
||||
}
|
||||
}
|
||||
|
||||
return compiled, nil
|
||||
}
|
||||
|
||||
// MustCompileDir is the same as CompileDir, except input is assumed error free. If else, panic.
|
||||
func MustCompileDir(dirname string, dopt DirOptions, opt Options) map[string]*template.Template {
|
||||
m, err := CompileDir(dirname, dopt, opt)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// Parse given raw amber template string.
|
||||
func (c *Compiler) Parse(input string) (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = errors.New(r.(string))
|
||||
}
|
||||
}()
|
||||
|
||||
parser, err := parser.StringParser(input)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.node = parser.Parse()
|
||||
return
|
||||
}
|
||||
|
||||
// Parse given raw amber template bytes, and the filename that belongs with it
|
||||
func (c *Compiler) ParseData(input []byte, filename string) (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = errors.New(r.(string))
|
||||
}
|
||||
}()
|
||||
|
||||
parser, err := parser.ByteParser(input)
|
||||
parser.SetFilename(filename)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.node = parser.Parse()
|
||||
return
|
||||
}
|
||||
|
||||
// ParseFile parses the amber template file in given path.
|
||||
func (c *Compiler) ParseFile(filename string) (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = errors.New(r.(string))
|
||||
}
|
||||
}()
|
||||
|
||||
parser, err := parser.FileParser(filename)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.node = parser.Parse()
|
||||
c.filename = filename
|
||||
return
|
||||
}
|
||||
|
||||
// Compile amber and create a Go Template (html/templates) instance.
|
||||
// Necessary runtime functions will be injected and the template will be ready to be executed.
|
||||
func (c *Compiler) Compile() (*template.Template, error) {
|
||||
return c.CompileWithName(filepath.Base(c.filename))
|
||||
}
|
||||
|
||||
// CompileWithName is the same as Compile, but allows to specify a name for the template.
|
||||
func (c *Compiler) CompileWithName(name string) (*template.Template, error) {
|
||||
return c.CompileWithTemplate(template.New(name))
|
||||
}
|
||||
|
||||
// CompileWithTemplate is the same as Compile but allows to specify a template.
|
||||
func (c *Compiler) CompileWithTemplate(t *template.Template) (*template.Template, error) {
|
||||
data, err := c.CompileString()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tpl, err := t.Funcs(FuncMap).Parse(data)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tpl, nil
|
||||
}
|
||||
|
||||
// CompileWriter compiles amber and writes the Go Template source into given io.Writer instance.
|
||||
// You would not be using this unless debugging / checking the output. Please use Compile
|
||||
// method to obtain a template instance directly.
|
||||
func (c *Compiler) CompileWriter(out io.Writer) (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = errors.New(r.(string))
|
||||
}
|
||||
}()
|
||||
|
||||
c.buffer = new(bytes.Buffer)
|
||||
c.visit(c.node)
|
||||
|
||||
if c.buffer.Len() > 0 {
|
||||
c.write("\n")
|
||||
}
|
||||
|
||||
_, err = c.buffer.WriteTo(out)
|
||||
return
|
||||
}
|
||||
|
||||
// CompileString compiles the template and returns the Go Template source.
|
||||
// You would not be using this unless debugging / checking the output. Please use Compile
|
||||
// method to obtain a template instance directly.
|
||||
func (c *Compiler) CompileString() (string, error) {
|
||||
var buf bytes.Buffer
|
||||
|
||||
if err := c.CompileWriter(&buf); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
result := buf.String()
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *Compiler) visit(node parser.Node) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if rs, ok := r.(string); ok && rs[:len("Amber Error")] == "Amber Error" {
|
||||
panic(r)
|
||||
}
|
||||
|
||||
pos := node.Pos()
|
||||
|
||||
if len(pos.Filename) > 0 {
|
||||
panic(fmt.Sprintf("Amber Error in <%s>: %v - Line: %d, Column: %d, Length: %d", pos.Filename, r, pos.LineNum, pos.ColNum, pos.TokenLength))
|
||||
} else {
|
||||
panic(fmt.Sprintf("Amber Error: %v - Line: %d, Column: %d, Length: %d", r, pos.LineNum, pos.ColNum, pos.TokenLength))
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
switch node.(type) {
|
||||
case *parser.Block:
|
||||
c.visitBlock(node.(*parser.Block))
|
||||
case *parser.Doctype:
|
||||
c.visitDoctype(node.(*parser.Doctype))
|
||||
case *parser.Comment:
|
||||
c.visitComment(node.(*parser.Comment))
|
||||
case *parser.Tag:
|
||||
c.visitTag(node.(*parser.Tag))
|
||||
case *parser.Text:
|
||||
c.visitText(node.(*parser.Text))
|
||||
case *parser.Condition:
|
||||
c.visitCondition(node.(*parser.Condition))
|
||||
case *parser.Each:
|
||||
c.visitEach(node.(*parser.Each))
|
||||
case *parser.Assignment:
|
||||
c.visitAssignment(node.(*parser.Assignment))
|
||||
case *parser.Mixin:
|
||||
c.visitMixin(node.(*parser.Mixin))
|
||||
case *parser.MixinCall:
|
||||
c.visitMixinCall(node.(*parser.MixinCall))
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Compiler) write(value string) {
|
||||
c.buffer.WriteString(value)
|
||||
}
|
||||
|
||||
func (c *Compiler) indent(offset int, newline bool) {
|
||||
if !c.PrettyPrint {
|
||||
return
|
||||
}
|
||||
|
||||
if newline && c.buffer.Len() > 0 {
|
||||
c.write("\n")
|
||||
}
|
||||
|
||||
for i := 0; i < c.indentLevel+offset; i++ {
|
||||
c.write("\t")
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Compiler) tempvar() string {
|
||||
c.tempvarIndex++
|
||||
return "$__amber_" + strconv.Itoa(c.tempvarIndex)
|
||||
}
|
||||
|
||||
func (c *Compiler) escape(input string) string {
|
||||
return strings.Replace(strings.Replace(input, `\`, `\\`, -1), `"`, `\"`, -1)
|
||||
}
|
||||
|
||||
func (c *Compiler) visitBlock(block *parser.Block) {
|
||||
for _, node := range block.Children {
|
||||
if _, ok := node.(*parser.Text); !block.CanInline() && ok {
|
||||
c.indent(0, true)
|
||||
}
|
||||
|
||||
c.visit(node)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Compiler) visitDoctype(doctype *parser.Doctype) {
|
||||
c.write(doctype.String())
|
||||
}
|
||||
|
||||
func (c *Compiler) visitComment(comment *parser.Comment) {
|
||||
if comment.Silent {
|
||||
return
|
||||
}
|
||||
|
||||
c.indent(0, false)
|
||||
|
||||
if comment.Block == nil {
|
||||
c.write(`{{unescaped "<!-- ` + c.escape(comment.Value) + ` -->"}}`)
|
||||
} else {
|
||||
c.write(`<!-- ` + comment.Value)
|
||||
c.visitBlock(comment.Block)
|
||||
c.write(` -->`)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Compiler) visitCondition(condition *parser.Condition) {
|
||||
c.write(`{{if ` + c.visitRawInterpolation(condition.Expression) + `}}`)
|
||||
c.visitBlock(condition.Positive)
|
||||
if condition.Negative != nil {
|
||||
c.write(`{{else}}`)
|
||||
c.visitBlock(condition.Negative)
|
||||
}
|
||||
c.write(`{{end}}`)
|
||||
}
|
||||
|
||||
func (c *Compiler) visitEach(each *parser.Each) {
|
||||
if each.Block == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if len(each.Y) == 0 {
|
||||
c.write(`{{range ` + each.X + ` := ` + c.visitRawInterpolation(each.Expression) + `}}`)
|
||||
} else {
|
||||
c.write(`{{range ` + each.X + `, ` + each.Y + ` := ` + c.visitRawInterpolation(each.Expression) + `}}`)
|
||||
}
|
||||
c.visitBlock(each.Block)
|
||||
c.write(`{{end}}`)
|
||||
}
|
||||
|
||||
func (c *Compiler) visitAssignment(assgn *parser.Assignment) {
|
||||
c.write(`{{` + assgn.X + ` := ` + c.visitRawInterpolation(assgn.Expression) + `}}`)
|
||||
}
|
||||
|
||||
func (c *Compiler) visitTag(tag *parser.Tag) {
|
||||
type attrib struct {
|
||||
name string
|
||||
value string
|
||||
condition string
|
||||
}
|
||||
|
||||
attribs := make(map[string]*attrib)
|
||||
|
||||
for _, item := range tag.Attributes {
|
||||
attr := new(attrib)
|
||||
attr.name = item.Name
|
||||
|
||||
if !item.IsRaw {
|
||||
attr.value = c.visitInterpolation(item.Value)
|
||||
} else if item.Value == "" {
|
||||
attr.value = ""
|
||||
} else {
|
||||
attr.value = item.Value
|
||||
}
|
||||
|
||||
if len(item.Condition) != 0 {
|
||||
attr.condition = c.visitRawInterpolation(item.Condition)
|
||||
}
|
||||
|
||||
if attr.name == "class" && attribs["class"] != nil {
|
||||
prevclass := attribs["class"]
|
||||
attr.value = ` ` + attr.value
|
||||
|
||||
if len(attr.condition) > 0 {
|
||||
attr.value = `{{if ` + attr.condition + `}}` + attr.value + `{{end}}`
|
||||
attr.condition = ""
|
||||
}
|
||||
|
||||
if len(prevclass.condition) > 0 {
|
||||
prevclass.value = `{{if ` + prevclass.condition + `}}` + prevclass.value + `{{end}}`
|
||||
prevclass.condition = ""
|
||||
}
|
||||
|
||||
prevclass.value = prevclass.value + attr.value
|
||||
} else {
|
||||
attribs[item.Name] = attr
|
||||
}
|
||||
}
|
||||
|
||||
keys := make([]string, 0, len(attribs))
|
||||
for key := range attribs {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
c.indent(0, true)
|
||||
c.write("<" + tag.Name)
|
||||
|
||||
for _, name := range keys {
|
||||
value := attribs[name]
|
||||
|
||||
if len(value.condition) > 0 {
|
||||
c.write(`{{if ` + value.condition + `}}`)
|
||||
}
|
||||
|
||||
if value.value == "" {
|
||||
c.write(` ` + name)
|
||||
} else {
|
||||
c.write(` ` + name + `="` + value.value + `"`)
|
||||
}
|
||||
|
||||
if len(value.condition) > 0 {
|
||||
c.write(`{{end}}`)
|
||||
}
|
||||
}
|
||||
|
||||
if tag.IsSelfClosing() {
|
||||
c.write(` />`)
|
||||
} else {
|
||||
c.write(`>`)
|
||||
|
||||
if tag.Block != nil {
|
||||
if !tag.Block.CanInline() {
|
||||
c.indentLevel++
|
||||
}
|
||||
|
||||
c.visitBlock(tag.Block)
|
||||
|
||||
if !tag.Block.CanInline() {
|
||||
c.indentLevel--
|
||||
c.indent(0, true)
|
||||
}
|
||||
}
|
||||
|
||||
c.write(`</` + tag.Name + `>`)
|
||||
}
|
||||
}
|
||||
|
||||
var textInterpolateRegexp = regexp.MustCompile(`#\{(.*?)\}`)
|
||||
var textEscapeRegexp = regexp.MustCompile(`\{\{(.*?)\}\}`)
|
||||
|
||||
func (c *Compiler) visitText(txt *parser.Text) {
|
||||
value := textEscapeRegexp.ReplaceAllStringFunc(txt.Value, func(value string) string {
|
||||
return `{{"{{"}}` + value[2:len(value)-2] + `{{"}}"}}`
|
||||
})
|
||||
|
||||
value = textInterpolateRegexp.ReplaceAllStringFunc(value, func(value string) string {
|
||||
return c.visitInterpolation(value[2 : len(value)-1])
|
||||
})
|
||||
|
||||
lines := strings.Split(value, "\n")
|
||||
for i := 0; i < len(lines); i++ {
|
||||
c.write(lines[i])
|
||||
|
||||
if i < len(lines)-1 {
|
||||
c.write("\n")
|
||||
c.indent(0, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Compiler) visitInterpolation(value string) string {
|
||||
return `{{` + c.visitRawInterpolation(value) + `}}`
|
||||
}
|
||||
|
||||
func (c *Compiler) visitRawInterpolation(value string) string {
|
||||
value = strings.Replace(value, "$", "__DOLLAR__", -1)
|
||||
expr, err := gp.ParseExpr(value)
|
||||
if err != nil {
|
||||
panic("Unable to parse expression.")
|
||||
}
|
||||
value = strings.Replace(c.visitExpression(expr), "__DOLLAR__", "$", -1)
|
||||
return value
|
||||
}
|
||||
|
||||
func (c *Compiler) visitExpression(outerexpr ast.Expr) string {
|
||||
stack := list.New()
|
||||
|
||||
pop := func() string {
|
||||
if stack.Front() == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
val := stack.Front().Value.(string)
|
||||
stack.Remove(stack.Front())
|
||||
return val
|
||||
}
|
||||
|
||||
var exec func(ast.Expr)
|
||||
|
||||
exec = func(expr ast.Expr) {
|
||||
switch expr.(type) {
|
||||
case *ast.BinaryExpr:
|
||||
{
|
||||
be := expr.(*ast.BinaryExpr)
|
||||
|
||||
exec(be.Y)
|
||||
exec(be.X)
|
||||
|
||||
negate := false
|
||||
name := c.tempvar()
|
||||
c.write(`{{` + name + ` := `)
|
||||
|
||||
switch be.Op {
|
||||
case gt.ADD:
|
||||
c.write("__amber_add ")
|
||||
case gt.SUB:
|
||||
c.write("__amber_sub ")
|
||||
case gt.MUL:
|
||||
c.write("__amber_mul ")
|
||||
case gt.QUO:
|
||||
c.write("__amber_quo ")
|
||||
case gt.REM:
|
||||
c.write("__amber_rem ")
|
||||
case gt.LAND:
|
||||
c.write("and ")
|
||||
case gt.LOR:
|
||||
c.write("or ")
|
||||
case gt.EQL:
|
||||
c.write("__amber_eql ")
|
||||
case gt.NEQ:
|
||||
c.write("__amber_eql ")
|
||||
negate = true
|
||||
case gt.LSS:
|
||||
c.write("__amber_lss ")
|
||||
case gt.GTR:
|
||||
c.write("__amber_gtr ")
|
||||
case gt.LEQ:
|
||||
c.write("__amber_gtr ")
|
||||
negate = true
|
||||
case gt.GEQ:
|
||||
c.write("__amber_lss ")
|
||||
negate = true
|
||||
default:
|
||||
panic("Unexpected operator!")
|
||||
}
|
||||
|
||||
c.write(pop() + ` ` + pop() + `}}`)
|
||||
|
||||
if !negate {
|
||||
stack.PushFront(name)
|
||||
} else {
|
||||
negname := c.tempvar()
|
||||
c.write(`{{` + negname + ` := not ` + name + `}}`)
|
||||
stack.PushFront(negname)
|
||||
}
|
||||
}
|
||||
case *ast.UnaryExpr:
|
||||
{
|
||||
ue := expr.(*ast.UnaryExpr)
|
||||
|
||||
exec(ue.X)
|
||||
|
||||
name := c.tempvar()
|
||||
c.write(`{{` + name + ` := `)
|
||||
|
||||
switch ue.Op {
|
||||
case gt.SUB:
|
||||
c.write("__amber_minus ")
|
||||
case gt.ADD:
|
||||
c.write("__amber_plus ")
|
||||
case gt.NOT:
|
||||
c.write("not ")
|
||||
default:
|
||||
panic("Unexpected operator!")
|
||||
}
|
||||
|
||||
c.write(pop() + `}}`)
|
||||
stack.PushFront(name)
|
||||
}
|
||||
case *ast.ParenExpr:
|
||||
exec(expr.(*ast.ParenExpr).X)
|
||||
case *ast.BasicLit:
|
||||
stack.PushFront(expr.(*ast.BasicLit).Value)
|
||||
case *ast.Ident:
|
||||
name := expr.(*ast.Ident).Name
|
||||
if len(name) >= len("__DOLLAR__") && name[:len("__DOLLAR__")] == "__DOLLAR__" {
|
||||
if name == "__DOLLAR__" {
|
||||
stack.PushFront(`.`)
|
||||
} else {
|
||||
stack.PushFront(`$` + expr.(*ast.Ident).Name[len("__DOLLAR__"):])
|
||||
}
|
||||
} else {
|
||||
stack.PushFront(`.` + expr.(*ast.Ident).Name)
|
||||
}
|
||||
case *ast.SelectorExpr:
|
||||
se := expr.(*ast.SelectorExpr)
|
||||
exec(se.X)
|
||||
x := pop()
|
||||
|
||||
if x == "." {
|
||||
x = ""
|
||||
}
|
||||
|
||||
name := c.tempvar()
|
||||
c.write(`{{` + name + ` := ` + x + `.` + se.Sel.Name + `}}`)
|
||||
stack.PushFront(name)
|
||||
case *ast.CallExpr:
|
||||
ce := expr.(*ast.CallExpr)
|
||||
|
||||
for i := len(ce.Args) - 1; i >= 0; i-- {
|
||||
exec(ce.Args[i])
|
||||
}
|
||||
|
||||
name := c.tempvar()
|
||||
builtin := false
|
||||
|
||||
if ident, ok := ce.Fun.(*ast.Ident); ok {
|
||||
for _, fname := range builtinFunctions {
|
||||
if fname == ident.Name {
|
||||
builtin = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if builtin {
|
||||
stack.PushFront(ce.Fun.(*ast.Ident).Name)
|
||||
c.write(`{{` + name + ` := ` + pop())
|
||||
} else {
|
||||
exec(ce.Fun)
|
||||
c.write(`{{` + name + ` := call ` + pop())
|
||||
}
|
||||
|
||||
for i := 0; i < len(ce.Args); i++ {
|
||||
c.write(` `)
|
||||
c.write(pop())
|
||||
}
|
||||
|
||||
c.write(`}}`)
|
||||
|
||||
stack.PushFront(name)
|
||||
default:
|
||||
panic("Unable to parse expression. Unsupported: " + reflect.TypeOf(expr).String())
|
||||
}
|
||||
}
|
||||
|
||||
exec(outerexpr)
|
||||
return pop()
|
||||
}
|
||||
|
||||
func (c *Compiler) visitMixin(mixin *parser.Mixin) {
|
||||
c.mixins[mixin.Name] = mixin
|
||||
}
|
||||
|
||||
func (c *Compiler) visitMixinCall(mixinCall *parser.MixinCall) {
|
||||
mixin := c.mixins[mixinCall.Name]
|
||||
for i, arg := range mixin.Args {
|
||||
c.write(fmt.Sprintf(`{{%s := %s}}`, arg, c.visitRawInterpolation(mixinCall.Args[i])))
|
||||
}
|
||||
c.visitBlock(mixin.Block)
|
||||
}
|
||||
257
vendor/github.com/eknkc/amber/doc.go
generated
vendored
257
vendor/github.com/eknkc/amber/doc.go
generated
vendored
@@ -1,257 +0,0 @@
|
||||
/*
|
||||
Package amber is an elegant templating engine for Go Programming Language.
|
||||
It is inspired from HAML and Jade.
|
||||
|
||||
Tags
|
||||
|
||||
A tag is simply a word:
|
||||
|
||||
html
|
||||
|
||||
is converted to
|
||||
|
||||
<html></html>
|
||||
|
||||
It is possible to add ID and CLASS attributes to tags:
|
||||
|
||||
div#main
|
||||
span.time
|
||||
|
||||
are converted to
|
||||
|
||||
<div id="main"></div>
|
||||
<span class="time"></span>
|
||||
|
||||
Any arbitrary attribute name / value pair can be added this way:
|
||||
|
||||
a[href="http://www.google.com"]
|
||||
|
||||
You can mix multiple attributes together
|
||||
|
||||
a#someid[href="/"][title="Main Page"].main.link Click Link
|
||||
|
||||
gets converted to
|
||||
|
||||
<a id="someid" class="main link" href="/" title="Main Page">Click Link</a>
|
||||
|
||||
It is also possible to define these attributes within the block of a tag
|
||||
|
||||
a
|
||||
#someid
|
||||
[href="/"]
|
||||
[title="Main Page"]
|
||||
.main
|
||||
.link
|
||||
| Click Link
|
||||
|
||||
Doctypes
|
||||
|
||||
To add a doctype, use `!!!` or `doctype` keywords:
|
||||
|
||||
!!! transitional
|
||||
// <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
or use `doctype`
|
||||
|
||||
doctype 5
|
||||
// <!DOCTYPE html>
|
||||
|
||||
Available options: `5`, `default`, `xml`, `transitional`, `strict`, `frameset`, `1.1`, `basic`, `mobile`
|
||||
|
||||
Tag Content
|
||||
|
||||
For single line tag text, you can just append the text after tag name:
|
||||
|
||||
p Testing!
|
||||
|
||||
would yield
|
||||
|
||||
<p>Testing!</p>
|
||||
|
||||
For multi line tag text, or nested tags, use indentation:
|
||||
|
||||
html
|
||||
head
|
||||
title Page Title
|
||||
body
|
||||
div#content
|
||||
p
|
||||
| This is a long page content
|
||||
| These lines are all part of the parent p
|
||||
|
||||
a[href="/"] Go To Main Page
|
||||
|
||||
Data
|
||||
|
||||
Input template data can be reached by key names directly. For example, assuming the template has been
|
||||
executed with following JSON data:
|
||||
|
||||
{
|
||||
"Name": "Ekin",
|
||||
"LastName": "Koc",
|
||||
"Repositories": [
|
||||
"amber",
|
||||
"dateformat"
|
||||
],
|
||||
"Avatar": "/images/ekin.jpg",
|
||||
"Friends": 17
|
||||
}
|
||||
|
||||
It is possible to interpolate fields using `#{}`
|
||||
|
||||
p Welcome #{Name}!
|
||||
|
||||
would print
|
||||
|
||||
<p>Welcome Ekin!</p>
|
||||
|
||||
Attributes can have field names as well
|
||||
|
||||
a[title=Name][href="/ekin.koc"]
|
||||
|
||||
would print
|
||||
|
||||
<a title="Ekin" href="/ekin.koc"></a>
|
||||
|
||||
Expressions
|
||||
|
||||
Amber can expand basic expressions. For example, it is possible to concatenate strings with + operator:
|
||||
|
||||
p Welcome #{Name + " " + LastName}
|
||||
|
||||
Arithmetic expressions are also supported:
|
||||
|
||||
p You need #{50 - Friends} more friends to reach 50!
|
||||
|
||||
Expressions can be used within attributes
|
||||
|
||||
img[alt=Name + " " + LastName][src=Avatar]
|
||||
|
||||
Variables
|
||||
|
||||
It is possible to define dynamic variables within templates,
|
||||
all variables must start with a $ character and can be assigned as in the following example:
|
||||
|
||||
div
|
||||
$fullname = Name + " " + LastName
|
||||
p Welcome #{$fullname}
|
||||
|
||||
If you need to access the supplied data itself (i.e. the object containing Name, LastName etc fields.) you can use `$` variable
|
||||
|
||||
p $.Name
|
||||
|
||||
Conditions
|
||||
|
||||
For conditional blocks, it is possible to use `if <expression>`
|
||||
|
||||
div
|
||||
if Friends > 10
|
||||
p You have more than 10 friends
|
||||
else if Friends > 5
|
||||
p You have more than 5 friends
|
||||
else
|
||||
p You need more friends
|
||||
|
||||
Again, it is possible to use arithmetic and boolean operators
|
||||
|
||||
div
|
||||
if Name == "Ekin" && LastName == "Koc"
|
||||
p Hey! I know you..
|
||||
|
||||
There is a special syntax for conditional attributes. Only block attributes can have conditions;
|
||||
|
||||
div
|
||||
.hasfriends ? Friends > 0
|
||||
|
||||
This would yield a div with `hasfriends` class only if the `Friends > 0` condition holds. It is
|
||||
perfectly fine to use the same method for other types of attributes:
|
||||
|
||||
div
|
||||
#foo ? Name == "Ekin"
|
||||
[bar=baz] ? len(Repositories) > 0
|
||||
|
||||
Iterations
|
||||
|
||||
It is possible to iterate over arrays and maps using `each`:
|
||||
|
||||
each $repo in Repositories
|
||||
p #{$repo}
|
||||
|
||||
would print
|
||||
|
||||
p amber
|
||||
p dateformat
|
||||
|
||||
It is also possible to iterate over values and indexes at the same time
|
||||
|
||||
each $i, $repo in Repositories
|
||||
p
|
||||
.even ? $i % 2 == 0
|
||||
.odd ? $i % 2 == 1
|
||||
|
||||
Includes
|
||||
|
||||
A template can include other templates using `include`:
|
||||
|
||||
a.amber
|
||||
p this is template a
|
||||
|
||||
b.amber
|
||||
p this is template b
|
||||
|
||||
c.amber
|
||||
div
|
||||
include a
|
||||
include b
|
||||
|
||||
gets compiled to
|
||||
|
||||
div
|
||||
p this is template a
|
||||
p this is template b
|
||||
|
||||
Inheritance
|
||||
|
||||
A template can inherit other templates. In order to inherit another template, an `extends` keyword should be used.
|
||||
Parent template can define several named blocks and child template can modify the blocks.
|
||||
|
||||
master.amber
|
||||
!!! 5
|
||||
html
|
||||
head
|
||||
block meta
|
||||
meta[name="description"][content="This is a great website"]
|
||||
|
||||
title
|
||||
block title
|
||||
| Default title
|
||||
body
|
||||
block content
|
||||
|
||||
subpage.amber
|
||||
extends master
|
||||
|
||||
block title
|
||||
| Some sub page!
|
||||
|
||||
block append meta
|
||||
// This will be added after the description meta tag. It is also possible
|
||||
// to prepend something to an existing block
|
||||
meta[name="keywords"][content="foo bar"]
|
||||
|
||||
block content
|
||||
div#main
|
||||
p Some content here
|
||||
|
||||
License
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2012 Ekin Koc <ekin@eknkc.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package amber
|
||||
281
vendor/github.com/eknkc/amber/parser/nodes.go
generated
vendored
281
vendor/github.com/eknkc/amber/parser/nodes.go
generated
vendored
@@ -1,281 +0,0 @@
|
||||
package parser
|
||||
|
||||
import "regexp"
|
||||
import "strings"
|
||||
|
||||
var selfClosingTags = [...]string{
|
||||
"meta",
|
||||
"img",
|
||||
"link",
|
||||
"input",
|
||||
"source",
|
||||
"area",
|
||||
"base",
|
||||
"col",
|
||||
"br",
|
||||
"hr",
|
||||
}
|
||||
|
||||
var doctypes = map[string]string{
|
||||
"5": `<!DOCTYPE html>`,
|
||||
"default": `<!DOCTYPE html>`,
|
||||
"xml": `<?xml version="1.0" encoding="utf-8" ?>`,
|
||||
"transitional": `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">`,
|
||||
"strict": `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">`,
|
||||
"frameset": `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">`,
|
||||
"1.1": `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">`,
|
||||
"basic": `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">`,
|
||||
"mobile": `<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">`,
|
||||
}
|
||||
|
||||
type Node interface {
|
||||
Pos() SourcePosition
|
||||
}
|
||||
|
||||
type SourcePosition struct {
|
||||
LineNum int
|
||||
ColNum int
|
||||
TokenLength int
|
||||
Filename string
|
||||
}
|
||||
|
||||
func (s *SourcePosition) Pos() SourcePosition {
|
||||
return *s
|
||||
}
|
||||
|
||||
type Doctype struct {
|
||||
SourcePosition
|
||||
Value string
|
||||
}
|
||||
|
||||
func newDoctype(value string) *Doctype {
|
||||
dt := new(Doctype)
|
||||
dt.Value = value
|
||||
return dt
|
||||
}
|
||||
|
||||
func (d *Doctype) String() string {
|
||||
if defined := doctypes[d.Value]; len(defined) != 0 {
|
||||
return defined
|
||||
}
|
||||
|
||||
return `<!DOCTYPE ` + d.Value + `>`
|
||||
}
|
||||
|
||||
type Comment struct {
|
||||
SourcePosition
|
||||
Value string
|
||||
Block *Block
|
||||
Silent bool
|
||||
}
|
||||
|
||||
func newComment(value string) *Comment {
|
||||
dt := new(Comment)
|
||||
dt.Value = value
|
||||
dt.Block = nil
|
||||
dt.Silent = false
|
||||
return dt
|
||||
}
|
||||
|
||||
type Text struct {
|
||||
SourcePosition
|
||||
Value string
|
||||
Raw bool
|
||||
}
|
||||
|
||||
func newText(value string, raw bool) *Text {
|
||||
dt := new(Text)
|
||||
dt.Value = value
|
||||
dt.Raw = raw
|
||||
return dt
|
||||
}
|
||||
|
||||
type Block struct {
|
||||
SourcePosition
|
||||
Children []Node
|
||||
}
|
||||
|
||||
func newBlock() *Block {
|
||||
block := new(Block)
|
||||
block.Children = make([]Node, 0)
|
||||
return block
|
||||
}
|
||||
|
||||
func (b *Block) push(node Node) {
|
||||
b.Children = append(b.Children, node)
|
||||
}
|
||||
|
||||
func (b *Block) pushFront(node Node) {
|
||||
b.Children = append([]Node{node}, b.Children...)
|
||||
}
|
||||
|
||||
func (b *Block) CanInline() bool {
|
||||
if len(b.Children) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
allText := true
|
||||
|
||||
for _, child := range b.Children {
|
||||
if txt, ok := child.(*Text); !ok || txt.Raw {
|
||||
allText = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return allText
|
||||
}
|
||||
|
||||
const (
|
||||
NamedBlockDefault = iota
|
||||
NamedBlockAppend
|
||||
NamedBlockPrepend
|
||||
)
|
||||
|
||||
type NamedBlock struct {
|
||||
Block
|
||||
Name string
|
||||
Modifier int
|
||||
}
|
||||
|
||||
func newNamedBlock(name string) *NamedBlock {
|
||||
bb := new(NamedBlock)
|
||||
bb.Name = name
|
||||
bb.Block.Children = make([]Node, 0)
|
||||
bb.Modifier = NamedBlockDefault
|
||||
return bb
|
||||
}
|
||||
|
||||
type Attribute struct {
|
||||
SourcePosition
|
||||
Name string
|
||||
Value string
|
||||
IsRaw bool
|
||||
Condition string
|
||||
}
|
||||
|
||||
type Tag struct {
|
||||
SourcePosition
|
||||
Block *Block
|
||||
Name string
|
||||
IsInterpolated bool
|
||||
Attributes []Attribute
|
||||
}
|
||||
|
||||
func newTag(name string) *Tag {
|
||||
tag := new(Tag)
|
||||
tag.Block = nil
|
||||
tag.Name = name
|
||||
tag.Attributes = make([]Attribute, 0)
|
||||
tag.IsInterpolated = false
|
||||
return tag
|
||||
|
||||
}
|
||||
|
||||
func (t *Tag) IsSelfClosing() bool {
|
||||
for _, tag := range selfClosingTags {
|
||||
if tag == t.Name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (t *Tag) IsRawText() bool {
|
||||
return t.Name == "style" || t.Name == "script"
|
||||
}
|
||||
|
||||
type Condition struct {
|
||||
SourcePosition
|
||||
Positive *Block
|
||||
Negative *Block
|
||||
Expression string
|
||||
}
|
||||
|
||||
func newCondition(exp string) *Condition {
|
||||
cond := new(Condition)
|
||||
cond.Expression = exp
|
||||
return cond
|
||||
}
|
||||
|
||||
type Each struct {
|
||||
SourcePosition
|
||||
X string
|
||||
Y string
|
||||
Expression string
|
||||
Block *Block
|
||||
}
|
||||
|
||||
func newEach(exp string) *Each {
|
||||
each := new(Each)
|
||||
each.Expression = exp
|
||||
return each
|
||||
}
|
||||
|
||||
type Assignment struct {
|
||||
SourcePosition
|
||||
X string
|
||||
Expression string
|
||||
}
|
||||
|
||||
func newAssignment(x, expression string) *Assignment {
|
||||
assgn := new(Assignment)
|
||||
assgn.X = x
|
||||
assgn.Expression = expression
|
||||
return assgn
|
||||
}
|
||||
|
||||
type Mixin struct {
|
||||
SourcePosition
|
||||
Block *Block
|
||||
Name string
|
||||
Args []string
|
||||
}
|
||||
|
||||
func newMixin(name, args string) *Mixin {
|
||||
mixin := new(Mixin)
|
||||
mixin.Name = name
|
||||
|
||||
delExp := regexp.MustCompile(`,\s`)
|
||||
mixin.Args = delExp.Split(args, -1)
|
||||
|
||||
for i := 0; i < len(mixin.Args); i++ {
|
||||
mixin.Args[i] = strings.TrimSpace(mixin.Args[i])
|
||||
if mixin.Args[i] == "" {
|
||||
mixin.Args = append(mixin.Args[:i], mixin.Args[i+1:]...)
|
||||
i--
|
||||
}
|
||||
}
|
||||
|
||||
return mixin
|
||||
}
|
||||
|
||||
type MixinCall struct {
|
||||
SourcePosition
|
||||
Name string
|
||||
Args []string
|
||||
}
|
||||
|
||||
func newMixinCall(name, args string) *MixinCall {
|
||||
mixinCall := new(MixinCall)
|
||||
mixinCall.Name = name
|
||||
|
||||
const t = "%s"
|
||||
quoteExp := regexp.MustCompile(`"(.*?)"`)
|
||||
delExp := regexp.MustCompile(`,\s`)
|
||||
|
||||
quotes := quoteExp.FindAllString(args, -1)
|
||||
replaced := quoteExp.ReplaceAllString(args, t)
|
||||
mixinCall.Args = delExp.Split(replaced, -1)
|
||||
|
||||
qi := 0
|
||||
for i, arg := range mixinCall.Args {
|
||||
if arg == t {
|
||||
mixinCall.Args[i] = quotes[qi]
|
||||
qi++
|
||||
}
|
||||
}
|
||||
|
||||
return mixinCall
|
||||
}
|
||||
454
vendor/github.com/eknkc/amber/parser/parser.go
generated
vendored
454
vendor/github.com/eknkc/amber/parser/parser.go
generated
vendored
@@ -1,454 +0,0 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Parser struct {
|
||||
scanner *scanner
|
||||
filename string
|
||||
currenttoken *token
|
||||
namedBlocks map[string]*NamedBlock
|
||||
parent *Parser
|
||||
result *Block
|
||||
}
|
||||
|
||||
func newParser(rdr io.Reader) *Parser {
|
||||
p := new(Parser)
|
||||
p.scanner = newScanner(rdr)
|
||||
p.namedBlocks = make(map[string]*NamedBlock)
|
||||
return p
|
||||
}
|
||||
|
||||
func StringParser(input string) (*Parser, error) {
|
||||
return newParser(bytes.NewReader([]byte(input))), nil
|
||||
}
|
||||
|
||||
func ByteParser(input []byte) (*Parser, error) {
|
||||
return newParser(bytes.NewReader(input)), nil
|
||||
}
|
||||
|
||||
func (p *Parser) SetFilename(filename string) {
|
||||
p.filename = filename
|
||||
}
|
||||
|
||||
func FileParser(filename string) (*Parser, error) {
|
||||
data, err := ioutil.ReadFile(filename)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
parser := newParser(bytes.NewReader(data))
|
||||
parser.filename = filename
|
||||
return parser, nil
|
||||
}
|
||||
|
||||
func (p *Parser) Parse() *Block {
|
||||
if p.result != nil {
|
||||
return p.result
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if rs, ok := r.(string); ok && rs[:len("Amber Error")] == "Amber Error" {
|
||||
panic(r)
|
||||
}
|
||||
|
||||
pos := p.pos()
|
||||
|
||||
if len(pos.Filename) > 0 {
|
||||
panic(fmt.Sprintf("Amber Error in <%s>: %v - Line: %d, Column: %d, Length: %d", pos.Filename, r, pos.LineNum, pos.ColNum, pos.TokenLength))
|
||||
} else {
|
||||
panic(fmt.Sprintf("Amber Error: %v - Line: %d, Column: %d, Length: %d", r, pos.LineNum, pos.ColNum, pos.TokenLength))
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
block := newBlock()
|
||||
p.advance()
|
||||
|
||||
for {
|
||||
if p.currenttoken == nil || p.currenttoken.Kind == tokEOF {
|
||||
break
|
||||
}
|
||||
|
||||
if p.currenttoken.Kind == tokBlank {
|
||||
p.advance()
|
||||
continue
|
||||
}
|
||||
|
||||
block.push(p.parse())
|
||||
}
|
||||
|
||||
if p.parent != nil {
|
||||
p.parent.Parse()
|
||||
|
||||
for _, prev := range p.parent.namedBlocks {
|
||||
ours := p.namedBlocks[prev.Name]
|
||||
|
||||
if ours == nil {
|
||||
// Put a copy of the named block into current context, so that sub-templates can use the block
|
||||
p.namedBlocks[prev.Name] = prev
|
||||
continue
|
||||
}
|
||||
|
||||
top := findTopmostParentWithNamedBlock(p, prev.Name)
|
||||
nb := top.namedBlocks[prev.Name]
|
||||
switch ours.Modifier {
|
||||
case NamedBlockAppend:
|
||||
for i := 0; i < len(ours.Children); i++ {
|
||||
nb.push(ours.Children[i])
|
||||
}
|
||||
case NamedBlockPrepend:
|
||||
for i := len(ours.Children) - 1; i >= 0; i-- {
|
||||
nb.pushFront(ours.Children[i])
|
||||
}
|
||||
default:
|
||||
nb.Children = ours.Children
|
||||
}
|
||||
}
|
||||
|
||||
block = p.parent.result
|
||||
}
|
||||
|
||||
p.result = block
|
||||
return block
|
||||
}
|
||||
|
||||
func (p *Parser) pos() SourcePosition {
|
||||
pos := p.scanner.Pos()
|
||||
pos.Filename = p.filename
|
||||
return pos
|
||||
}
|
||||
|
||||
func (p *Parser) parseRelativeFile(filename string) *Parser {
|
||||
if len(p.filename) == 0 {
|
||||
panic("Unable to import or extend " + filename + " in a non filesystem based parser.")
|
||||
}
|
||||
|
||||
filename = filepath.Join(filepath.Dir(p.filename), filename)
|
||||
|
||||
if strings.IndexRune(filepath.Base(filename), '.') < 0 {
|
||||
filename = filename + ".amber"
|
||||
}
|
||||
|
||||
parser, err := FileParser(filename)
|
||||
if err != nil {
|
||||
panic("Unable to read " + filename + ", Error: " + string(err.Error()))
|
||||
}
|
||||
|
||||
return parser
|
||||
}
|
||||
|
||||
func (p *Parser) parse() Node {
|
||||
switch p.currenttoken.Kind {
|
||||
case tokDoctype:
|
||||
return p.parseDoctype()
|
||||
case tokComment:
|
||||
return p.parseComment()
|
||||
case tokText:
|
||||
return p.parseText()
|
||||
case tokIf:
|
||||
return p.parseIf()
|
||||
case tokEach:
|
||||
return p.parseEach()
|
||||
case tokImport:
|
||||
return p.parseImport()
|
||||
case tokTag:
|
||||
return p.parseTag()
|
||||
case tokAssignment:
|
||||
return p.parseAssignment()
|
||||
case tokNamedBlock:
|
||||
return p.parseNamedBlock()
|
||||
case tokExtends:
|
||||
return p.parseExtends()
|
||||
case tokIndent:
|
||||
return p.parseBlock(nil)
|
||||
case tokMixin:
|
||||
return p.parseMixin()
|
||||
case tokMixinCall:
|
||||
return p.parseMixinCall()
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Unexpected token: %d", p.currenttoken.Kind))
|
||||
}
|
||||
|
||||
func (p *Parser) expect(typ rune) *token {
|
||||
if p.currenttoken.Kind != typ {
|
||||
panic("Unexpected token!")
|
||||
}
|
||||
curtok := p.currenttoken
|
||||
p.advance()
|
||||
return curtok
|
||||
}
|
||||
|
||||
func (p *Parser) advance() {
|
||||
p.currenttoken = p.scanner.Next()
|
||||
}
|
||||
|
||||
func (p *Parser) parseExtends() *Block {
|
||||
if p.parent != nil {
|
||||
panic("Unable to extend multiple parent templates.")
|
||||
}
|
||||
|
||||
tok := p.expect(tokExtends)
|
||||
parser := p.parseRelativeFile(tok.Value)
|
||||
parser.Parse()
|
||||
p.parent = parser
|
||||
return newBlock()
|
||||
}
|
||||
|
||||
func (p *Parser) parseBlock(parent Node) *Block {
|
||||
p.expect(tokIndent)
|
||||
block := newBlock()
|
||||
block.SourcePosition = p.pos()
|
||||
|
||||
for {
|
||||
if p.currenttoken == nil || p.currenttoken.Kind == tokEOF || p.currenttoken.Kind == tokOutdent {
|
||||
break
|
||||
}
|
||||
|
||||
if p.currenttoken.Kind == tokBlank {
|
||||
p.advance()
|
||||
continue
|
||||
}
|
||||
|
||||
if p.currenttoken.Kind == tokId ||
|
||||
p.currenttoken.Kind == tokClassName ||
|
||||
p.currenttoken.Kind == tokAttribute {
|
||||
|
||||
if tag, ok := parent.(*Tag); ok {
|
||||
attr := p.expect(p.currenttoken.Kind)
|
||||
cond := attr.Data["Condition"]
|
||||
|
||||
switch attr.Kind {
|
||||
case tokId:
|
||||
tag.Attributes = append(tag.Attributes, Attribute{p.pos(), "id", attr.Value, true, cond})
|
||||
case tokClassName:
|
||||
tag.Attributes = append(tag.Attributes, Attribute{p.pos(), "class", attr.Value, true, cond})
|
||||
case tokAttribute:
|
||||
tag.Attributes = append(tag.Attributes, Attribute{p.pos(), attr.Value, attr.Data["Content"], attr.Data["Mode"] == "raw", cond})
|
||||
}
|
||||
|
||||
continue
|
||||
} else {
|
||||
panic("Conditional attributes must be placed immediately within a parent tag.")
|
||||
}
|
||||
}
|
||||
|
||||
block.push(p.parse())
|
||||
}
|
||||
|
||||
p.expect(tokOutdent)
|
||||
|
||||
return block
|
||||
}
|
||||
|
||||
func (p *Parser) parseIf() *Condition {
|
||||
tok := p.expect(tokIf)
|
||||
cnd := newCondition(tok.Value)
|
||||
cnd.SourcePosition = p.pos()
|
||||
|
||||
readmore:
|
||||
switch p.currenttoken.Kind {
|
||||
case tokIndent:
|
||||
cnd.Positive = p.parseBlock(cnd)
|
||||
goto readmore
|
||||
case tokElse:
|
||||
p.expect(tokElse)
|
||||
if p.currenttoken.Kind == tokIf {
|
||||
cnd.Negative = newBlock()
|
||||
cnd.Negative.push(p.parseIf())
|
||||
} else if p.currenttoken.Kind == tokIndent {
|
||||
cnd.Negative = p.parseBlock(cnd)
|
||||
} else {
|
||||
panic("Unexpected token!")
|
||||
}
|
||||
goto readmore
|
||||
}
|
||||
|
||||
return cnd
|
||||
}
|
||||
|
||||
func (p *Parser) parseEach() *Each {
|
||||
tok := p.expect(tokEach)
|
||||
ech := newEach(tok.Value)
|
||||
ech.SourcePosition = p.pos()
|
||||
ech.X = tok.Data["X"]
|
||||
ech.Y = tok.Data["Y"]
|
||||
|
||||
if p.currenttoken.Kind == tokIndent {
|
||||
ech.Block = p.parseBlock(ech)
|
||||
}
|
||||
|
||||
return ech
|
||||
}
|
||||
|
||||
func (p *Parser) parseImport() *Block {
|
||||
tok := p.expect(tokImport)
|
||||
node := p.parseRelativeFile(tok.Value).Parse()
|
||||
node.SourcePosition = p.pos()
|
||||
return node
|
||||
}
|
||||
|
||||
func (p *Parser) parseNamedBlock() *Block {
|
||||
tok := p.expect(tokNamedBlock)
|
||||
|
||||
if p.namedBlocks[tok.Value] != nil {
|
||||
panic("Multiple definitions of named blocks are not permitted. Block " + tok.Value + " has been re defined.")
|
||||
}
|
||||
|
||||
block := newNamedBlock(tok.Value)
|
||||
block.SourcePosition = p.pos()
|
||||
|
||||
if tok.Data["Modifier"] == "append" {
|
||||
block.Modifier = NamedBlockAppend
|
||||
} else if tok.Data["Modifier"] == "prepend" {
|
||||
block.Modifier = NamedBlockPrepend
|
||||
}
|
||||
|
||||
if p.currenttoken.Kind == tokIndent {
|
||||
block.Block = *(p.parseBlock(nil))
|
||||
}
|
||||
|
||||
p.namedBlocks[block.Name] = block
|
||||
|
||||
if block.Modifier == NamedBlockDefault {
|
||||
return &block.Block
|
||||
}
|
||||
|
||||
return newBlock()
|
||||
}
|
||||
|
||||
func (p *Parser) parseDoctype() *Doctype {
|
||||
tok := p.expect(tokDoctype)
|
||||
node := newDoctype(tok.Value)
|
||||
node.SourcePosition = p.pos()
|
||||
return node
|
||||
}
|
||||
|
||||
func (p *Parser) parseComment() *Comment {
|
||||
tok := p.expect(tokComment)
|
||||
cmnt := newComment(tok.Value)
|
||||
cmnt.SourcePosition = p.pos()
|
||||
cmnt.Silent = tok.Data["Mode"] == "silent"
|
||||
|
||||
if p.currenttoken.Kind == tokIndent {
|
||||
cmnt.Block = p.parseBlock(cmnt)
|
||||
}
|
||||
|
||||
return cmnt
|
||||
}
|
||||
|
||||
func (p *Parser) parseText() *Text {
|
||||
tok := p.expect(tokText)
|
||||
node := newText(tok.Value, tok.Data["Mode"] == "raw")
|
||||
node.SourcePosition = p.pos()
|
||||
return node
|
||||
}
|
||||
|
||||
func (p *Parser) parseAssignment() *Assignment {
|
||||
tok := p.expect(tokAssignment)
|
||||
node := newAssignment(tok.Data["X"], tok.Value)
|
||||
node.SourcePosition = p.pos()
|
||||
return node
|
||||
}
|
||||
|
||||
func (p *Parser) parseTag() *Tag {
|
||||
tok := p.expect(tokTag)
|
||||
tag := newTag(tok.Value)
|
||||
tag.SourcePosition = p.pos()
|
||||
|
||||
ensureBlock := func() {
|
||||
if tag.Block == nil {
|
||||
tag.Block = newBlock()
|
||||
}
|
||||
}
|
||||
|
||||
readmore:
|
||||
switch p.currenttoken.Kind {
|
||||
case tokIndent:
|
||||
if tag.IsRawText() {
|
||||
p.scanner.readRaw = true
|
||||
}
|
||||
|
||||
block := p.parseBlock(tag)
|
||||
if tag.Block == nil {
|
||||
tag.Block = block
|
||||
} else {
|
||||
for _, c := range block.Children {
|
||||
tag.Block.push(c)
|
||||
}
|
||||
}
|
||||
case tokId:
|
||||
id := p.expect(tokId)
|
||||
if len(id.Data["Condition"]) > 0 {
|
||||
panic("Conditional attributes must be placed in a block within a tag.")
|
||||
}
|
||||
tag.Attributes = append(tag.Attributes, Attribute{p.pos(), "id", id.Value, true, ""})
|
||||
goto readmore
|
||||
case tokClassName:
|
||||
cls := p.expect(tokClassName)
|
||||
if len(cls.Data["Condition"]) > 0 {
|
||||
panic("Conditional attributes must be placed in a block within a tag.")
|
||||
}
|
||||
tag.Attributes = append(tag.Attributes, Attribute{p.pos(), "class", cls.Value, true, ""})
|
||||
goto readmore
|
||||
case tokAttribute:
|
||||
attr := p.expect(tokAttribute)
|
||||
if len(attr.Data["Condition"]) > 0 {
|
||||
panic("Conditional attributes must be placed in a block within a tag.")
|
||||
}
|
||||
tag.Attributes = append(tag.Attributes, Attribute{p.pos(), attr.Value, attr.Data["Content"], attr.Data["Mode"] == "raw", ""})
|
||||
goto readmore
|
||||
case tokText:
|
||||
if p.currenttoken.Data["Mode"] != "piped" {
|
||||
ensureBlock()
|
||||
tag.Block.pushFront(p.parseText())
|
||||
goto readmore
|
||||
}
|
||||
}
|
||||
|
||||
return tag
|
||||
}
|
||||
|
||||
func (p *Parser) parseMixin() *Mixin {
|
||||
tok := p.expect(tokMixin)
|
||||
mixin := newMixin(tok.Value, tok.Data["Args"])
|
||||
mixin.SourcePosition = p.pos()
|
||||
|
||||
if p.currenttoken.Kind == tokIndent {
|
||||
mixin.Block = p.parseBlock(mixin)
|
||||
}
|
||||
|
||||
return mixin
|
||||
}
|
||||
|
||||
func (p *Parser) parseMixinCall() *MixinCall {
|
||||
tok := p.expect(tokMixinCall)
|
||||
mixinCall := newMixinCall(tok.Value, tok.Data["Args"])
|
||||
mixinCall.SourcePosition = p.pos()
|
||||
return mixinCall
|
||||
}
|
||||
|
||||
func findTopmostParentWithNamedBlock(p *Parser, name string) *Parser {
|
||||
top := p
|
||||
|
||||
for {
|
||||
if top.namedBlocks[name] == nil {
|
||||
return nil
|
||||
}
|
||||
if top.parent == nil {
|
||||
return top
|
||||
}
|
||||
if top.parent.namedBlocks[name] != nil {
|
||||
top = top.parent
|
||||
}
|
||||
}
|
||||
}
|
||||
501
vendor/github.com/eknkc/amber/parser/scanner.go
generated
vendored
501
vendor/github.com/eknkc/amber/parser/scanner.go
generated
vendored
@@ -1,501 +0,0 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"container/list"
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
const (
|
||||
tokEOF = -(iota + 1)
|
||||
tokDoctype
|
||||
tokComment
|
||||
tokIndent
|
||||
tokOutdent
|
||||
tokBlank
|
||||
tokId
|
||||
tokClassName
|
||||
tokTag
|
||||
tokText
|
||||
tokAttribute
|
||||
tokIf
|
||||
tokElse
|
||||
tokEach
|
||||
tokAssignment
|
||||
tokImport
|
||||
tokNamedBlock
|
||||
tokExtends
|
||||
tokMixin
|
||||
tokMixinCall
|
||||
)
|
||||
|
||||
const (
|
||||
scnNewLine = iota
|
||||
scnLine
|
||||
scnEOF
|
||||
)
|
||||
|
||||
type scanner struct {
|
||||
reader *bufio.Reader
|
||||
indentStack *list.List
|
||||
stash *list.List
|
||||
|
||||
state int32
|
||||
buffer string
|
||||
|
||||
line int
|
||||
col int
|
||||
lastTokenLine int
|
||||
lastTokenCol int
|
||||
lastTokenSize int
|
||||
|
||||
readRaw bool
|
||||
}
|
||||
|
||||
type token struct {
|
||||
Kind rune
|
||||
Value string
|
||||
Data map[string]string
|
||||
}
|
||||
|
||||
func newScanner(r io.Reader) *scanner {
|
||||
s := new(scanner)
|
||||
s.reader = bufio.NewReader(r)
|
||||
s.indentStack = list.New()
|
||||
s.stash = list.New()
|
||||
s.state = scnNewLine
|
||||
s.line = -1
|
||||
s.col = 0
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *scanner) Pos() SourcePosition {
|
||||
return SourcePosition{s.lastTokenLine + 1, s.lastTokenCol + 1, s.lastTokenSize, ""}
|
||||
}
|
||||
|
||||
// Returns next token found in buffer
|
||||
func (s *scanner) Next() *token {
|
||||
if s.readRaw {
|
||||
s.readRaw = false
|
||||
return s.NextRaw()
|
||||
}
|
||||
|
||||
s.ensureBuffer()
|
||||
|
||||
if stashed := s.stash.Front(); stashed != nil {
|
||||
tok := stashed.Value.(*token)
|
||||
s.stash.Remove(stashed)
|
||||
return tok
|
||||
}
|
||||
|
||||
switch s.state {
|
||||
case scnEOF:
|
||||
if outdent := s.indentStack.Back(); outdent != nil {
|
||||
s.indentStack.Remove(outdent)
|
||||
return &token{tokOutdent, "", nil}
|
||||
}
|
||||
|
||||
return &token{tokEOF, "", nil}
|
||||
case scnNewLine:
|
||||
s.state = scnLine
|
||||
|
||||
if tok := s.scanIndent(); tok != nil {
|
||||
return tok
|
||||
}
|
||||
|
||||
return s.Next()
|
||||
case scnLine:
|
||||
if tok := s.scanMixin(); tok != nil {
|
||||
return tok
|
||||
}
|
||||
|
||||
if tok := s.scanMixinCall(); tok != nil {
|
||||
return tok
|
||||
}
|
||||
|
||||
if tok := s.scanDoctype(); tok != nil {
|
||||
return tok
|
||||
}
|
||||
|
||||
if tok := s.scanCondition(); tok != nil {
|
||||
return tok
|
||||
}
|
||||
|
||||
if tok := s.scanEach(); tok != nil {
|
||||
return tok
|
||||
}
|
||||
|
||||
if tok := s.scanImport(); tok != nil {
|
||||
return tok
|
||||
}
|
||||
|
||||
if tok := s.scanExtends(); tok != nil {
|
||||
return tok
|
||||
}
|
||||
|
||||
if tok := s.scanBlock(); tok != nil {
|
||||
return tok
|
||||
}
|
||||
|
||||
if tok := s.scanAssignment(); tok != nil {
|
||||
return tok
|
||||
}
|
||||
|
||||
if tok := s.scanTag(); tok != nil {
|
||||
return tok
|
||||
}
|
||||
|
||||
if tok := s.scanId(); tok != nil {
|
||||
return tok
|
||||
}
|
||||
|
||||
if tok := s.scanClassName(); tok != nil {
|
||||
return tok
|
||||
}
|
||||
|
||||
if tok := s.scanAttribute(); tok != nil {
|
||||
return tok
|
||||
}
|
||||
|
||||
if tok := s.scanComment(); tok != nil {
|
||||
return tok
|
||||
}
|
||||
|
||||
if tok := s.scanText(); tok != nil {
|
||||
return tok
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *scanner) NextRaw() *token {
|
||||
result := ""
|
||||
level := 0
|
||||
|
||||
for {
|
||||
s.ensureBuffer()
|
||||
|
||||
switch s.state {
|
||||
case scnEOF:
|
||||
return &token{tokText, result, map[string]string{"Mode": "raw"}}
|
||||
case scnNewLine:
|
||||
s.state = scnLine
|
||||
|
||||
if tok := s.scanIndent(); tok != nil {
|
||||
if tok.Kind == tokIndent {
|
||||
level++
|
||||
} else if tok.Kind == tokOutdent {
|
||||
level--
|
||||
} else {
|
||||
result = result + "\n"
|
||||
continue
|
||||
}
|
||||
|
||||
if level < 0 {
|
||||
s.stash.PushBack(&token{tokOutdent, "", nil})
|
||||
|
||||
if len(result) > 0 && result[len(result)-1] == '\n' {
|
||||
result = result[:len(result)-1]
|
||||
}
|
||||
|
||||
return &token{tokText, result, map[string]string{"Mode": "raw"}}
|
||||
}
|
||||
}
|
||||
case scnLine:
|
||||
if len(result) > 0 {
|
||||
result = result + "\n"
|
||||
}
|
||||
for i := 0; i < level; i++ {
|
||||
result += "\t"
|
||||
}
|
||||
result = result + s.buffer
|
||||
s.consume(len(s.buffer))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var rgxIndent = regexp.MustCompile(`^(\s+)`)
|
||||
|
||||
func (s *scanner) scanIndent() *token {
|
||||
if len(s.buffer) == 0 {
|
||||
return &token{tokBlank, "", nil}
|
||||
}
|
||||
|
||||
var head *list.Element
|
||||
for head = s.indentStack.Front(); head != nil; head = head.Next() {
|
||||
value := head.Value.(*regexp.Regexp)
|
||||
|
||||
if match := value.FindString(s.buffer); len(match) != 0 {
|
||||
s.consume(len(match))
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
newIndent := rgxIndent.FindString(s.buffer)
|
||||
|
||||
if len(newIndent) != 0 && head == nil {
|
||||
s.indentStack.PushBack(regexp.MustCompile(regexp.QuoteMeta(newIndent)))
|
||||
s.consume(len(newIndent))
|
||||
return &token{tokIndent, newIndent, nil}
|
||||
}
|
||||
|
||||
if len(newIndent) == 0 && head != nil {
|
||||
for head != nil {
|
||||
next := head.Next()
|
||||
s.indentStack.Remove(head)
|
||||
if next == nil {
|
||||
return &token{tokOutdent, "", nil}
|
||||
} else {
|
||||
s.stash.PushBack(&token{tokOutdent, "", nil})
|
||||
}
|
||||
head = next
|
||||
}
|
||||
}
|
||||
|
||||
if len(newIndent) != 0 && head != nil {
|
||||
panic("Mismatching indentation. Please use a coherent indent schema.")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var rgxDoctype = regexp.MustCompile(`^(!!!|doctype)\s*(.*)`)
|
||||
|
||||
func (s *scanner) scanDoctype() *token {
|
||||
if sm := rgxDoctype.FindStringSubmatch(s.buffer); len(sm) != 0 {
|
||||
if len(sm[2]) == 0 {
|
||||
sm[2] = "html"
|
||||
}
|
||||
|
||||
s.consume(len(sm[0]))
|
||||
return &token{tokDoctype, sm[2], nil}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var rgxIf = regexp.MustCompile(`^if\s+(.+)$`)
|
||||
var rgxElse = regexp.MustCompile(`^else\s*`)
|
||||
|
||||
func (s *scanner) scanCondition() *token {
|
||||
if sm := rgxIf.FindStringSubmatch(s.buffer); len(sm) != 0 {
|
||||
s.consume(len(sm[0]))
|
||||
return &token{tokIf, sm[1], nil}
|
||||
}
|
||||
|
||||
if sm := rgxElse.FindStringSubmatch(s.buffer); len(sm) != 0 {
|
||||
s.consume(len(sm[0]))
|
||||
return &token{tokElse, "", nil}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var rgxEach = regexp.MustCompile(`^each\s+(\$[\w0-9\-_]*)(?:\s*,\s*(\$[\w0-9\-_]*))?\s+in\s+(.+)$`)
|
||||
|
||||
func (s *scanner) scanEach() *token {
|
||||
if sm := rgxEach.FindStringSubmatch(s.buffer); len(sm) != 0 {
|
||||
s.consume(len(sm[0]))
|
||||
return &token{tokEach, sm[3], map[string]string{"X": sm[1], "Y": sm[2]}}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var rgxAssignment = regexp.MustCompile(`^(\$[\w0-9\-_]*)?\s*=\s*(.+)$`)
|
||||
|
||||
func (s *scanner) scanAssignment() *token {
|
||||
if sm := rgxAssignment.FindStringSubmatch(s.buffer); len(sm) != 0 {
|
||||
s.consume(len(sm[0]))
|
||||
return &token{tokAssignment, sm[2], map[string]string{"X": sm[1]}}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var rgxComment = regexp.MustCompile(`^\/\/(-)?\s*(.*)$`)
|
||||
|
||||
func (s *scanner) scanComment() *token {
|
||||
if sm := rgxComment.FindStringSubmatch(s.buffer); len(sm) != 0 {
|
||||
mode := "embed"
|
||||
if len(sm[1]) != 0 {
|
||||
mode = "silent"
|
||||
}
|
||||
|
||||
s.consume(len(sm[0]))
|
||||
return &token{tokComment, sm[2], map[string]string{"Mode": mode}}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var rgxId = regexp.MustCompile(`^#([\w-]+)(?:\s*\?\s*(.*)$)?`)
|
||||
|
||||
func (s *scanner) scanId() *token {
|
||||
if sm := rgxId.FindStringSubmatch(s.buffer); len(sm) != 0 {
|
||||
s.consume(len(sm[0]))
|
||||
return &token{tokId, sm[1], map[string]string{"Condition": sm[2]}}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var rgxClassName = regexp.MustCompile(`^\.([\w-]+)(?:\s*\?\s*(.*)$)?`)
|
||||
|
||||
func (s *scanner) scanClassName() *token {
|
||||
if sm := rgxClassName.FindStringSubmatch(s.buffer); len(sm) != 0 {
|
||||
s.consume(len(sm[0]))
|
||||
return &token{tokClassName, sm[1], map[string]string{"Condition": sm[2]}}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var rgxAttribute = regexp.MustCompile(`^\[([\w\-]+)\s*(?:=\s*(\"([^\"\\]*)\"|([^\]]+)))?\](?:\s*\?\s*(.*)$)?`)
|
||||
|
||||
func (s *scanner) scanAttribute() *token {
|
||||
if sm := rgxAttribute.FindStringSubmatch(s.buffer); len(sm) != 0 {
|
||||
s.consume(len(sm[0]))
|
||||
|
||||
if len(sm[3]) != 0 || sm[2] == "" {
|
||||
return &token{tokAttribute, sm[1], map[string]string{"Content": sm[3], "Mode": "raw", "Condition": sm[5]}}
|
||||
}
|
||||
|
||||
return &token{tokAttribute, sm[1], map[string]string{"Content": sm[4], "Mode": "expression", "Condition": sm[5]}}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var rgxImport = regexp.MustCompile(`^import\s+([0-9a-zA-Z_\-\. \/]*)$`)
|
||||
|
||||
func (s *scanner) scanImport() *token {
|
||||
if sm := rgxImport.FindStringSubmatch(s.buffer); len(sm) != 0 {
|
||||
s.consume(len(sm[0]))
|
||||
return &token{tokImport, sm[1], nil}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var rgxExtends = regexp.MustCompile(`^extends\s+([0-9a-zA-Z_\-\. \/]*)$`)
|
||||
|
||||
func (s *scanner) scanExtends() *token {
|
||||
if sm := rgxExtends.FindStringSubmatch(s.buffer); len(sm) != 0 {
|
||||
s.consume(len(sm[0]))
|
||||
return &token{tokExtends, sm[1], nil}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var rgxBlock = regexp.MustCompile(`^block\s+(?:(append|prepend)\s+)?([0-9a-zA-Z_\-\. \/]*)$`)
|
||||
|
||||
func (s *scanner) scanBlock() *token {
|
||||
if sm := rgxBlock.FindStringSubmatch(s.buffer); len(sm) != 0 {
|
||||
s.consume(len(sm[0]))
|
||||
return &token{tokNamedBlock, sm[2], map[string]string{"Modifier": sm[1]}}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var rgxTag = regexp.MustCompile(`^(\w[-:\w]*)`)
|
||||
|
||||
func (s *scanner) scanTag() *token {
|
||||
if sm := rgxTag.FindStringSubmatch(s.buffer); len(sm) != 0 {
|
||||
s.consume(len(sm[0]))
|
||||
return &token{tokTag, sm[1], nil}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var rgxMixin = regexp.MustCompile(`^mixin ([a-zA-Z_]+\w*)(\(((\$\w*(,\s)?)*)\))?$`)
|
||||
|
||||
func (s *scanner) scanMixin() *token {
|
||||
if sm := rgxMixin.FindStringSubmatch(s.buffer); len(sm) != 0 {
|
||||
s.consume(len(sm[0]))
|
||||
return &token{tokMixin, sm[1], map[string]string{"Args": sm[3]}}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var rgxMixinCall = regexp.MustCompile(`^\+([A-Za-z_]+\w*)(\((.+(,\s)?)*\))?$`)
|
||||
|
||||
func (s *scanner) scanMixinCall() *token {
|
||||
if sm := rgxMixinCall.FindStringSubmatch(s.buffer); len(sm) != 0 {
|
||||
s.consume(len(sm[0]))
|
||||
return &token{tokMixinCall, sm[1], map[string]string{"Args": sm[3]}}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var rgxText = regexp.MustCompile(`^(\|)? ?(.*)$`)
|
||||
|
||||
func (s *scanner) scanText() *token {
|
||||
if sm := rgxText.FindStringSubmatch(s.buffer); len(sm) != 0 {
|
||||
s.consume(len(sm[0]))
|
||||
|
||||
mode := "inline"
|
||||
if sm[1] == "|" {
|
||||
mode = "piped"
|
||||
}
|
||||
|
||||
return &token{tokText, sm[2], map[string]string{"Mode": mode}}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Moves position forward, and removes beginning of s.buffer (len bytes)
|
||||
func (s *scanner) consume(runes int) {
|
||||
if len(s.buffer) < runes {
|
||||
panic(fmt.Sprintf("Unable to consume %d runes from buffer.", runes))
|
||||
}
|
||||
|
||||
s.lastTokenLine = s.line
|
||||
s.lastTokenCol = s.col
|
||||
s.lastTokenSize = runes
|
||||
|
||||
s.buffer = s.buffer[runes:]
|
||||
s.col += runes
|
||||
}
|
||||
|
||||
// Reads string into s.buffer
|
||||
func (s *scanner) ensureBuffer() {
|
||||
if len(s.buffer) > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := s.reader.ReadString('\n')
|
||||
|
||||
if err != nil && err != io.EOF {
|
||||
panic(err)
|
||||
} else if err != nil && len(buf) == 0 {
|
||||
s.state = scnEOF
|
||||
} else {
|
||||
// endline "LF only" or "\n" use Unix, Linux, modern MacOS X, FreeBSD, BeOS, RISC OS
|
||||
if buf[len(buf)-1] == '\n' {
|
||||
buf = buf[:len(buf)-1]
|
||||
}
|
||||
// endline "CR+LF" or "\r\n" use internet protocols, DEC RT-11, Windows, CP/M, MS-DOS, OS/2, Symbian OS
|
||||
if len(buf) > 0 && buf[len(buf)-1] == '\r' {
|
||||
buf = buf[:len(buf)-1]
|
||||
}
|
||||
|
||||
s.state = scnNewLine
|
||||
s.buffer = buf
|
||||
s.line += 1
|
||||
s.col = 0
|
||||
}
|
||||
}
|
||||
287
vendor/github.com/eknkc/amber/runtime.go
generated
vendored
287
vendor/github.com/eknkc/amber/runtime.go
generated
vendored
@@ -1,287 +0,0 @@
|
||||
package amber
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
var FuncMap = template.FuncMap{
|
||||
"__amber_add": runtime_add,
|
||||
"__amber_sub": runtime_sub,
|
||||
"__amber_mul": runtime_mul,
|
||||
"__amber_quo": runtime_quo,
|
||||
"__amber_rem": runtime_rem,
|
||||
"__amber_minus": runtime_minus,
|
||||
"__amber_plus": runtime_plus,
|
||||
"__amber_eql": runtime_eql,
|
||||
"__amber_gtr": runtime_gtr,
|
||||
"__amber_lss": runtime_lss,
|
||||
|
||||
"json": runtime_json,
|
||||
"unescaped": runtime_unescaped,
|
||||
}
|
||||
|
||||
func runtime_add(x, y interface{}) interface{} {
|
||||
vx, vy := reflect.ValueOf(x), reflect.ValueOf(y)
|
||||
switch vx.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
{
|
||||
switch vy.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
return vx.Int() + vy.Int()
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return float64(vx.Int()) + vy.Float()
|
||||
case reflect.String:
|
||||
return fmt.Sprintf("%d%s", vx.Int(), vy.String())
|
||||
}
|
||||
}
|
||||
case reflect.Float32, reflect.Float64:
|
||||
{
|
||||
switch vy.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
return vx.Float() + float64(vy.Int())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return vx.Float() + vy.Float()
|
||||
case reflect.String:
|
||||
return fmt.Sprintf("%f%s", vx.Float(), vy.String())
|
||||
}
|
||||
}
|
||||
case reflect.String:
|
||||
{
|
||||
switch vy.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
return fmt.Sprintf("%s%d", vx.String(), vy.Int())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return fmt.Sprintf("%s%f", vx.String(), vy.Float())
|
||||
case reflect.String:
|
||||
return fmt.Sprintf("%s%s", vx.String(), vy.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "<nil>"
|
||||
}
|
||||
|
||||
func runtime_sub(x, y interface{}) interface{} {
|
||||
vx, vy := reflect.ValueOf(x), reflect.ValueOf(y)
|
||||
switch vx.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
{
|
||||
switch vy.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
return vx.Int() - vy.Int()
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return float64(vx.Int()) - vy.Float()
|
||||
}
|
||||
}
|
||||
case reflect.Float32, reflect.Float64:
|
||||
{
|
||||
switch vy.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
return vx.Float() - float64(vy.Int())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return vx.Float() - vy.Float()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "<nil>"
|
||||
}
|
||||
|
||||
func runtime_mul(x, y interface{}) interface{} {
|
||||
vx, vy := reflect.ValueOf(x), reflect.ValueOf(y)
|
||||
switch vx.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
{
|
||||
switch vy.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
return vx.Int() * vy.Int()
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return float64(vx.Int()) * vy.Float()
|
||||
}
|
||||
}
|
||||
case reflect.Float32, reflect.Float64:
|
||||
{
|
||||
switch vy.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
return vx.Float() * float64(vy.Int())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return vx.Float() * vy.Float()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "<nil>"
|
||||
}
|
||||
|
||||
func runtime_quo(x, y interface{}) interface{} {
|
||||
vx, vy := reflect.ValueOf(x), reflect.ValueOf(y)
|
||||
switch vx.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
{
|
||||
switch vy.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
return vx.Int() / vy.Int()
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return float64(vx.Int()) / vy.Float()
|
||||
}
|
||||
}
|
||||
case reflect.Float32, reflect.Float64:
|
||||
{
|
||||
switch vy.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
return vx.Float() / float64(vy.Int())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return vx.Float() / vy.Float()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "<nil>"
|
||||
}
|
||||
|
||||
func runtime_rem(x, y interface{}) interface{} {
|
||||
vx, vy := reflect.ValueOf(x), reflect.ValueOf(y)
|
||||
switch vx.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
{
|
||||
switch vy.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
return vx.Int() % vy.Int()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "<nil>"
|
||||
}
|
||||
|
||||
func runtime_minus(x interface{}) interface{} {
|
||||
vx := reflect.ValueOf(x)
|
||||
switch vx.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
return -vx.Int()
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return -vx.Float()
|
||||
}
|
||||
|
||||
return "<nil>"
|
||||
}
|
||||
|
||||
func runtime_plus(x interface{}) interface{} {
|
||||
vx := reflect.ValueOf(x)
|
||||
switch vx.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
return +vx.Int()
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return +vx.Float()
|
||||
}
|
||||
|
||||
return "<nil>"
|
||||
}
|
||||
|
||||
func runtime_eql(x, y interface{}) bool {
|
||||
vx, vy := reflect.ValueOf(x), reflect.ValueOf(y)
|
||||
switch vx.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
{
|
||||
switch vy.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
return vx.Int() == vy.Int()
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return float64(vx.Int()) == vy.Float()
|
||||
case reflect.String:
|
||||
return fmt.Sprintf("%d", vx.Int()) == vy.String()
|
||||
}
|
||||
}
|
||||
case reflect.Float32, reflect.Float64:
|
||||
{
|
||||
switch vy.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
return vx.Float() == float64(vy.Int())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return vx.Float() == vy.Float()
|
||||
case reflect.String:
|
||||
return fmt.Sprintf("%f", vx.Float()) == vy.String()
|
||||
}
|
||||
}
|
||||
case reflect.String:
|
||||
{
|
||||
switch vy.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
return vx.String() == fmt.Sprintf("%d", vy.Int())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return vx.String() == fmt.Sprintf("%f", vy.Float())
|
||||
case reflect.String:
|
||||
return vx.String() == fmt.Sprintf("%s", vy.String())
|
||||
}
|
||||
}
|
||||
case reflect.Bool:
|
||||
{
|
||||
switch vy.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
return vx.Bool() && vy.Int() != 0
|
||||
case reflect.Bool:
|
||||
return vx.Bool() == vy.Bool()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func runtime_lss(x, y interface{}) bool {
|
||||
vx, vy := reflect.ValueOf(x), reflect.ValueOf(y)
|
||||
switch vx.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
{
|
||||
switch vy.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
return vx.Int() < vy.Int()
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return float64(vx.Int()) < vy.Float()
|
||||
case reflect.String:
|
||||
return fmt.Sprintf("%d", vx.Int()) < vy.String()
|
||||
}
|
||||
}
|
||||
case reflect.Float32, reflect.Float64:
|
||||
{
|
||||
switch vy.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
return vx.Float() < float64(vy.Int())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return vx.Float() < vy.Float()
|
||||
case reflect.String:
|
||||
return fmt.Sprintf("%f", vx.Float()) < vy.String()
|
||||
}
|
||||
}
|
||||
case reflect.String:
|
||||
{
|
||||
switch vy.Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int16, reflect.Int8:
|
||||
return vx.String() < fmt.Sprintf("%d", vy.Int())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return vx.String() < fmt.Sprintf("%f", vy.Float())
|
||||
case reflect.String:
|
||||
return vx.String() < vy.String()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func runtime_gtr(x, y interface{}) bool {
|
||||
return !runtime_lss(x, y) && !runtime_eql(x, y)
|
||||
}
|
||||
|
||||
func runtime_json(x interface{}) (res string, err error) {
|
||||
bres, err := json.Marshal(x)
|
||||
res = string(bres)
|
||||
return
|
||||
}
|
||||
|
||||
func runtime_unescaped(x string) interface{} {
|
||||
return template.HTML(x)
|
||||
}
|
||||
23
vendor/github.com/elazarl/go-bindata-assetfs/LICENSE
generated
vendored
23
vendor/github.com/elazarl/go-bindata-assetfs/LICENSE
generated
vendored
@@ -1,23 +0,0 @@
|
||||
Copyright (c) 2014, Elazar Leibovich
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
46
vendor/github.com/elazarl/go-bindata-assetfs/README.md
generated
vendored
46
vendor/github.com/elazarl/go-bindata-assetfs/README.md
generated
vendored
@@ -1,46 +0,0 @@
|
||||
# go-bindata-assetfs
|
||||
|
||||
Serve embedded files from [jteeuwen/go-bindata](https://github.com/jteeuwen/go-bindata) with `net/http`.
|
||||
|
||||
[GoDoc](http://godoc.org/github.com/elazarl/go-bindata-assetfs)
|
||||
|
||||
### Installation
|
||||
|
||||
Install with
|
||||
|
||||
$ go get github.com/jteeuwen/go-bindata/...
|
||||
$ go get github.com/elazarl/go-bindata-assetfs/...
|
||||
|
||||
### Creating embedded data
|
||||
|
||||
Usage is identical to [jteeuwen/go-bindata](https://github.com/jteeuwen/go-bindata) usage,
|
||||
instead of running `go-bindata` run `go-bindata-assetfs`.
|
||||
|
||||
The tool will create a `bindata_assetfs.go` file, which contains the embedded data.
|
||||
|
||||
A typical use case is
|
||||
|
||||
$ go-bindata-assetfs data/...
|
||||
|
||||
### Using assetFS in your code
|
||||
|
||||
The generated file provides an `assetFS()` function that returns a `http.Filesystem`
|
||||
wrapping the embedded files. What you usually want to do is:
|
||||
|
||||
http.Handle("/", http.FileServer(assetFS()))
|
||||
|
||||
This would run an HTTP server serving the embedded files.
|
||||
|
||||
## Without running binary tool
|
||||
|
||||
You can always just run the `go-bindata` tool, and then
|
||||
|
||||
use
|
||||
|
||||
import "github.com/elazarl/go-bindata-assetfs"
|
||||
...
|
||||
http.Handle("/",
|
||||
http.FileServer(
|
||||
&assetfs.AssetFS{Asset: Asset, AssetDir: AssetDir, Prefix: "data"}))
|
||||
|
||||
to serve files embedded from the `data` directory.
|
||||
147
vendor/github.com/elazarl/go-bindata-assetfs/assetfs.go
generated
vendored
147
vendor/github.com/elazarl/go-bindata-assetfs/assetfs.go
generated
vendored
@@ -1,147 +0,0 @@
|
||||
package assetfs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
fileTimestamp = time.Now()
|
||||
)
|
||||
|
||||
// FakeFile implements os.FileInfo interface for a given path and size
|
||||
type FakeFile struct {
|
||||
// Path is the path of this file
|
||||
Path string
|
||||
// Dir marks of the path is a directory
|
||||
Dir bool
|
||||
// Len is the length of the fake file, zero if it is a directory
|
||||
Len int64
|
||||
}
|
||||
|
||||
func (f *FakeFile) Name() string {
|
||||
_, name := filepath.Split(f.Path)
|
||||
return name
|
||||
}
|
||||
|
||||
func (f *FakeFile) Mode() os.FileMode {
|
||||
mode := os.FileMode(0644)
|
||||
if f.Dir {
|
||||
return mode | os.ModeDir
|
||||
}
|
||||
return mode
|
||||
}
|
||||
|
||||
func (f *FakeFile) ModTime() time.Time {
|
||||
return fileTimestamp
|
||||
}
|
||||
|
||||
func (f *FakeFile) Size() int64 {
|
||||
return f.Len
|
||||
}
|
||||
|
||||
func (f *FakeFile) IsDir() bool {
|
||||
return f.Mode().IsDir()
|
||||
}
|
||||
|
||||
func (f *FakeFile) Sys() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AssetFile implements http.File interface for a no-directory file with content
|
||||
type AssetFile struct {
|
||||
*bytes.Reader
|
||||
io.Closer
|
||||
FakeFile
|
||||
}
|
||||
|
||||
func NewAssetFile(name string, content []byte) *AssetFile {
|
||||
return &AssetFile{
|
||||
bytes.NewReader(content),
|
||||
ioutil.NopCloser(nil),
|
||||
FakeFile{name, false, int64(len(content))}}
|
||||
}
|
||||
|
||||
func (f *AssetFile) Readdir(count int) ([]os.FileInfo, error) {
|
||||
return nil, errors.New("not a directory")
|
||||
}
|
||||
|
||||
func (f *AssetFile) Size() int64 {
|
||||
return f.FakeFile.Size()
|
||||
}
|
||||
|
||||
func (f *AssetFile) Stat() (os.FileInfo, error) {
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// AssetDirectory implements http.File interface for a directory
|
||||
type AssetDirectory struct {
|
||||
AssetFile
|
||||
ChildrenRead int
|
||||
Children []os.FileInfo
|
||||
}
|
||||
|
||||
func NewAssetDirectory(name string, children []string, fs *AssetFS) *AssetDirectory {
|
||||
fileinfos := make([]os.FileInfo, 0, len(children))
|
||||
for _, child := range children {
|
||||
_, err := fs.AssetDir(filepath.Join(name, child))
|
||||
fileinfos = append(fileinfos, &FakeFile{child, err == nil, 0})
|
||||
}
|
||||
return &AssetDirectory{
|
||||
AssetFile{
|
||||
bytes.NewReader(nil),
|
||||
ioutil.NopCloser(nil),
|
||||
FakeFile{name, true, 0},
|
||||
},
|
||||
0,
|
||||
fileinfos}
|
||||
}
|
||||
|
||||
func (f *AssetDirectory) Readdir(count int) ([]os.FileInfo, error) {
|
||||
if count <= 0 {
|
||||
return f.Children, nil
|
||||
}
|
||||
if f.ChildrenRead+count > len(f.Children) {
|
||||
count = len(f.Children) - f.ChildrenRead
|
||||
}
|
||||
rv := f.Children[f.ChildrenRead : f.ChildrenRead+count]
|
||||
f.ChildrenRead += count
|
||||
return rv, nil
|
||||
}
|
||||
|
||||
func (f *AssetDirectory) Stat() (os.FileInfo, error) {
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// AssetFS implements http.FileSystem, allowing
|
||||
// embedded files to be served from net/http package.
|
||||
type AssetFS struct {
|
||||
// Asset should return content of file in path if exists
|
||||
Asset func(path string) ([]byte, error)
|
||||
// AssetDir should return list of files in the path
|
||||
AssetDir func(path string) ([]string, error)
|
||||
// Prefix would be prepended to http requests
|
||||
Prefix string
|
||||
}
|
||||
|
||||
func (fs *AssetFS) Open(name string) (http.File, error) {
|
||||
name = path.Join(fs.Prefix, name)
|
||||
if len(name) > 0 && name[0] == '/' {
|
||||
name = name[1:]
|
||||
}
|
||||
if children, err := fs.AssetDir(name); err == nil {
|
||||
return NewAssetDirectory(name, children, fs), nil
|
||||
}
|
||||
b, err := fs.Asset(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewAssetFile(name, b), nil
|
||||
}
|
||||
13
vendor/github.com/elazarl/go-bindata-assetfs/doc.go
generated
vendored
13
vendor/github.com/elazarl/go-bindata-assetfs/doc.go
generated
vendored
@@ -1,13 +0,0 @@
|
||||
// assetfs allows packages to serve static content embedded
|
||||
// with the go-bindata tool with the standard net/http package.
|
||||
//
|
||||
// See https://github.com/jteeuwen/go-bindata for more information
|
||||
// about embedding binary data with go-bindata.
|
||||
//
|
||||
// Usage example, after running
|
||||
// $ go-bindata data/...
|
||||
// use:
|
||||
// http.Handle("/",
|
||||
// http.FileServer(
|
||||
// &assetfs.AssetFS{Asset: Asset, AssetDir: AssetDir, Prefix: "data"}))
|
||||
package assetfs
|
||||
202
vendor/github.com/samalba/dockerclient/LICENSE
generated
vendored
202
vendor/github.com/samalba/dockerclient/LICENSE
generated
vendored
@@ -1,202 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2014 Sam Alba <sam.alba@gmail.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
98
vendor/github.com/samalba/dockerclient/README.md
generated
vendored
98
vendor/github.com/samalba/dockerclient/README.md
generated
vendored
@@ -1,98 +0,0 @@
|
||||
Docker client library in Go
|
||||
===========================
|
||||
[](http://godoc.org/github.com/samalba/dockerclient)
|
||||
|
||||
Well maintained docker client library.
|
||||
|
||||
# How to use it?
|
||||
|
||||
Here is an example showing how to use it:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/samalba/dockerclient"
|
||||
"log"
|
||||
"time"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Callback used to listen to Docker's events
|
||||
func eventCallback(event *dockerclient.Event, ec chan error, args ...interface{}) {
|
||||
log.Printf("Received event: %#v\n", *event)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Init the client
|
||||
docker, _ := dockerclient.NewDockerClient("unix:///var/run/docker.sock", nil)
|
||||
|
||||
// Get only running containers
|
||||
containers, err := docker.ListContainers(false, false, "")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
for _, c := range containers {
|
||||
log.Println(c.Id, c.Names)
|
||||
}
|
||||
|
||||
// Inspect the first container returned
|
||||
if len(containers) > 0 {
|
||||
id := containers[0].Id
|
||||
info, _ := docker.InspectContainer(id)
|
||||
log.Println(info)
|
||||
}
|
||||
|
||||
// Build a docker image
|
||||
// some.tar contains the build context (Dockerfile any any files it needs to add/copy)
|
||||
dockerBuildContext, err := os.Open("some.tar")
|
||||
defer dockerBuildContext.Close()
|
||||
buildImageConfig := &dockerclient.BuildImage{
|
||||
Context: dockerBuildContext,
|
||||
RepoName: "your_image_name",
|
||||
SuppressOutput: false,
|
||||
}
|
||||
reader, err := docker.BuildImage(buildImageConfig)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Create a container
|
||||
containerConfig := &dockerclient.ContainerConfig{
|
||||
Image: "ubuntu:14.04",
|
||||
Cmd: []string{"bash"},
|
||||
AttachStdin: true,
|
||||
Tty: true}
|
||||
containerId, err := docker.CreateContainer(containerConfig, "foobar", nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Start the container
|
||||
hostConfig := &dockerclient.HostConfig{}
|
||||
err = docker.StartContainer(containerId, hostConfig)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Stop the container (with 5 seconds timeout)
|
||||
docker.StopContainer(containerId, 5)
|
||||
|
||||
// Listen to events
|
||||
docker.StartMonitorEvents(eventCallback, nil)
|
||||
|
||||
// Hold the execution to look at the events coming
|
||||
time.Sleep(3600 * time.Second)
|
||||
}
|
||||
```
|
||||
|
||||
# Maintainers
|
||||
|
||||
List of people you can ping for feedback on Pull Requests or any questions.
|
||||
|
||||
- [Sam Alba](https://github.com/samalba)
|
||||
- [Michael Crosby](https://github.com/crosbymichael)
|
||||
- [Andrea Luzzardi](https://github.com/aluzzardi)
|
||||
- [Victor Vieux](https://github.com/vieux)
|
||||
- [Evan Hazlett](https://github.com/ehazlett)
|
||||
- [Donald Huang](https://github.com/donhcd)
|
||||
39
vendor/github.com/samalba/dockerclient/auth.go
generated
vendored
39
vendor/github.com/samalba/dockerclient/auth.go
generated
vendored
@@ -1,39 +0,0 @@
|
||||
package dockerclient
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// AuthConfig hold parameters for authenticating with the docker registry
|
||||
type AuthConfig struct {
|
||||
Username string `json:"username,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Email string `json:"email,omitempty"`
|
||||
RegistryToken string `json:"registrytoken,omitempty"`
|
||||
}
|
||||
|
||||
// encode the auth configuration struct into base64 for the X-Registry-Auth header
|
||||
func (c *AuthConfig) encode() (string, error) {
|
||||
var buf bytes.Buffer
|
||||
if err := json.NewEncoder(&buf).Encode(c); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return base64.URLEncoding.EncodeToString(buf.Bytes()), nil
|
||||
}
|
||||
|
||||
// ConfigFile holds parameters for authenticating during a BuildImage request
|
||||
type ConfigFile struct {
|
||||
Configs map[string]AuthConfig `json:"configs,omitempty"`
|
||||
rootPath string
|
||||
}
|
||||
|
||||
// encode the configuration struct into base64 for the X-Registry-Config header
|
||||
func (c *ConfigFile) encode() (string, error) {
|
||||
var buf bytes.Buffer
|
||||
if err := json.NewEncoder(&buf).Encode(c); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return base64.URLEncoding.EncodeToString(buf.Bytes()), nil
|
||||
}
|
||||
1001
vendor/github.com/samalba/dockerclient/dockerclient.go
generated
vendored
1001
vendor/github.com/samalba/dockerclient/dockerclient.go
generated
vendored
File diff suppressed because it is too large
Load Diff
15
vendor/github.com/samalba/dockerclient/example_responses.go
generated
vendored
15
vendor/github.com/samalba/dockerclient/example_responses.go
generated
vendored
@@ -1,15 +0,0 @@
|
||||
package dockerclient
|
||||
|
||||
var haproxyPullOutput = `{"status":"The image you are pulling has been verified","id":"haproxy:1"}
|
||||
{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"66301eb54a7d"}{"status":"Already exists","progressDetail":{},"id":"e3990b07573f"}{"status":"Already exists","progressDetail":{},"id":"ecb4b23ca7ce"}{"status":"Already exists","progressDetail":{},"id":"f453e940c177"}{"status":"Already exists","progressDetail":{},"id":"fc5ea1bc05ab"}{"status":"Already exists","progressDetail":{},"id":"380557f8f7b3"}{"status":"The image you are pulling has been verified","id":"haproxy:1.4"}
|
||||
{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"63a1b9929e14"}{"status":"Already exists","progressDetail":{},"id":"af43bf7d176e"}{"status":"Already exists","progressDetail":{},"id":"851aac2d69aa"}{"status":"Already exists","progressDetail":{},"id":"345053a92c95"}{"status":"Already exists","progressDetail":{},"id":"b41231d429c9"}{"status":"The image you are pulling has been verified","id":"haproxy:1.4.25"}
|
||||
{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"63a1b9929e14"}{"status":"Already exists","progressDetail":{},"id":"af43bf7d176e"}{"status":"Already exists","progressDetail":{},"id":"851aac2d69aa"}{"status":"Already exists","progressDetail":{},"id":"345053a92c95"}{"status":"Already exists","progressDetail":{},"id":"b41231d429c9"}{"status":"The image you are pulling has been verified","id":"haproxy:1.5"}
|
||||
{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"66301eb54a7d"}{"status":"Already exists","progressDetail":{},"id":"e3990b07573f"}{"status":"Already exists","progressDetail":{},"id":"ecb4b23ca7ce"}{"status":"Already exists","progressDetail":{},"id":"f453e940c177"}{"status":"Already exists","progressDetail":{},"id":"fc5ea1bc05ab"}{"status":"Already exists","progressDetail":{},"id":"380557f8f7b3"}{"status":"The image you are pulling has been verified","id":"haproxy:1.5.10"}
|
||||
{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"66301eb54a7d"}{"status":"Already exists","progressDetail":{},"id":"e3990b07573f"}{"status":"Already exists","progressDetail":{},"id":"ecb4b23ca7ce"}{"status":"Already exists","progressDetail":{},"id":"f453e940c177"}{"status":"Already exists","progressDetail":{},"id":"fc5ea1bc05ab"}{"status":"Already exists","progressDetail":{},"id":"380557f8f7b3"}{"status":"The image you are pulling has been verified","id":"haproxy:1.5.9"}
|
||||
{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"66301eb54a7d"}{"status":"Already exists","progressDetail":{},"id":"e3990b07573f"}{"status":"Already exists","progressDetail":{},"id":"3d894e6f7e63"}{"status":"Already exists","progressDetail":{},"id":"4d949c40bc77"}{"status":"Already exists","progressDetail":{},"id":"55e031889365"}{"status":"Already exists","progressDetail":{},"id":"c7aa675e1876"}{"status":"The image you are pulling has been verified","id":"haproxy:latest"}
|
||||
{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"66301eb54a7d"}{"status":"Already exists","progressDetail":{},"id":"e3990b07573f"}{"status":"Already exists","progressDetail":{},"id":"ecb4b23ca7ce"}{"status":"Already exists","progressDetail":{},"id":"f453e940c177"}{"status":"Already exists","progressDetail":{},"id":"fc5ea1bc05ab"}{"status":"Already exists","progressDetail":{},"id":"380557f8f7b3"}{"status":"Status: Image is up to date for haproxy"}
|
||||
`
|
||||
|
||||
var statsResp = `{"read":"2015-02-02T17:06:08.187833376-05:00","network":{"rx_bytes":99988,"rx_packets":928,"rx_errors":0,"rx_dropped":0,"tx_bytes":1786548,"tx_packets":877,"tx_errors":0,"tx_dropped":0},"cpu_stats":{"cpu_usage":{"total_usage":170018598,"percpu_usage":[170018598],"usage_in_kernelmode":30000000,"usage_in_usermode":70000000},"system_cpu_usage":9020930000000,"throttling_data":{"periods":0,"throttled_periods":0,"throttled_time":0}},"memory_stats":{"usage":18022400,"max_usage":20541440,"stats":{"active_anon":6213632,"active_file":176128,"cache":11808768,"hierarchical_memory_limit":9223372036854775807,"hierarchical_memsw_limit":9223372036854775807,"inactive_anon":0,"inactive_file":11632640,"mapped_file":5165056,"pgfault":2535,"pgmajfault":13,"pgpgin":4293,"pgpgout":1937,"rss":6213632,"rss_huge":2097152,"swap":0,"total_active_anon":6213632,"total_active_file":176128,"total_cache":11808768,"total_inactive_anon":0,"total_inactive_file":11632640,"total_mapped_file":5165056,"total_pgfault":2535,"total_pgmajfault":13,"total_pgpgin":4293,"total_pgpgout":1937,"total_rss":6213632,"total_rss_huge":2097152,"total_swap":0,"total_unevictable":0,"unevictable":0},"failcnt":0,"limit":1041051648},"blkio_stats":{"io_service_bytes_recursive":[{"major":7,"minor":0,"op":"Read","value":28672},{"major":7,"minor":0,"op":"Write","value":0},{"major":7,"minor":0,"op":"Sync","value":0},{"major":7,"minor":0,"op":"Async","value":28672},{"major":7,"minor":0,"op":"Total","value":28672},{"major":253,"minor":0,"op":"Read","value":28672},{"major":253,"minor":0,"op":"Write","value":0},{"major":253,"minor":0,"op":"Sync","value":0},{"major":253,"minor":0,"op":"Async","value":28672},{"major":253,"minor":0,"op":"Total","value":28672},{"major":253,"minor":7,"op":"Read","value":11718656},{"major":253,"minor":7,"op":"Write","value":0},{"major":253,"minor":7,"op":"Sync","value":0},{"major":253,"minor":7,"op":"Async","value":11718656},{"major":253,"minor":7,"op":"Total","value":11718656},{"major":202,"minor":0,"op":"Read","value":0},{"major":202,"minor":0,"op":"Write","value":0},{"major":202,"minor":0,"op":"Sync","value":0},{"major":202,"minor":0,"op":"Async","value":0},{"major":202,"minor":0,"op":"Total","value":0}],"io_serviced_recursive":[{"major":7,"minor":0,"op":"Read","value":7},{"major":7,"minor":0,"op":"Write","value":0},{"major":7,"minor":0,"op":"Sync","value":0},{"major":7,"minor":0,"op":"Async","value":7},{"major":7,"minor":0,"op":"Total","value":7},{"major":253,"minor":0,"op":"Read","value":7},{"major":253,"minor":0,"op":"Write","value":0},{"major":253,"minor":0,"op":"Sync","value":0},{"major":253,"minor":0,"op":"Async","value":7},{"major":253,"minor":0,"op":"Total","value":7},{"major":253,"minor":7,"op":"Read","value":312},{"major":253,"minor":7,"op":"Write","value":0},{"major":253,"minor":7,"op":"Sync","value":0},{"major":253,"minor":7,"op":"Async","value":312},{"major":253,"minor":7,"op":"Total","value":312},{"major":202,"minor":0,"op":"Read","value":0},{"major":202,"minor":0,"op":"Write","value":0},{"major":202,"minor":0,"op":"Sync","value":0},{"major":202,"minor":0,"op":"Async","value":0},{"major":202,"minor":0,"op":"Total","value":0}],"io_queue_recursive":[],"io_service_time_recursive":[],"io_wait_time_recursive":[],"io_merged_recursive":[],"io_time_recursive":[],"sectors_recursive":[]}}`
|
||||
|
||||
var eventsResp = `{"status":"pull","id":"nginx:latest","time":1428620433}{"status":"create","id":"9b818c3b8291708fdcecd7c4086b75c222cb503be10a93d9c11040886032a48b","from":"nginx:latest","time":1428620433}{"status":"start","id":"9b818c3b8291708fdcecd7c4086b75c222cb503be10a93d9c11040886032a48b","from":"nginx:latest","time":1428620433}{"status":"die","id":"9b818c3b8291708fdcecd7c4086b75c222cb503be10a93d9c11040886032a48b","from":"nginx:latest","time":1428620442}{"status":"create","id":"352d0b412aae5a5d2b14ae9d88be59dc276602d9edb9dcc33e138e475b3e4720","from":"52.11.96.81/foobar/ubuntu:latest","time":1428620444}{"status":"start","id":"352d0b412aae5a5d2b14ae9d88be59dc276602d9edb9dcc33e138e475b3e4720","from":"52.11.96.81/foobar/ubuntu:latest","time":1428620444}{"status":"die","id":"352d0b412aae5a5d2b14ae9d88be59dc276602d9edb9dcc33e138e475b3e4720","from":"52.11.96.81/foobar/ubuntu:latest","time":1428620444}{"status":"pull","id":"debian:latest","time":1428620453}{"status":"create","id":"668887b5729946546b3072655dc6da08f0e3210111b68b704eb842adfce53f6c","from":"debian:latest","time":1428620453}{"status":"start","id":"668887b5729946546b3072655dc6da08f0e3210111b68b704eb842adfce53f6c","from":"debian:latest","time":1428620453}{"status":"die","id":"668887b5729946546b3072655dc6da08f0e3210111b68b704eb842adfce53f6c","from":"debian:latest","time":1428620453}{"status":"create","id":"eb4a19ec21ab29bbbffbf3ee2e2df9d99cb749780e1eff06a591cee5ba505180","from":"nginx:latest","time":1428620458}{"status":"start","id":"eb4a19ec21ab29bbbffbf3ee2e2df9d99cb749780e1eff06a591cee5ba505180","from":"nginx:latest","time":1428620458}{"status":"pause","id":"eb4a19ec21ab29bbbffbf3ee2e2df9d99cb749780e1eff06a591cee5ba505180","from":"nginx:latest","time":1428620462}{"status":"unpause","id":"eb4a19ec21ab29bbbffbf3ee2e2df9d99cb749780e1eff06a591cee5ba505180","from":"nginx:latest","time":1428620466}{"status":"die","id":"eb4a19ec21ab29bbbffbf3ee2e2df9d99cb749780e1eff06a591cee5ba505180","from":"nginx:latest","time":1428620469}`
|
||||
66
vendor/github.com/samalba/dockerclient/interface.go
generated
vendored
66
vendor/github.com/samalba/dockerclient/interface.go
generated
vendored
@@ -1,66 +0,0 @@
|
||||
package dockerclient
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
type Callback func(*Event, chan error, ...interface{})
|
||||
|
||||
type StatCallback func(string, *Stats, chan error, ...interface{})
|
||||
|
||||
type Client interface {
|
||||
Info() (*Info, error)
|
||||
ListContainers(all, size bool, filters string) ([]Container, error)
|
||||
InspectContainer(id string) (*ContainerInfo, error)
|
||||
InspectImage(id string) (*ImageInfo, error)
|
||||
CreateContainer(config *ContainerConfig, name string, authConfig *AuthConfig) (string, error)
|
||||
ContainerLogs(id string, options *LogOptions) (io.ReadCloser, error)
|
||||
ContainerChanges(id string) ([]*ContainerChanges, error)
|
||||
// ContainerStats takes a container ID and an optional stop channel and
|
||||
// returns a StatsOrError channel. If an error is ever sent, then no
|
||||
// more stats will be sent on that channel. If a stop channel is
|
||||
// provided, events will stop being monitored after the stop channel is
|
||||
// closed.
|
||||
ContainerStats(id string, stopChan <-chan struct{}) (<-chan StatsOrError, error)
|
||||
ExecCreate(config *ExecConfig) (string, error)
|
||||
ExecStart(id string, config *ExecConfig) error
|
||||
ExecResize(id string, width, height int) error
|
||||
StartContainer(id string, config *HostConfig) error
|
||||
AttachContainer(id string, options *AttachOptions) (io.ReadCloser, error)
|
||||
StopContainer(id string, timeout int) error
|
||||
RestartContainer(id string, timeout int) error
|
||||
KillContainer(id, signal string) error
|
||||
Wait(id string) <-chan WaitResult
|
||||
// MonitorEvents takes options and an optional stop channel, and returns
|
||||
// an EventOrError channel. If an error is ever sent, then no more
|
||||
// events will be sent. If a stop channel is provided, events will stop
|
||||
// being monitored after the stop channel is closed.
|
||||
MonitorEvents(options *MonitorEventsOptions, stopChan <-chan struct{}) (<-chan EventOrError, error)
|
||||
StartMonitorEvents(cb Callback, ec chan error, args ...interface{})
|
||||
StopAllMonitorEvents()
|
||||
StartMonitorStats(id string, cb StatCallback, ec chan error, args ...interface{})
|
||||
StopAllMonitorStats()
|
||||
TagImage(nameOrID string, repo string, tag string, force bool) error
|
||||
Version() (*Version, error)
|
||||
PullImage(name string, auth *AuthConfig) error
|
||||
PushImage(name string, tag string, auth *AuthConfig) error
|
||||
LoadImage(reader io.Reader) error
|
||||
RemoveContainer(id string, force, volumes bool) error
|
||||
ListImages(all bool) ([]*Image, error)
|
||||
RemoveImage(name string, force bool) ([]*ImageDelete, error)
|
||||
SearchImages(query, registry string, auth *AuthConfig) ([]ImageSearch, error)
|
||||
PauseContainer(name string) error
|
||||
UnpauseContainer(name string) error
|
||||
RenameContainer(oldName string, newName string) error
|
||||
ImportImage(source string, repository string, tag string, tar io.Reader) (io.ReadCloser, error)
|
||||
BuildImage(image *BuildImage) (io.ReadCloser, error)
|
||||
ListVolumes() ([]*Volume, error)
|
||||
RemoveVolume(name string) error
|
||||
CreateVolume(request *VolumeCreateRequest) (*Volume, error)
|
||||
ListNetworks(filters string) ([]*NetworkResource, error)
|
||||
InspectNetwork(id string) (*NetworkResource, error)
|
||||
CreateNetwork(config *NetworkCreate) (*NetworkCreateResponse, error)
|
||||
ConnectNetwork(id, container string) error
|
||||
DisconnectNetwork(id, container string, force bool) error
|
||||
RemoveNetwork(id string) error
|
||||
}
|
||||
38
vendor/github.com/samalba/dockerclient/tls.go
generated
vendored
38
vendor/github.com/samalba/dockerclient/tls.go
generated
vendored
@@ -1,38 +0,0 @@
|
||||
package dockerclient
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// TLSConfigFromCertPath returns a configuration based on PEM files in the directory
|
||||
//
|
||||
// path is usually what is set by the environment variable `DOCKER_CERT_PATH`,
|
||||
// or `$HOME/.docker`.
|
||||
func TLSConfigFromCertPath(path string) (*tls.Config, error) {
|
||||
cert, err := ioutil.ReadFile(filepath.Join(path, "cert.pem"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key, err := ioutil.ReadFile(filepath.Join(path, "key.pem"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ca, err := ioutil.ReadFile(filepath.Join(path, "ca.pem"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tlsCert, err := tls.X509KeyPair(cert, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tlsConfig := &tls.Config{Certificates: []tls.Certificate{tlsCert}}
|
||||
tlsConfig.RootCAs = x509.NewCertPool()
|
||||
if !tlsConfig.RootCAs.AppendCertsFromPEM(ca) {
|
||||
return nil, errors.New("Could not add RootCA pem")
|
||||
}
|
||||
return tlsConfig, nil
|
||||
}
|
||||
637
vendor/github.com/samalba/dockerclient/types.go
generated
vendored
637
vendor/github.com/samalba/dockerclient/types.go
generated
vendored
@@ -1,637 +0,0 @@
|
||||
package dockerclient
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/docker/go-units"
|
||||
)
|
||||
|
||||
type ContainerConfig struct {
|
||||
Hostname string
|
||||
Domainname string
|
||||
User string
|
||||
AttachStdin bool
|
||||
AttachStdout bool
|
||||
AttachStderr bool
|
||||
ExposedPorts map[string]struct{}
|
||||
Tty bool
|
||||
OpenStdin bool
|
||||
StdinOnce bool
|
||||
Env []string
|
||||
Cmd []string
|
||||
Image string
|
||||
Volumes map[string]struct{}
|
||||
WorkingDir string
|
||||
Entrypoint []string
|
||||
NetworkDisabled bool
|
||||
MacAddress string
|
||||
OnBuild []string
|
||||
Labels map[string]string
|
||||
StopSignal string
|
||||
|
||||
// FIXME: VolumeDriver have been removed since docker 1.9
|
||||
VolumeDriver string
|
||||
|
||||
// FIXME: The following fields have been removed since API v1.18
|
||||
Memory int64
|
||||
MemorySwap int64
|
||||
CpuShares int64
|
||||
Cpuset string
|
||||
PortSpecs []string
|
||||
|
||||
// This is used only by the create command
|
||||
HostConfig HostConfig
|
||||
|
||||
// Network configuration support
|
||||
NetworkingConfig NetworkingConfig
|
||||
}
|
||||
|
||||
type HostConfig struct {
|
||||
Binds []string
|
||||
ContainerIDFile string
|
||||
LxcConf []map[string]string
|
||||
Memory int64
|
||||
MemoryReservation int64
|
||||
MemorySwap int64
|
||||
KernelMemory int64
|
||||
CpuShares int64
|
||||
CpuPeriod int64
|
||||
CpusetCpus string
|
||||
CpusetMems string
|
||||
CpuQuota int64
|
||||
BlkioWeight int64
|
||||
OomKillDisable bool
|
||||
MemorySwappiness int64
|
||||
Privileged bool
|
||||
PortBindings map[string][]PortBinding
|
||||
Links []string
|
||||
PublishAllPorts bool
|
||||
Dns []string
|
||||
DNSOptions []string
|
||||
DnsSearch []string
|
||||
ExtraHosts []string
|
||||
VolumesFrom []string
|
||||
Devices []DeviceMapping
|
||||
NetworkMode string
|
||||
IpcMode string
|
||||
PidMode string
|
||||
UTSMode string
|
||||
CapAdd []string
|
||||
CapDrop []string
|
||||
GroupAdd []string
|
||||
RestartPolicy RestartPolicy
|
||||
SecurityOpt []string
|
||||
ReadonlyRootfs bool
|
||||
Ulimits []Ulimit
|
||||
LogConfig LogConfig
|
||||
CgroupParent string
|
||||
ConsoleSize [2]int
|
||||
VolumeDriver string
|
||||
OomScoreAdj int
|
||||
Tmpfs map[string]string
|
||||
ShmSize int64 `json:"omitempty"`
|
||||
BlkioWeightDevice []WeightDevice
|
||||
BlkioDeviceReadBps []ThrottleDevice
|
||||
BlkioDeviceWriteBps []ThrottleDevice
|
||||
BlkioDeviceReadIOps []ThrottleDevice
|
||||
BlkioDeviceWriteIOps []ThrottleDevice
|
||||
}
|
||||
|
||||
type WeightDevice struct {
|
||||
Path string
|
||||
Weight uint16
|
||||
}
|
||||
|
||||
type ThrottleDevice struct {
|
||||
Path string
|
||||
Rate uint64
|
||||
}
|
||||
|
||||
type DeviceMapping struct {
|
||||
PathOnHost string `json:"PathOnHost"`
|
||||
PathInContainer string `json:"PathInContainer"`
|
||||
CgroupPermissions string `json:"CgroupPermissions"`
|
||||
}
|
||||
|
||||
type ExecConfig struct {
|
||||
AttachStdin bool
|
||||
AttachStdout bool
|
||||
AttachStderr bool
|
||||
Tty bool
|
||||
Cmd []string
|
||||
Container string
|
||||
Detach bool
|
||||
}
|
||||
|
||||
type LogOptions struct {
|
||||
Follow bool
|
||||
Stdout bool
|
||||
Stderr bool
|
||||
Timestamps bool
|
||||
Tail int64
|
||||
}
|
||||
|
||||
type AttachOptions struct {
|
||||
Logs bool
|
||||
Stream bool
|
||||
Stdin bool
|
||||
Stdout bool
|
||||
Stderr bool
|
||||
}
|
||||
|
||||
type MonitorEventsFilters struct {
|
||||
Event string `json:",omitempty"`
|
||||
Image string `json:",omitempty"`
|
||||
Container string `json:",omitempty"`
|
||||
}
|
||||
|
||||
type MonitorEventsOptions struct {
|
||||
Since int
|
||||
Until int
|
||||
Filters *MonitorEventsFilters `json:",omitempty"`
|
||||
}
|
||||
|
||||
type RestartPolicy struct {
|
||||
Name string
|
||||
MaximumRetryCount int64
|
||||
}
|
||||
|
||||
type PortBinding struct {
|
||||
HostIp string
|
||||
HostPort string
|
||||
}
|
||||
|
||||
type State struct {
|
||||
Running bool
|
||||
Paused bool
|
||||
Restarting bool
|
||||
OOMKilled bool
|
||||
Dead bool
|
||||
Pid int
|
||||
ExitCode int
|
||||
Error string // contains last known error when starting the container
|
||||
StartedAt time.Time
|
||||
FinishedAt time.Time
|
||||
Ghost bool
|
||||
}
|
||||
|
||||
// String returns a human-readable description of the state
|
||||
// Stoken from docker/docker/daemon/state.go
|
||||
func (s *State) String() string {
|
||||
if s.Running {
|
||||
if s.Paused {
|
||||
return fmt.Sprintf("Up %s (Paused)", units.HumanDuration(time.Now().UTC().Sub(s.StartedAt)))
|
||||
}
|
||||
if s.Restarting {
|
||||
return fmt.Sprintf("Restarting (%d) %s ago", s.ExitCode, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt)))
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Up %s", units.HumanDuration(time.Now().UTC().Sub(s.StartedAt)))
|
||||
}
|
||||
|
||||
if s.Dead {
|
||||
return "Dead"
|
||||
}
|
||||
|
||||
if s.StartedAt.IsZero() {
|
||||
return "Created"
|
||||
}
|
||||
|
||||
if s.FinishedAt.IsZero() {
|
||||
return ""
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Exited (%d) %s ago", s.ExitCode, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt)))
|
||||
}
|
||||
|
||||
// StateString returns a single string to describe state
|
||||
// Stoken from docker/docker/daemon/state.go
|
||||
func (s *State) StateString() string {
|
||||
if s.Running {
|
||||
if s.Paused {
|
||||
return "paused"
|
||||
}
|
||||
if s.Restarting {
|
||||
return "restarting"
|
||||
}
|
||||
return "running"
|
||||
}
|
||||
|
||||
if s.Dead {
|
||||
return "dead"
|
||||
}
|
||||
|
||||
if s.StartedAt.IsZero() {
|
||||
return "created"
|
||||
}
|
||||
|
||||
return "exited"
|
||||
}
|
||||
|
||||
type ImageInfo struct {
|
||||
Architecture string
|
||||
Author string
|
||||
Comment string
|
||||
Config *ContainerConfig
|
||||
Container string
|
||||
ContainerConfig *ContainerConfig
|
||||
Created time.Time
|
||||
DockerVersion string
|
||||
Id string
|
||||
Os string
|
||||
Parent string
|
||||
Size int64
|
||||
VirtualSize int64
|
||||
}
|
||||
|
||||
type ImageSearch struct {
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
IsOfficial bool `json:"is_official,omitempty" yaml:"is_official,omitempty"`
|
||||
IsAutomated bool `json:"is_automated,omitempty" yaml:"is_automated,omitempty"`
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
StarCount int `json:"star_count,omitempty" yaml:"star_count,omitempty"`
|
||||
}
|
||||
|
||||
type ContainerInfo struct {
|
||||
Id string
|
||||
Created string
|
||||
Path string
|
||||
Name string
|
||||
Args []string
|
||||
ExecIDs []string
|
||||
Config *ContainerConfig
|
||||
State *State
|
||||
Image string
|
||||
NetworkSettings struct {
|
||||
IPAddress string `json:"IpAddress"`
|
||||
IPPrefixLen int `json:"IpPrefixLen"`
|
||||
Gateway string
|
||||
Bridge string
|
||||
Ports map[string][]PortBinding
|
||||
Networks map[string]*EndpointSettings
|
||||
}
|
||||
SysInitPath string
|
||||
ResolvConfPath string
|
||||
Volumes map[string]string
|
||||
HostConfig *HostConfig
|
||||
}
|
||||
|
||||
type ContainerChanges struct {
|
||||
Path string
|
||||
Kind int
|
||||
}
|
||||
|
||||
type Port struct {
|
||||
IP string
|
||||
PrivatePort int
|
||||
PublicPort int
|
||||
Type string
|
||||
}
|
||||
|
||||
// EndpointSettings stores the network endpoint details
|
||||
type EndpointSettings struct {
|
||||
// Configurations
|
||||
IPAMConfig *EndpointIPAMConfig
|
||||
Links []string
|
||||
Aliases []string
|
||||
// Operational data
|
||||
NetworkID string
|
||||
EndpointID string
|
||||
Gateway string
|
||||
IPAddress string
|
||||
IPPrefixLen int
|
||||
IPv6Gateway string
|
||||
GlobalIPv6Address string
|
||||
GlobalIPv6PrefixLen int
|
||||
MacAddress string
|
||||
}
|
||||
|
||||
// NetworkingConfig represents the container's networking configuration for each of its interfaces
|
||||
// Carries the networink configs specified in the `docker run` and `docker network connect` commands
|
||||
type NetworkingConfig struct {
|
||||
EndpointsConfig map[string]*EndpointSettings // Endpoint configs for each conencting network
|
||||
}
|
||||
|
||||
type Container struct {
|
||||
Id string
|
||||
Names []string
|
||||
Image string
|
||||
Command string
|
||||
Created int64
|
||||
Status string
|
||||
Ports []Port
|
||||
SizeRw int64
|
||||
SizeRootFs int64
|
||||
Labels map[string]string
|
||||
NetworkSettings struct {
|
||||
Networks map[string]EndpointSettings
|
||||
}
|
||||
}
|
||||
|
||||
type Actor struct {
|
||||
ID string
|
||||
Attributes map[string]string
|
||||
}
|
||||
|
||||
type Event struct {
|
||||
Status string `json:"status,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
From string `json:"from,omitempty"`
|
||||
|
||||
Type string
|
||||
Action string
|
||||
Actor Actor
|
||||
|
||||
Time int64 `json:"time,omitempty"`
|
||||
TimeNano int64 `json:"timeNano,omitempty"`
|
||||
}
|
||||
|
||||
type Version struct {
|
||||
ApiVersion string
|
||||
Arch string
|
||||
GitCommit string
|
||||
GoVersion string
|
||||
KernelVersion string
|
||||
Os string
|
||||
Version string
|
||||
}
|
||||
|
||||
type RespContainersCreate struct {
|
||||
Id string
|
||||
Warnings []string
|
||||
}
|
||||
|
||||
type Image struct {
|
||||
Created int64
|
||||
Id string
|
||||
Labels map[string]string
|
||||
ParentId string
|
||||
RepoDigests []string
|
||||
RepoTags []string
|
||||
Size int64
|
||||
VirtualSize int64
|
||||
}
|
||||
|
||||
// Info is the struct returned by /info
|
||||
// The API is currently in flux, so Debug, MemoryLimit, SwapLimit, and
|
||||
// IPv4Forwarding are interfaces because in docker 1.6.1 they are 0 or 1 but in
|
||||
// master they are bools.
|
||||
type Info struct {
|
||||
ID string
|
||||
Containers int64
|
||||
Driver string
|
||||
DriverStatus [][]string
|
||||
ExecutionDriver string
|
||||
Images int64
|
||||
KernelVersion string
|
||||
OperatingSystem string
|
||||
NCPU int64
|
||||
MemTotal int64
|
||||
Name string
|
||||
Labels []string
|
||||
Debug interface{}
|
||||
NFd int64
|
||||
NGoroutines int64
|
||||
SystemTime string
|
||||
NEventsListener int64
|
||||
InitPath string
|
||||
InitSha1 string
|
||||
IndexServerAddress string
|
||||
MemoryLimit interface{}
|
||||
SwapLimit interface{}
|
||||
IPv4Forwarding interface{}
|
||||
BridgeNfIptables bool
|
||||
BridgeNfIp6tables bool
|
||||
DockerRootDir string
|
||||
HttpProxy string
|
||||
HttpsProxy string
|
||||
NoProxy string
|
||||
}
|
||||
|
||||
type ImageDelete struct {
|
||||
Deleted string
|
||||
Untagged string
|
||||
}
|
||||
|
||||
type StatsOrError struct {
|
||||
Stats
|
||||
Error error
|
||||
}
|
||||
|
||||
type EventOrError struct {
|
||||
Event
|
||||
Error error
|
||||
}
|
||||
|
||||
type WaitResult struct {
|
||||
ExitCode int
|
||||
Error error
|
||||
}
|
||||
|
||||
type decodingResult struct {
|
||||
result interface{}
|
||||
err error
|
||||
}
|
||||
|
||||
// The following are types for the API stats endpoint
|
||||
type ThrottlingData struct {
|
||||
// Number of periods with throttling active
|
||||
Periods uint64 `json:"periods"`
|
||||
// Number of periods when the container hit its throttling limit.
|
||||
ThrottledPeriods uint64 `json:"throttled_periods"`
|
||||
// Aggregate time the container was throttled for in nanoseconds.
|
||||
ThrottledTime uint64 `json:"throttled_time"`
|
||||
}
|
||||
|
||||
// All CPU stats are aggregated since container inception.
|
||||
type CpuUsage struct {
|
||||
// Total CPU time consumed.
|
||||
// Units: nanoseconds.
|
||||
TotalUsage uint64 `json:"total_usage"`
|
||||
// Total CPU time consumed per core.
|
||||
// Units: nanoseconds.
|
||||
PercpuUsage []uint64 `json:"percpu_usage"`
|
||||
// Time spent by tasks of the cgroup in kernel mode.
|
||||
// Units: nanoseconds.
|
||||
UsageInKernelmode uint64 `json:"usage_in_kernelmode"`
|
||||
// Time spent by tasks of the cgroup in user mode.
|
||||
// Units: nanoseconds.
|
||||
UsageInUsermode uint64 `json:"usage_in_usermode"`
|
||||
}
|
||||
|
||||
type CpuStats struct {
|
||||
CpuUsage CpuUsage `json:"cpu_usage"`
|
||||
SystemUsage uint64 `json:"system_cpu_usage"`
|
||||
ThrottlingData ThrottlingData `json:"throttling_data,omitempty"`
|
||||
}
|
||||
|
||||
type NetworkStats struct {
|
||||
RxBytes uint64 `json:"rx_bytes"`
|
||||
RxPackets uint64 `json:"rx_packets"`
|
||||
RxErrors uint64 `json:"rx_errors"`
|
||||
RxDropped uint64 `json:"rx_dropped"`
|
||||
TxBytes uint64 `json:"tx_bytes"`
|
||||
TxPackets uint64 `json:"tx_packets"`
|
||||
TxErrors uint64 `json:"tx_errors"`
|
||||
TxDropped uint64 `json:"tx_dropped"`
|
||||
}
|
||||
|
||||
type MemoryStats struct {
|
||||
Usage uint64 `json:"usage"`
|
||||
MaxUsage uint64 `json:"max_usage"`
|
||||
Stats map[string]uint64 `json:"stats"`
|
||||
Failcnt uint64 `json:"failcnt"`
|
||||
Limit uint64 `json:"limit"`
|
||||
}
|
||||
|
||||
type BlkioStatEntry struct {
|
||||
Major uint64 `json:"major"`
|
||||
Minor uint64 `json:"minor"`
|
||||
Op string `json:"op"`
|
||||
Value uint64 `json:"value"`
|
||||
}
|
||||
|
||||
type BlkioStats struct {
|
||||
// number of bytes tranferred to and from the block device
|
||||
IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive"`
|
||||
IoServicedRecursive []BlkioStatEntry `json:"io_serviced_recursive"`
|
||||
IoQueuedRecursive []BlkioStatEntry `json:"io_queue_recursive"`
|
||||
IoServiceTimeRecursive []BlkioStatEntry `json:"io_service_time_recursive"`
|
||||
IoWaitTimeRecursive []BlkioStatEntry `json:"io_wait_time_recursive"`
|
||||
IoMergedRecursive []BlkioStatEntry `json:"io_merged_recursive"`
|
||||
IoTimeRecursive []BlkioStatEntry `json:"io_time_recursive"`
|
||||
SectorsRecursive []BlkioStatEntry `json:"sectors_recursive"`
|
||||
}
|
||||
|
||||
type Stats struct {
|
||||
Read time.Time `json:"read"`
|
||||
NetworkStats NetworkStats `json:"network,omitempty"`
|
||||
CpuStats CpuStats `json:"cpu_stats,omitempty"`
|
||||
MemoryStats MemoryStats `json:"memory_stats,omitempty"`
|
||||
BlkioStats BlkioStats `json:"blkio_stats,omitempty"`
|
||||
}
|
||||
|
||||
type Ulimit struct {
|
||||
Name string `json:"name"`
|
||||
Soft uint64 `json:"soft"`
|
||||
Hard uint64 `json:"hard"`
|
||||
}
|
||||
|
||||
type LogConfig struct {
|
||||
Type string `json:"type"`
|
||||
Config map[string]string `json:"config"`
|
||||
}
|
||||
|
||||
type BuildImage struct {
|
||||
Config *ConfigFile
|
||||
DockerfileName string
|
||||
Context io.Reader
|
||||
RemoteURL string
|
||||
RepoName string
|
||||
SuppressOutput bool
|
||||
NoCache bool
|
||||
Remove bool
|
||||
ForceRemove bool
|
||||
Pull bool
|
||||
Memory int64
|
||||
MemorySwap int64
|
||||
CpuShares int64
|
||||
CpuPeriod int64
|
||||
CpuQuota int64
|
||||
CpuSetCpus string
|
||||
CpuSetMems string
|
||||
CgroupParent string
|
||||
BuildArgs map[string]string
|
||||
Labels map[string]string // Labels hold metadata about the image
|
||||
}
|
||||
|
||||
type Volume struct {
|
||||
Name string // Name is the name of the volume
|
||||
Driver string // Driver is the Driver name used to create the volume
|
||||
Mountpoint string // Mountpoint is the location on disk of the volume
|
||||
Labels map[string]string // Labels hold metadata about the volume
|
||||
}
|
||||
|
||||
type VolumesListResponse struct {
|
||||
Volumes []*Volume // Volumes is the list of volumes being returned
|
||||
}
|
||||
|
||||
type VolumeCreateRequest struct {
|
||||
Name string // Name is the requested name of the volume
|
||||
Driver string // Driver is the name of the driver that should be used to create the volume
|
||||
DriverOpts map[string]string // DriverOpts holds the driver specific options to use for when creating the volume.
|
||||
Labels map[string]string // Labels hold metadata about the volume
|
||||
}
|
||||
|
||||
// IPAM represents IP Address Management
|
||||
type IPAM struct {
|
||||
Driver string
|
||||
Options map[string]string //Per network IPAM driver options
|
||||
Config []IPAMConfig
|
||||
}
|
||||
|
||||
// IPAMConfig represents IPAM configurations
|
||||
type IPAMConfig struct {
|
||||
Subnet string `json:",omitempty"`
|
||||
IPRange string `json:",omitempty"`
|
||||
Gateway string `json:",omitempty"`
|
||||
AuxAddress map[string]string `json:"AuxiliaryAddresses,omitempty"`
|
||||
}
|
||||
|
||||
// EndpointIPAMConfig represents IPAM configurations for the endpoint
|
||||
type EndpointIPAMConfig struct {
|
||||
IPv4Address string `json:",omitempty"`
|
||||
IPv6Address string `json:",omitempty"`
|
||||
}
|
||||
|
||||
// NetworkResource is the body of the "get network" http response message
|
||||
type NetworkResource struct {
|
||||
Name string
|
||||
ID string `json:"Id"`
|
||||
Scope string
|
||||
Driver string
|
||||
IPAM IPAM
|
||||
//Internal bool
|
||||
Containers map[string]EndpointResource
|
||||
Options map[string]string
|
||||
Labels map[string]string // Labels hold metadata about the network
|
||||
}
|
||||
|
||||
// EndpointResource contains network resources allocated and used for a container in a network
|
||||
type EndpointResource struct {
|
||||
Name string
|
||||
EndpointID string
|
||||
MacAddress string
|
||||
IPv4Address string
|
||||
IPv6Address string
|
||||
}
|
||||
|
||||
// NetworkCreate is the expected body of the "create network" http request message
|
||||
type NetworkCreate struct {
|
||||
Name string
|
||||
CheckDuplicate bool
|
||||
Driver string
|
||||
IPAM IPAM
|
||||
Internal bool
|
||||
Options map[string]string
|
||||
Labels map[string]string // Labels hold metadata about the network
|
||||
}
|
||||
|
||||
// NetworkCreateResponse is the response message sent by the server for network create call
|
||||
type NetworkCreateResponse struct {
|
||||
ID string `json:"Id"`
|
||||
Warning string
|
||||
}
|
||||
|
||||
// NetworkConnect represents the data to be used to connect a container to the network
|
||||
type NetworkConnect struct {
|
||||
Container string
|
||||
}
|
||||
|
||||
// NetworkDisconnect represents the data to be used to disconnect a container from the network
|
||||
type NetworkDisconnect struct {
|
||||
Container string
|
||||
Force bool
|
||||
}
|
||||
41
vendor/github.com/samalba/dockerclient/utils.go
generated
vendored
41
vendor/github.com/samalba/dockerclient/utils.go
generated
vendored
@@ -1,41 +0,0 @@
|
||||
package dockerclient
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
type tcpFunc func(*net.TCPConn, time.Duration) error
|
||||
|
||||
func newHTTPClient(u *url.URL, tlsConfig *tls.Config, timeout time.Duration, setUserTimeout tcpFunc) *http.Client {
|
||||
httpTransport := &http.Transport{
|
||||
TLSClientConfig: tlsConfig,
|
||||
}
|
||||
|
||||
switch u.Scheme {
|
||||
default:
|
||||
httpTransport.Dial = func(proto, addr string) (net.Conn, error) {
|
||||
conn, err := net.DialTimeout(proto, addr, timeout)
|
||||
if tcpConn, ok := conn.(*net.TCPConn); ok && setUserTimeout != nil {
|
||||
// Sender can break TCP connection if the remote side doesn't
|
||||
// acknowledge packets within timeout
|
||||
setUserTimeout(tcpConn, timeout)
|
||||
}
|
||||
return conn, err
|
||||
}
|
||||
case "unix":
|
||||
socketPath := u.Path
|
||||
unixDial := func(proto, addr string) (net.Conn, error) {
|
||||
return net.DialTimeout("unix", socketPath, timeout)
|
||||
}
|
||||
httpTransport.Dial = unixDial
|
||||
// Override the main URL object so the HTTP lib won't complain
|
||||
u.Scheme = "http"
|
||||
u.Host = "unix.sock"
|
||||
u.Path = ""
|
||||
}
|
||||
return &http.Client{Transport: httpTransport}
|
||||
}
|
||||
392
vendor/github.com/urfave/cli/CHANGELOG.md
generated
vendored
Normal file
392
vendor/github.com/urfave/cli/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,392 @@
|
||||
# Change Log
|
||||
|
||||
**ATTN**: This project uses [semantic versioning](http://semver.org/).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [1.19.1] - 2016-11-21
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixes regression introduced in 1.19.0 where using an `ActionFunc` as
|
||||
the `Action` for a command would cause it to error rather than calling the
|
||||
function. Should not have a affected declarative cases using `func(c
|
||||
*cli.Context) err)`.
|
||||
- Shell completion now handles the case where the user specifies
|
||||
`--generate-bash-completion` immediately after a flag that takes an argument.
|
||||
Previously it call the application with `--generate-bash-completion` as the
|
||||
flag value.
|
||||
|
||||
## [1.19.0] - 2016-11-19
|
||||
### Added
|
||||
- `FlagsByName` was added to make it easy to sort flags (e.g. `sort.Sort(cli.FlagsByName(app.Flags))`)
|
||||
- A `Description` field was added to `App` for a more detailed description of
|
||||
the application (similar to the existing `Description` field on `Command`)
|
||||
- Flag type code generation via `go generate`
|
||||
- Write to stderr and exit 1 if action returns non-nil error
|
||||
- Added support for TOML to the `altsrc` loader
|
||||
- `SkipArgReorder` was added to allow users to skip the argument reordering.
|
||||
This is useful if you want to consider all "flags" after an argument as
|
||||
arguments rather than flags (the default behavior of the stdlib `flag`
|
||||
library). This is backported functionality from the [removal of the flag
|
||||
reordering](https://github.com/urfave/cli/pull/398) in the unreleased version
|
||||
2
|
||||
- For formatted errors (those implementing `ErrorFormatter`), the errors will
|
||||
be formatted during output. Compatible with `pkg/errors`.
|
||||
|
||||
### Changed
|
||||
- Raise minimum tested/supported Go version to 1.2+
|
||||
|
||||
### Fixed
|
||||
- Consider empty environment variables as set (previously environment variables
|
||||
with the equivalent of `""` would be skipped rather than their value used).
|
||||
- Return an error if the value in a given environment variable cannot be parsed
|
||||
as the flag type. Previously these errors were silently swallowed.
|
||||
- Print full error when an invalid flag is specified (which includes the invalid flag)
|
||||
- `App.Writer` defaults to `stdout` when `nil`
|
||||
- If no action is specified on a command or app, the help is now printed instead of `panic`ing
|
||||
- `App.Metadata` is initialized automatically now (previously was `nil` unless initialized)
|
||||
- Correctly show help message if `-h` is provided to a subcommand
|
||||
- `context.(Global)IsSet` now respects environment variables. Previously it
|
||||
would return `false` if a flag was specified in the environment rather than
|
||||
as an argument
|
||||
- Removed deprecation warnings to STDERR to avoid them leaking to the end-user
|
||||
- `altsrc`s import paths were updated to use `gopkg.in/urfave/cli.v1`. This
|
||||
fixes issues that occurred when `gopkg.in/urfave/cli.v1` was imported as well
|
||||
as `altsrc` where Go would complain that the types didn't match
|
||||
|
||||
## [1.18.1] - 2016-08-28
|
||||
### Fixed
|
||||
- Removed deprecation warnings to STDERR to avoid them leaking to the end-user (backported)
|
||||
|
||||
## [1.18.0] - 2016-06-27
|
||||
### Added
|
||||
- `./runtests` test runner with coverage tracking by default
|
||||
- testing on OS X
|
||||
- testing on Windows
|
||||
- `UintFlag`, `Uint64Flag`, and `Int64Flag` types and supporting code
|
||||
|
||||
### Changed
|
||||
- Use spaces for alignment in help/usage output instead of tabs, making the
|
||||
output alignment consistent regardless of tab width
|
||||
|
||||
### Fixed
|
||||
- Printing of command aliases in help text
|
||||
- Printing of visible flags for both struct and struct pointer flags
|
||||
- Display the `help` subcommand when using `CommandCategories`
|
||||
- No longer swallows `panic`s that occur within the `Action`s themselves when
|
||||
detecting the signature of the `Action` field
|
||||
|
||||
## [1.17.1] - 2016-08-28
|
||||
### Fixed
|
||||
- Removed deprecation warnings to STDERR to avoid them leaking to the end-user
|
||||
|
||||
## [1.17.0] - 2016-05-09
|
||||
### Added
|
||||
- Pluggable flag-level help text rendering via `cli.DefaultFlagStringFunc`
|
||||
- `context.GlobalBoolT` was added as an analogue to `context.GlobalBool`
|
||||
- Support for hiding commands by setting `Hidden: true` -- this will hide the
|
||||
commands in help output
|
||||
|
||||
### Changed
|
||||
- `Float64Flag`, `IntFlag`, and `DurationFlag` default values are no longer
|
||||
quoted in help text output.
|
||||
- All flag types now include `(default: {value})` strings following usage when a
|
||||
default value can be (reasonably) detected.
|
||||
- `IntSliceFlag` and `StringSliceFlag` usage strings are now more consistent
|
||||
with non-slice flag types
|
||||
- Apps now exit with a code of 3 if an unknown subcommand is specified
|
||||
(previously they printed "No help topic for...", but still exited 0. This
|
||||
makes it easier to script around apps built using `cli` since they can trust
|
||||
that a 0 exit code indicated a successful execution.
|
||||
- cleanups based on [Go Report Card
|
||||
feedback](https://goreportcard.com/report/github.com/urfave/cli)
|
||||
|
||||
## [1.16.1] - 2016-08-28
|
||||
### Fixed
|
||||
- Removed deprecation warnings to STDERR to avoid them leaking to the end-user
|
||||
|
||||
## [1.16.0] - 2016-05-02
|
||||
### Added
|
||||
- `Hidden` field on all flag struct types to omit from generated help text
|
||||
|
||||
### Changed
|
||||
- `BashCompletionFlag` (`--enable-bash-completion`) is now omitted from
|
||||
generated help text via the `Hidden` field
|
||||
|
||||
### Fixed
|
||||
- handling of error values in `HandleAction` and `HandleExitCoder`
|
||||
|
||||
## [1.15.0] - 2016-04-30
|
||||
### Added
|
||||
- This file!
|
||||
- Support for placeholders in flag usage strings
|
||||
- `App.Metadata` map for arbitrary data/state management
|
||||
- `Set` and `GlobalSet` methods on `*cli.Context` for altering values after
|
||||
parsing.
|
||||
- Support for nested lookup of dot-delimited keys in structures loaded from
|
||||
YAML.
|
||||
|
||||
### Changed
|
||||
- The `App.Action` and `Command.Action` now prefer a return signature of
|
||||
`func(*cli.Context) error`, as defined by `cli.ActionFunc`. If a non-nil
|
||||
`error` is returned, there may be two outcomes:
|
||||
- If the error fulfills `cli.ExitCoder`, then `os.Exit` will be called
|
||||
automatically
|
||||
- Else the error is bubbled up and returned from `App.Run`
|
||||
- Specifying an `Action` with the legacy return signature of
|
||||
`func(*cli.Context)` will produce a deprecation message to stderr
|
||||
- Specifying an `Action` that is not a `func` type will produce a non-zero exit
|
||||
from `App.Run`
|
||||
- Specifying an `Action` func that has an invalid (input) signature will
|
||||
produce a non-zero exit from `App.Run`
|
||||
|
||||
### Deprecated
|
||||
- <a name="deprecated-cli-app-runandexitonerror"></a>
|
||||
`cli.App.RunAndExitOnError`, which should now be done by returning an error
|
||||
that fulfills `cli.ExitCoder` to `cli.App.Run`.
|
||||
- <a name="deprecated-cli-app-action-signature"></a> the legacy signature for
|
||||
`cli.App.Action` of `func(*cli.Context)`, which should now have a return
|
||||
signature of `func(*cli.Context) error`, as defined by `cli.ActionFunc`.
|
||||
|
||||
### Fixed
|
||||
- Added missing `*cli.Context.GlobalFloat64` method
|
||||
|
||||
## [1.14.0] - 2016-04-03 (backfilled 2016-04-25)
|
||||
### Added
|
||||
- Codebeat badge
|
||||
- Support for categorization via `CategorizedHelp` and `Categories` on app.
|
||||
|
||||
### Changed
|
||||
- Use `filepath.Base` instead of `path.Base` in `Name` and `HelpName`.
|
||||
|
||||
### Fixed
|
||||
- Ensure version is not shown in help text when `HideVersion` set.
|
||||
|
||||
## [1.13.0] - 2016-03-06 (backfilled 2016-04-25)
|
||||
### Added
|
||||
- YAML file input support.
|
||||
- `NArg` method on context.
|
||||
|
||||
## [1.12.0] - 2016-02-17 (backfilled 2016-04-25)
|
||||
### Added
|
||||
- Custom usage error handling.
|
||||
- Custom text support in `USAGE` section of help output.
|
||||
- Improved help messages for empty strings.
|
||||
- AppVeyor CI configuration.
|
||||
|
||||
### Changed
|
||||
- Removed `panic` from default help printer func.
|
||||
- De-duping and optimizations.
|
||||
|
||||
### Fixed
|
||||
- Correctly handle `Before`/`After` at command level when no subcommands.
|
||||
- Case of literal `-` argument causing flag reordering.
|
||||
- Environment variable hints on Windows.
|
||||
- Docs updates.
|
||||
|
||||
## [1.11.1] - 2015-12-21 (backfilled 2016-04-25)
|
||||
### Changed
|
||||
- Use `path.Base` in `Name` and `HelpName`
|
||||
- Export `GetName` on flag types.
|
||||
|
||||
### Fixed
|
||||
- Flag parsing when skipping is enabled.
|
||||
- Test output cleanup.
|
||||
- Move completion check to account for empty input case.
|
||||
|
||||
## [1.11.0] - 2015-11-15 (backfilled 2016-04-25)
|
||||
### Added
|
||||
- Destination scan support for flags.
|
||||
- Testing against `tip` in Travis CI config.
|
||||
|
||||
### Changed
|
||||
- Go version in Travis CI config.
|
||||
|
||||
### Fixed
|
||||
- Removed redundant tests.
|
||||
- Use correct example naming in tests.
|
||||
|
||||
## [1.10.2] - 2015-10-29 (backfilled 2016-04-25)
|
||||
### Fixed
|
||||
- Remove unused var in bash completion.
|
||||
|
||||
## [1.10.1] - 2015-10-21 (backfilled 2016-04-25)
|
||||
### Added
|
||||
- Coverage and reference logos in README.
|
||||
|
||||
### Fixed
|
||||
- Use specified values in help and version parsing.
|
||||
- Only display app version and help message once.
|
||||
|
||||
## [1.10.0] - 2015-10-06 (backfilled 2016-04-25)
|
||||
### Added
|
||||
- More tests for existing functionality.
|
||||
- `ArgsUsage` at app and command level for help text flexibility.
|
||||
|
||||
### Fixed
|
||||
- Honor `HideHelp` and `HideVersion` in `App.Run`.
|
||||
- Remove juvenile word from README.
|
||||
|
||||
## [1.9.0] - 2015-09-08 (backfilled 2016-04-25)
|
||||
### Added
|
||||
- `FullName` on command with accompanying help output update.
|
||||
- Set default `$PROG` in bash completion.
|
||||
|
||||
### Changed
|
||||
- Docs formatting.
|
||||
|
||||
### Fixed
|
||||
- Removed self-referential imports in tests.
|
||||
|
||||
## [1.8.0] - 2015-06-30 (backfilled 2016-04-25)
|
||||
### Added
|
||||
- Support for `Copyright` at app level.
|
||||
- `Parent` func at context level to walk up context lineage.
|
||||
|
||||
### Fixed
|
||||
- Global flag processing at top level.
|
||||
|
||||
## [1.7.1] - 2015-06-11 (backfilled 2016-04-25)
|
||||
### Added
|
||||
- Aggregate errors from `Before`/`After` funcs.
|
||||
- Doc comments on flag structs.
|
||||
- Include non-global flags when checking version and help.
|
||||
- Travis CI config updates.
|
||||
|
||||
### Fixed
|
||||
- Ensure slice type flags have non-nil values.
|
||||
- Collect global flags from the full command hierarchy.
|
||||
- Docs prose.
|
||||
|
||||
## [1.7.0] - 2015-05-03 (backfilled 2016-04-25)
|
||||
### Changed
|
||||
- `HelpPrinter` signature includes output writer.
|
||||
|
||||
### Fixed
|
||||
- Specify go 1.1+ in docs.
|
||||
- Set `Writer` when running command as app.
|
||||
|
||||
## [1.6.0] - 2015-03-23 (backfilled 2016-04-25)
|
||||
### Added
|
||||
- Multiple author support.
|
||||
- `NumFlags` at context level.
|
||||
- `Aliases` at command level.
|
||||
|
||||
### Deprecated
|
||||
- `ShortName` at command level.
|
||||
|
||||
### Fixed
|
||||
- Subcommand help output.
|
||||
- Backward compatible support for deprecated `Author` and `Email` fields.
|
||||
- Docs regarding `Names`/`Aliases`.
|
||||
|
||||
## [1.5.0] - 2015-02-20 (backfilled 2016-04-25)
|
||||
### Added
|
||||
- `After` hook func support at app and command level.
|
||||
|
||||
### Fixed
|
||||
- Use parsed context when running command as subcommand.
|
||||
- Docs prose.
|
||||
|
||||
## [1.4.1] - 2015-01-09 (backfilled 2016-04-25)
|
||||
### Added
|
||||
- Support for hiding `-h / --help` flags, but not `help` subcommand.
|
||||
- Stop flag parsing after `--`.
|
||||
|
||||
### Fixed
|
||||
- Help text for generic flags to specify single value.
|
||||
- Use double quotes in output for defaults.
|
||||
- Use `ParseInt` instead of `ParseUint` for int environment var values.
|
||||
- Use `0` as base when parsing int environment var values.
|
||||
|
||||
## [1.4.0] - 2014-12-12 (backfilled 2016-04-25)
|
||||
### Added
|
||||
- Support for environment variable lookup "cascade".
|
||||
- Support for `Stdout` on app for output redirection.
|
||||
|
||||
### Fixed
|
||||
- Print command help instead of app help in `ShowCommandHelp`.
|
||||
|
||||
## [1.3.1] - 2014-11-13 (backfilled 2016-04-25)
|
||||
### Added
|
||||
- Docs and example code updates.
|
||||
|
||||
### Changed
|
||||
- Default `-v / --version` flag made optional.
|
||||
|
||||
## [1.3.0] - 2014-08-10 (backfilled 2016-04-25)
|
||||
### Added
|
||||
- `FlagNames` at context level.
|
||||
- Exposed `VersionPrinter` var for more control over version output.
|
||||
- Zsh completion hook.
|
||||
- `AUTHOR` section in default app help template.
|
||||
- Contribution guidelines.
|
||||
- `DurationFlag` type.
|
||||
|
||||
## [1.2.0] - 2014-08-02
|
||||
### Added
|
||||
- Support for environment variable defaults on flags plus tests.
|
||||
|
||||
## [1.1.0] - 2014-07-15
|
||||
### Added
|
||||
- Bash completion.
|
||||
- Optional hiding of built-in help command.
|
||||
- Optional skipping of flag parsing at command level.
|
||||
- `Author`, `Email`, and `Compiled` metadata on app.
|
||||
- `Before` hook func support at app and command level.
|
||||
- `CommandNotFound` func support at app level.
|
||||
- Command reference available on context.
|
||||
- `GenericFlag` type.
|
||||
- `Float64Flag` type.
|
||||
- `BoolTFlag` type.
|
||||
- `IsSet` flag helper on context.
|
||||
- More flag lookup funcs at context level.
|
||||
- More tests & docs.
|
||||
|
||||
### Changed
|
||||
- Help template updates to account for presence/absence of flags.
|
||||
- Separated subcommand help template.
|
||||
- Exposed `HelpPrinter` var for more control over help output.
|
||||
|
||||
## [1.0.0] - 2013-11-01
|
||||
### Added
|
||||
- `help` flag in default app flag set and each command flag set.
|
||||
- Custom handling of argument parsing errors.
|
||||
- Command lookup by name at app level.
|
||||
- `StringSliceFlag` type and supporting `StringSlice` type.
|
||||
- `IntSliceFlag` type and supporting `IntSlice` type.
|
||||
- Slice type flag lookups by name at context level.
|
||||
- Export of app and command help functions.
|
||||
- More tests & docs.
|
||||
|
||||
## 0.1.0 - 2013-07-22
|
||||
### Added
|
||||
- Initial implementation.
|
||||
|
||||
[Unreleased]: https://github.com/urfave/cli/compare/v1.18.0...HEAD
|
||||
[1.18.0]: https://github.com/urfave/cli/compare/v1.17.0...v1.18.0
|
||||
[1.17.0]: https://github.com/urfave/cli/compare/v1.16.0...v1.17.0
|
||||
[1.16.0]: https://github.com/urfave/cli/compare/v1.15.0...v1.16.0
|
||||
[1.15.0]: https://github.com/urfave/cli/compare/v1.14.0...v1.15.0
|
||||
[1.14.0]: https://github.com/urfave/cli/compare/v1.13.0...v1.14.0
|
||||
[1.13.0]: https://github.com/urfave/cli/compare/v1.12.0...v1.13.0
|
||||
[1.12.0]: https://github.com/urfave/cli/compare/v1.11.1...v1.12.0
|
||||
[1.11.1]: https://github.com/urfave/cli/compare/v1.11.0...v1.11.1
|
||||
[1.11.0]: https://github.com/urfave/cli/compare/v1.10.2...v1.11.0
|
||||
[1.10.2]: https://github.com/urfave/cli/compare/v1.10.1...v1.10.2
|
||||
[1.10.1]: https://github.com/urfave/cli/compare/v1.10.0...v1.10.1
|
||||
[1.10.0]: https://github.com/urfave/cli/compare/v1.9.0...v1.10.0
|
||||
[1.9.0]: https://github.com/urfave/cli/compare/v1.8.0...v1.9.0
|
||||
[1.8.0]: https://github.com/urfave/cli/compare/v1.7.1...v1.8.0
|
||||
[1.7.1]: https://github.com/urfave/cli/compare/v1.7.0...v1.7.1
|
||||
[1.7.0]: https://github.com/urfave/cli/compare/v1.6.0...v1.7.0
|
||||
[1.6.0]: https://github.com/urfave/cli/compare/v1.5.0...v1.6.0
|
||||
[1.5.0]: https://github.com/urfave/cli/compare/v1.4.1...v1.5.0
|
||||
[1.4.1]: https://github.com/urfave/cli/compare/v1.4.0...v1.4.1
|
||||
[1.4.0]: https://github.com/urfave/cli/compare/v1.3.1...v1.4.0
|
||||
[1.3.1]: https://github.com/urfave/cli/compare/v1.3.0...v1.3.1
|
||||
[1.3.0]: https://github.com/urfave/cli/compare/v1.2.0...v1.3.0
|
||||
[1.2.0]: https://github.com/urfave/cli/compare/v1.1.0...v1.2.0
|
||||
[1.1.0]: https://github.com/urfave/cli/compare/v1.0.0...v1.1.0
|
||||
[1.0.0]: https://github.com/urfave/cli/compare/v0.1.0...v1.0.0
|
||||
5
vendor/github.com/djherbis/fscache/LICENSE → vendor/github.com/urfave/cli/LICENSE
generated
vendored
5
vendor/github.com/djherbis/fscache/LICENSE → vendor/github.com/urfave/cli/LICENSE
generated
vendored
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2015 Dustin H
|
||||
Copyright (c) 2016 Jeremy Saenz & Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -19,4 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
1381
vendor/github.com/urfave/cli/README.md
generated
vendored
Normal file
1381
vendor/github.com/urfave/cli/README.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
492
vendor/github.com/urfave/cli/app.go
generated
vendored
Normal file
492
vendor/github.com/urfave/cli/app.go
generated
vendored
Normal file
@@ -0,0 +1,492 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
changeLogURL = "https://github.com/urfave/cli/blob/master/CHANGELOG.md"
|
||||
appActionDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-action-signature", changeLogURL)
|
||||
runAndExitOnErrorDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-runandexitonerror", changeLogURL)
|
||||
|
||||
contactSysadmin = "This is an error in the application. Please contact the distributor of this application if this is not you."
|
||||
|
||||
errInvalidActionType = NewExitError("ERROR invalid Action type. "+
|
||||
fmt.Sprintf("Must be `func(*Context`)` or `func(*Context) error). %s", contactSysadmin)+
|
||||
fmt.Sprintf("See %s", appActionDeprecationURL), 2)
|
||||
)
|
||||
|
||||
// App is the main structure of a cli application. It is recommended that
|
||||
// an app be created with the cli.NewApp() function
|
||||
type App struct {
|
||||
// The name of the program. Defaults to path.Base(os.Args[0])
|
||||
Name string
|
||||
// Full name of command for help, defaults to Name
|
||||
HelpName string
|
||||
// Description of the program.
|
||||
Usage string
|
||||
// Text to override the USAGE section of help
|
||||
UsageText string
|
||||
// Description of the program argument format.
|
||||
ArgsUsage string
|
||||
// Version of the program
|
||||
Version string
|
||||
// Description of the program
|
||||
Description string
|
||||
// List of commands to execute
|
||||
Commands []Command
|
||||
// List of flags to parse
|
||||
Flags []Flag
|
||||
// Boolean to enable bash completion commands
|
||||
EnableBashCompletion bool
|
||||
// Boolean to hide built-in help command
|
||||
HideHelp bool
|
||||
// Boolean to hide built-in version flag and the VERSION section of help
|
||||
HideVersion bool
|
||||
// Populate on app startup, only gettable through method Categories()
|
||||
categories CommandCategories
|
||||
// An action to execute when the bash-completion flag is set
|
||||
BashComplete BashCompleteFunc
|
||||
// An action to execute before any subcommands are run, but after the context is ready
|
||||
// If a non-nil error is returned, no subcommands are run
|
||||
Before BeforeFunc
|
||||
// An action to execute after any subcommands are run, but after the subcommand has finished
|
||||
// It is run even if Action() panics
|
||||
After AfterFunc
|
||||
|
||||
// The action to execute when no subcommands are specified
|
||||
// Expects a `cli.ActionFunc` but will accept the *deprecated* signature of `func(*cli.Context) {}`
|
||||
// *Note*: support for the deprecated `Action` signature will be removed in a future version
|
||||
Action interface{}
|
||||
|
||||
// Execute this function if the proper command cannot be found
|
||||
CommandNotFound CommandNotFoundFunc
|
||||
// Execute this function if an usage error occurs
|
||||
OnUsageError OnUsageErrorFunc
|
||||
// Compilation date
|
||||
Compiled time.Time
|
||||
// List of all authors who contributed
|
||||
Authors []Author
|
||||
// Copyright of the binary if any
|
||||
Copyright string
|
||||
// Name of Author (Note: Use App.Authors, this is deprecated)
|
||||
Author string
|
||||
// Email of Author (Note: Use App.Authors, this is deprecated)
|
||||
Email string
|
||||
// Writer writer to write output to
|
||||
Writer io.Writer
|
||||
// ErrWriter writes error output
|
||||
ErrWriter io.Writer
|
||||
// Other custom info
|
||||
Metadata map[string]interface{}
|
||||
|
||||
didSetup bool
|
||||
}
|
||||
|
||||
// Tries to find out when this binary was compiled.
|
||||
// Returns the current time if it fails to find it.
|
||||
func compileTime() time.Time {
|
||||
info, err := os.Stat(os.Args[0])
|
||||
if err != nil {
|
||||
return time.Now()
|
||||
}
|
||||
return info.ModTime()
|
||||
}
|
||||
|
||||
// NewApp creates a new cli Application with some reasonable defaults for Name,
|
||||
// Usage, Version and Action.
|
||||
func NewApp() *App {
|
||||
return &App{
|
||||
Name: filepath.Base(os.Args[0]),
|
||||
HelpName: filepath.Base(os.Args[0]),
|
||||
Usage: "A new cli application",
|
||||
UsageText: "",
|
||||
Version: "0.0.0",
|
||||
BashComplete: DefaultAppComplete,
|
||||
Action: helpCommand.Action,
|
||||
Compiled: compileTime(),
|
||||
Writer: os.Stdout,
|
||||
}
|
||||
}
|
||||
|
||||
// Setup runs initialization code to ensure all data structures are ready for
|
||||
// `Run` or inspection prior to `Run`. It is internally called by `Run`, but
|
||||
// will return early if setup has already happened.
|
||||
func (a *App) Setup() {
|
||||
if a.didSetup {
|
||||
return
|
||||
}
|
||||
|
||||
a.didSetup = true
|
||||
|
||||
if a.Author != "" || a.Email != "" {
|
||||
a.Authors = append(a.Authors, Author{Name: a.Author, Email: a.Email})
|
||||
}
|
||||
|
||||
newCmds := []Command{}
|
||||
for _, c := range a.Commands {
|
||||
if c.HelpName == "" {
|
||||
c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name)
|
||||
}
|
||||
newCmds = append(newCmds, c)
|
||||
}
|
||||
a.Commands = newCmds
|
||||
|
||||
if a.Command(helpCommand.Name) == nil && !a.HideHelp {
|
||||
a.Commands = append(a.Commands, helpCommand)
|
||||
if (HelpFlag != BoolFlag{}) {
|
||||
a.appendFlag(HelpFlag)
|
||||
}
|
||||
}
|
||||
|
||||
if !a.HideVersion {
|
||||
a.appendFlag(VersionFlag)
|
||||
}
|
||||
|
||||
a.categories = CommandCategories{}
|
||||
for _, command := range a.Commands {
|
||||
a.categories = a.categories.AddCommand(command.Category, command)
|
||||
}
|
||||
sort.Sort(a.categories)
|
||||
|
||||
if a.Metadata == nil {
|
||||
a.Metadata = make(map[string]interface{})
|
||||
}
|
||||
|
||||
if a.Writer == nil {
|
||||
a.Writer = os.Stdout
|
||||
}
|
||||
}
|
||||
|
||||
// Run is the entry point to the cli app. Parses the arguments slice and routes
|
||||
// to the proper flag/args combination
|
||||
func (a *App) Run(arguments []string) (err error) {
|
||||
a.Setup()
|
||||
|
||||
// handle the completion flag separately from the flagset since
|
||||
// completion could be attempted after a flag, but before its value was put
|
||||
// on the command line. this causes the flagset to interpret the completion
|
||||
// flag name as the value of the flag before it which is undesirable
|
||||
// note that we can only do this because the shell autocomplete function
|
||||
// always appends the completion flag at the end of the command
|
||||
shellComplete, arguments := checkShellCompleteFlag(a, arguments)
|
||||
|
||||
// parse flags
|
||||
set, err := flagSet(a.Name, a.Flags)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
set.SetOutput(ioutil.Discard)
|
||||
err = set.Parse(arguments[1:])
|
||||
nerr := normalizeFlags(a.Flags, set)
|
||||
context := NewContext(a, set, nil)
|
||||
if nerr != nil {
|
||||
fmt.Fprintln(a.Writer, nerr)
|
||||
ShowAppHelp(context)
|
||||
return nerr
|
||||
}
|
||||
context.shellComplete = shellComplete
|
||||
|
||||
if checkCompletions(context) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if a.OnUsageError != nil {
|
||||
err := a.OnUsageError(context, err, false)
|
||||
HandleExitCoder(err)
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error())
|
||||
ShowAppHelp(context)
|
||||
return err
|
||||
}
|
||||
|
||||
if !a.HideHelp && checkHelp(context) {
|
||||
ShowAppHelp(context)
|
||||
return nil
|
||||
}
|
||||
|
||||
if !a.HideVersion && checkVersion(context) {
|
||||
ShowVersion(context)
|
||||
return nil
|
||||
}
|
||||
|
||||
if a.After != nil {
|
||||
defer func() {
|
||||
if afterErr := a.After(context); afterErr != nil {
|
||||
if err != nil {
|
||||
err = NewMultiError(err, afterErr)
|
||||
} else {
|
||||
err = afterErr
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
if a.Before != nil {
|
||||
beforeErr := a.Before(context)
|
||||
if beforeErr != nil {
|
||||
fmt.Fprintf(a.Writer, "%v\n\n", beforeErr)
|
||||
ShowAppHelp(context)
|
||||
HandleExitCoder(beforeErr)
|
||||
err = beforeErr
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
args := context.Args()
|
||||
if args.Present() {
|
||||
name := args.First()
|
||||
c := a.Command(name)
|
||||
if c != nil {
|
||||
return c.Run(context)
|
||||
}
|
||||
}
|
||||
|
||||
if a.Action == nil {
|
||||
a.Action = helpCommand.Action
|
||||
}
|
||||
|
||||
// Run default Action
|
||||
err = HandleAction(a.Action, context)
|
||||
|
||||
HandleExitCoder(err)
|
||||
return err
|
||||
}
|
||||
|
||||
// RunAndExitOnError calls .Run() and exits non-zero if an error was returned
|
||||
//
|
||||
// Deprecated: instead you should return an error that fulfills cli.ExitCoder
|
||||
// to cli.App.Run. This will cause the application to exit with the given eror
|
||||
// code in the cli.ExitCoder
|
||||
func (a *App) RunAndExitOnError() {
|
||||
if err := a.Run(os.Args); err != nil {
|
||||
fmt.Fprintln(a.errWriter(), err)
|
||||
OsExiter(1)
|
||||
}
|
||||
}
|
||||
|
||||
// RunAsSubcommand invokes the subcommand given the context, parses ctx.Args() to
|
||||
// generate command-specific flags
|
||||
func (a *App) RunAsSubcommand(ctx *Context) (err error) {
|
||||
// append help to commands
|
||||
if len(a.Commands) > 0 {
|
||||
if a.Command(helpCommand.Name) == nil && !a.HideHelp {
|
||||
a.Commands = append(a.Commands, helpCommand)
|
||||
if (HelpFlag != BoolFlag{}) {
|
||||
a.appendFlag(HelpFlag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newCmds := []Command{}
|
||||
for _, c := range a.Commands {
|
||||
if c.HelpName == "" {
|
||||
c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name)
|
||||
}
|
||||
newCmds = append(newCmds, c)
|
||||
}
|
||||
a.Commands = newCmds
|
||||
|
||||
// parse flags
|
||||
set, err := flagSet(a.Name, a.Flags)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
set.SetOutput(ioutil.Discard)
|
||||
err = set.Parse(ctx.Args().Tail())
|
||||
nerr := normalizeFlags(a.Flags, set)
|
||||
context := NewContext(a, set, ctx)
|
||||
|
||||
if nerr != nil {
|
||||
fmt.Fprintln(a.Writer, nerr)
|
||||
fmt.Fprintln(a.Writer)
|
||||
if len(a.Commands) > 0 {
|
||||
ShowSubcommandHelp(context)
|
||||
} else {
|
||||
ShowCommandHelp(ctx, context.Args().First())
|
||||
}
|
||||
return nerr
|
||||
}
|
||||
|
||||
if checkCompletions(context) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if a.OnUsageError != nil {
|
||||
err = a.OnUsageError(context, err, true)
|
||||
HandleExitCoder(err)
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error())
|
||||
ShowSubcommandHelp(context)
|
||||
return err
|
||||
}
|
||||
|
||||
if len(a.Commands) > 0 {
|
||||
if checkSubcommandHelp(context) {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
if checkCommandHelp(ctx, context.Args().First()) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if a.After != nil {
|
||||
defer func() {
|
||||
afterErr := a.After(context)
|
||||
if afterErr != nil {
|
||||
HandleExitCoder(err)
|
||||
if err != nil {
|
||||
err = NewMultiError(err, afterErr)
|
||||
} else {
|
||||
err = afterErr
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
if a.Before != nil {
|
||||
beforeErr := a.Before(context)
|
||||
if beforeErr != nil {
|
||||
HandleExitCoder(beforeErr)
|
||||
err = beforeErr
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
args := context.Args()
|
||||
if args.Present() {
|
||||
name := args.First()
|
||||
c := a.Command(name)
|
||||
if c != nil {
|
||||
return c.Run(context)
|
||||
}
|
||||
}
|
||||
|
||||
// Run default Action
|
||||
err = HandleAction(a.Action, context)
|
||||
|
||||
HandleExitCoder(err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Command returns the named command on App. Returns nil if the command does not exist
|
||||
func (a *App) Command(name string) *Command {
|
||||
for _, c := range a.Commands {
|
||||
if c.HasName(name) {
|
||||
return &c
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Categories returns a slice containing all the categories with the commands they contain
|
||||
func (a *App) Categories() CommandCategories {
|
||||
return a.categories
|
||||
}
|
||||
|
||||
// VisibleCategories returns a slice of categories and commands that are
|
||||
// Hidden=false
|
||||
func (a *App) VisibleCategories() []*CommandCategory {
|
||||
ret := []*CommandCategory{}
|
||||
for _, category := range a.categories {
|
||||
if visible := func() *CommandCategory {
|
||||
for _, command := range category.Commands {
|
||||
if !command.Hidden {
|
||||
return category
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}(); visible != nil {
|
||||
ret = append(ret, visible)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// VisibleCommands returns a slice of the Commands with Hidden=false
|
||||
func (a *App) VisibleCommands() []Command {
|
||||
ret := []Command{}
|
||||
for _, command := range a.Commands {
|
||||
if !command.Hidden {
|
||||
ret = append(ret, command)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// VisibleFlags returns a slice of the Flags with Hidden=false
|
||||
func (a *App) VisibleFlags() []Flag {
|
||||
return visibleFlags(a.Flags)
|
||||
}
|
||||
|
||||
func (a *App) hasFlag(flag Flag) bool {
|
||||
for _, f := range a.Flags {
|
||||
if flag == f {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *App) errWriter() io.Writer {
|
||||
|
||||
// When the app ErrWriter is nil use the package level one.
|
||||
if a.ErrWriter == nil {
|
||||
return ErrWriter
|
||||
}
|
||||
|
||||
return a.ErrWriter
|
||||
}
|
||||
|
||||
func (a *App) appendFlag(flag Flag) {
|
||||
if !a.hasFlag(flag) {
|
||||
a.Flags = append(a.Flags, flag)
|
||||
}
|
||||
}
|
||||
|
||||
// Author represents someone who has contributed to a cli project.
|
||||
type Author struct {
|
||||
Name string // The Authors name
|
||||
Email string // The Authors email
|
||||
}
|
||||
|
||||
// String makes Author comply to the Stringer interface, to allow an easy print in the templating process
|
||||
func (a Author) String() string {
|
||||
e := ""
|
||||
if a.Email != "" {
|
||||
e = " <" + a.Email + ">"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%v%v", a.Name, e)
|
||||
}
|
||||
|
||||
// HandleAction attempts to figure out which Action signature was used. If
|
||||
// it's an ActionFunc or a func with the legacy signature for Action, the func
|
||||
// is run!
|
||||
func HandleAction(action interface{}, context *Context) (err error) {
|
||||
if a, ok := action.(ActionFunc); ok {
|
||||
return a(context)
|
||||
} else if a, ok := action.(func(*Context) error); ok {
|
||||
return a(context)
|
||||
} else if a, ok := action.(func(*Context)); ok { // deprecated function signature
|
||||
a(context)
|
||||
return nil
|
||||
} else {
|
||||
return errInvalidActionType
|
||||
}
|
||||
}
|
||||
24
vendor/github.com/urfave/cli/appveyor.yml
generated
vendored
Normal file
24
vendor/github.com/urfave/cli/appveyor.yml
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
version: "{build}"
|
||||
|
||||
os: Windows Server 2012 R2
|
||||
|
||||
clone_folder: c:\gopath\src\github.com\urfave\cli
|
||||
|
||||
environment:
|
||||
GOPATH: C:\gopath
|
||||
GOVERSION: 1.6
|
||||
PYTHON: C:\Python27-x64
|
||||
PYTHON_VERSION: 2.7.x
|
||||
PYTHON_ARCH: 64
|
||||
|
||||
install:
|
||||
- set PATH=%GOPATH%\bin;C:\go\bin;%PATH%
|
||||
- go version
|
||||
- go env
|
||||
- go get github.com/urfave/gfmrun/...
|
||||
- go get -v -t ./...
|
||||
|
||||
build_script:
|
||||
- python runtests vet
|
||||
- python runtests test
|
||||
- python runtests gfmrun
|
||||
44
vendor/github.com/urfave/cli/category.go
generated
vendored
Normal file
44
vendor/github.com/urfave/cli/category.go
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
package cli
|
||||
|
||||
// CommandCategories is a slice of *CommandCategory.
|
||||
type CommandCategories []*CommandCategory
|
||||
|
||||
// CommandCategory is a category containing commands.
|
||||
type CommandCategory struct {
|
||||
Name string
|
||||
Commands Commands
|
||||
}
|
||||
|
||||
func (c CommandCategories) Less(i, j int) bool {
|
||||
return c[i].Name < c[j].Name
|
||||
}
|
||||
|
||||
func (c CommandCategories) Len() int {
|
||||
return len(c)
|
||||
}
|
||||
|
||||
func (c CommandCategories) Swap(i, j int) {
|
||||
c[i], c[j] = c[j], c[i]
|
||||
}
|
||||
|
||||
// AddCommand adds a command to a category.
|
||||
func (c CommandCategories) AddCommand(category string, command Command) CommandCategories {
|
||||
for _, commandCategory := range c {
|
||||
if commandCategory.Name == category {
|
||||
commandCategory.Commands = append(commandCategory.Commands, command)
|
||||
return c
|
||||
}
|
||||
}
|
||||
return append(c, &CommandCategory{Name: category, Commands: []Command{command}})
|
||||
}
|
||||
|
||||
// VisibleCommands returns a slice of the Commands with Hidden=false
|
||||
func (c *CommandCategory) VisibleCommands() []Command {
|
||||
ret := []Command{}
|
||||
for _, command := range c.Commands {
|
||||
if !command.Hidden {
|
||||
ret = append(ret, command)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
23
vendor/github.com/codegangsta/cli/cli.go → vendor/github.com/urfave/cli/cli.go
generated
vendored
23
vendor/github.com/codegangsta/cli/cli.go → vendor/github.com/urfave/cli/cli.go
generated
vendored
@@ -10,7 +10,7 @@
|
||||
// app := cli.NewApp()
|
||||
// app.Name = "greet"
|
||||
// app.Usage = "say a greeting"
|
||||
// app.Action = func(c *cli.Context) {
|
||||
// app.Action = func(c *cli.Context) error {
|
||||
// println("Greetings")
|
||||
// }
|
||||
//
|
||||
@@ -18,23 +18,4 @@
|
||||
// }
|
||||
package cli
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type MultiError struct {
|
||||
Errors []error
|
||||
}
|
||||
|
||||
func NewMultiError(err ...error) MultiError {
|
||||
return MultiError{Errors: err}
|
||||
}
|
||||
|
||||
func (m MultiError) Error() string {
|
||||
errs := make([]string, len(m.Errors))
|
||||
for i, err := range m.Errors {
|
||||
errs[i] = err.Error()
|
||||
}
|
||||
|
||||
return strings.Join(errs, "\n")
|
||||
}
|
||||
//go:generate python ./generate-flag-types cli -i flag-types.json -o flag_generated.go
|
||||
300
vendor/github.com/urfave/cli/command.go
generated
vendored
Normal file
300
vendor/github.com/urfave/cli/command.go
generated
vendored
Normal file
@@ -0,0 +1,300 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Command is a subcommand for a cli.App.
|
||||
type Command struct {
|
||||
// The name of the command
|
||||
Name string
|
||||
// short name of the command. Typically one character (deprecated, use `Aliases`)
|
||||
ShortName string
|
||||
// A list of aliases for the command
|
||||
Aliases []string
|
||||
// A short description of the usage of this command
|
||||
Usage string
|
||||
// Custom text to show on USAGE section of help
|
||||
UsageText string
|
||||
// A longer explanation of how the command works
|
||||
Description string
|
||||
// A short description of the arguments of this command
|
||||
ArgsUsage string
|
||||
// The category the command is part of
|
||||
Category string
|
||||
// The function to call when checking for bash command completions
|
||||
BashComplete BashCompleteFunc
|
||||
// An action to execute before any sub-subcommands are run, but after the context is ready
|
||||
// If a non-nil error is returned, no sub-subcommands are run
|
||||
Before BeforeFunc
|
||||
// An action to execute after any subcommands are run, but after the subcommand has finished
|
||||
// It is run even if Action() panics
|
||||
After AfterFunc
|
||||
// The function to call when this command is invoked
|
||||
Action interface{}
|
||||
// TODO: replace `Action: interface{}` with `Action: ActionFunc` once some kind
|
||||
// of deprecation period has passed, maybe?
|
||||
|
||||
// Execute this function if a usage error occurs.
|
||||
OnUsageError OnUsageErrorFunc
|
||||
// List of child commands
|
||||
Subcommands Commands
|
||||
// List of flags to parse
|
||||
Flags []Flag
|
||||
// Treat all flags as normal arguments if true
|
||||
SkipFlagParsing bool
|
||||
// Skip argument reordering which attempts to move flags before arguments,
|
||||
// but only works if all flags appear after all arguments. This behavior was
|
||||
// removed n version 2 since it only works under specific conditions so we
|
||||
// backport here by exposing it as an option for compatibility.
|
||||
SkipArgReorder bool
|
||||
// Boolean to hide built-in help command
|
||||
HideHelp bool
|
||||
// Boolean to hide this command from help or completion
|
||||
Hidden bool
|
||||
|
||||
// Full name of command for help, defaults to full command name, including parent commands.
|
||||
HelpName string
|
||||
commandNamePath []string
|
||||
}
|
||||
|
||||
type CommandsByName []Command
|
||||
|
||||
func (c CommandsByName) Len() int {
|
||||
return len(c)
|
||||
}
|
||||
|
||||
func (c CommandsByName) Less(i, j int) bool {
|
||||
return c[i].Name < c[j].Name
|
||||
}
|
||||
|
||||
func (c CommandsByName) Swap(i, j int) {
|
||||
c[i], c[j] = c[j], c[i]
|
||||
}
|
||||
|
||||
// FullName returns the full name of the command.
|
||||
// For subcommands this ensures that parent commands are part of the command path
|
||||
func (c Command) FullName() string {
|
||||
if c.commandNamePath == nil {
|
||||
return c.Name
|
||||
}
|
||||
return strings.Join(c.commandNamePath, " ")
|
||||
}
|
||||
|
||||
// Commands is a slice of Command
|
||||
type Commands []Command
|
||||
|
||||
// Run invokes the command given the context, parses ctx.Args() to generate command-specific flags
|
||||
func (c Command) Run(ctx *Context) (err error) {
|
||||
if len(c.Subcommands) > 0 {
|
||||
return c.startApp(ctx)
|
||||
}
|
||||
|
||||
if !c.HideHelp && (HelpFlag != BoolFlag{}) {
|
||||
// append help to flags
|
||||
c.Flags = append(
|
||||
c.Flags,
|
||||
HelpFlag,
|
||||
)
|
||||
}
|
||||
|
||||
set, err := flagSet(c.Name, c.Flags)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
set.SetOutput(ioutil.Discard)
|
||||
|
||||
if c.SkipFlagParsing {
|
||||
err = set.Parse(append([]string{"--"}, ctx.Args().Tail()...))
|
||||
} else if !c.SkipArgReorder {
|
||||
firstFlagIndex := -1
|
||||
terminatorIndex := -1
|
||||
for index, arg := range ctx.Args() {
|
||||
if arg == "--" {
|
||||
terminatorIndex = index
|
||||
break
|
||||
} else if arg == "-" {
|
||||
// Do nothing. A dash alone is not really a flag.
|
||||
continue
|
||||
} else if strings.HasPrefix(arg, "-") && firstFlagIndex == -1 {
|
||||
firstFlagIndex = index
|
||||
}
|
||||
}
|
||||
|
||||
if firstFlagIndex > -1 {
|
||||
args := ctx.Args()
|
||||
regularArgs := make([]string, len(args[1:firstFlagIndex]))
|
||||
copy(regularArgs, args[1:firstFlagIndex])
|
||||
|
||||
var flagArgs []string
|
||||
if terminatorIndex > -1 {
|
||||
flagArgs = args[firstFlagIndex:terminatorIndex]
|
||||
regularArgs = append(regularArgs, args[terminatorIndex:]...)
|
||||
} else {
|
||||
flagArgs = args[firstFlagIndex:]
|
||||
}
|
||||
|
||||
err = set.Parse(append(flagArgs, regularArgs...))
|
||||
} else {
|
||||
err = set.Parse(ctx.Args().Tail())
|
||||
}
|
||||
} else {
|
||||
err = set.Parse(ctx.Args().Tail())
|
||||
}
|
||||
|
||||
nerr := normalizeFlags(c.Flags, set)
|
||||
if nerr != nil {
|
||||
fmt.Fprintln(ctx.App.Writer, nerr)
|
||||
fmt.Fprintln(ctx.App.Writer)
|
||||
ShowCommandHelp(ctx, c.Name)
|
||||
return nerr
|
||||
}
|
||||
|
||||
context := NewContext(ctx.App, set, ctx)
|
||||
if checkCommandCompletions(context, c.Name) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if c.OnUsageError != nil {
|
||||
err := c.OnUsageError(ctx, err, false)
|
||||
HandleExitCoder(err)
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(ctx.App.Writer, "Incorrect Usage:", err.Error())
|
||||
fmt.Fprintln(ctx.App.Writer)
|
||||
ShowCommandHelp(ctx, c.Name)
|
||||
return err
|
||||
}
|
||||
|
||||
if checkCommandHelp(context, c.Name) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if c.After != nil {
|
||||
defer func() {
|
||||
afterErr := c.After(context)
|
||||
if afterErr != nil {
|
||||
HandleExitCoder(err)
|
||||
if err != nil {
|
||||
err = NewMultiError(err, afterErr)
|
||||
} else {
|
||||
err = afterErr
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
if c.Before != nil {
|
||||
err = c.Before(context)
|
||||
if err != nil {
|
||||
fmt.Fprintln(ctx.App.Writer, err)
|
||||
fmt.Fprintln(ctx.App.Writer)
|
||||
ShowCommandHelp(ctx, c.Name)
|
||||
HandleExitCoder(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if c.Action == nil {
|
||||
c.Action = helpSubcommand.Action
|
||||
}
|
||||
|
||||
context.Command = c
|
||||
err = HandleAction(c.Action, context)
|
||||
|
||||
if err != nil {
|
||||
HandleExitCoder(err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Names returns the names including short names and aliases.
|
||||
func (c Command) Names() []string {
|
||||
names := []string{c.Name}
|
||||
|
||||
if c.ShortName != "" {
|
||||
names = append(names, c.ShortName)
|
||||
}
|
||||
|
||||
return append(names, c.Aliases...)
|
||||
}
|
||||
|
||||
// HasName returns true if Command.Name or Command.ShortName matches given name
|
||||
func (c Command) HasName(name string) bool {
|
||||
for _, n := range c.Names() {
|
||||
if n == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c Command) startApp(ctx *Context) error {
|
||||
app := NewApp()
|
||||
app.Metadata = ctx.App.Metadata
|
||||
// set the name and usage
|
||||
app.Name = fmt.Sprintf("%s %s", ctx.App.Name, c.Name)
|
||||
if c.HelpName == "" {
|
||||
app.HelpName = c.HelpName
|
||||
} else {
|
||||
app.HelpName = app.Name
|
||||
}
|
||||
|
||||
if c.Description != "" {
|
||||
app.Usage = c.Description
|
||||
} else {
|
||||
app.Usage = c.Usage
|
||||
}
|
||||
|
||||
// set CommandNotFound
|
||||
app.CommandNotFound = ctx.App.CommandNotFound
|
||||
|
||||
// set the flags and commands
|
||||
app.Commands = c.Subcommands
|
||||
app.Flags = c.Flags
|
||||
app.HideHelp = c.HideHelp
|
||||
|
||||
app.Version = ctx.App.Version
|
||||
app.HideVersion = ctx.App.HideVersion
|
||||
app.Compiled = ctx.App.Compiled
|
||||
app.Author = ctx.App.Author
|
||||
app.Email = ctx.App.Email
|
||||
app.Writer = ctx.App.Writer
|
||||
|
||||
app.categories = CommandCategories{}
|
||||
for _, command := range c.Subcommands {
|
||||
app.categories = app.categories.AddCommand(command.Category, command)
|
||||
}
|
||||
|
||||
sort.Sort(app.categories)
|
||||
|
||||
// bash completion
|
||||
app.EnableBashCompletion = ctx.App.EnableBashCompletion
|
||||
if c.BashComplete != nil {
|
||||
app.BashComplete = c.BashComplete
|
||||
}
|
||||
|
||||
// set the actions
|
||||
app.Before = c.Before
|
||||
app.After = c.After
|
||||
if c.Action != nil {
|
||||
app.Action = c.Action
|
||||
} else {
|
||||
app.Action = helpSubcommand.Action
|
||||
}
|
||||
|
||||
for index, cc := range app.Commands {
|
||||
app.Commands[index].commandNamePath = []string{c.Name, cc.Name}
|
||||
}
|
||||
|
||||
return app.RunAsSubcommand(ctx)
|
||||
}
|
||||
|
||||
// VisibleFlags returns a slice of the Flags with Hidden=false
|
||||
func (c Command) VisibleFlags() []Flag {
|
||||
return visibleFlags(c.Flags)
|
||||
}
|
||||
276
vendor/github.com/urfave/cli/context.go
generated
vendored
Normal file
276
vendor/github.com/urfave/cli/context.go
generated
vendored
Normal file
@@ -0,0 +1,276 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"reflect"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Context is a type that is passed through to
|
||||
// each Handler action in a cli application. Context
|
||||
// can be used to retrieve context-specific Args and
|
||||
// parsed command-line options.
|
||||
type Context struct {
|
||||
App *App
|
||||
Command Command
|
||||
shellComplete bool
|
||||
flagSet *flag.FlagSet
|
||||
setFlags map[string]bool
|
||||
parentContext *Context
|
||||
}
|
||||
|
||||
// NewContext creates a new context. For use in when invoking an App or Command action.
|
||||
func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context {
|
||||
c := &Context{App: app, flagSet: set, parentContext: parentCtx}
|
||||
|
||||
if parentCtx != nil {
|
||||
c.shellComplete = parentCtx.shellComplete
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// NumFlags returns the number of flags set
|
||||
func (c *Context) NumFlags() int {
|
||||
return c.flagSet.NFlag()
|
||||
}
|
||||
|
||||
// Set sets a context flag to a value.
|
||||
func (c *Context) Set(name, value string) error {
|
||||
return c.flagSet.Set(name, value)
|
||||
}
|
||||
|
||||
// GlobalSet sets a context flag to a value on the global flagset
|
||||
func (c *Context) GlobalSet(name, value string) error {
|
||||
return globalContext(c).flagSet.Set(name, value)
|
||||
}
|
||||
|
||||
// IsSet determines if the flag was actually set
|
||||
func (c *Context) IsSet(name string) bool {
|
||||
if c.setFlags == nil {
|
||||
c.setFlags = make(map[string]bool)
|
||||
|
||||
c.flagSet.Visit(func(f *flag.Flag) {
|
||||
c.setFlags[f.Name] = true
|
||||
})
|
||||
|
||||
c.flagSet.VisitAll(func(f *flag.Flag) {
|
||||
if _, ok := c.setFlags[f.Name]; ok {
|
||||
return
|
||||
}
|
||||
c.setFlags[f.Name] = false
|
||||
})
|
||||
|
||||
// XXX hack to support IsSet for flags with EnvVar
|
||||
//
|
||||
// There isn't an easy way to do this with the current implementation since
|
||||
// whether a flag was set via an environment variable is very difficult to
|
||||
// determine here. Instead, we intend to introduce a backwards incompatible
|
||||
// change in version 2 to add `IsSet` to the Flag interface to push the
|
||||
// responsibility closer to where the information required to determine
|
||||
// whether a flag is set by non-standard means such as environment
|
||||
// variables is avaliable.
|
||||
//
|
||||
// See https://github.com/urfave/cli/issues/294 for additional discussion
|
||||
flags := c.Command.Flags
|
||||
if c.Command.Name == "" { // cannot == Command{} since it contains slice types
|
||||
if c.App != nil {
|
||||
flags = c.App.Flags
|
||||
}
|
||||
}
|
||||
for _, f := range flags {
|
||||
eachName(f.GetName(), func(name string) {
|
||||
if isSet, ok := c.setFlags[name]; isSet || !ok {
|
||||
return
|
||||
}
|
||||
|
||||
val := reflect.ValueOf(f)
|
||||
if val.Kind() == reflect.Ptr {
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
envVarValue := val.FieldByName("EnvVar")
|
||||
if !envVarValue.IsValid() {
|
||||
return
|
||||
}
|
||||
|
||||
eachName(envVarValue.String(), func(envVar string) {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if _, ok := syscall.Getenv(envVar); ok {
|
||||
c.setFlags[name] = true
|
||||
return
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return c.setFlags[name]
|
||||
}
|
||||
|
||||
// GlobalIsSet determines if the global flag was actually set
|
||||
func (c *Context) GlobalIsSet(name string) bool {
|
||||
ctx := c
|
||||
if ctx.parentContext != nil {
|
||||
ctx = ctx.parentContext
|
||||
}
|
||||
|
||||
for ; ctx != nil; ctx = ctx.parentContext {
|
||||
if ctx.IsSet(name) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// FlagNames returns a slice of flag names used in this context.
|
||||
func (c *Context) FlagNames() (names []string) {
|
||||
for _, flag := range c.Command.Flags {
|
||||
name := strings.Split(flag.GetName(), ",")[0]
|
||||
if name == "help" {
|
||||
continue
|
||||
}
|
||||
names = append(names, name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GlobalFlagNames returns a slice of global flag names used by the app.
|
||||
func (c *Context) GlobalFlagNames() (names []string) {
|
||||
for _, flag := range c.App.Flags {
|
||||
name := strings.Split(flag.GetName(), ",")[0]
|
||||
if name == "help" || name == "version" {
|
||||
continue
|
||||
}
|
||||
names = append(names, name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Parent returns the parent context, if any
|
||||
func (c *Context) Parent() *Context {
|
||||
return c.parentContext
|
||||
}
|
||||
|
||||
// value returns the value of the flag coressponding to `name`
|
||||
func (c *Context) value(name string) interface{} {
|
||||
return c.flagSet.Lookup(name).Value.(flag.Getter).Get()
|
||||
}
|
||||
|
||||
// Args contains apps console arguments
|
||||
type Args []string
|
||||
|
||||
// Args returns the command line arguments associated with the context.
|
||||
func (c *Context) Args() Args {
|
||||
args := Args(c.flagSet.Args())
|
||||
return args
|
||||
}
|
||||
|
||||
// NArg returns the number of the command line arguments.
|
||||
func (c *Context) NArg() int {
|
||||
return len(c.Args())
|
||||
}
|
||||
|
||||
// Get returns the nth argument, or else a blank string
|
||||
func (a Args) Get(n int) string {
|
||||
if len(a) > n {
|
||||
return a[n]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// First returns the first argument, or else a blank string
|
||||
func (a Args) First() string {
|
||||
return a.Get(0)
|
||||
}
|
||||
|
||||
// Tail returns the rest of the arguments (not the first one)
|
||||
// or else an empty string slice
|
||||
func (a Args) Tail() []string {
|
||||
if len(a) >= 2 {
|
||||
return []string(a)[1:]
|
||||
}
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// Present checks if there are any arguments present
|
||||
func (a Args) Present() bool {
|
||||
return len(a) != 0
|
||||
}
|
||||
|
||||
// Swap swaps arguments at the given indexes
|
||||
func (a Args) Swap(from, to int) error {
|
||||
if from >= len(a) || to >= len(a) {
|
||||
return errors.New("index out of range")
|
||||
}
|
||||
a[from], a[to] = a[to], a[from]
|
||||
return nil
|
||||
}
|
||||
|
||||
func globalContext(ctx *Context) *Context {
|
||||
if ctx == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for {
|
||||
if ctx.parentContext == nil {
|
||||
return ctx
|
||||
}
|
||||
ctx = ctx.parentContext
|
||||
}
|
||||
}
|
||||
|
||||
func lookupGlobalFlagSet(name string, ctx *Context) *flag.FlagSet {
|
||||
if ctx.parentContext != nil {
|
||||
ctx = ctx.parentContext
|
||||
}
|
||||
for ; ctx != nil; ctx = ctx.parentContext {
|
||||
if f := ctx.flagSet.Lookup(name); f != nil {
|
||||
return ctx.flagSet
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
|
||||
switch ff.Value.(type) {
|
||||
case *StringSlice:
|
||||
default:
|
||||
set.Set(name, ff.Value.String())
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeFlags(flags []Flag, set *flag.FlagSet) error {
|
||||
visited := make(map[string]bool)
|
||||
set.Visit(func(f *flag.Flag) {
|
||||
visited[f.Name] = true
|
||||
})
|
||||
for _, f := range flags {
|
||||
parts := strings.Split(f.GetName(), ",")
|
||||
if len(parts) == 1 {
|
||||
continue
|
||||
}
|
||||
var ff *flag.Flag
|
||||
for _, name := range parts {
|
||||
name = strings.Trim(name, " ")
|
||||
if visited[name] {
|
||||
if ff != nil {
|
||||
return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name)
|
||||
}
|
||||
ff = set.Lookup(name)
|
||||
}
|
||||
}
|
||||
if ff == nil {
|
||||
continue
|
||||
}
|
||||
for _, name := range parts {
|
||||
name = strings.Trim(name, " ")
|
||||
if !visited[name] {
|
||||
copyFlag(name, ff, set)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
124
vendor/github.com/urfave/cli/errors.go
generated
vendored
Normal file
124
vendor/github.com/urfave/cli/errors.go
generated
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// OsExiter is the function used when the app exits. If not set defaults to os.Exit.
|
||||
var OsExiter = os.Exit
|
||||
|
||||
// ErrWriter is used to write errors to the user. This can be anything
|
||||
// implementing the io.Writer interface and defaults to os.Stderr.
|
||||
var ErrWriter io.Writer = os.Stderr
|
||||
|
||||
// MultiError is an error that wraps multiple errors.
|
||||
type MultiError struct {
|
||||
Errors []error
|
||||
}
|
||||
|
||||
// NewMultiError creates a new MultiError. Pass in one or more errors.
|
||||
func NewMultiError(err ...error) MultiError {
|
||||
return MultiError{Errors: err}
|
||||
}
|
||||
|
||||
// Error implements the error interface.
|
||||
func (m MultiError) Error() string {
|
||||
errs := make([]string, len(m.Errors))
|
||||
for i, err := range m.Errors {
|
||||
errs[i] = err.Error()
|
||||
}
|
||||
|
||||
return strings.Join(errs, "\n")
|
||||
}
|
||||
|
||||
type ErrorFormatter interface {
|
||||
Format(s fmt.State, verb rune)
|
||||
}
|
||||
|
||||
// ExitCoder is the interface checked by `App` and `Command` for a custom exit
|
||||
// code
|
||||
type ExitCoder interface {
|
||||
error
|
||||
ExitCode() int
|
||||
}
|
||||
|
||||
// ExitError fulfills both the builtin `error` interface and `ExitCoder`
|
||||
type ExitError struct {
|
||||
exitCode int
|
||||
message interface{}
|
||||
}
|
||||
|
||||
// NewExitError makes a new *ExitError
|
||||
func NewExitError(message interface{}, exitCode int) *ExitError {
|
||||
return &ExitError{
|
||||
exitCode: exitCode,
|
||||
message: message,
|
||||
}
|
||||
}
|
||||
|
||||
// Error returns the string message, fulfilling the interface required by
|
||||
// `error`
|
||||
func (ee *ExitError) Error() string {
|
||||
return fmt.Sprintf("%v", ee.message)
|
||||
}
|
||||
|
||||
// ExitCode returns the exit code, fulfilling the interface required by
|
||||
// `ExitCoder`
|
||||
func (ee *ExitError) ExitCode() int {
|
||||
return ee.exitCode
|
||||
}
|
||||
|
||||
// HandleExitCoder checks if the error fulfills the ExitCoder interface, and if
|
||||
// so prints the error to stderr (if it is non-empty) and calls OsExiter with the
|
||||
// given exit code. If the given error is a MultiError, then this func is
|
||||
// called on all members of the Errors slice and calls OsExiter with the last exit code.
|
||||
func HandleExitCoder(err error) {
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if exitErr, ok := err.(ExitCoder); ok {
|
||||
if err.Error() != "" {
|
||||
if _, ok := exitErr.(ErrorFormatter); ok {
|
||||
fmt.Fprintf(ErrWriter, "%+v\n", err)
|
||||
} else {
|
||||
fmt.Fprintln(ErrWriter, err)
|
||||
}
|
||||
}
|
||||
OsExiter(exitErr.ExitCode())
|
||||
return
|
||||
}
|
||||
|
||||
if multiErr, ok := err.(MultiError); ok {
|
||||
code := handleMultiError(multiErr)
|
||||
OsExiter(code)
|
||||
return
|
||||
}
|
||||
|
||||
if err.Error() != "" {
|
||||
if _, ok := err.(ErrorFormatter); ok {
|
||||
fmt.Fprintf(ErrWriter, "%+v\n", err)
|
||||
} else {
|
||||
fmt.Fprintln(ErrWriter, err)
|
||||
}
|
||||
}
|
||||
OsExiter(1)
|
||||
}
|
||||
|
||||
func handleMultiError(multiErr MultiError) int {
|
||||
code := 1
|
||||
for _, merr := range multiErr.Errors {
|
||||
if multiErr2, ok := merr.(MultiError); ok {
|
||||
code = handleMultiError(multiErr2)
|
||||
} else {
|
||||
fmt.Fprintln(ErrWriter, merr)
|
||||
if exitErr, ok := merr.(ExitCoder); ok {
|
||||
code = exitErr.ExitCode()
|
||||
}
|
||||
}
|
||||
}
|
||||
return code
|
||||
}
|
||||
93
vendor/github.com/urfave/cli/flag-types.json
generated
vendored
Normal file
93
vendor/github.com/urfave/cli/flag-types.json
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
[
|
||||
{
|
||||
"name": "Bool",
|
||||
"type": "bool",
|
||||
"value": false,
|
||||
"context_default": "false",
|
||||
"parser": "strconv.ParseBool(f.Value.String())"
|
||||
},
|
||||
{
|
||||
"name": "BoolT",
|
||||
"type": "bool",
|
||||
"value": false,
|
||||
"doctail": " that is true by default",
|
||||
"context_default": "false",
|
||||
"parser": "strconv.ParseBool(f.Value.String())"
|
||||
},
|
||||
{
|
||||
"name": "Duration",
|
||||
"type": "time.Duration",
|
||||
"doctail": " (see https://golang.org/pkg/time/#ParseDuration)",
|
||||
"context_default": "0",
|
||||
"parser": "time.ParseDuration(f.Value.String())"
|
||||
},
|
||||
{
|
||||
"name": "Float64",
|
||||
"type": "float64",
|
||||
"context_default": "0",
|
||||
"parser": "strconv.ParseFloat(f.Value.String(), 64)"
|
||||
},
|
||||
{
|
||||
"name": "Generic",
|
||||
"type": "Generic",
|
||||
"dest": false,
|
||||
"context_default": "nil",
|
||||
"context_type": "interface{}"
|
||||
},
|
||||
{
|
||||
"name": "Int64",
|
||||
"type": "int64",
|
||||
"context_default": "0",
|
||||
"parser": "strconv.ParseInt(f.Value.String(), 0, 64)"
|
||||
},
|
||||
{
|
||||
"name": "Int",
|
||||
"type": "int",
|
||||
"context_default": "0",
|
||||
"parser": "strconv.ParseInt(f.Value.String(), 0, 64)",
|
||||
"parser_cast": "int(parsed)"
|
||||
},
|
||||
{
|
||||
"name": "IntSlice",
|
||||
"type": "*IntSlice",
|
||||
"dest": false,
|
||||
"context_default": "nil",
|
||||
"context_type": "[]int",
|
||||
"parser": "(f.Value.(*IntSlice)).Value(), error(nil)"
|
||||
},
|
||||
{
|
||||
"name": "Int64Slice",
|
||||
"type": "*Int64Slice",
|
||||
"dest": false,
|
||||
"context_default": "nil",
|
||||
"context_type": "[]int64",
|
||||
"parser": "(f.Value.(*Int64Slice)).Value(), error(nil)"
|
||||
},
|
||||
{
|
||||
"name": "String",
|
||||
"type": "string",
|
||||
"context_default": "\"\"",
|
||||
"parser": "f.Value.String(), error(nil)"
|
||||
},
|
||||
{
|
||||
"name": "StringSlice",
|
||||
"type": "*StringSlice",
|
||||
"dest": false,
|
||||
"context_default": "nil",
|
||||
"context_type": "[]string",
|
||||
"parser": "(f.Value.(*StringSlice)).Value(), error(nil)"
|
||||
},
|
||||
{
|
||||
"name": "Uint64",
|
||||
"type": "uint64",
|
||||
"context_default": "0",
|
||||
"parser": "strconv.ParseUint(f.Value.String(), 0, 64)"
|
||||
},
|
||||
{
|
||||
"name": "Uint",
|
||||
"type": "uint",
|
||||
"context_default": "0",
|
||||
"parser": "strconv.ParseUint(f.Value.String(), 0, 64)",
|
||||
"parser_cast": "uint(parsed)"
|
||||
}
|
||||
]
|
||||
799
vendor/github.com/urfave/cli/flag.go
generated
vendored
Normal file
799
vendor/github.com/urfave/cli/flag.go
generated
vendored
Normal file
@@ -0,0 +1,799 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
const defaultPlaceholder = "value"
|
||||
|
||||
// BashCompletionFlag enables bash-completion for all commands and subcommands
|
||||
var BashCompletionFlag = BoolFlag{
|
||||
Name: "generate-bash-completion",
|
||||
Hidden: true,
|
||||
}
|
||||
|
||||
// VersionFlag prints the version for the application
|
||||
var VersionFlag = BoolFlag{
|
||||
Name: "version, v",
|
||||
Usage: "print the version",
|
||||
}
|
||||
|
||||
// HelpFlag prints the help for all commands and subcommands
|
||||
// Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand
|
||||
// unless HideHelp is set to true)
|
||||
var HelpFlag = BoolFlag{
|
||||
Name: "help, h",
|
||||
Usage: "show help",
|
||||
}
|
||||
|
||||
// FlagStringer converts a flag definition to a string. This is used by help
|
||||
// to display a flag.
|
||||
var FlagStringer FlagStringFunc = stringifyFlag
|
||||
|
||||
// FlagsByName is a slice of Flag.
|
||||
type FlagsByName []Flag
|
||||
|
||||
func (f FlagsByName) Len() int {
|
||||
return len(f)
|
||||
}
|
||||
|
||||
func (f FlagsByName) Less(i, j int) bool {
|
||||
return f[i].GetName() < f[j].GetName()
|
||||
}
|
||||
|
||||
func (f FlagsByName) Swap(i, j int) {
|
||||
f[i], f[j] = f[j], f[i]
|
||||
}
|
||||
|
||||
// Flag is a common interface related to parsing flags in cli.
|
||||
// For more advanced flag parsing techniques, it is recommended that
|
||||
// this interface be implemented.
|
||||
type Flag interface {
|
||||
fmt.Stringer
|
||||
// Apply Flag settings to the given flag set
|
||||
Apply(*flag.FlagSet)
|
||||
GetName() string
|
||||
}
|
||||
|
||||
// errorableFlag is an interface that allows us to return errors during apply
|
||||
// it allows flags defined in this library to return errors in a fashion backwards compatible
|
||||
// TODO remove in v2 and modify the existing Flag interface to return errors
|
||||
type errorableFlag interface {
|
||||
Flag
|
||||
|
||||
ApplyWithError(*flag.FlagSet) error
|
||||
}
|
||||
|
||||
func flagSet(name string, flags []Flag) (*flag.FlagSet, error) {
|
||||
set := flag.NewFlagSet(name, flag.ContinueOnError)
|
||||
|
||||
for _, f := range flags {
|
||||
//TODO remove in v2 when errorableFlag is removed
|
||||
if ef, ok := f.(errorableFlag); ok {
|
||||
if err := ef.ApplyWithError(set); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
f.Apply(set)
|
||||
}
|
||||
}
|
||||
return set, nil
|
||||
}
|
||||
|
||||
func eachName(longName string, fn func(string)) {
|
||||
parts := strings.Split(longName, ",")
|
||||
for _, name := range parts {
|
||||
name = strings.Trim(name, " ")
|
||||
fn(name)
|
||||
}
|
||||
}
|
||||
|
||||
// Generic is a generic parseable type identified by a specific flag
|
||||
type Generic interface {
|
||||
Set(value string) error
|
||||
String() string
|
||||
}
|
||||
|
||||
// Apply takes the flagset and calls Set on the generic flag with the value
|
||||
// provided by the user for parsing by the flag
|
||||
// Ignores parsing errors
|
||||
func (f GenericFlag) Apply(set *flag.FlagSet) {
|
||||
f.ApplyWithError(set)
|
||||
}
|
||||
|
||||
// ApplyWithError takes the flagset and calls Set on the generic flag with the value
|
||||
// provided by the user for parsing by the flag
|
||||
func (f GenericFlag) ApplyWithError(set *flag.FlagSet) error {
|
||||
val := f.Value
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||
if err := val.Set(envVal); err != nil {
|
||||
return fmt.Errorf("could not parse %s as value for flag %s: %s", envVal, f.Name, err)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
set.Var(f.Value, name, f.Usage)
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// StringSlice is an opaque type for []string to satisfy flag.Value and flag.Getter
|
||||
type StringSlice []string
|
||||
|
||||
// Set appends the string value to the list of values
|
||||
func (f *StringSlice) Set(value string) error {
|
||||
*f = append(*f, value)
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value (for usage defaults)
|
||||
func (f *StringSlice) String() string {
|
||||
return fmt.Sprintf("%s", *f)
|
||||
}
|
||||
|
||||
// Value returns the slice of strings set by this flag
|
||||
func (f *StringSlice) Value() []string {
|
||||
return *f
|
||||
}
|
||||
|
||||
// Get returns the slice of strings set by this flag
|
||||
func (f *StringSlice) Get() interface{} {
|
||||
return *f
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
// Ignores errors
|
||||
func (f StringSliceFlag) Apply(set *flag.FlagSet) {
|
||||
f.ApplyWithError(set)
|
||||
}
|
||||
|
||||
// ApplyWithError populates the flag given the flag set and environment
|
||||
func (f StringSliceFlag) ApplyWithError(set *flag.FlagSet) error {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||
newVal := &StringSlice{}
|
||||
for _, s := range strings.Split(envVal, ",") {
|
||||
s = strings.TrimSpace(s)
|
||||
if err := newVal.Set(s); err != nil {
|
||||
return fmt.Errorf("could not parse %s as string value for flag %s: %s", envVal, f.Name, err)
|
||||
}
|
||||
}
|
||||
f.Value = newVal
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Value == nil {
|
||||
f.Value = &StringSlice{}
|
||||
}
|
||||
set.Var(f.Value, name, f.Usage)
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IntSlice is an opaque type for []int to satisfy flag.Value and flag.Getter
|
||||
type IntSlice []int
|
||||
|
||||
// Set parses the value into an integer and appends it to the list of values
|
||||
func (f *IntSlice) Set(value string) error {
|
||||
tmp, err := strconv.Atoi(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*f = append(*f, tmp)
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value (for usage defaults)
|
||||
func (f *IntSlice) String() string {
|
||||
return fmt.Sprintf("%#v", *f)
|
||||
}
|
||||
|
||||
// Value returns the slice of ints set by this flag
|
||||
func (f *IntSlice) Value() []int {
|
||||
return *f
|
||||
}
|
||||
|
||||
// Get returns the slice of ints set by this flag
|
||||
func (f *IntSlice) Get() interface{} {
|
||||
return *f
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
// Ignores errors
|
||||
func (f IntSliceFlag) Apply(set *flag.FlagSet) {
|
||||
f.ApplyWithError(set)
|
||||
}
|
||||
|
||||
// ApplyWithError populates the flag given the flag set and environment
|
||||
func (f IntSliceFlag) ApplyWithError(set *flag.FlagSet) error {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||
newVal := &IntSlice{}
|
||||
for _, s := range strings.Split(envVal, ",") {
|
||||
s = strings.TrimSpace(s)
|
||||
if err := newVal.Set(s); err != nil {
|
||||
return fmt.Errorf("could not parse %s as int slice value for flag %s: %s", envVal, f.Name, err)
|
||||
}
|
||||
}
|
||||
f.Value = newVal
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Value == nil {
|
||||
f.Value = &IntSlice{}
|
||||
}
|
||||
set.Var(f.Value, name, f.Usage)
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Int64Slice is an opaque type for []int to satisfy flag.Value and flag.Getter
|
||||
type Int64Slice []int64
|
||||
|
||||
// Set parses the value into an integer and appends it to the list of values
|
||||
func (f *Int64Slice) Set(value string) error {
|
||||
tmp, err := strconv.ParseInt(value, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*f = append(*f, tmp)
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value (for usage defaults)
|
||||
func (f *Int64Slice) String() string {
|
||||
return fmt.Sprintf("%#v", *f)
|
||||
}
|
||||
|
||||
// Value returns the slice of ints set by this flag
|
||||
func (f *Int64Slice) Value() []int64 {
|
||||
return *f
|
||||
}
|
||||
|
||||
// Get returns the slice of ints set by this flag
|
||||
func (f *Int64Slice) Get() interface{} {
|
||||
return *f
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
// Ignores errors
|
||||
func (f Int64SliceFlag) Apply(set *flag.FlagSet) {
|
||||
f.ApplyWithError(set)
|
||||
}
|
||||
|
||||
// ApplyWithError populates the flag given the flag set and environment
|
||||
func (f Int64SliceFlag) ApplyWithError(set *flag.FlagSet) error {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||
newVal := &Int64Slice{}
|
||||
for _, s := range strings.Split(envVal, ",") {
|
||||
s = strings.TrimSpace(s)
|
||||
if err := newVal.Set(s); err != nil {
|
||||
return fmt.Errorf("could not parse %s as int64 slice value for flag %s: %s", envVal, f.Name, err)
|
||||
}
|
||||
}
|
||||
f.Value = newVal
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Value == nil {
|
||||
f.Value = &Int64Slice{}
|
||||
}
|
||||
set.Var(f.Value, name, f.Usage)
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
// Ignores errors
|
||||
func (f BoolFlag) Apply(set *flag.FlagSet) {
|
||||
f.ApplyWithError(set)
|
||||
}
|
||||
|
||||
// ApplyWithError populates the flag given the flag set and environment
|
||||
func (f BoolFlag) ApplyWithError(set *flag.FlagSet) error {
|
||||
val := false
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||
if envVal == "" {
|
||||
val = false
|
||||
break
|
||||
}
|
||||
|
||||
envValBool, err := strconv.ParseBool(envVal)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err)
|
||||
}
|
||||
|
||||
val = envValBool
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Destination != nil {
|
||||
set.BoolVar(f.Destination, name, val, f.Usage)
|
||||
return
|
||||
}
|
||||
set.Bool(name, val, f.Usage)
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
// Ignores errors
|
||||
func (f BoolTFlag) Apply(set *flag.FlagSet) {
|
||||
f.ApplyWithError(set)
|
||||
}
|
||||
|
||||
// ApplyWithError populates the flag given the flag set and environment
|
||||
func (f BoolTFlag) ApplyWithError(set *flag.FlagSet) error {
|
||||
val := true
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||
if envVal == "" {
|
||||
val = false
|
||||
break
|
||||
}
|
||||
|
||||
envValBool, err := strconv.ParseBool(envVal)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err)
|
||||
}
|
||||
|
||||
val = envValBool
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Destination != nil {
|
||||
set.BoolVar(f.Destination, name, val, f.Usage)
|
||||
return
|
||||
}
|
||||
set.Bool(name, val, f.Usage)
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
// Ignores errors
|
||||
func (f StringFlag) Apply(set *flag.FlagSet) {
|
||||
f.ApplyWithError(set)
|
||||
}
|
||||
|
||||
// ApplyWithError populates the flag given the flag set and environment
|
||||
func (f StringFlag) ApplyWithError(set *flag.FlagSet) error {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||
f.Value = envVal
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Destination != nil {
|
||||
set.StringVar(f.Destination, name, f.Value, f.Usage)
|
||||
return
|
||||
}
|
||||
set.String(name, f.Value, f.Usage)
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
// Ignores errors
|
||||
func (f IntFlag) Apply(set *flag.FlagSet) {
|
||||
f.ApplyWithError(set)
|
||||
}
|
||||
|
||||
// ApplyWithError populates the flag given the flag set and environment
|
||||
func (f IntFlag) ApplyWithError(set *flag.FlagSet) error {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||
envValInt, err := strconv.ParseInt(envVal, 0, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err)
|
||||
}
|
||||
f.Value = int(envValInt)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Destination != nil {
|
||||
set.IntVar(f.Destination, name, f.Value, f.Usage)
|
||||
return
|
||||
}
|
||||
set.Int(name, f.Value, f.Usage)
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
// Ignores errors
|
||||
func (f Int64Flag) Apply(set *flag.FlagSet) {
|
||||
f.ApplyWithError(set)
|
||||
}
|
||||
|
||||
// ApplyWithError populates the flag given the flag set and environment
|
||||
func (f Int64Flag) ApplyWithError(set *flag.FlagSet) error {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||
envValInt, err := strconv.ParseInt(envVal, 0, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err)
|
||||
}
|
||||
|
||||
f.Value = envValInt
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Destination != nil {
|
||||
set.Int64Var(f.Destination, name, f.Value, f.Usage)
|
||||
return
|
||||
}
|
||||
set.Int64(name, f.Value, f.Usage)
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
// Ignores errors
|
||||
func (f UintFlag) Apply(set *flag.FlagSet) {
|
||||
f.ApplyWithError(set)
|
||||
}
|
||||
|
||||
// ApplyWithError populates the flag given the flag set and environment
|
||||
func (f UintFlag) ApplyWithError(set *flag.FlagSet) error {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||
envValInt, err := strconv.ParseUint(envVal, 0, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse %s as uint value for flag %s: %s", envVal, f.Name, err)
|
||||
}
|
||||
|
||||
f.Value = uint(envValInt)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Destination != nil {
|
||||
set.UintVar(f.Destination, name, f.Value, f.Usage)
|
||||
return
|
||||
}
|
||||
set.Uint(name, f.Value, f.Usage)
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
// Ignores errors
|
||||
func (f Uint64Flag) Apply(set *flag.FlagSet) {
|
||||
f.ApplyWithError(set)
|
||||
}
|
||||
|
||||
// ApplyWithError populates the flag given the flag set and environment
|
||||
func (f Uint64Flag) ApplyWithError(set *flag.FlagSet) error {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||
envValInt, err := strconv.ParseUint(envVal, 0, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse %s as uint64 value for flag %s: %s", envVal, f.Name, err)
|
||||
}
|
||||
|
||||
f.Value = uint64(envValInt)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Destination != nil {
|
||||
set.Uint64Var(f.Destination, name, f.Value, f.Usage)
|
||||
return
|
||||
}
|
||||
set.Uint64(name, f.Value, f.Usage)
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
// Ignores errors
|
||||
func (f DurationFlag) Apply(set *flag.FlagSet) {
|
||||
f.ApplyWithError(set)
|
||||
}
|
||||
|
||||
// ApplyWithError populates the flag given the flag set and environment
|
||||
func (f DurationFlag) ApplyWithError(set *flag.FlagSet) error {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||
envValDuration, err := time.ParseDuration(envVal)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse %s as duration for flag %s: %s", envVal, f.Name, err)
|
||||
}
|
||||
|
||||
f.Value = envValDuration
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Destination != nil {
|
||||
set.DurationVar(f.Destination, name, f.Value, f.Usage)
|
||||
return
|
||||
}
|
||||
set.Duration(name, f.Value, f.Usage)
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
// Ignores errors
|
||||
func (f Float64Flag) Apply(set *flag.FlagSet) {
|
||||
f.ApplyWithError(set)
|
||||
}
|
||||
|
||||
// ApplyWithError populates the flag given the flag set and environment
|
||||
func (f Float64Flag) ApplyWithError(set *flag.FlagSet) error {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||
envValFloat, err := strconv.ParseFloat(envVal, 10)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse %s as float64 value for flag %s: %s", envVal, f.Name, err)
|
||||
}
|
||||
|
||||
f.Value = float64(envValFloat)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Destination != nil {
|
||||
set.Float64Var(f.Destination, name, f.Value, f.Usage)
|
||||
return
|
||||
}
|
||||
set.Float64(name, f.Value, f.Usage)
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func visibleFlags(fl []Flag) []Flag {
|
||||
visible := []Flag{}
|
||||
for _, flag := range fl {
|
||||
if !flagValue(flag).FieldByName("Hidden").Bool() {
|
||||
visible = append(visible, flag)
|
||||
}
|
||||
}
|
||||
return visible
|
||||
}
|
||||
|
||||
func prefixFor(name string) (prefix string) {
|
||||
if len(name) == 1 {
|
||||
prefix = "-"
|
||||
} else {
|
||||
prefix = "--"
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Returns the placeholder, if any, and the unquoted usage string.
|
||||
func unquoteUsage(usage string) (string, string) {
|
||||
for i := 0; i < len(usage); i++ {
|
||||
if usage[i] == '`' {
|
||||
for j := i + 1; j < len(usage); j++ {
|
||||
if usage[j] == '`' {
|
||||
name := usage[i+1 : j]
|
||||
usage = usage[:i] + name + usage[j+1:]
|
||||
return name, usage
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return "", usage
|
||||
}
|
||||
|
||||
func prefixedNames(fullName, placeholder string) string {
|
||||
var prefixed string
|
||||
parts := strings.Split(fullName, ",")
|
||||
for i, name := range parts {
|
||||
name = strings.Trim(name, " ")
|
||||
prefixed += prefixFor(name) + name
|
||||
if placeholder != "" {
|
||||
prefixed += " " + placeholder
|
||||
}
|
||||
if i < len(parts)-1 {
|
||||
prefixed += ", "
|
||||
}
|
||||
}
|
||||
return prefixed
|
||||
}
|
||||
|
||||
func withEnvHint(envVar, str string) string {
|
||||
envText := ""
|
||||
if envVar != "" {
|
||||
prefix := "$"
|
||||
suffix := ""
|
||||
sep := ", $"
|
||||
if runtime.GOOS == "windows" {
|
||||
prefix = "%"
|
||||
suffix = "%"
|
||||
sep = "%, %"
|
||||
}
|
||||
envText = fmt.Sprintf(" [%s%s%s]", prefix, strings.Join(strings.Split(envVar, ","), sep), suffix)
|
||||
}
|
||||
return str + envText
|
||||
}
|
||||
|
||||
func flagValue(f Flag) reflect.Value {
|
||||
fv := reflect.ValueOf(f)
|
||||
for fv.Kind() == reflect.Ptr {
|
||||
fv = reflect.Indirect(fv)
|
||||
}
|
||||
return fv
|
||||
}
|
||||
|
||||
func stringifyFlag(f Flag) string {
|
||||
fv := flagValue(f)
|
||||
|
||||
switch f.(type) {
|
||||
case IntSliceFlag:
|
||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
||||
stringifyIntSliceFlag(f.(IntSliceFlag)))
|
||||
case Int64SliceFlag:
|
||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
||||
stringifyInt64SliceFlag(f.(Int64SliceFlag)))
|
||||
case StringSliceFlag:
|
||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
||||
stringifyStringSliceFlag(f.(StringSliceFlag)))
|
||||
}
|
||||
|
||||
placeholder, usage := unquoteUsage(fv.FieldByName("Usage").String())
|
||||
|
||||
needsPlaceholder := false
|
||||
defaultValueString := ""
|
||||
val := fv.FieldByName("Value")
|
||||
|
||||
if val.IsValid() {
|
||||
needsPlaceholder = true
|
||||
defaultValueString = fmt.Sprintf(" (default: %v)", val.Interface())
|
||||
|
||||
if val.Kind() == reflect.String && val.String() != "" {
|
||||
defaultValueString = fmt.Sprintf(" (default: %q)", val.String())
|
||||
}
|
||||
}
|
||||
|
||||
if defaultValueString == " (default: )" {
|
||||
defaultValueString = ""
|
||||
}
|
||||
|
||||
if needsPlaceholder && placeholder == "" {
|
||||
placeholder = defaultPlaceholder
|
||||
}
|
||||
|
||||
usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultValueString))
|
||||
|
||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
||||
fmt.Sprintf("%s\t%s", prefixedNames(fv.FieldByName("Name").String(), placeholder), usageWithDefault))
|
||||
}
|
||||
|
||||
func stringifyIntSliceFlag(f IntSliceFlag) string {
|
||||
defaultVals := []string{}
|
||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||
for _, i := range f.Value.Value() {
|
||||
defaultVals = append(defaultVals, fmt.Sprintf("%d", i))
|
||||
}
|
||||
}
|
||||
|
||||
return stringifySliceFlag(f.Usage, f.Name, defaultVals)
|
||||
}
|
||||
|
||||
func stringifyInt64SliceFlag(f Int64SliceFlag) string {
|
||||
defaultVals := []string{}
|
||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||
for _, i := range f.Value.Value() {
|
||||
defaultVals = append(defaultVals, fmt.Sprintf("%d", i))
|
||||
}
|
||||
}
|
||||
|
||||
return stringifySliceFlag(f.Usage, f.Name, defaultVals)
|
||||
}
|
||||
|
||||
func stringifyStringSliceFlag(f StringSliceFlag) string {
|
||||
defaultVals := []string{}
|
||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||
for _, s := range f.Value.Value() {
|
||||
if len(s) > 0 {
|
||||
defaultVals = append(defaultVals, fmt.Sprintf("%q", s))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return stringifySliceFlag(f.Usage, f.Name, defaultVals)
|
||||
}
|
||||
|
||||
func stringifySliceFlag(usage, name string, defaultVals []string) string {
|
||||
placeholder, usage := unquoteUsage(usage)
|
||||
if placeholder == "" {
|
||||
placeholder = defaultPlaceholder
|
||||
}
|
||||
|
||||
defaultVal := ""
|
||||
if len(defaultVals) > 0 {
|
||||
defaultVal = fmt.Sprintf(" (default: %s)", strings.Join(defaultVals, ", "))
|
||||
}
|
||||
|
||||
usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultVal))
|
||||
return fmt.Sprintf("%s\t%s", prefixedNames(name, placeholder), usageWithDefault)
|
||||
}
|
||||
627
vendor/github.com/urfave/cli/flag_generated.go
generated
vendored
Normal file
627
vendor/github.com/urfave/cli/flag_generated.go
generated
vendored
Normal file
@@ -0,0 +1,627 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// WARNING: This file is generated!
|
||||
|
||||
// BoolFlag is a flag with type bool
|
||||
type BoolFlag struct {
|
||||
Name string
|
||||
Usage string
|
||||
EnvVar string
|
||||
Hidden bool
|
||||
Destination *bool
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value
|
||||
// (for usage defaults)
|
||||
func (f BoolFlag) String() string {
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag
|
||||
func (f BoolFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// Bool looks up the value of a local BoolFlag, returns
|
||||
// false if not found
|
||||
func (c *Context) Bool(name string) bool {
|
||||
return lookupBool(name, c.flagSet)
|
||||
}
|
||||
|
||||
// GlobalBool looks up the value of a global BoolFlag, returns
|
||||
// false if not found
|
||||
func (c *Context) GlobalBool(name string) bool {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupBool(name, fs)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func lookupBool(name string, set *flag.FlagSet) bool {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
parsed, err := strconv.ParseBool(f.Value.String())
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// BoolTFlag is a flag with type bool that is true by default
|
||||
type BoolTFlag struct {
|
||||
Name string
|
||||
Usage string
|
||||
EnvVar string
|
||||
Hidden bool
|
||||
Destination *bool
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value
|
||||
// (for usage defaults)
|
||||
func (f BoolTFlag) String() string {
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag
|
||||
func (f BoolTFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// BoolT looks up the value of a local BoolTFlag, returns
|
||||
// false if not found
|
||||
func (c *Context) BoolT(name string) bool {
|
||||
return lookupBoolT(name, c.flagSet)
|
||||
}
|
||||
|
||||
// GlobalBoolT looks up the value of a global BoolTFlag, returns
|
||||
// false if not found
|
||||
func (c *Context) GlobalBoolT(name string) bool {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupBoolT(name, fs)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func lookupBoolT(name string, set *flag.FlagSet) bool {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
parsed, err := strconv.ParseBool(f.Value.String())
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// DurationFlag is a flag with type time.Duration (see https://golang.org/pkg/time/#ParseDuration)
|
||||
type DurationFlag struct {
|
||||
Name string
|
||||
Usage string
|
||||
EnvVar string
|
||||
Hidden bool
|
||||
Value time.Duration
|
||||
Destination *time.Duration
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value
|
||||
// (for usage defaults)
|
||||
func (f DurationFlag) String() string {
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag
|
||||
func (f DurationFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// Duration looks up the value of a local DurationFlag, returns
|
||||
// 0 if not found
|
||||
func (c *Context) Duration(name string) time.Duration {
|
||||
return lookupDuration(name, c.flagSet)
|
||||
}
|
||||
|
||||
// GlobalDuration looks up the value of a global DurationFlag, returns
|
||||
// 0 if not found
|
||||
func (c *Context) GlobalDuration(name string) time.Duration {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupDuration(name, fs)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func lookupDuration(name string, set *flag.FlagSet) time.Duration {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
parsed, err := time.ParseDuration(f.Value.String())
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Float64Flag is a flag with type float64
|
||||
type Float64Flag struct {
|
||||
Name string
|
||||
Usage string
|
||||
EnvVar string
|
||||
Hidden bool
|
||||
Value float64
|
||||
Destination *float64
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value
|
||||
// (for usage defaults)
|
||||
func (f Float64Flag) String() string {
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag
|
||||
func (f Float64Flag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// Float64 looks up the value of a local Float64Flag, returns
|
||||
// 0 if not found
|
||||
func (c *Context) Float64(name string) float64 {
|
||||
return lookupFloat64(name, c.flagSet)
|
||||
}
|
||||
|
||||
// GlobalFloat64 looks up the value of a global Float64Flag, returns
|
||||
// 0 if not found
|
||||
func (c *Context) GlobalFloat64(name string) float64 {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupFloat64(name, fs)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func lookupFloat64(name string, set *flag.FlagSet) float64 {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
parsed, err := strconv.ParseFloat(f.Value.String(), 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GenericFlag is a flag with type Generic
|
||||
type GenericFlag struct {
|
||||
Name string
|
||||
Usage string
|
||||
EnvVar string
|
||||
Hidden bool
|
||||
Value Generic
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value
|
||||
// (for usage defaults)
|
||||
func (f GenericFlag) String() string {
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag
|
||||
func (f GenericFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// Generic looks up the value of a local GenericFlag, returns
|
||||
// nil if not found
|
||||
func (c *Context) Generic(name string) interface{} {
|
||||
return lookupGeneric(name, c.flagSet)
|
||||
}
|
||||
|
||||
// GlobalGeneric looks up the value of a global GenericFlag, returns
|
||||
// nil if not found
|
||||
func (c *Context) GlobalGeneric(name string) interface{} {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupGeneric(name, fs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func lookupGeneric(name string, set *flag.FlagSet) interface{} {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
parsed, err := f.Value, error(nil)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Int64Flag is a flag with type int64
|
||||
type Int64Flag struct {
|
||||
Name string
|
||||
Usage string
|
||||
EnvVar string
|
||||
Hidden bool
|
||||
Value int64
|
||||
Destination *int64
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value
|
||||
// (for usage defaults)
|
||||
func (f Int64Flag) String() string {
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag
|
||||
func (f Int64Flag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// Int64 looks up the value of a local Int64Flag, returns
|
||||
// 0 if not found
|
||||
func (c *Context) Int64(name string) int64 {
|
||||
return lookupInt64(name, c.flagSet)
|
||||
}
|
||||
|
||||
// GlobalInt64 looks up the value of a global Int64Flag, returns
|
||||
// 0 if not found
|
||||
func (c *Context) GlobalInt64(name string) int64 {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupInt64(name, fs)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func lookupInt64(name string, set *flag.FlagSet) int64 {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
parsed, err := strconv.ParseInt(f.Value.String(), 0, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// IntFlag is a flag with type int
|
||||
type IntFlag struct {
|
||||
Name string
|
||||
Usage string
|
||||
EnvVar string
|
||||
Hidden bool
|
||||
Value int
|
||||
Destination *int
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value
|
||||
// (for usage defaults)
|
||||
func (f IntFlag) String() string {
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag
|
||||
func (f IntFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// Int looks up the value of a local IntFlag, returns
|
||||
// 0 if not found
|
||||
func (c *Context) Int(name string) int {
|
||||
return lookupInt(name, c.flagSet)
|
||||
}
|
||||
|
||||
// GlobalInt looks up the value of a global IntFlag, returns
|
||||
// 0 if not found
|
||||
func (c *Context) GlobalInt(name string) int {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupInt(name, fs)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func lookupInt(name string, set *flag.FlagSet) int {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
parsed, err := strconv.ParseInt(f.Value.String(), 0, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return int(parsed)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// IntSliceFlag is a flag with type *IntSlice
|
||||
type IntSliceFlag struct {
|
||||
Name string
|
||||
Usage string
|
||||
EnvVar string
|
||||
Hidden bool
|
||||
Value *IntSlice
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value
|
||||
// (for usage defaults)
|
||||
func (f IntSliceFlag) String() string {
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag
|
||||
func (f IntSliceFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// IntSlice looks up the value of a local IntSliceFlag, returns
|
||||
// nil if not found
|
||||
func (c *Context) IntSlice(name string) []int {
|
||||
return lookupIntSlice(name, c.flagSet)
|
||||
}
|
||||
|
||||
// GlobalIntSlice looks up the value of a global IntSliceFlag, returns
|
||||
// nil if not found
|
||||
func (c *Context) GlobalIntSlice(name string) []int {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupIntSlice(name, fs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func lookupIntSlice(name string, set *flag.FlagSet) []int {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
parsed, err := (f.Value.(*IntSlice)).Value(), error(nil)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Int64SliceFlag is a flag with type *Int64Slice
|
||||
type Int64SliceFlag struct {
|
||||
Name string
|
||||
Usage string
|
||||
EnvVar string
|
||||
Hidden bool
|
||||
Value *Int64Slice
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value
|
||||
// (for usage defaults)
|
||||
func (f Int64SliceFlag) String() string {
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag
|
||||
func (f Int64SliceFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// Int64Slice looks up the value of a local Int64SliceFlag, returns
|
||||
// nil if not found
|
||||
func (c *Context) Int64Slice(name string) []int64 {
|
||||
return lookupInt64Slice(name, c.flagSet)
|
||||
}
|
||||
|
||||
// GlobalInt64Slice looks up the value of a global Int64SliceFlag, returns
|
||||
// nil if not found
|
||||
func (c *Context) GlobalInt64Slice(name string) []int64 {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupInt64Slice(name, fs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func lookupInt64Slice(name string, set *flag.FlagSet) []int64 {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
parsed, err := (f.Value.(*Int64Slice)).Value(), error(nil)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// StringFlag is a flag with type string
|
||||
type StringFlag struct {
|
||||
Name string
|
||||
Usage string
|
||||
EnvVar string
|
||||
Hidden bool
|
||||
Value string
|
||||
Destination *string
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value
|
||||
// (for usage defaults)
|
||||
func (f StringFlag) String() string {
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag
|
||||
func (f StringFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// String looks up the value of a local StringFlag, returns
|
||||
// "" if not found
|
||||
func (c *Context) String(name string) string {
|
||||
return lookupString(name, c.flagSet)
|
||||
}
|
||||
|
||||
// GlobalString looks up the value of a global StringFlag, returns
|
||||
// "" if not found
|
||||
func (c *Context) GlobalString(name string) string {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupString(name, fs)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func lookupString(name string, set *flag.FlagSet) string {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
parsed, err := f.Value.String(), error(nil)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// StringSliceFlag is a flag with type *StringSlice
|
||||
type StringSliceFlag struct {
|
||||
Name string
|
||||
Usage string
|
||||
EnvVar string
|
||||
Hidden bool
|
||||
Value *StringSlice
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value
|
||||
// (for usage defaults)
|
||||
func (f StringSliceFlag) String() string {
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag
|
||||
func (f StringSliceFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// StringSlice looks up the value of a local StringSliceFlag, returns
|
||||
// nil if not found
|
||||
func (c *Context) StringSlice(name string) []string {
|
||||
return lookupStringSlice(name, c.flagSet)
|
||||
}
|
||||
|
||||
// GlobalStringSlice looks up the value of a global StringSliceFlag, returns
|
||||
// nil if not found
|
||||
func (c *Context) GlobalStringSlice(name string) []string {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupStringSlice(name, fs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func lookupStringSlice(name string, set *flag.FlagSet) []string {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
parsed, err := (f.Value.(*StringSlice)).Value(), error(nil)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Uint64Flag is a flag with type uint64
|
||||
type Uint64Flag struct {
|
||||
Name string
|
||||
Usage string
|
||||
EnvVar string
|
||||
Hidden bool
|
||||
Value uint64
|
||||
Destination *uint64
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value
|
||||
// (for usage defaults)
|
||||
func (f Uint64Flag) String() string {
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag
|
||||
func (f Uint64Flag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// Uint64 looks up the value of a local Uint64Flag, returns
|
||||
// 0 if not found
|
||||
func (c *Context) Uint64(name string) uint64 {
|
||||
return lookupUint64(name, c.flagSet)
|
||||
}
|
||||
|
||||
// GlobalUint64 looks up the value of a global Uint64Flag, returns
|
||||
// 0 if not found
|
||||
func (c *Context) GlobalUint64(name string) uint64 {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupUint64(name, fs)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func lookupUint64(name string, set *flag.FlagSet) uint64 {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
parsed, err := strconv.ParseUint(f.Value.String(), 0, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// UintFlag is a flag with type uint
|
||||
type UintFlag struct {
|
||||
Name string
|
||||
Usage string
|
||||
EnvVar string
|
||||
Hidden bool
|
||||
Value uint
|
||||
Destination *uint
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value
|
||||
// (for usage defaults)
|
||||
func (f UintFlag) String() string {
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag
|
||||
func (f UintFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// Uint looks up the value of a local UintFlag, returns
|
||||
// 0 if not found
|
||||
func (c *Context) Uint(name string) uint {
|
||||
return lookupUint(name, c.flagSet)
|
||||
}
|
||||
|
||||
// GlobalUint looks up the value of a global UintFlag, returns
|
||||
// 0 if not found
|
||||
func (c *Context) GlobalUint(name string) uint {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupUint(name, fs)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func lookupUint(name string, set *flag.FlagSet) uint {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
parsed, err := strconv.ParseUint(f.Value.String(), 0, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return uint(parsed)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
28
vendor/github.com/urfave/cli/funcs.go
generated
vendored
Normal file
28
vendor/github.com/urfave/cli/funcs.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
package cli
|
||||
|
||||
// BashCompleteFunc is an action to execute when the bash-completion flag is set
|
||||
type BashCompleteFunc func(*Context)
|
||||
|
||||
// BeforeFunc is an action to execute before any subcommands are run, but after
|
||||
// the context is ready if a non-nil error is returned, no subcommands are run
|
||||
type BeforeFunc func(*Context) error
|
||||
|
||||
// AfterFunc is an action to execute after any subcommands are run, but after the
|
||||
// subcommand has finished it is run even if Action() panics
|
||||
type AfterFunc func(*Context) error
|
||||
|
||||
// ActionFunc is the action to execute when no subcommands are specified
|
||||
type ActionFunc func(*Context) error
|
||||
|
||||
// CommandNotFoundFunc is executed if the proper command cannot be found
|
||||
type CommandNotFoundFunc func(*Context, string)
|
||||
|
||||
// OnUsageErrorFunc is executed if an usage error occurs. This is useful for displaying
|
||||
// customized usage error messages. This function is able to replace the
|
||||
// original error messages. If this function is not set, the "Incorrect usage"
|
||||
// is displayed and the execution is interrupted.
|
||||
type OnUsageErrorFunc func(context *Context, err error, isSubcommand bool) error
|
||||
|
||||
// FlagStringFunc is used by the help generation to display a flag, which is
|
||||
// expected to be a single line.
|
||||
type FlagStringFunc func(Flag) string
|
||||
255
vendor/github.com/urfave/cli/generate-flag-types
generated
vendored
Executable file
255
vendor/github.com/urfave/cli/generate-flag-types
generated
vendored
Executable file
@@ -0,0 +1,255 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
The flag types that ship with the cli library have many things in common, and
|
||||
so we can take advantage of the `go generate` command to create much of the
|
||||
source code from a list of definitions. These definitions attempt to cover
|
||||
the parts that vary between flag types, and should evolve as needed.
|
||||
|
||||
An example of the minimum definition needed is:
|
||||
|
||||
{
|
||||
"name": "SomeType",
|
||||
"type": "sometype",
|
||||
"context_default": "nil"
|
||||
}
|
||||
|
||||
In this example, the code generated for the `cli` package will include a type
|
||||
named `SomeTypeFlag` that is expected to wrap a value of type `sometype`.
|
||||
Fetching values by name via `*cli.Context` will default to a value of `nil`.
|
||||
|
||||
A more complete, albeit somewhat redundant, example showing all available
|
||||
definition keys is:
|
||||
|
||||
{
|
||||
"name": "VeryMuchType",
|
||||
"type": "*VeryMuchType",
|
||||
"value": true,
|
||||
"dest": false,
|
||||
"doctail": " which really only wraps a []float64, oh well!",
|
||||
"context_type": "[]float64",
|
||||
"context_default": "nil",
|
||||
"parser": "parseVeryMuchType(f.Value.String())",
|
||||
"parser_cast": "[]float64(parsed)"
|
||||
}
|
||||
|
||||
The meaning of each field is as follows:
|
||||
|
||||
name (string) - The type "name", which will be suffixed with
|
||||
`Flag` when generating the type definition
|
||||
for `cli` and the wrapper type for `altsrc`
|
||||
type (string) - The type that the generated `Flag` type for `cli`
|
||||
is expected to "contain" as its `.Value` member
|
||||
value (bool) - Should the generated `cli` type have a `Value`
|
||||
member?
|
||||
dest (bool) - Should the generated `cli` type support a
|
||||
destination pointer?
|
||||
doctail (string) - Additional docs for the `cli` flag type comment
|
||||
context_type (string) - The literal type used in the `*cli.Context`
|
||||
reader func signature
|
||||
context_default (string) - The literal value used as the default by the
|
||||
`*cli.Context` reader funcs when no value is
|
||||
present
|
||||
parser (string) - Literal code used to parse the flag `f`,
|
||||
expected to have a return signature of
|
||||
(value, error)
|
||||
parser_cast (string) - Literal code used to cast the `parsed` value
|
||||
returned from the `parser` code
|
||||
"""
|
||||
|
||||
from __future__ import print_function, unicode_literals
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import textwrap
|
||||
|
||||
|
||||
class _FancyFormatter(argparse.ArgumentDefaultsHelpFormatter,
|
||||
argparse.RawDescriptionHelpFormatter):
|
||||
pass
|
||||
|
||||
|
||||
def main(sysargs=sys.argv[:]):
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Generate flag type code!',
|
||||
formatter_class=_FancyFormatter)
|
||||
parser.add_argument(
|
||||
'package',
|
||||
type=str, default='cli', choices=_WRITEFUNCS.keys(),
|
||||
help='Package for which flag types will be generated'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-i', '--in-json',
|
||||
type=argparse.FileType('r'),
|
||||
default=sys.stdin,
|
||||
help='Input JSON file which defines each type to be generated'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-o', '--out-go',
|
||||
type=argparse.FileType('w'),
|
||||
default=sys.stdout,
|
||||
help='Output file/stream to which generated source will be written'
|
||||
)
|
||||
parser.epilog = __doc__
|
||||
|
||||
args = parser.parse_args(sysargs[1:])
|
||||
_generate_flag_types(_WRITEFUNCS[args.package], args.out_go, args.in_json)
|
||||
return 0
|
||||
|
||||
|
||||
def _generate_flag_types(writefunc, output_go, input_json):
|
||||
types = json.load(input_json)
|
||||
|
||||
tmp = tempfile.NamedTemporaryFile(suffix='.go', delete=False)
|
||||
writefunc(tmp, types)
|
||||
tmp.close()
|
||||
|
||||
new_content = subprocess.check_output(
|
||||
['goimports', tmp.name]
|
||||
).decode('utf-8')
|
||||
|
||||
print(new_content, file=output_go, end='')
|
||||
output_go.flush()
|
||||
os.remove(tmp.name)
|
||||
|
||||
|
||||
def _set_typedef_defaults(typedef):
|
||||
typedef.setdefault('doctail', '')
|
||||
typedef.setdefault('context_type', typedef['type'])
|
||||
typedef.setdefault('dest', True)
|
||||
typedef.setdefault('value', True)
|
||||
typedef.setdefault('parser', 'f.Value, error(nil)')
|
||||
typedef.setdefault('parser_cast', 'parsed')
|
||||
|
||||
|
||||
def _write_cli_flag_types(outfile, types):
|
||||
_fwrite(outfile, """\
|
||||
package cli
|
||||
|
||||
// WARNING: This file is generated!
|
||||
|
||||
""")
|
||||
|
||||
for typedef in types:
|
||||
_set_typedef_defaults(typedef)
|
||||
|
||||
_fwrite(outfile, """\
|
||||
// {name}Flag is a flag with type {type}{doctail}
|
||||
type {name}Flag struct {{
|
||||
Name string
|
||||
Usage string
|
||||
EnvVar string
|
||||
Hidden bool
|
||||
""".format(**typedef))
|
||||
|
||||
if typedef['value']:
|
||||
_fwrite(outfile, """\
|
||||
Value {type}
|
||||
""".format(**typedef))
|
||||
|
||||
if typedef['dest']:
|
||||
_fwrite(outfile, """\
|
||||
Destination *{type}
|
||||
""".format(**typedef))
|
||||
|
||||
_fwrite(outfile, "\n}\n\n")
|
||||
|
||||
_fwrite(outfile, """\
|
||||
// String returns a readable representation of this value
|
||||
// (for usage defaults)
|
||||
func (f {name}Flag) String() string {{
|
||||
return FlagStringer(f)
|
||||
}}
|
||||
|
||||
// GetName returns the name of the flag
|
||||
func (f {name}Flag) GetName() string {{
|
||||
return f.Name
|
||||
}}
|
||||
|
||||
// {name} looks up the value of a local {name}Flag, returns
|
||||
// {context_default} if not found
|
||||
func (c *Context) {name}(name string) {context_type} {{
|
||||
return lookup{name}(name, c.flagSet)
|
||||
}}
|
||||
|
||||
// Global{name} looks up the value of a global {name}Flag, returns
|
||||
// {context_default} if not found
|
||||
func (c *Context) Global{name}(name string) {context_type} {{
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {{
|
||||
return lookup{name}(name, fs)
|
||||
}}
|
||||
return {context_default}
|
||||
}}
|
||||
|
||||
func lookup{name}(name string, set *flag.FlagSet) {context_type} {{
|
||||
f := set.Lookup(name)
|
||||
if f != nil {{
|
||||
parsed, err := {parser}
|
||||
if err != nil {{
|
||||
return {context_default}
|
||||
}}
|
||||
return {parser_cast}
|
||||
}}
|
||||
return {context_default}
|
||||
}}
|
||||
""".format(**typedef))
|
||||
|
||||
|
||||
def _write_altsrc_flag_types(outfile, types):
|
||||
_fwrite(outfile, """\
|
||||
package altsrc
|
||||
|
||||
import (
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
)
|
||||
|
||||
// WARNING: This file is generated!
|
||||
|
||||
""")
|
||||
|
||||
for typedef in types:
|
||||
_set_typedef_defaults(typedef)
|
||||
|
||||
_fwrite(outfile, """\
|
||||
// {name}Flag is the flag type that wraps cli.{name}Flag to allow
|
||||
// for other values to be specified
|
||||
type {name}Flag struct {{
|
||||
cli.{name}Flag
|
||||
set *flag.FlagSet
|
||||
}}
|
||||
|
||||
// New{name}Flag creates a new {name}Flag
|
||||
func New{name}Flag(fl cli.{name}Flag) *{name}Flag {{
|
||||
return &{name}Flag{{{name}Flag: fl, set: nil}}
|
||||
}}
|
||||
|
||||
// Apply saves the flagSet for later usage calls, then calls the
|
||||
// wrapped {name}Flag.Apply
|
||||
func (f *{name}Flag) Apply(set *flag.FlagSet) {{
|
||||
f.set = set
|
||||
f.{name}Flag.Apply(set)
|
||||
}}
|
||||
|
||||
// ApplyWithError saves the flagSet for later usage calls, then calls the
|
||||
// wrapped {name}Flag.ApplyWithError
|
||||
func (f *{name}Flag) ApplyWithError(set *flag.FlagSet) error {{
|
||||
f.set = set
|
||||
return f.{name}Flag.ApplyWithError(set)
|
||||
}}
|
||||
""".format(**typedef))
|
||||
|
||||
|
||||
def _fwrite(outfile, text):
|
||||
print(textwrap.dedent(text), end='', file=outfile)
|
||||
|
||||
|
||||
_WRITEFUNCS = {
|
||||
'cli': _write_cli_flag_types,
|
||||
'altsrc': _write_altsrc_flag_types
|
||||
}
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
294
vendor/github.com/urfave/cli/help.go
generated
vendored
Normal file
294
vendor/github.com/urfave/cli/help.go
generated
vendored
Normal file
@@ -0,0 +1,294 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
// AppHelpTemplate is the text template for the Default help topic.
|
||||
// cli.go uses text/template to render templates. You can
|
||||
// render custom help text by setting this variable.
|
||||
var AppHelpTemplate = `NAME:
|
||||
{{.Name}}{{if .Usage}} - {{.Usage}}{{end}}
|
||||
|
||||
USAGE:
|
||||
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
|
||||
|
||||
VERSION:
|
||||
{{.Version}}{{end}}{{end}}{{if .Description}}
|
||||
|
||||
DESCRIPTION:
|
||||
{{.Description}}{{end}}{{if len .Authors}}
|
||||
|
||||
AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
|
||||
{{range $index, $author := .Authors}}{{if $index}}
|
||||
{{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}}
|
||||
|
||||
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
|
||||
{{.Name}}:{{end}}{{range .VisibleCommands}}
|
||||
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
|
||||
|
||||
GLOBAL OPTIONS:
|
||||
{{range $index, $option := .VisibleFlags}}{{if $index}}
|
||||
{{end}}{{$option}}{{end}}{{end}}{{if .Copyright}}
|
||||
|
||||
COPYRIGHT:
|
||||
{{.Copyright}}{{end}}
|
||||
`
|
||||
|
||||
// CommandHelpTemplate is the text template for the command help topic.
|
||||
// cli.go uses text/template to render templates. You can
|
||||
// render custom help text by setting this variable.
|
||||
var CommandHelpTemplate = `NAME:
|
||||
{{.HelpName}} - {{.Usage}}
|
||||
|
||||
USAGE:
|
||||
{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{if .Category}}
|
||||
|
||||
CATEGORY:
|
||||
{{.Category}}{{end}}{{if .Description}}
|
||||
|
||||
DESCRIPTION:
|
||||
{{.Description}}{{end}}{{if .VisibleFlags}}
|
||||
|
||||
OPTIONS:
|
||||
{{range .VisibleFlags}}{{.}}
|
||||
{{end}}{{end}}
|
||||
`
|
||||
|
||||
// SubcommandHelpTemplate is the text template for the subcommand help topic.
|
||||
// cli.go uses text/template to render templates. You can
|
||||
// render custom help text by setting this variable.
|
||||
var SubcommandHelpTemplate = `NAME:
|
||||
{{.HelpName}} - {{.Usage}}
|
||||
|
||||
USAGE:
|
||||
{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}
|
||||
|
||||
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
|
||||
{{.Name}}:{{end}}{{range .VisibleCommands}}
|
||||
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}
|
||||
{{end}}{{if .VisibleFlags}}
|
||||
OPTIONS:
|
||||
{{range .VisibleFlags}}{{.}}
|
||||
{{end}}{{end}}
|
||||
`
|
||||
|
||||
var helpCommand = Command{
|
||||
Name: "help",
|
||||
Aliases: []string{"h"},
|
||||
Usage: "Shows a list of commands or help for one command",
|
||||
ArgsUsage: "[command]",
|
||||
Action: func(c *Context) error {
|
||||
args := c.Args()
|
||||
if args.Present() {
|
||||
return ShowCommandHelp(c, args.First())
|
||||
}
|
||||
|
||||
ShowAppHelp(c)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var helpSubcommand = Command{
|
||||
Name: "help",
|
||||
Aliases: []string{"h"},
|
||||
Usage: "Shows a list of commands or help for one command",
|
||||
ArgsUsage: "[command]",
|
||||
Action: func(c *Context) error {
|
||||
args := c.Args()
|
||||
if args.Present() {
|
||||
return ShowCommandHelp(c, args.First())
|
||||
}
|
||||
|
||||
return ShowSubcommandHelp(c)
|
||||
},
|
||||
}
|
||||
|
||||
// Prints help for the App or Command
|
||||
type helpPrinter func(w io.Writer, templ string, data interface{})
|
||||
|
||||
// HelpPrinter is a function that writes the help output. If not set a default
|
||||
// is used. The function signature is:
|
||||
// func(w io.Writer, templ string, data interface{})
|
||||
var HelpPrinter helpPrinter = printHelp
|
||||
|
||||
// VersionPrinter prints the version for the App
|
||||
var VersionPrinter = printVersion
|
||||
|
||||
// ShowAppHelp is an action that displays the help.
|
||||
func ShowAppHelp(c *Context) error {
|
||||
HelpPrinter(c.App.Writer, AppHelpTemplate, c.App)
|
||||
return nil
|
||||
}
|
||||
|
||||
// DefaultAppComplete prints the list of subcommands as the default app completion method
|
||||
func DefaultAppComplete(c *Context) {
|
||||
for _, command := range c.App.Commands {
|
||||
if command.Hidden {
|
||||
continue
|
||||
}
|
||||
for _, name := range command.Names() {
|
||||
fmt.Fprintln(c.App.Writer, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ShowCommandHelp prints help for the given command
|
||||
func ShowCommandHelp(ctx *Context, command string) error {
|
||||
// show the subcommand help for a command with subcommands
|
||||
if command == "" {
|
||||
HelpPrinter(ctx.App.Writer, SubcommandHelpTemplate, ctx.App)
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, c := range ctx.App.Commands {
|
||||
if c.HasName(command) {
|
||||
HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.App.CommandNotFound == nil {
|
||||
return NewExitError(fmt.Sprintf("No help topic for '%v'", command), 3)
|
||||
}
|
||||
|
||||
ctx.App.CommandNotFound(ctx, command)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ShowSubcommandHelp prints help for the given subcommand
|
||||
func ShowSubcommandHelp(c *Context) error {
|
||||
return ShowCommandHelp(c, c.Command.Name)
|
||||
}
|
||||
|
||||
// ShowVersion prints the version number of the App
|
||||
func ShowVersion(c *Context) {
|
||||
VersionPrinter(c)
|
||||
}
|
||||
|
||||
func printVersion(c *Context) {
|
||||
fmt.Fprintf(c.App.Writer, "%v version %v\n", c.App.Name, c.App.Version)
|
||||
}
|
||||
|
||||
// ShowCompletions prints the lists of commands within a given context
|
||||
func ShowCompletions(c *Context) {
|
||||
a := c.App
|
||||
if a != nil && a.BashComplete != nil {
|
||||
a.BashComplete(c)
|
||||
}
|
||||
}
|
||||
|
||||
// ShowCommandCompletions prints the custom completions for a given command
|
||||
func ShowCommandCompletions(ctx *Context, command string) {
|
||||
c := ctx.App.Command(command)
|
||||
if c != nil && c.BashComplete != nil {
|
||||
c.BashComplete(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
func printHelp(out io.Writer, templ string, data interface{}) {
|
||||
funcMap := template.FuncMap{
|
||||
"join": strings.Join,
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(out, 1, 8, 2, ' ', 0)
|
||||
t := template.Must(template.New("help").Funcs(funcMap).Parse(templ))
|
||||
err := t.Execute(w, data)
|
||||
if err != nil {
|
||||
// If the writer is closed, t.Execute will fail, and there's nothing
|
||||
// we can do to recover.
|
||||
if os.Getenv("CLI_TEMPLATE_ERROR_DEBUG") != "" {
|
||||
fmt.Fprintf(ErrWriter, "CLI TEMPLATE ERROR: %#v\n", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
w.Flush()
|
||||
}
|
||||
|
||||
func checkVersion(c *Context) bool {
|
||||
found := false
|
||||
if VersionFlag.Name != "" {
|
||||
eachName(VersionFlag.Name, func(name string) {
|
||||
if c.GlobalBool(name) || c.Bool(name) {
|
||||
found = true
|
||||
}
|
||||
})
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
||||
func checkHelp(c *Context) bool {
|
||||
found := false
|
||||
if HelpFlag.Name != "" {
|
||||
eachName(HelpFlag.Name, func(name string) {
|
||||
if c.GlobalBool(name) || c.Bool(name) {
|
||||
found = true
|
||||
}
|
||||
})
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
||||
func checkCommandHelp(c *Context, name string) bool {
|
||||
if c.Bool("h") || c.Bool("help") {
|
||||
ShowCommandHelp(c, name)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func checkSubcommandHelp(c *Context) bool {
|
||||
if c.Bool("h") || c.Bool("help") {
|
||||
ShowSubcommandHelp(c)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) {
|
||||
if !a.EnableBashCompletion {
|
||||
return false, arguments
|
||||
}
|
||||
|
||||
pos := len(arguments) - 1
|
||||
lastArg := arguments[pos]
|
||||
|
||||
if lastArg != "--"+BashCompletionFlag.Name {
|
||||
return false, arguments
|
||||
}
|
||||
|
||||
return true, arguments[:pos]
|
||||
}
|
||||
|
||||
func checkCompletions(c *Context) bool {
|
||||
if !c.shellComplete {
|
||||
return false
|
||||
}
|
||||
|
||||
if args := c.Args(); args.Present() {
|
||||
name := args.First()
|
||||
if cmd := c.App.Command(name); cmd != nil {
|
||||
// let the command handle the completion
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
ShowCompletions(c)
|
||||
return true
|
||||
}
|
||||
|
||||
func checkCommandCompletions(c *Context, name string) bool {
|
||||
if !c.shellComplete {
|
||||
return false
|
||||
}
|
||||
|
||||
ShowCommandCompletions(c, name)
|
||||
return true
|
||||
}
|
||||
122
vendor/github.com/urfave/cli/runtests
generated
vendored
Executable file
122
vendor/github.com/urfave/cli/runtests
generated
vendored
Executable file
@@ -0,0 +1,122 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
from subprocess import check_call, check_output
|
||||
|
||||
|
||||
PACKAGE_NAME = os.environ.get(
|
||||
'CLI_PACKAGE_NAME', 'github.com/urfave/cli'
|
||||
)
|
||||
|
||||
|
||||
def main(sysargs=sys.argv[:]):
|
||||
targets = {
|
||||
'vet': _vet,
|
||||
'test': _test,
|
||||
'gfmrun': _gfmrun,
|
||||
'toc': _toc,
|
||||
'gen': _gen,
|
||||
}
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
'target', nargs='?', choices=tuple(targets.keys()), default='test'
|
||||
)
|
||||
args = parser.parse_args(sysargs[1:])
|
||||
|
||||
targets[args.target]()
|
||||
return 0
|
||||
|
||||
|
||||
def _test():
|
||||
if check_output('go version'.split()).split()[2] < 'go1.2':
|
||||
_run('go test -v .')
|
||||
return
|
||||
|
||||
coverprofiles = []
|
||||
for subpackage in ['', 'altsrc']:
|
||||
coverprofile = 'cli.coverprofile'
|
||||
if subpackage != '':
|
||||
coverprofile = '{}.coverprofile'.format(subpackage)
|
||||
|
||||
coverprofiles.append(coverprofile)
|
||||
|
||||
_run('go test -v'.split() + [
|
||||
'-coverprofile={}'.format(coverprofile),
|
||||
('{}/{}'.format(PACKAGE_NAME, subpackage)).rstrip('/')
|
||||
])
|
||||
|
||||
combined_name = _combine_coverprofiles(coverprofiles)
|
||||
_run('go tool cover -func={}'.format(combined_name))
|
||||
os.remove(combined_name)
|
||||
|
||||
|
||||
def _gfmrun():
|
||||
go_version = check_output('go version'.split()).split()[2]
|
||||
if go_version < 'go1.3':
|
||||
print('runtests: skip on {}'.format(go_version), file=sys.stderr)
|
||||
return
|
||||
_run(['gfmrun', '-c', str(_gfmrun_count()), '-s', 'README.md'])
|
||||
|
||||
|
||||
def _vet():
|
||||
_run('go vet ./...')
|
||||
|
||||
|
||||
def _toc():
|
||||
_run('node_modules/.bin/markdown-toc -i README.md')
|
||||
_run('git diff --exit-code')
|
||||
|
||||
|
||||
def _gen():
|
||||
go_version = check_output('go version'.split()).split()[2]
|
||||
if go_version < 'go1.5':
|
||||
print('runtests: skip on {}'.format(go_version), file=sys.stderr)
|
||||
return
|
||||
|
||||
_run('go generate ./...')
|
||||
_run('git diff --exit-code')
|
||||
|
||||
|
||||
def _run(command):
|
||||
if hasattr(command, 'split'):
|
||||
command = command.split()
|
||||
print('runtests: {}'.format(' '.join(command)), file=sys.stderr)
|
||||
check_call(command)
|
||||
|
||||
|
||||
def _gfmrun_count():
|
||||
with open('README.md') as infile:
|
||||
lines = infile.read().splitlines()
|
||||
return len(filter(_is_go_runnable, lines))
|
||||
|
||||
|
||||
def _is_go_runnable(line):
|
||||
return line.startswith('package main')
|
||||
|
||||
|
||||
def _combine_coverprofiles(coverprofiles):
|
||||
combined = tempfile.NamedTemporaryFile(
|
||||
suffix='.coverprofile', delete=False
|
||||
)
|
||||
combined.write('mode: set\n')
|
||||
|
||||
for coverprofile in coverprofiles:
|
||||
with open(coverprofile, 'r') as infile:
|
||||
for line in infile.readlines():
|
||||
if not line.startswith('mode: '):
|
||||
combined.write(line)
|
||||
|
||||
combined.flush()
|
||||
name = combined.name
|
||||
combined.close()
|
||||
return name
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user