Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Download template #30

Merged
merged 4 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 0 additions & 17 deletions .github/workflows/codeball.yml

This file was deleted.

12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ For Chinese users, you can install the CMDR via a proxy:

```shell
curl -o- https://raw.githubusercontent.com/MrLYC/cmdr/master/install.sh | bash -s -p
```

### Manual
1. Download the latest release from [GitHub](https://github.com/mrlyc/cmdr/releases/latest);
Expand Down Expand Up @@ -45,8 +46,17 @@ Use a specified command version:
cmdr command use -n <command-name> -v <version>
```

## Upgrade
## Features

### Upgrade
To upgrade the CMDR, just run:
```shell
cmdr upgrade
```

### Url replacement
Speed up the download process by replacing the `url` to github proxy:
```shell
cmdr config set -k download.replace -v '{"match": "^https://raw.githubusercontent.com/.*$", "template": "https://ghproxy.com/{{ .input | urlquery }}"}'
cmdr command install -n install.sh -v 0.0.0 -l https://raw.githubusercontent.com/MrLYC/cmdr/master/install.sh
```
8 changes: 6 additions & 2 deletions cmd/config/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"

"github.com/spf13/cobra"
"gopkg.in/yaml.v2"

"github.com/mrlyc/cmdr/core"
"github.com/mrlyc/cmdr/core/utils"
Expand All @@ -16,9 +17,12 @@ var getCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
cfg := core.GetConfiguration()
key := cfg.GetString(core.CfgKeyXConfigGetKey)
value := cfg.Get(key)
var dumps interface{}
utils.PanicOnError("unmarshal config failed", cfg.UnmarshalKey(key, &dumps))

fmt.Printf("key: %s, type: %T, value: %v\n", key, value, value)
out, err := yaml.Marshal(dumps)
utils.PanicOnError("marshal config failed", err)
fmt.Printf("%s", out)
},
}

Expand Down
6 changes: 5 additions & 1 deletion cmd/config/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"path/filepath"

"github.com/spf13/cobra"
"gopkg.in/yaml.v2"

"github.com/mrlyc/cmdr/core"
"github.com/mrlyc/cmdr/core/utils"
Expand Down Expand Up @@ -32,7 +33,10 @@ var setCmd = &cobra.Command{
}

key := cfg.GetString(core.CfgKeyXConfigSetKey)
value := cfg.GetString(core.CfgKeyXConfigSetValue)
yamlValue := cfg.GetString(core.CfgKeyXConfigSetValue)

var value interface{}
utils.PanicOnError("mark yaml value", yaml.Unmarshal([]byte(yamlValue), &value))

userCfg.Set(key, value)

Expand Down
3 changes: 3 additions & 0 deletions core/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ const (
CfgKeyLogLevel = "log.level"
CfgKeyLogOutput = "log.output"

// download
CfgKeyDownloadReplace = "download.replace"

// cmd.command.define
CfgKeyXCommandDefineName = "_.command.define.name"
CfgKeyXCommandDefineVersion = "_.command.define.version"
Expand Down
14 changes: 11 additions & 3 deletions core/initializer/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,17 @@
return nil, errors.Wrapf(err, "failed to create command query")
}

commands, err := query.
WithName(c.name).
All()
query = query.WithName(c.name)
count, err := query.Count()
if err != nil {
return nil, errors.Wrapf(err, "failed to count commands")

Check warning on line 31 in core/initializer/command.go

View check run for this annotation

Codecov / codecov/patch

core/initializer/command.go#L31

Added line #L31 was not covered by tests
}

if count == 0 {
return nil, nil

Check warning on line 35 in core/initializer/command.go

View check run for this annotation

Codecov / codecov/patch

core/initializer/command.go#L35

Added line #L35 was not covered by tests
}

commands, err := query.All()

if err != nil {
return nil, errors.Wrapf(err, "failed to get commands")
Expand Down
1 change: 1 addition & 0 deletions core/initializer/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ var _ = Describe("Command", func() {
query.EXPECT().WithActivated(true).Return(query).AnyTimes()
query.EXPECT().All().Return([]core.Command{legacyCommand, activatedCommand}, nil).AnyTimes()
query.EXPECT().One().Return(activatedCommand, nil).AnyTimes()
query.EXPECT().Count().Return(2, nil).AnyTimes()

manager = mock.NewMockCommandManager(ctrl)
manager.EXPECT().Query().Return(query, nil).AnyTimes()
Expand Down
28 changes: 24 additions & 4 deletions core/manager/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,13 @@

type DownloadManager struct {
core.CommandManager
fetchers []core.Fetcher
retries int
fetchers []core.Fetcher
retries int
replacements utils.Replacements
}

func (m *DownloadManager) SetReplacements(replacements utils.Replacements) {
m.replacements = replacements
}

func (m *DownloadManager) search(name, output string) (string, error) {
Expand Down Expand Up @@ -65,6 +70,9 @@
func (m *DownloadManager) fetch(fetcher core.Fetcher, name, version, location, output string) (string, error) {
var err error
logger := core.GetLogger()
logger.Info("fetching", map[string]interface{}{
"uri": location,
})

for i := 0; i < m.retries; i++ {
err = fetcher.Fetch(name, version, location, output)
Expand All @@ -85,6 +93,8 @@
}

func (m *DownloadManager) Define(name string, version string, uriOrLocation string) (core.Command, error) {
uriOrLocation, _ = m.replacements.ReplaceString(uriOrLocation)

for _, fetcher := range m.fetchers {
if !fetcher.IsSupport(uriOrLocation) {
continue
Expand All @@ -107,11 +117,14 @@
return m.CommandManager.Define(name, version, uriOrLocation)
}

func NewDownloadManager(manager core.CommandManager, fetchers []core.Fetcher, retries int) *DownloadManager {
func NewDownloadManager(
manager core.CommandManager, fetchers []core.Fetcher, retries int, replacements utils.Replacements,
) *DownloadManager {
return &DownloadManager{
CommandManager: manager,
fetchers: fetchers,
retries: retries,
replacements: replacements,
}
}

Expand All @@ -122,9 +135,16 @@
utils.ExitOnError("Failed to create command manager", err)
}

var replacements utils.Replacements

err = cfg.UnmarshalKey(core.CfgKeyDownloadReplace, &replacements)
if err != nil {
utils.ExitOnError("Failed to parse download replace config", err)

Check warning on line 142 in core/manager/download.go

View check run for this annotation

Codecov / codecov/patch

core/manager/download.go#L142

Added line #L142 was not covered by tests
}

return NewDownloadManager(manager, []core.Fetcher{
fetcher.NewDefaultGoInstaller(),
fetcher.NewDefaultGoGetter(os.Stderr),
}, 3), nil
}, 3, replacements), nil
})
}
20 changes: 19 additions & 1 deletion core/manager/download_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/mrlyc/cmdr/core"
"github.com/mrlyc/cmdr/core/manager"
"github.com/mrlyc/cmdr/core/mock"
"github.com/mrlyc/cmdr/core/utils"
)

var _ = Describe("Download", func() {
Expand Down Expand Up @@ -50,7 +51,7 @@ var _ = Describe("Download", func() {
BeforeEach(func() {
fetcher = mock.NewMockFetcher(ctrl)
baseManager = mock.NewMockCommandManager(ctrl)
downloadManager = manager.NewDownloadManager(baseManager, []core.Fetcher{fetcher}, 1)
downloadManager = manager.NewDownloadManager(baseManager, []core.Fetcher{fetcher}, 1, nil)
})

It("should call base manager", func() {
Expand Down Expand Up @@ -139,6 +140,23 @@ var _ = Describe("Download", func() {
"sub/dir/cmdr": 0755,
}, "cmdr"),
)

It("should replace url", func() {
input := "http://github.com/MrLYC/cmdr"
replaced := "mock://github.com/MrLYC/cmdr"

downloadManager.SetReplacements(utils.Replacements{
{
Match: "http://(.*)",
Template: "mock://{{ index .group 1 }}",
},
})

fetcher.EXPECT().IsSupport(replaced).Return(false)
baseManager.EXPECT().Define(name, version, replaced)

Expect(downloadManager.Define(name, version, input)).To(Succeed())
})
})

Context("Factory", func() {
Expand Down
56 changes: 56 additions & 0 deletions core/utils/replacement.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package utils

import (
"bytes"
"regexp"
"text/template"

"github.com/mrlyc/cmdr/core"
)

type Replacement struct {
Match string
Template string
}

func (r *Replacement) ReplaceString(s string) (string, bool) {
logger := core.GetLogger()

regex := regexp.MustCompile(r.Match)
group := regex.FindStringSubmatch(s)
if group == nil {
return s, false
}

tmpl := template.Must(template.New("").Parse(r.Template))
buf := &bytes.Buffer{}
err := tmpl.Execute(buf, map[string]interface{}{
"input": s,
"group": group,
})
if err != nil {
return s, false

Check warning on line 32 in core/utils/replacement.go

View check run for this annotation

Codecov / codecov/patch

core/utils/replacement.go#L32

Added line #L32 was not covered by tests
}

replaced := buf.String()
logger.Debug("replaced", map[string]interface{}{
"location": s,
"match": r.Match,
"replaced": replaced,
})

return replaced, true
}

type Replacements []*Replacement

func (r Replacements) ReplaceString(s string) (string, bool) {
for _, r := range r {
s, ok := r.ReplaceString(s)
if ok {
return s, ok

Check warning on line 51 in core/utils/replacement.go

View check run for this annotation

Codecov / codecov/patch

core/utils/replacement.go#L47-L51

Added lines #L47 - L51 were not covered by tests
}
}

return s, false

Check warning on line 55 in core/utils/replacement.go

View check run for this annotation

Codecov / codecov/patch

core/utils/replacement.go#L55

Added line #L55 was not covered by tests
}
26 changes: 26 additions & 0 deletions core/utils/replacement_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package utils_test

import (
"github.com/mrlyc/cmdr/core/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/extensions/table"
. "github.com/onsi/gomega"
)

var _ = Describe("Replacement", func() {
DescribeTable("ReplaceString", func(match, template, input, output string, replaced bool) {
replacement := utils.Replacement{
Match: match,
Template: template,
}

realOutput, realReplaced := replacement.ReplaceString(input)
Expect(realOutput).To(Equal(output))
Expect(realReplaced).To(Equal(replaced))
},
Entry("concat", "", "hello {{ .input }}", "world", "hello world", true),
Entry("replace", "hi (.*)", "hello {{ index .group 1 }}", "hi world", "hello world", true),
Entry("urlencode", "", "{{ .input | urlquery }}", " ", "+", true),
Entry("nothing", "noting", "fail", "ok", "ok", false),
)
})
Loading