Asking if imports not in code should be imported
diff --git a/action/create.go b/action/create.go
index 800ec48..bad74e1 100644
--- a/action/create.go
+++ b/action/create.go
@@ -31,13 +31,13 @@
// If skipImport is set to true, this will not attempt to import from an existing
// GPM, Godep, or GB project if one should exist. However, it will still attempt
// to read the local source to determine required packages.
-func Create(base string, skipImport bool) {
+func Create(base string, skipImport, noInteract bool) {
glidefile := gpath.GlideFile
// Guard against overwrites.
guardYAML(glidefile)
// Guess deps
- conf := guessDeps(base, skipImport)
+ conf := guessDeps(base, skipImport, noInteract)
// Write YAML
msg.Info("Writing glide.yaml file")
if err := conf.WriteFile(glidefile); err != nil {
@@ -64,7 +64,7 @@
//
// FIXME: This function is likely a one-off that has a more standard alternative.
// It's also long and could use a refactor.
-func guessDeps(base string, skipImport bool) *cfg.Config {
+func guessDeps(base string, skipImport, noInteract bool) *cfg.Config {
buildContext, err := util.GetBuildContext()
if err != nil {
msg.Die("Failed to build an import context: %s", err)
@@ -80,21 +80,17 @@
// Import by looking at other package managers and looking over the
// entire directory structure.
+ var deps cfg.Dependencies
// Attempt to import from other package managers.
if !skipImport {
- guessImportDeps(base, config)
+ deps = guessImportDeps(base)
+ if len(deps) == 0 {
+ msg.Info("No dependencies found to import")
+ }
}
- importLen := len(config.Imports)
- if importLen > 0 {
- msg.Info("Scanning code to look for additional dependencies")
- } else if !skipImport {
- msg.Info("No dependencies found to import")
- msg.Info("Scanning code to look for dependencies")
- } else {
- msg.Info("Scanning code to look for dependencies")
- }
+ msg.Info("Scanning code to look for dependencies")
// Resolve dependencies by looking at the tree.
r, err := dependency.NewResolver(base)
@@ -124,37 +120,72 @@
if !config.HasDependency(root) {
count++
- msg.Info("--> Found reference to %s\n", n)
- d := &cfg.Dependency{
- Name: root,
+ d := deps.Get(root)
+ if d == nil {
+ d = &cfg.Dependency{
+ Name: root,
+ }
+ msg.Info("--> Found reference to %s", n)
+ } else {
+ msg.Info("--> Found reference to %s. Importing version %s", n, d.Reference)
}
- if len(subpkg) > 0 {
- d.Subpackages = []string{subpkg}
+
+ if subpkg != "" {
+ if !d.HasSubpackage(subpkg) {
+ d.Subpackages = append(d.Subpackages, subpkg)
+ }
+ msg.Verbose("--> Noting sub-package %s to %s", subpkg, root)
}
+
config.Imports = append(config.Imports, d)
} else {
if len(subpkg) > 0 {
subpkg = strings.TrimPrefix(subpkg, "/")
d := config.Imports.Get(root)
if !d.HasSubpackage(subpkg) {
- count++
- msg.Info("--> Adding sub-package %s to %s\n", subpkg, root)
d.Subpackages = append(d.Subpackages, subpkg)
}
+ msg.Verbose("--> Noting sub-package %s to %s", subpkg, root)
+ }
+ }
+ }
+
+ if !skipImport && len(deps) > count {
+ var res string
+ if noInteract {
+ res = "y"
+ } else {
+ msg.Info("%d unused imported dependencies found. These are likely transitive dependencies ", len(deps)-count)
+ msg.Info("(dependencies of your dependencies). Would you like to track them in your")
+ msg.Info("glide.yaml file? Note, Glide will automatically scan your codebase to detect")
+ msg.Info("the complete dependency tree and import the complete tree. If your dependencies")
+ msg.Info("do not track dependency version information some version information may be lost.")
+ msg.Info("Yes (y) or No (n)?")
+ res, err = msg.PromptUntil([]string{"y", "yes", "n", "no"})
+ if err != nil {
+ msg.Die("Error processing response: %s", err)
+ }
+ }
+ if res == "y" || res == "yes" {
+ msg.Info("Including additional imports in the glide.yaml file")
+ for _, dep := range deps {
+ found := config.Imports.Get(dep.Name)
+ if found == nil {
+ config.Imports = append(config.Imports, dep)
+ if dep.Reference != "" {
+ msg.Info("--> Adding %s at version %s", dep.Name, dep.Reference)
+ } else {
+ msg.Info("--> Adding %s", dep.Name)
+ }
+ }
}
}
}
- if count == 0 && importLen > 0 {
- msg.Info("--> Scanning found no additional dependencies to import")
- } else if count == 0 {
- msg.Info("--> Scanning found no dependencies to import")
- }
-
return config
}
-func guessImportDeps(base string, config *cfg.Config) {
+func guessImportDeps(base string) cfg.Dependencies {
msg.Info("Attempting to import from other package managers (use --skip-import to skip)")
deps := []*cfg.Dependency{}
absBase, err := filepath.Abs(base)
@@ -178,7 +209,7 @@
}
if len(deps) > 0 {
- msg.Info("--> Attempting to detect versions from commit ids")
+ msg.Info("--> Attempting to detect versions from imported commit ids")
}
var wg sync.WaitGroup
@@ -194,19 +225,19 @@
}
ver := createGuessVersion(remote, dep.Reference)
if ver != dep.Reference {
- msg.Info("--> Found imported reference to %s at version %s", dep.Name, ver)
+ msg.Verbose("--> Found imported reference to %s at version %s", dep.Name, ver)
dep.Reference = ver
- } else {
- msg.Info("--> Found imported reference to %s", dep.Name)
}
+ msg.Debug("--> Found imported reference to %s at revision %s", dep.Name, dep.Reference)
+
wg.Done()
}(i)
-
- config.Imports = append(config.Imports, i)
}
wg.Wait()
+
+ return deps
}
func guessImportGodep(dir string) ([]*cfg.Dependency, bool) {
diff --git a/action/debug.go b/action/debug.go
index 7b8eea6..6af9d26 100644
--- a/action/debug.go
+++ b/action/debug.go
@@ -7,6 +7,15 @@
// Debug sets the debugging flags across components.
func Debug(on bool) {
msg.Default.IsDebugging = on
+
+ if on == true {
+ msg.Default.IsVerbose = on
+ }
+}
+
+// Verbose sets the verbose flags across components.
+func Verbose(on bool) {
+ msg.Default.IsVerbose = on
}
// Quiet sets the quiet flags across components.
diff --git a/glide.go b/glide.go
index 2ce9fcc..3f703b4 100644
--- a/glide.go
+++ b/glide.go
@@ -92,8 +92,12 @@
Usage: "Quiet (no info or debug messages)",
},
cli.BoolFlag{
+ Name: "verbose",
+ Usage: "Print detailed informational messages",
+ },
+ cli.BoolFlag{
Name: "debug",
- Usage: "Print Debug messages (verbose)",
+ Usage: "Print debug verbose informational messages",
},
cli.StringFlag{
Name: "home",
@@ -146,9 +150,13 @@
Name: "skip-import",
Usage: "When initializing skip importing from other package managers.",
},
+ cli.BoolFlag{
+ Name: "non-interactive",
+ Usage: "Disable interactive prompts.",
+ },
},
Action: func(c *cli.Context) {
- action.Create(".", c.Bool("skip-import"))
+ action.Create(".", c.Bool("skip-import"), c.Bool("non-interactive"))
},
},
{
@@ -664,6 +672,7 @@
// so it can be used by any Glide command.
func startup(c *cli.Context) error {
action.Debug(c.Bool("debug"))
+ action.Verbose(c.Bool("verbose"))
action.NoColor(c.Bool("no-color"))
action.Quiet(c.Bool("quiet"))
action.Init(c.String("yaml"), c.String("home"))
diff --git a/msg/msg.go b/msg/msg.go
index b2a7bfe..2f9c6c8 100644
--- a/msg/msg.go
+++ b/msg/msg.go
@@ -1,6 +1,7 @@
package msg
import (
+ "bufio"
"fmt"
"io"
"os"
@@ -16,9 +17,12 @@
// Quiet, if true, suppresses chatty levels, like Info.
Quiet bool
- // IsDebugging, if true, shows verbose levels, like Debug.
+ // IsDebugging, if true, shows Debug.
IsDebugging bool
+ // IsVerbose, if true, shows detailed informational messages.
+ IsVerbose bool
+
// NoColor, if true, will not use color in the output.
NoColor bool
@@ -28,6 +32,9 @@
// Stderr is the location where this prints logs.
Stderr io.Writer
+ // Stdin is the location where input is read.
+ Stdin io.Reader
+
// PanicOnDie if true Die() will panic instead of exiting.
PanicOnDie bool
@@ -43,9 +50,11 @@
m := &Messenger{
Quiet: false,
IsDebugging: false,
+ IsVerbose: false,
NoColor: false,
Stdout: os.Stdout,
Stderr: os.Stderr,
+ Stdin: os.Stdin,
PanicOnDie: false,
ecode: 1,
}
@@ -76,7 +85,7 @@
return
}
prefix := "[DEBUG] "
- Msg(prefix+msg, args...)
+ m.Msg(prefix+msg, args...)
}
// Debug logs debug information using the Default Messenger
@@ -84,6 +93,19 @@
Default.Debug(msg, args...)
}
+// Verbose logs detailed information
+func (m *Messenger) Verbose(msg string, args ...interface{}) {
+ if m.Quiet || !m.IsVerbose {
+ return
+ }
+ m.Info(msg, args...)
+}
+
+// Verbose detailed information using the Default Messenger
+func Verbose(msg string, args ...interface{}) {
+ Default.Verbose(msg, args...)
+}
+
// Warn logs a warning
func (m *Messenger) Warn(msg string, args ...interface{}) {
prefix := m.Color(Yellow, "[WARN] ")
@@ -238,3 +260,30 @@
func Color(code, msg string) string {
return Default.Color(code, msg)
}
+
+// PromptUntil provides a prompt until one of the passed in strings has been
+// entered and return is hit. Note, the comparisons are case insensitive meaning
+// Y == y. The returned value is the one from the passed in options (same case).
+func (m *Messenger) PromptUntil(opts []string) (string, error) {
+ reader := bufio.NewReader(os.Stdin)
+ for {
+ text, err := reader.ReadString('\n')
+ if err != nil {
+ return "", err
+ }
+
+ for _, c := range opts {
+ if strings.EqualFold(c, strings.TrimSpace(text)) {
+ return c, nil
+ }
+ }
+ }
+}
+
+// PromptUntil provides a prompt until one of the passed in strings has been
+// entered and return is hit. Note, the comparisons are case insensitive meaning
+// Y == y. The returned value is the one from the passed in options (same case).
+// Uses the default setup.
+func PromptUntil(opts []string) (string, error) {
+ return Default.PromptUntil(opts)
+}