Skip to content

Commit

Permalink
update readme
Browse files Browse the repository at this point in the history
  • Loading branch information
MrLYC committed Nov 21, 2021
1 parent 8a5b05c commit a4ef3fd
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 7 deletions.
37 changes: 33 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,36 @@
# CMDR
CMDR is a simple command version manager, easy to manage and switch multiple commands.
CMDR is a simple command version management tool that helps you quickly switch from multiple command versions.

## Installation
1. Download the pre-compiled binaries from [releases](https://github.com/MrLYC/cmdr/releases).
2. Decompress the tar.gz file.
3. In order to setup the cmdr environment, run: `cmdr setup`.
Download the latest release from [GitHub](https://github.com/MrLYC/cmdr/releases) and make sure it is executable.
Run the following command to install it in your system:
```shell
% /path/to/cmdr setup
```

Check the CMDR version information by running the following command:
```shell
% cmdr version -a
```

## Get Started
To install a new command, run the following command:
```shell
% cmdr command install -n <command-name> -v <version> -l <path_or_url>
```

Then you can list the installed commands by running the following command:
```shell
% cmdr command list -n <command-name>
```

Use a specified command version:
```shell
% cmdr command use -n <command-name> -v <version>
```

## Upgrade
To upgrade the CMDR, run:
```shell
% cmdr upgrade
```
File renamed without changes.
15 changes: 12 additions & 3 deletions cmd/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import (
)

var setupCmdFlag struct {
doNotInstall bool
doNotInstall bool
doNotWriteProfile bool
}

// setupCmd represents the setup command
Expand All @@ -27,6 +28,7 @@ var setupCmd = &cobra.Command{
}),
core.NewDBClientMaker(),
core.NewDBMigrator(new(model.Command)),
core.NewShellProfiler(os.Getenv("SHELL")),
)

cmdrLocation, err := os.Executable()
Expand All @@ -39,6 +41,12 @@ var setupCmd = &cobra.Command{
)
}

if !setupCmdFlag.doNotWriteProfile {
runner.Add(
core.NewShellProfiler(os.Getenv("SHELL")),
)
}

utils.ExitWithError(runner.Run(utils.SetIntoContext(cmd.Context(), map[define.ContextKey]interface{}{
define.ContextKeyName: define.Name,
define.ContextKeyVersion: define.Version,
Expand All @@ -48,9 +56,10 @@ var setupCmd = &cobra.Command{
},
}

func setup() {
func init() {
rootCmd.AddCommand(setupCmd)

flags := setupCmd.Flags()
flags.BoolVar(&setupCmdFlag.doNotInstall, "do-not-install-cmdr", false, "do not install cmdr")
flags.BoolVar(&setupCmdFlag.doNotInstall, "skip-install", false, "do not install cmdr")
flags.BoolVar(&setupCmdFlag.doNotWriteProfile, "skip-profile", false, "do not write profile")
}
17 changes: 17 additions & 0 deletions cmd/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
var upgradeCmdFlag struct {
release string
asset string
keep bool
}

// upgradeCmd represents the upgrade command
Expand All @@ -26,6 +27,21 @@ var upgradeCmd = &cobra.Command{
core.NewCommandInstaller(),
)

if !upgradeCmdFlag.keep {
runner.Add(
core.NewContextValueSetter(map[define.ContextKey]interface{}{
define.ContextKeyVersion: define.Version,
}),
core.NewCommandQuerierByNameAndVersion(
define.Name, define.Version,
),
core.NewBinaryRemover(),
core.NewCommandRemover(),
core.NewBinaryRemover(),
core.NewCommandRemover(),
)
}

utils.ExitWithError(runner.Run(utils.SetIntoContext(cmd.Context(), map[define.ContextKey]interface{}{
define.ContextKeyName: define.Name,
define.ContextKeyCommandManaged: true,
Expand All @@ -38,4 +54,5 @@ func init() {
flags := upgradeCmd.Flags()
flags.StringVarP(&upgradeCmdFlag.release, "release", "r", "latest", "cmdr release tag name")
flags.StringVarP(&upgradeCmdFlag.asset, "asset", "a", define.Asset, "cmdr release assert name")
flags.BoolVarP(&upgradeCmdFlag.keep, "keep", "k", false, "keep the last cmdr version")
}
19 changes: 19 additions & 0 deletions core/utils.go → core/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,22 @@ func GetCommandsFromContext(ctx context.Context) ([]*model.Command, error) {

return commands, nil
}

type ContextValueSetter struct {
BaseStep
values map[define.ContextKey]interface{}
}

func (s *ContextValueSetter) String() string {
return "context-value-setter"
}

func (s *ContextValueSetter) Run(ctx context.Context) (context.Context, error) {
return utils.SetIntoContext(ctx, s.values), nil
}

func NewContextValueSetter(values map[define.ContextKey]interface{}) *ContextValueSetter {
return &ContextValueSetter{
values: values,
}
}
89 changes: 89 additions & 0 deletions core/shell.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package core

import (
"bytes"
"context"
"fmt"
"io/ioutil"
"os"
"path/filepath"

"github.com/pkg/errors"

"github.com/mrlyc/cmdr/define"
"github.com/mrlyc/cmdr/utils"
)

type ShellProfiler struct {
BaseStep
shell string
script string
}

func (s *ShellProfiler) String() string {
return "shell-profiler"
}

func (s *ShellProfiler) isContainsProfile(path string) bool {
fs := define.FS

file, err := fs.Open(path)
if err != nil {
return false
}
defer utils.CallClose(file)

content, err := ioutil.ReadAll(file)
if err != nil {
return false
}

return bytes.Contains(content, []byte(s.script))
}

func (s *ShellProfiler) Run(ctx context.Context) (context.Context, error) {
fs := define.FS
logger := define.Logger
homeDir, err := os.UserHomeDir()
if err != nil {
return ctx, errors.Wrapf(err, "failed to get user home dir")
}

script := `eval "$(cmdr init)`
var profile string
switch s.shell {
case "bash":
profile = filepath.Join(homeDir, ".bashrc")
case "zsh":
profile = filepath.Join(homeDir, ".zshrc")
default:
logger.Warn("shell is not supported, please execute this script to init cmdr environment", map[string]interface{}{
"shell": s.shell,
"script": script,
})
}

if s.isContainsProfile(profile) {
return ctx, nil
}

file, err := fs.OpenFile(profile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return ctx, errors.Wrapf(err, "failed to open profile file")
}
defer utils.CallClose(file)

_, err = fmt.Fprintf(file, "\n%s\n", script)
if err != nil {
return ctx, errors.Wrapf(err, "failed to write to profile file")
}

return ctx, nil
}

func NewShellProfiler(shell string) *ShellProfiler {
return &ShellProfiler{
shell: filepath.Base(shell),
script: `eval "$(cmdr init)`,
}
}

0 comments on commit a4ef3fd

Please sign in to comment.