View the release notes for guidance on migrating => https://github.com/urfave/cli/releases/tag/v2.0.0
Here's a PR where @ffrank and @purpleidea make the v1 => v2 migration https://github.com/purpleidea/mgmt/pull/571
Here's a quirky example of someone moving from the _very very old_ v2 branch, to the latest v1 release https://github.com/sourcegraph/godockerize/pull/10
☝️ I don't think that's the type of migration where's really looking to write documentation for? but it's interesting to look at
Here's another example migration PR https://github.com/google/cloud-print-connector/pull/470
I'm going to work on this as a part of https://github.com/urfave/cli/issues/952
In addition to working on this as a part of https://github.com/urfave/cli/issues/952, I've been progressively updating the v2 release notes => https://github.com/urfave/cli/releases/tag/v2.0.0 to include fine grain migration instructions. I'll add more as I find them!
+1 migration PR => https://github.com/technosophos/dashing/pull/52
command line flag migration steps also need to be updated, at the very least to document the way command-line flag aliases now behave.
Previously you could define aliases liek:
cli.StringFlag{
Name: "config, cfg"
}
however you now need to do
cli.StringFlag{
Name: "config",
Aliases: []string{"cfg"},
}
Here is a minimal repro
package main
import (
"fmt"
"os"
// auto register pprof handlers
_ "net/http/pprof"
au "github.com/logrusorgru/aurora"
"github.com/urfave/cli/v2"
)
func main() {
// generate the actual cli app
app := newApp()
// runthe cli app
if err := app.Run(os.Args); err != nil {
fmt.Printf(
"%s %s\n",
au.Bold(au.Red("error encountered:")),
au.Red(err.Error()),
)
os.Exit(1)
}
}
func newApp() *cli.App {
app := cli.NewApp()
app.Flags = loadFlags()
return app
}
func loadFlags() []cli.Flag {
return []cli.Flag{
&cli.BoolFlag{
Name: "bootstrap, bp",
Usage: "bootstrap against public ipfs",
},
&cli.StringFlag{
Name: "config, cfg",
Usage: "load the configuration file at `PATH`",
Value: "./config.yml",
},
}
}
@bonedaddy 👍 I added these lines
- Removed the ability to specify multiple entries in the
Command.Namefield
- when updating, replace
Name: "a, b, c"withName: "a", Aliases: []string{"b", "c"}
@bonedaddy I added these lines
Removed the ability to specify multiple entries in the
Command.Namefield
- when updating, replace
Name: "a, b, c"withName: "a", Aliases: []string{"b", "c"}
sweet, thank you :rocket:
I kept notes as I did a recent conversion. I think these are going to be the typical "first steps" for people (well... people like me!)
import "github.com/urfave/cli"import "github.com/urfave/cli/v2"Change Name: "foo, f to "Name: "foo", Aliases: []string{"f"}`
(Steal the examples in
https://github.com/urfave/cli/issues/921#issuecomment-570763084
...they are better)
What this means to you:
a. Look for []cli.Command{} and change it to []*cli.Command{}
Example:
var commands = []cli.Command{}var commands = []*cli.Command{}Compiler messages you might see:
commands/commands.go:56:30: cannot convert commands (type []cli.Command) to type cli.CommandsByName
commands/commands.go:57:15: cannot use commands (type []cli.Command) as type []*cli.Command in assignment
b. If you are building a list of commands, change to pointers
cli.Command{&cli.Command{Compiler messages you might see:
./commands.go:32:34: cannot use cli.Command literal (type cli.Command) as type *cli.Command in argument to
cli.Flag is now a list of pointersWhat this means to you:
If you make a list of flags, add a & in front of each
item. cli.BoolFlag, cli.StringFlag, etc
OLD:
app.Flags = []cli.Flag{
cli.BoolFlag{
NEW:
app.Flags = []cli.Flag{
&cli.BoolFlag{
Compiler messages you might see:
cli.StringFlag does not implement cli.Flag (Apply method has pointer receiver)
b. appending to a list of commands needs pointers:
commands = append(commands, *c)commands = append(commands, c)Compiler messages you might see:
commands/commands.go:28:19: cannot use c (type *cli.Command) as type cli.Command in append
Action: now returns an errorAction: func(c *cli.Context) {Action: func(c *cli.Context) error {Compiler messages you might see:
`
./commands.go:35:2: cannot use func literal (type func(*cli.Context)) as type cli.ActionFunc in field value
Those are good notes, thanks @TomOnTime ✨
Those are good notes, thanks @TomOnTime ✨
Thanks!
If I may be so bold: I think the typical user of urfave/cli would rather have a few conversion tips now than the perfect document in the future. I would be honored if you published my notes as the starting point; people could send PRs with improvements over time.
It turns out that the conversion process is pretty easy, but I had been avoiding it because I didn't know how hard or difficult it would be. Luckily I had some free time this weekend and decided to guess my way through the compiler errors and see if it would "just work". Other people might not be so willing to "just try it". A nudge in the docs would empower people to give it a try.
If I may be so bold: I think the typical user of urfave/cli would rather have a few conversion tips now than the perfect document in the future.
I'll follow up on this sometime soon 👍
I'm not sure if this is intentional, a side effect or something I have done wrong but after moving from v1 to v2, flags must come before args ie:
This will work
cli hello --shout rick
This will not
cli hello rick --shout
If this is intentional i couldn't find it documented anywhere and is a major gotcha for migrating.
I took a swing at this. See https://github.com/urfave/cli/pull/1098
@nodefortytwo that change isn't specific to V2, it's an issue where the behavior flipped back and forth in V1 too. Here's an example of me changing some V1 code for this problem => https://github.com/urfave/cli/pull/872
@nodefortytwo if you have capacity, I would welcome contributors for more test cases here! It's never been 100% clear what the ideal behavior should be, which is why the behavior has shifted over time.
In cli.StringFlag type,
V1 expression is EnvVar: "XXXXX"
V2 expression is EnvVars: []string{"XXXXX"}
@guo1017138 ... please take a look at https://github.com/urfave/cli/pull/1137
Another change to document - c.GlobalBool(), c.GlobalString() and friends seem to have gone.
cli.Context.Parent() is gone, and seems to be replaced by cli.Context.Lineage
Most helpful comment
I kept notes as I did a recent conversion. I think these are going to be the typical "first steps" for people (well... people like me!)
import "github.com/urfave/cli"import "github.com/urfave/cli/v2"Change
Name: "foo, fto "Name: "foo", Aliases: []string{"f"}`(Steal the examples in
https://github.com/urfave/cli/issues/921#issuecomment-570763084
...they are better)
What this means to you:
a. Look for
[]cli.Command{}and change it to[]*cli.Command{}Example:
var commands = []cli.Command{}var commands = []*cli.Command{}Compiler messages you might see:
commands/commands.go:56:30: cannot convert commands (type []cli.Command) to type cli.CommandsByName commands/commands.go:57:15: cannot use commands (type []cli.Command) as type []*cli.Command in assignmentb. If you are building a list of commands, change to pointers
cli.Command{&cli.Command{Compiler messages you might see:
./commands.go:32:34: cannot use cli.Command literal (type cli.Command) as type *cli.Command in argument tocli.Flagis now a list of pointersWhat this means to you:
If you make a list of flags, add a
&in front of eachitem. cli.BoolFlag, cli.StringFlag, etc
OLD:
app.Flags = []cli.Flag{ cli.BoolFlag{NEW:
app.Flags = []cli.Flag{ &cli.BoolFlag{Compiler messages you might see:
cli.StringFlag does not implement cli.Flag (Apply method has pointer receiver)b. appending to a list of commands needs pointers:
commands = append(commands, *c)commands = append(commands, c)Compiler messages you might see:
commands/commands.go:28:19: cannot use c (type *cli.Command) as type cli.Command in appendAction:now returns anerrorAction: func(c *cli.Context) {Action: func(c *cli.Context) error {Compiler messages you might see:
`
./commands.go:35:2: cannot use func literal (type func(*cli.Context)) as type cli.ActionFunc in field value