| // Copyright 2019 CUE Authors |
| // |
| // 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. |
| |
| package cmd |
| |
| import ( |
| "fmt" |
| "math/rand" |
| "net/url" |
| "os" |
| "path/filepath" |
| "strings" |
| |
| "github.com/spf13/cobra" |
| ) |
| |
| func newModCmd(c *Command) *cobra.Command { |
| cmd := &cobra.Command{ |
| Use: "mod <cmd> [arguments]", |
| Short: "module maintenance", |
| Long: ` |
| `, |
| RunE: mkRunE(c, func(cmd *Command, args []string) error { |
| stderr := cmd.Stderr() |
| if len(args) == 0 { |
| fmt.Fprintln(stderr, "mod must be run as one of its subcommands") |
| } else { |
| fmt.Fprintf(stderr, "mod must be run as one of its subcommands: unknown subcommand %q\n", args[0]) |
| } |
| fmt.Fprintln(stderr, "Run 'cue help mod' for known subcommands.") |
| os.Exit(1) // TODO: get rid of this |
| return nil |
| }), |
| } |
| |
| cmd.AddCommand(newModInitCmd(c)) |
| return cmd |
| } |
| |
| func newModInitCmd(c *Command) *cobra.Command { |
| cmd := &cobra.Command{ |
| Use: "init [module]", |
| Short: "initialize new module in current directory", |
| Long: `Init initializes a cue.mod directory in the current directory, |
| in effect creating a new module rooted at the current directory. |
| The cue.mod directory must not already exist. |
| A legacy cue.mod file in the current directory is moved |
| to the new subdirectory. |
| |
| A module name is optional, but if it is not given a packages |
| within the module cannot imported another package defined |
| in the module. |
| `, |
| RunE: mkRunE(c, runModInit), |
| } |
| |
| cmd.Flags().BoolP(string(flagForce), "f", false, "force moving old-style cue.mod file") |
| |
| return cmd |
| } |
| |
| func runModInit(cmd *Command, args []string) (err error) { |
| defer func() { |
| if err != nil { |
| // TODO: Refactor Cobra usage to do something more principled |
| fmt.Fprintln(cmd.OutOrStderr(), err) |
| os.Exit(1) |
| } |
| }() |
| |
| module := "" |
| if len(args) > 0 { |
| if len(args) != 1 { |
| return fmt.Errorf("too many arguments") |
| } |
| module = args[0] |
| u, err := url.Parse("https://" + module) |
| if err != nil { |
| return fmt.Errorf("invalid module name: %v", module) |
| } |
| if h := u.Hostname(); !strings.Contains(h, ".") { |
| return fmt.Errorf("invalid host name %q", h) |
| } |
| } |
| |
| cwd, err := os.Getwd() |
| if err != nil { |
| return err |
| } |
| |
| mod := filepath.Join(cwd, "cue.mod") |
| |
| info, err := os.Stat(mod) |
| |
| // Detect old setups and backport it if requested. |
| if err == nil && !info.IsDir() { |
| // This path backports |
| if !flagForce.Bool(cmd) { |
| return fmt.Errorf("detected old-style config file; use --force to upgrade") |
| } |
| return backport(mod, cwd) |
| } |
| |
| if err == nil { |
| return fmt.Errorf("cue.mod directory already exists") |
| } |
| |
| err = os.Mkdir(mod, 0755) |
| if err != nil && !os.IsExist(err) { |
| return err |
| } |
| |
| f, err := os.Create(filepath.Join(mod, "module.cue")) |
| if err != nil { |
| return err |
| } |
| defer f.Close() |
| |
| // Set module even if it is empty, making it easier for users to fill it in. |
| _, err = fmt.Fprintf(f, "module: %q\n", module) |
| |
| if err = os.Mkdir(filepath.Join(mod, "usr"), 0755); err != nil { |
| return err |
| } |
| if err = os.Mkdir(filepath.Join(mod, "pkg"), 0755); err != nil { |
| return err |
| } |
| |
| return err |
| } |
| |
| // backport backports an old cue.mod setup to a new one. |
| func backport(mod, cwd string) error { |
| tmp := filepath.Join(cwd, fmt.Sprintf("_%x_cue.mod", rand.Int())) |
| err := os.Rename(mod, tmp) |
| if err != nil { |
| return err |
| } |
| |
| err = os.Mkdir(filepath.Join(cwd, "cue.mod"), 0755) |
| if err != nil { |
| os.Rename(tmp, mod) |
| return err |
| } |
| |
| err = os.Rename(tmp, filepath.Join(cwd, "cue.mod", "module.cue")) |
| if err != nil { |
| return err |
| } |
| |
| err = os.Rename(filepath.Join(cwd, "pkg"), filepath.Join(cwd, "cue.mod", "gen")) |
| if err != nil && !os.IsNotExist(err) { |
| return err |
| } |
| |
| if err = os.Mkdir(filepath.Join(mod, "usr"), 0755); err != nil { |
| return err |
| } |
| if err = os.Mkdir(filepath.Join(mod, "pkg"), 0755); err != nil { |
| return err |
| } |
| |
| return nil |
| } |