示例#1
0
func TestCLIConfirmation(t *testing.T) {
	Convey("Given a buffer", t, func() {
		w := &bytes.Buffer{}
		r := &bytes.Buffer{}

		Convey("AskForConfirmation should respond correctly to all cases", func() {
			// Yes case
			var wg sync.WaitGroup
			wg.Add(1)

			var (
				resp bool
				cerr error
			)
			go func() {
				resp, cerr = utils.AskForConfirmation(w, r, "hello: ")
				wg.Done()
			}()

			r.WriteString("yes\n")
			wg.Wait()

			So(cerr, ShouldBeNil)
			So(w.String(), ShouldEqual, "hello: ")
			So(resp, ShouldBeTrue)

			// Clean up
			w.Reset()
			r.Reset()

			// No case
			wg.Add(1)
			go func() {
				resp, cerr = utils.AskForConfirmation(w, r, "hello: ")
				wg.Done()
			}()

			r.WriteString("no\n")
			wg.Wait()

			So(cerr, ShouldBeNil)
			So(w.String(), ShouldEqual, "hello: ")
			So(resp, ShouldBeFalse)

			// Clean up for the second time
			w.Reset()
			r.Reset()

			// Retry case
			wg.Add(1)
			go func() {
				resp, cerr = utils.AskForConfirmation(w, r, "hello: ")
				wg.Done()
			}()

			r.WriteString("invalid\n")
			r.WriteString("yes\n")
			wg.Wait()

			So(cerr, ShouldBeNil)
			So(w.String(), ShouldEqual, "hello: hello: ")
			So(resp, ShouldBeTrue)

			// Closed stdin case
			w.Reset()
			r2 := &dumbReader{}
			resp, err := utils.AskForConfirmation(w, r2, "hello: ")
			So(err, ShouldNotBeNil)
			So(w.String(), ShouldEqual, "hello: ")
			So(resp, ShouldBeFalse)
		})
	})
}
示例#2
0
文件: database.go 项目: pgpst/pgpst
func databaseMigrate(c *cli.Context) int {
	// Connect to RethinkDB
	opts, session, connected := connectToRethinkDB(c)
	if !connected {
		return 1
	}

	// Get the migration status from the database
	version, err := getDatabaseVersion(opts, session)
	if err != nil {
		writeError(c, err)
		return 1
	}

	// Show the current migration's status
	fmt.Fprintf(c.App.Writer, "Current database schema's version is %d.\n", version)
	fmt.Fprintf(c.App.Writer, "Latest migration's version is %d.\n", len(migrations)-1)

	// Only proceed if the schema is outdated
	if version >= len(migrations)-1 {
		fmt.Fprintln(c.App.Writer, "Your schema is up to date.")
		return 0
	}

	// I don't know why would anyone use it, but it's here
	if c.Bool("no") {
		fmt.Fprintln(c.App.Writer, "Aborting the command because of the --no option.")
		return 1
	}

	// Ask for confirmations
	if !c.Bool("yes") {
		want, err := utils.AskForConfirmation(
			c.App.Writer,
			c.App.Env["reader"].(io.Reader),
			"Would you like to run "+strconv.Itoa(len(migrations)-1-version)+" migrations? [y/n]: ",
		)
		if err != nil {
			writeError(c, err)
			return 1
		}

		if !want {
			fmt.Fprintln(c.App.Writer, "Aborting the command.")
			return 1
		}
	}

	// Collect all queries
	queries := []r.Term{}
	for _, migration := range migrations[version+1:] {
		queries = append(queries, migration.Migrate(opts)...)
		queries = append(queries, r.Table("migration_status").Get("revision").Update(map[string]interface{}{
			"value": migration.Revision,
		}))
	}

	// Create a new progress bar
	bar := pb.StartNew(len(queries))
	for i, query := range queries {
		if c.Bool("dry") {
			fmt.Fprintf(c.App.Writer, "Executing %s\n", query.String())
		} else {
			if err := query.Exec(session); err != nil {
				bar.FinishPrint("Failed to execute migration #" + strconv.Itoa(i) + ":")
				fmt.Fprintf(c.App.Writer, "\tQuery: %s\n", query.String())
				fmt.Fprintf(c.App.Writer, "\tError: %v\n", err)
				return 1
			}
		}
		bar.Increment()
	}

	// Show a "finished" message
	bar.FinishPrint("Migration completed. " + strconv.Itoa(len(queries)) + " queries executed.")
	return 0
}