Exemple #1
0
func migrateConfigV1ToV101() {
	if !isMcConfigExists() {
		return
	}
	conf := newConfigV1()
	config, err := quick.New(conf)
	if err != nil {
		console.Fatalln(NewIodine(iodine.New(err, nil)))
	}
	config.Load(mustGetMcConfigPath())
	conf = config.Data().(*configV1)
	// version is the same return
	if conf.Version == mcCurrentConfigVersion {
		return
	}
	conf.Version = mcCurrentConfigVersion

	localHostConfig := new(hostConfig)
	localHostConfig.AccessKeyID = ""
	localHostConfig.SecretAccessKey = ""

	if _, ok := conf.Hosts["localhost:*"]; !ok {
		conf.Hosts["localhost:*"] = localHostConfig
	}
	if _, ok := conf.Hosts["127.0.0.1:*"]; !ok {
		conf.Hosts["127.0.0.1:*"] = localHostConfig
	}

	newConfig, err := quick.New(conf)
	if err := newConfig.Save(mustGetMcConfigPath()); err != nil {
		console.Fatalln(NewIodine(iodine.New(err, nil)))
	}
	console.Infof("Successfully migrated %s from version: %s to version: %s\n", mustGetMcConfigPath(), mcPreviousConfigVersion, mcCurrentConfigVersion)
}
Exemple #2
0
// fatalIf wrapper function which takes error and selectively prints stack frames if available on debug
func fatalIf(err *probe.Error, msg string) {
	if err == nil {
		return
	}
	if globalJSON {
		errorMsg := errorMessage{
			Message: msg,
			Type:    "fatal",
			Cause: causeMessage{
				Message: err.ToGoError().Error(),
				Error:   err.ToGoError(),
			},
			SysInfo: err.SysInfo,
		}
		if globalDebug {
			errorMsg.CallTrace = err.CallTrace
		}
		json, err := json.Marshal(struct {
			Status string       `json:"status"`
			Error  errorMessage `json:"error"`
		}{
			Status: "error",
			Error:  errorMsg,
		})
		if err != nil {
			console.Fatalln(probe.NewError(err))
		}
		console.Println(string(json))
		console.Fatalln()
	}
	if !globalDebug {
		console.Fatalln(fmt.Sprintf("%s %s", msg, err.ToGoError()))
	}
	console.Fatalln(fmt.Sprintf("%s %s", msg, err))
}
Exemple #3
0
// fatalIf wrapper function which takes error and selectively prints stack frames if available on debug
func fatalIf(err *probe.Error, msg string) {
	if err == nil {
		return
	}
	if globalJSONFlag {
		errorMessage := ErrorMessage{
			Message: msg,
			Type:    "fatal",
			Cause:   err.ToGoError(),
			SysInfo: err.SysInfo,
		}
		if globalDebugFlag {
			errorMessage.CallTrace = err.CallTrace
		}
		json, err := json.Marshal(struct {
			Error ErrorMessage `json:"error"`
		}{
			Error: errorMessage,
		})
		if err != nil {
			console.Fatalln(probe.NewError(err))
		}
		console.Println(string(json))
		os.Exit(1)
	}
	if !globalDebugFlag {
		console.Fatalln(fmt.Sprintf("%s %s", msg, err.ToGoError()))
	}
	console.Fatalln(fmt.Sprintf("%s %s", msg, err))
}
Exemple #4
0
// check if minimum Go version is met.
func checkGoVersion() {
	runtimeVersion := runtime.Version()

	// Checking version is always successful with go tip
	if strings.HasPrefix(runtimeVersion, "devel") {
		return
	}

	// Parsing golang version
	curVersion, e := version.NewVersion(runtimeVersion[2:])
	if e != nil {
		console.Fatalln("Unable to determine current go version.", e)
	}

	// Prepare version constraint.
	constraints, e := version.NewConstraint(minGoVersion)
	if e != nil {
		console.Fatalln("Unable to check go version.")
	}

	// Check for minimum version.
	if !constraints.Check(curVersion) {
		console.Fatalln(fmt.Sprintf("Please recompile Minio with Golang version %s.", minGoVersion))
	}
}
Exemple #5
0
// runMakeBucketCmd is the handler for mc mb command
func runMakeBucketCmd(ctx *cli.Context) {
	if !ctx.Args().Present() || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "mb", 1) // last argument is exit code
	}
	if !isMcConfigExists() {
		console.Fatalf("Please run \"mc config generate\". %s\n", errNotConfigured{})
	}
	config := mustGetMcConfig()
	for _, arg := range ctx.Args() {
		targetURL, err := getExpandedURL(arg, config.Aliases)
		if err != nil {
			switch e := iodine.ToError(err).(type) {
			case errUnsupportedScheme:
				console.Fatalf("Unknown type of URL %s. %s\n", e.url, err)
			default:
				console.Fatalf("Unable to parse argument %s. %s\n", arg, err)
			}
		}
		msg, err := doMakeBucketCmd(targetURL)
		if err != nil {
			console.Fatalln(msg)
		}
		console.Infoln(msg)
	}
}
Exemple #6
0
func registerApp() *cli.App {
	// Register all commands.
	registerCommand(serverCmd)
	registerCommand(versionCmd)
	registerCommand(updateCmd)
	registerCommand(controlCmd)

	// Set up app.
	app := cli.NewApp()
	app.Name = "Minio"
	app.Author = "Minio.io"
	app.Usage = "Cloud Storage Server."
	app.Description = `Minio is an Amazon S3 compatible object storage server. Use it to store photos, videos, VMs, containers, log files, or any blob of data as objects.`
	app.Flags = globalFlags
	app.Commands = commands
	app.CustomAppHelpTemplate = minioHelpTemplate
	app.CommandNotFound = func(ctx *cli.Context, command string) {
		msg := fmt.Sprintf("‘%s’ is not a minio sub-command. See ‘minio --help’.", command)
		closestCommands := findClosestCommands(command)
		if len(closestCommands) > 0 {
			msg += fmt.Sprintf("\n\nDid you mean one of these?\n")
			for _, cmd := range closestCommands {
				msg += fmt.Sprintf("        ‘%s’\n", cmd)
			}
		}
		console.Fatalln(msg)
	}
	return app
}
Exemple #7
0
func runCatCmd(ctx *cli.Context) {
	if !ctx.Args().Present() || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "cat", 1) // last argument is exit code
	}
	if !isMcConfigExists() {
		console.Fatalf("Please run \"mc config generate\". %s\n", errNotConfigured{})
	}
	config := mustGetMcConfig()
	// Convert arguments to URLs: expand alias, fix format...
	for _, arg := range ctx.Args() {
		sourceURL, err := getExpandedURL(arg, config.Aliases)
		if err != nil {
			switch e := iodine.ToError(err).(type) {
			case errUnsupportedScheme:
				console.Fatalf("Unknown type of URL %s. %s\n", e.url, err)
			default:
				console.Fatalf("Unable to parse argument %s. %s\n", arg, err)
			}
		}
		errorMsg, err := doCatCmd(sourceURL)
		if err != nil {
			console.Fatalln(errorMsg)
		}
	}
}
Exemple #8
0
func runAccessCmd(ctx *cli.Context) {
	if !ctx.Args().Present() || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "access", 1) // last argument is exit code
	}
	config := mustGetMcConfig()
	acl := bucketACL(ctx.Args().First())
	if !acl.isValidBucketACL() {
		console.Fatalf("Valid types are [private, public, readonly]. %s\n", errInvalidACL{acl: acl.String()})
	}
	for _, arg := range ctx.Args().Tail() {
		targetURL, err := getExpandedURL(arg, config.Aliases)
		if err != nil {
			switch e := iodine.ToError(err).(type) {
			case errUnsupportedScheme:
				console.Fatalf("Unknown type of URL %s. %s\n", e.url, err)
			default:
				console.Fatalf("Unable to parse argument %s. %s\n", arg, err)
			}
		}
		msg, err := doUpdateAccessCmd(targetURL, acl)
		if err != nil {
			console.Fatalln(msg)
		}
		console.Infoln(msg)
	}
}
Exemple #9
0
// checkCastSyntax(URLs []string)
func checkCastSyntax(ctx *cli.Context) {
	if len(ctx.Args()) < 2 || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "cast", 1) // last argument is exit code.
	}
	// extract URLs.
	URLs, err := args2URLs(ctx.Args())
	if err != nil {
		console.Fatalf("One or more unknown URL types found %s. %s\n", ctx.Args(), NewIodine(iodine.New(err, nil)))
	}

	srcURL := URLs[0]
	tgtURLs := URLs[1:]

	/****** Generic rules *******/
	// Source cannot be a folder (except when recursive)
	if !isURLRecursive(srcURL) {
		_, srcContent, err := url2Stat(srcURL)
		// Source exist?.
		if err != nil {
			console.Fatalf("Unable to stat source ‘%s’. %s\n", srcURL, NewIodine(iodine.New(err, nil)))
		}
		if !srcContent.Type.IsRegular() {
			if srcContent.Type.IsDir() {
				console.Fatalf("Source ‘%s’ is a folder. Please use ‘%s...’ to recursively copy this folder and its contents.\n", srcURL, srcURL)
			}
			console.Fatalf("Source ‘%s’ is not a regular file.\n", srcURL)
		}
	}
	// Recursive URLs are not allowed in target.
	for _, tgtURL := range tgtURLs {
		if isURLRecursive(tgtURL) {
			console.Fatalf("Target ‘%s’ cannot be recursive. %s\n", tgtURL, NewIodine(iodine.New(errInvalidArgument{}, nil)))
		}
	}

	for _, tgtURL := range tgtURLs {
		url, err := client.Parse(tgtURL)
		if err != nil {
			console.Fatalf("Unable to parse target ‘%s’ argument. %s\n", tgtURL, NewIodine(iodine.New(err, nil)))
		}
		if url.Host != "" {
			if url.Path == string(url.Separator) {
				console.Fatalf("Bucket creation detected for %s, cloud storage URL's should use ‘mc mb’ to create buckets\n", tgtURL)
			}
		}
	}

	switch guessCastURLType(srcURL, tgtURLs) {
	case castURLsTypeA: // File -> File.
		checkCastSyntaxTypeA(srcURL, tgtURLs)
	case castURLsTypeB: // File -> Folder.
		checkCastSyntaxTypeB(srcURL, tgtURLs)
	case castURLsTypeC: // Folder -> Folder.
		checkCastSyntaxTypeC(srcURL, tgtURLs)
	default:
		console.Fatalln("Invalid arguments. Unable to determine how to cast. Please report this issue at https://github.com/minio/mc/issues")
	}
}
Exemple #10
0
// check if minimum Go version is met.
func checkGoVersion() {
	// Current version.
	curVersion, e := version.NewVersion(runtime.Version()[2:])
	if e != nil {
		console.Fatalln("Unable to determine current go version.", e)
	}

	// Prepare version constraint.
	constraints, e := version.NewConstraint(minGoVersion)
	if e != nil {
		console.Fatalln("Unable to check go version.")
	}

	// Check for minimum version.
	if !constraints.Check(curVersion) {
		console.Fatalln(fmt.Sprintf("Please recompile Minio with Golang version %s.", minGoVersion))
	}
}
Exemple #11
0
// Verify main command syntax.
func checkMainSyntax(c *cli.Context) {
	configPath, err := getConfigPath()
	if err != nil {
		console.Fatalf("Unable to obtain user's home directory. \nError: %s\n", err)
	}
	if configPath == "" {
		console.Fatalln("Config folder cannot be empty, please specify --config-dir <foldername>.")
	}
}
Exemple #12
0
// checkCastSyntax(URLs []string)
func checkCastSyntax(ctx *cli.Context) {
	if len(ctx.Args()) < 2 || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "cast", 1) // last argument is exit code.
	}

	// extract URLs.
	URLs, err := args2URLs(ctx.Args())
	if err != nil {
		console.Fatalf("One or more unknown URL types found %s. %s\n", ctx.Args(), iodine.New(err, nil))
	}

	srcURL := URLs[0]
	tgtURLs := URLs[1:]

	/****** Generic rules *******/
	// Source cannot be a directory (except when recursive)
	if !isURLRecursive(srcURL) {
		_, srcContent, err := url2Stat(srcURL)
		// Source exist?.
		if err != nil {
			console.Fatalf("Unable to stat source ‘%s’. %s\n", srcURL, iodine.New(err, nil))
		}
		if !srcContent.Type.IsRegular() {
			if srcContent.Type.IsDir() {
				console.Fatalf("Source ‘%s’ is a directory. Please use ‘%s...’ to recursively copy this directory and its contents.\n", srcURL, srcURL)
			}
			console.Fatalf("Source ‘%s’ is not a regular file.\n", srcURL)
		}
	}
	// Recursive URLs are not allowed in target.
	for _, tgtURL := range tgtURLs {
		if isURLRecursive(tgtURL) {
			console.Fatalf("Target ‘%s’ cannot be recursive. %s\n", tgtURL, iodine.New(err, nil))
		}
	}

	switch guessCastURLType(srcURL, tgtURLs) {
	case castURLsTypeA: // Source is already a regular file.
		//
	case castURLsTypeB: // Source is already a regular file.
		//
	case castURLsTypeC:
		srcURL = stripRecursiveURL(srcURL)
		_, srcContent, err := url2Stat(srcURL)
		// Source exist?.
		if err != nil {
			console.Fatalf("Unable to stat source ‘%s’. %s\n", srcURL, iodine.New(err, nil))
		}

		if srcContent.Type.IsRegular() { // Ellipses is supported only for directories.
			console.Fatalf("Source ‘%s’ is not a directory. %s\n", stripRecursiveURL(srcURL), iodine.New(err, nil))
		}

	default:
		console.Fatalln("Invalid arguments. Unable to determine how to cast. Please report this issue at https://github.com/minio/mc/issues")
	}
}
Exemple #13
0
// runUpdateCmd -
func runUpdateCmd(ctx *cli.Context) {
	if ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "update", 1) // last argument is exit code
	}
	msg, err := doUpdateCheck()
	if err != nil {
		console.Fatalln(msg)
	}
	// no msg do not print one
	if msg != "" {
		console.Infoln(msg)
	}
}
Exemple #14
0
func firstTimeRun() {
	if !isMcConfigExists() {
		if err := createMcConfigDir(); err != nil {
			console.Fatalf("Unable to create ‘mc’ config folder. %s\n", err)
		}
		config, err := newConfig()
		if err != nil {
			console.Fatalln(NewIodine(iodine.New(err, nil)))
		}
		err = writeConfig(config)
		if err != nil {
			console.Fatalln(NewIodine(iodine.New(err, nil)))
		}
		console.Infoln("Configuration written to [" + mustGetMcConfigPath() + "]. Please update your access credentials.")
	}
	if !isSessionDirExists() {
		if err := createSessionDir(); err != nil {
			console.Fatalf("Unable to create ‘mc’ session folder. %s\n", err)
		}
	}
	checkGolangVersion()
}
Exemple #15
0
// runUpdateCmd -
func runUpdateCmd(ctx *cli.Context) {
	if ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "update", 1) // last argument is exit code
	}
	if !isMcConfigExists() {
		console.Fatalf("Please run \"mc config generate\". %s\n", NewIodine(iodine.New(errNotConfigured{}, nil)))
	}
	msg, err := doUpdateCheck()
	if err != nil {
		console.Fatalln(msg)
	}
	// no msg do not print one
	if msg != "" {
		console.Infoln(msg)
	}
}
Exemple #16
0
// runConfigCmd is the handle for "mc config" sub-command
func runConfigCmd(ctx *cli.Context) {
	// show help if nothing is set
	if !ctx.Args().Present() || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "config", 1) // last argument is exit code
	}
	arg := ctx.Args().First()
	tailArgs := ctx.Args().Tail()
	if len(tailArgs) > 2 {
		console.Fatalf("Incorrect number of arguments, please use \"mc config help\". %s", errInvalidArgument{})
	}
	msg, err := doConfig(arg, tailArgs)
	if err != nil {
		console.Fatalln(msg)
	}
	console.Infoln(msg)
}
Exemple #17
0
//   NOTE: All the parse rules should reduced to A: Copy(Source, Target).
//
//   * VALID RULES
//   =======================
//   A: copy(f, f) -> copy(f, f)
//   B: copy(f, d) -> copy(f, d/f) -> A
//   C: copy(d1..., d2) -> []copy(d1/f, d1/d2/f) -> []A
//
//   * INVALID RULES
//   =========================
//   A: copy(d, *)
//   B: copy(d..., f)
//   C: copy(*, d...)
//
func checkCopySyntax(ctx *cli.Context) {
	if len(ctx.Args()) < 2 || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "cp", 1) // last argument is exit code.
	}

	// extract URLs.
	URLs, err := args2URLs(ctx.Args())
	if err != nil {
		console.Fatalf("One or more unknown URL types found %s. %s\n", ctx.Args(), iodine.New(err, nil))
	}

	srcURLs := URLs[:len(URLs)-1]
	tgtURL := URLs[len(URLs)-1]

	/****** Generic rules *******/
	// Recursive URLs are not allowed in target.
	if isURLRecursive(tgtURL) {
		console.Fatalf("Target ‘%s’ cannot be recursive. %s\n", tgtURL, iodine.New(err, nil))
	}

	switch guessCopyURLType(srcURLs, tgtURL) {
	case copyURLsTypeA: // Source is already a regular file.
		// no verification needed, pass through
	case copyURLsTypeB: // Source is already a regular file.
		// no verification needed, pass through
	case copyURLsTypeC:
		for _, srcURL := range srcURLs {
			srcURL = stripRecursiveURL(srcURL)
			_, srcContent, err := url2Stat(srcURL)
			// Source exist?.
			if err != nil {
				console.Fatalf("Unable to stat source ‘%s’. %s\n", srcURL, iodine.New(err, nil))
			}
			if srcContent.Type.IsRegular() { // Ellipses is supported only for directories.
				console.Fatalf("Source ‘%s’ is not a directory. %s\n", stripRecursiveURL(srcURL), iodine.New(err, nil))
			}
		}
	case copyURLsTypeD:
		// only verify if target is a valid directory and exists
		if !isTargetURLDir(tgtURL) {
			console.Fatalf("Target ‘%s’ should be a directory and exist, when we have a mixture of files and folders in source\n", tgtURL)
		}
	default:
		console.Fatalln("Invalid arguments. Unable to determine how to copy. Please report this issue at https://github.com/minio/mc/issues")
	}
}
Exemple #18
0
// runDiffCmd - is a handler for mc diff command
func runDiffCmd(ctx *cli.Context) {
	if len(ctx.Args()) != 2 || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "diff", 1) // last argument is exit code
	}
	if !isMcConfigExists() {
		console.Fatalf("Please run \"mc config generate\". %s\n", errNotConfigured{})
	}

	config := mustGetMcConfig()
	firstURL := ctx.Args().First()
	secondURL := ctx.Args()[1]

	var err error
	firstURL, err = getExpandedURL(firstURL, config.Aliases)
	if err != nil {
		switch e := iodine.ToError(err).(type) {
		case errUnsupportedScheme:
			console.Fatalf("Unknown type of URL %s. %s\n", e.url, err)
		default:
			console.Fatalf("Unable to parse argument %s. %s\n", firstURL, err)
		}
	}
	secondURL, err = getExpandedURL(secondURL, config.Aliases)
	if err != nil {
		switch e := iodine.ToError(err).(type) {
		case errUnsupportedScheme:
			console.Fatalf("Unknown type of URL %s. %s\n", e.url, err)
		default:
			console.Fatalf("Unable to parse argument %s. %s\n", secondURL, err)
		}
	}
	if isURLRecursive(secondURL) {
		console.Fatalf("Second URL cannot be recursive. %s\n", errInvalidArgument{})
	}
	newFirstURL := stripRecursiveURL(firstURL)
	for diff := range doDiffCmd(newFirstURL, secondURL, isURLRecursive(firstURL)) {
		if diff.err != nil {
			console.Fatalln(diff.message)
		}
		console.Infoln(diff.message)
	}
}
Exemple #19
0
//   NOTE: All the parse rules should reduced to A: Copy(Source, Target).
//
//   * VALID RULES
//   =======================
//   A: copy(f, f) -> copy(f, f)
//   B: copy(f, d) -> copy(f, d/f) -> A
//   C: copy(d1..., d2) -> []copy(d1/f, d2/d1/f) -> []A
//   D: copy([]{d1... | f}, d2) -> []{copy(d1/f, d2/d1/f) | copy(f, d2/f )} -> []A
//
//   * INVALID RULES
//   =========================
//   A: copy(d, *)
//   B: copy(d..., f)
//   C: copy(*, d...)
//
func checkCopySyntax(ctx *cli.Context) {
	if len(ctx.Args()) < 2 || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "cp", 1) // last argument is exit code.
	}
	// extract URLs.
	URLs, err := args2URLs(ctx.Args())
	if err != nil {
		console.Fatalf("One or more unknown URL types found %s. %s\n", ctx.Args(), NewIodine(iodine.New(err, nil)))
	}

	srcURLs := URLs[:len(URLs)-1]
	tgtURL := URLs[len(URLs)-1]

	/****** Generic rules *******/
	// Recursive URLs are not allowed in target.
	if isURLRecursive(tgtURL) {
		console.Fatalf("Recursive option is not supported for target ‘%s’ argument. %s\n", tgtURL, NewIodine(iodine.New(errInvalidArgument{}, nil)))
	}
	url, err := client.Parse(tgtURL)
	if err != nil {
		console.Fatalf("Unable to parse target ‘%s’ argument. %s\n", tgtURL, NewIodine(iodine.New(err, nil)))
	}
	if url.Host != "" {
		if url.Path == string(url.Separator) {
			console.Fatalf("Bucket creation detected for %s, cloud storage URL's should use ‘mc mb’ to create buckets\n", tgtURL)
		}
	}
	switch guessCopyURLType(srcURLs, tgtURL) {
	case copyURLsTypeA: // File -> File.
		checkCopySyntaxTypeA(srcURLs, tgtURL)
	case copyURLsTypeB: // File -> Folder.
		checkCopySyntaxTypeB(srcURLs, tgtURL)
	case copyURLsTypeC: // Folder... -> Folder.
		checkCopySyntaxTypeC(srcURLs, tgtURL)
	case copyURLsTypeD: // File | Folder... -> Folder.
		checkCopySyntaxTypeD(srcURLs, tgtURL)
	default:
		console.Fatalln("Invalid arguments. Unable to determine how to copy. Please report this issue at https://github.com/minio/mc/issues")
	}
}
Exemple #20
0
// Check for sane config environment early on and gracefully report.
func checkConfig() {
	// Refresh the config once.
	loadMcConfig = loadMcConfigFactory()
	// Ensures config file is sane.
	config, err := loadMcConfig()
	// Verify if the path is accesible before validating the config
	fatalIf(err.Trace(mustGetMcConfigPath()), "Unable to access configuration file.")

	// Validate and print error messges
	ok, errMsgs := validateConfigFile(config)
	if !ok {
		var errorMsg bytes.Buffer
		for index, errMsg := range errMsgs {
			// Print atmost 10 errors
			if index > 10 {
				break
			}
			errorMsg.WriteString(errMsg + "\n")
		}
		console.Fatalln(errorMsg.String())
	}
}
Exemple #21
0
func runSessionCmd(ctx *cli.Context) {
	if len(ctx.Args()) < 1 || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "session", 1) // last argument is exit code
	}
	if strings.TrimSpace(ctx.Args().First()) == "" {
		cli.ShowCommandHelpAndExit(ctx, "session", 1) // last argument is exit code
	}
	if !isSessionDirExists() {
		if err := createSessionDir(); err != nil {
			console.Fatalf("Unable to create session folder. %s\n", err)
		}
	}
	switch strings.TrimSpace(ctx.Args().First()) {
	// list resumable sessions
	case "list":
		err := listSessions()
		if err != nil {
			console.Fatalln(err)
		}
	case "resume":
		if len(ctx.Args().Tail()) != 1 {
			cli.ShowCommandHelpAndExit(ctx, "session", 1) // last argument is exit code
		}
		if strings.TrimSpace(ctx.Args().Tail().First()) == "" {
			cli.ShowCommandHelpAndExit(ctx, "session", 1) // last argument is exit code
		}

		sid := strings.TrimSpace(ctx.Args().Tail().First())

		_, err := os.Stat(getSessionFile(sid))
		if err != nil {
			console.Fatalln(errInvalidSessionID{id: sid})
		}
		s, err := loadSessionV2(sid)
		if err != nil {
			console.Fatalln(errInvalidSessionID{id: sid})
		}
		// extra check for testing purposes
		if s == nil {
			return
		}
		savedCwd, err := os.Getwd()
		if err != nil {
			console.Fatalln("Unable to verify your current working folder. %s\n", err)
		}
		if s.Header.RootPath != "" {
			// chdir to RootPath
			os.Chdir(s.Header.RootPath)
		}

		sessionExecute(s)
		err = s.Close()
		if err != nil {
			console.Fatalf("Unable to close session file properly. %s\n", err)
		}
		err = s.Delete()
		if err != nil {
			console.Fatalf("Unable to clear session files properly. %s\n", err)
		}
		// change dir back
		os.Chdir(savedCwd)

	// purge a requested pending session, if "*" purge everything
	case "clear":
		if len(ctx.Args().Tail()) != 1 {
			cli.ShowCommandHelpAndExit(ctx, "session", 1) // last argument is exit code
		}
		if strings.TrimSpace(ctx.Args().Tail().First()) == "" {
			cli.ShowCommandHelpAndExit(ctx, "session", 1) // last argument is exit code
		}
		clearSession(strings.TrimSpace(ctx.Args().Tail().First()))
	default:
		cli.ShowCommandHelpAndExit(ctx, "session", 1) // last argument is exit code
	}
}
Exemple #22
0
// Close a session and exit.
func (s sessionV8) CloseAndDie() {
	s.Close()
	console.Fatalln("Session safely terminated. To resume session ‘mc session resume " + s.SessionID + "’")
}