Skip to content

Commit

Permalink
feat: support to specific the format of target file (#364)
Browse files Browse the repository at this point in the history
  • Loading branch information
LinuxSuRen authored Feb 27, 2023
1 parent 844aa9b commit b706d1b
Show file tree
Hide file tree
Showing 13 changed files with 141 additions and 32 deletions.
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ build: fmt test
export GOPROXY=https://goproxy.io
CGO_ENABLE=0 go build -ldflags "-w -s" -o bin/hd

build-windows:
GOOS=windows CGO_ENABLE=0 go build -ldflags "-w -s" -o bin/windows/hd.exe
build-linux: fmt lint build-linux-no-check
build-linux-no-check:
export GOPROXY=https://goproxy.io
Expand Down
2 changes: 0 additions & 2 deletions cmd/fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ func newFetchCmd(context.Context) (cmd *cobra.Command) {
"If you want to reset the hd-config which means delete and clone it again")
flags.IntVarP(&opt.retry, "retry", "", 6, "Retry times due to timeout error")
flags.DurationVarP(&opt.timeout, "timeout", "", time.Second*10, "Timeout of fetching")

_ = cmd.RegisterFlagCompletionFunc("provider", ArrayCompletion(ProviderGitHub, ProviderGitee))
return
}

Expand Down
22 changes: 12 additions & 10 deletions cmd/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,7 @@ func newGetCmd(ctx context.Context) (cmd *cobra.Command) {
`The default timeout in seconds with the HTTP request`)
flags.IntVarP(&opt.MaxAttempts, "max-attempts", "", 10,
`Max times to attempt to download, zero means there's no retry action'`)
flags.BoolVarP(&opt.NoProxy, "no-proxy", "", false, "Indicate no HTTP proxy taken")
flags.BoolVarP(&opt.ShowProgress, "show-progress", "", true, "If show the progress of download")
flags.Int64VarP(&opt.ContinueAt, "continue-at", "", -1, "ContinueAt")
flags.IntVarP(&opt.Thread, "thread", "t", viper.GetInt("thread"),
`Download file with multi-threads. It only works when its value is bigger than 1`)
flags.BoolVarP(&opt.KeepPart, "keep-part", "", false,
"If you want to keep the part files instead of deleting them")
flags.BoolVarP(&opt.PrintSchema, "print-schema", "", false,
Expand All @@ -77,10 +73,7 @@ func newGetCmd(ctx context.Context) (cmd *cobra.Command) {
flags.IntVarP(&opt.PrintVersionCount, "print-version-count", "", 20,
"The number of the version list")
flags.BoolVarP(&opt.Magnet, "magnet", "", false, "Fetch magnet list from a website")

_ = cmd.RegisterFlagCompletionFunc("proxy-github", ArrayCompletion("gh.api.99988866.xyz",
"ghproxy.com", "mirror.ghproxy.com"))
_ = cmd.RegisterFlagCompletionFunc("provider", ArrayCompletion(ProviderGitHub, ProviderGitee))
flags.StringVarP(&opt.Format, "format", "", "", "Specific the file format, for instance: tar, zip, msi")
return
}

Expand Down Expand Up @@ -111,6 +104,7 @@ type downloadOption struct {
Force bool
Mod int
SkipTLS bool
Format string

ContinueAt int64

Expand Down Expand Up @@ -145,6 +139,10 @@ const (
func (o *downloadOption) addDownloadFlags(flags *pflag.FlagSet) {
flags.IntVarP(&o.Mod, "mod", "", -1, "The file permission, -1 means using the system default")
flags.BoolVarP(&o.SkipTLS, "skip-tls", "k", false, "Skip the TLS")
flags.BoolVarP(&o.ShowProgress, "show-progress", "", true, "If show the progress of download")
flags.IntVarP(&o.Thread, "thread", "t", viper.GetInt("thread"),
`Download file with multi-threads. It only works when its value is bigger than 1`)
flags.BoolVarP(&o.NoProxy, "no-proxy", "", viper.GetBool("no-proxy"), "Indicate no HTTP proxy taken")
}

func (o *downloadOption) fetch() (err error) {
Expand Down Expand Up @@ -195,7 +193,11 @@ func (o *downloadOption) preRunE(cmd *cobra.Command, args []string) (err error)
}

targetURL := args[0]
o.Package = &installer.HDConfig{}
o.Package = &installer.HDConfig{
FormatOverrides: installer.PackagingFormat{
Format: o.Format,
},
}
if o.Magnet || strings.HasPrefix(targetURL, "magnet:?") {
// download via external tool
o.URL = targetURL
Expand All @@ -206,6 +208,7 @@ func (o *downloadOption) preRunE(cmd *cobra.Command, args []string) (err error)
OS: o.OS,
Arch: o.Arch,
Fetch: o.Fetch,
Package: o.Package,
}
if targetURL, err = ins.ProviderURLParse(targetURL, o.AcceptPreRelease); err != nil {
err = fmt.Errorf("only http:// or https:// supported, error: %v", err)
Expand Down Expand Up @@ -351,7 +354,6 @@ func (o *downloadOption) runE(cmd *cobra.Command, args []string) (err error) {
}
var yes bool
if confirmErr := survey.AskOne(confirm, &yes); confirmErr == nil && yes {
fmt.Println("rename")
err = sysos.Rename(o.Output, suggested)
}
}
Expand Down
6 changes: 0 additions & 6 deletions cmd/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ Cannot find your desired package? Please run command: hd fetch --reset, then try
opt.addDownloadFlags(flags)
flags.StringVarP(&opt.Category, "category", "c", "",
"The category of the potentials packages")
flags.BoolVarP(&opt.ShowProgress, "show-progress", "", true, "If show the progress of download")
flags.BoolVarP(&opt.AcceptPreRelease, "accept-preRelease", "", false,
"If you accept preRelease as the binary asset from GitHub")
flags.BoolVarP(&opt.AcceptPreRelease, "pre", "", false,
Expand All @@ -61,13 +60,8 @@ Cannot find your desired package? Please run command: hd fetch --reset, then try
"Indicate if force to download the package even it is exist")
flags.BoolVarP(&opt.CleanPackage, "clean-package", "", true,
"Clean the package if the installation is success")
flags.IntVarP(&opt.Thread, "thread", "t", viper.GetInt("thread"),
`Download file with multi-threads. It only works when its value is bigger than 1`)
flags.BoolVarP(&opt.NoProxy, "no-proxy", "", viper.GetBool("no-proxy"), "Indicate no HTTP proxy taken")
flags.BoolVarP(&opt.KeepPart, "keep-part", "", false,
"If you want to keep the part files instead of deleting them")

_ = cmd.RegisterFlagCompletionFunc("provider", ArrayCompletion(ProviderGitHub, ProviderGitee))
return
}

Expand Down
17 changes: 17 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,26 @@ func NewRoot(cxt context.Context) (cmd *cobra.Command) {
newGetCmd(cxt), newInstallCmd(cxt), newFetchCmd(cxt), newSearchCmd(cxt), newSetupCommand(v, stdio),
extver.NewVersionCmd("linuxsuren", "http-downloader", "hd", nil),
extpkg.NewCompletionCmd(cmd))

for _, c := range cmd.Commands() {
registerFlagCompletionFunc(c, "provider", ArrayCompletion(ProviderGitHub, ProviderGitee))
registerFlagCompletionFunc(c, "proxy-github", ArrayCompletion("gh.api.99988866.xyz",
"ghproxy.com", "mirror.ghproxy.com"))
registerFlagCompletionFunc(c, "os", ArrayCompletion("window", "linux", "darwin"))
registerFlagCompletionFunc(c, "arch", ArrayCompletion("amd64", "arm64"))
registerFlagCompletionFunc(c, "format", ArrayCompletion("tar.gz", "zip", "msi"))
}
return
}

func registerFlagCompletionFunc(cmd *cobra.Command, flag string, completionFunc CompletionFunc) {
if p := cmd.Flag(flag); p != nil {
if err := cmd.RegisterFlagCompletionFunc(flag, completionFunc); err != nil {
cmd.Println(err)
}
}
}

func loadConfig() (err error) {
viper.SetConfigName("hd")
viper.SetConfigType("yaml")
Expand Down
8 changes: 6 additions & 2 deletions cmd/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"io"

"github.com/linuxsuren/http-downloader/pkg/installer"
"github.com/linuxsuren/http-downloader/pkg/log"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"
Expand Down Expand Up @@ -46,11 +47,13 @@ Thanks to https://github.com/hunshcn/gh-proxy`)
}

func (s *searchOption) runE(c *cobra.Command, args []string) (err error) {
err = search(args[0], s.Fetch, s.fetcher, c.OutOrStdout())
logger := log.GetLoggerFromContextOrDefault(c)

err = search(args[0], s.Fetch, s.fetcher, c.OutOrStdout(), logger)
return
}

func search(keyword string, fetch bool, fetcher installer.Fetcher, writer io.Writer) (err error) {
func search(keyword string, fetch bool, fetcher installer.Fetcher, writer io.Writer, logger *log.LevelLog) (err error) {
if fetch {
if err = fetcher.FetchLatestRepo("", "", writer); err != nil {
return
Expand All @@ -62,6 +65,7 @@ func search(keyword string, fetch bool, fetcher installer.Fetcher, writer io.Wri
return
}

logger.Info("start to search in:", configDir)
result := installer.FindByKeyword(keyword, configDir)
for _, item := range result {
fmt.Fprintln(writer, item)
Expand Down
11 changes: 7 additions & 4 deletions cmd/search_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,24 @@ import (
"testing"

"github.com/linuxsuren/http-downloader/pkg/installer"
"github.com/linuxsuren/http-downloader/pkg/log"
"github.com/stretchr/testify/assert"
)

func Test_search(t *testing.T) {
logger := log.GetLogger()

buf := &bytes.Buffer{}
err := search("keyword", true, &installer.FakeFetcher{}, buf)
err := search("keyword", true, &installer.FakeFetcher{}, buf, logger)
assert.Nil(t, err)
assert.Empty(t, buf.String())

// expect an error with GetConfigDir
err = search("", true, &installer.FakeFetcher{GetConfigDirErr: errors.New("fake")}, buf)
err = search("", true, &installer.FakeFetcher{GetConfigDirErr: errors.New("fake")}, buf, logger)
assert.NotNil(t, err)

// expect an error with FetchLatestRepo
err = search("", true, &installer.FakeFetcher{FetchLatestRepoErr: errors.New("fake")}, buf)
err = search("", true, &installer.FakeFetcher{FetchLatestRepoErr: errors.New("fake")}, buf, logger)
assert.NotNil(t, err)

tempDir, err := os.MkdirTemp("", "config")
Expand All @@ -41,7 +44,7 @@ func Test_search(t *testing.T) {
err = os.WriteFile(path.Join(orgDir, "fake.yml"), []byte{}, os.ModeAppend)
assert.Nil(t, err)

err = search("repo", true, &installer.FakeFetcher{ConfigDir: tempDir}, buf)
err = search("repo", true, &installer.FakeFetcher{ConfigDir: tempDir}, buf, logger)
assert.Nil(t, err)
}

Expand Down
7 changes: 6 additions & 1 deletion cmd/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/AlecAivazis/survey/v2"
"github.com/AlecAivazis/survey/v2/terminal"
"github.com/linuxsuren/http-downloader/pkg/installer"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
Expand Down Expand Up @@ -52,7 +53,11 @@ func (o *setupOption) runE(cmd *cobra.Command, args []string) (err error) {
return
}

configDir := os.ExpandEnv("$HOME/.config")
var configDir string
fetcher := &installer.DefaultFetcher{}
if configDir, err = fetcher.GetConfigDir(); err != nil {
return
}
if err = os.MkdirAll(configDir, 0750); err != nil {
err = fmt.Errorf("failed to create directory: %s, error: %v", configDir, err)
return
Expand Down
17 changes: 13 additions & 4 deletions pkg/installer/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,13 @@ func (o *Installer) GetVersion(path string) (version string, err error) {
return
}

func getOrgAndRepo(orgAndRepo string) (string, string) {
return strings.Split(orgAndRepo, "/")[0], strings.Split(orgAndRepo, "/")[1]
func getOrgAndRepo(orgAndRepo string) (org string, repo string) {
items := strings.Split(orgAndRepo, "/")
if len(items) >= 2 {
org = items[0]
repo = items[1]
}
return
}

// ProviderURLParse parse the URL
Expand Down Expand Up @@ -217,6 +222,7 @@ func (o *Installer) ProviderURLParse(path string, acceptPreRelease bool) (packag
}
cfg.Org = o.Org
cfg.Repo = o.Repo
cfg.FormatOverrides.Format = o.Package.FormatOverrides.Format
o.Package = &cfg
o.AdditionBinaries = cfg.AdditionBinaries
o.Tar = cfg.Tar != "false"
Expand Down Expand Up @@ -481,14 +487,17 @@ func chooseOneFromArray(options []string) (result string, err error) {
}

func getPackagingFormat(installer *Installer) string {
if installer.Package != nil && installer.Package.FormatOverrides.Format != "" {
return installer.Package.FormatOverrides.Format
}
platformType := strings.ToLower(installer.OS)
if platformType == "windows" {
if installer.Package != nil {
if installer.Package != nil && installer.Package.FormatOverrides.Windows != "" {
return installer.Package.FormatOverrides.Windows
}
return "zip"
}
if installer.Package != nil {
if installer.Package != nil && installer.Package.FormatOverrides.Linux != "" {
return installer.Package.FormatOverrides.Linux
}
return "tar.gz"
Expand Down
62 changes: 62 additions & 0 deletions pkg/installer/check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -507,3 +507,65 @@ func Test_getVersionOrDefault(t *testing.T) {
})
}
}

func TestGetPackagingFormat(t *testing.T) {
tests := []struct {
name string
installer *Installer
expect string
}{{
name: "have specific format",
installer: &Installer{
OS: "Darwin",
Package: &HDConfig{
FormatOverrides: PackagingFormat{
Format: "msi",
},
},
},
expect: "msi",
}, {
name: "windows with config",
installer: &Installer{
OS: "Windows",
Package: &HDConfig{
FormatOverrides: PackagingFormat{
Windows: "msi",
},
},
},
expect: "msi",
}, {
name: "windows without config",
installer: &Installer{
OS: "Windows",
},
expect: "zip",
}, {
name: "darwin without config",
installer: &Installer{},
expect: "tar.gz",
}, {
name: "linux, and package is not nil, but the override is empty",
installer: &Installer{
Package: &HDConfig{},
},
expect: "tar.gz",
}, {
name: "linux with override",
installer: &Installer{
Package: &HDConfig{
FormatOverrides: PackagingFormat{
Linux: "tar.gz",
},
},
},
expect: "tar.gz",
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := getPackagingFormat(tt.installer)
assert.Equal(t, tt.expect, result)
})
}
}
6 changes: 4 additions & 2 deletions pkg/installer/fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ package installer
import (
"context"
"fmt"
"github.com/go-git/go-git/v5/plumbing/object"
"io"
"os"
"path"
"strings"

"github.com/go-git/go-git/v5/plumbing/object"

"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
Expand Down Expand Up @@ -45,7 +46,7 @@ type DefaultFetcher struct {
func (f *DefaultFetcher) GetConfigDir() (configDir string, err error) {
var userHome string
if userHome, err = homedir.Dir(); err == nil {
configDir = path.Join(userHome, "/.config/hd-home")
configDir = path.Join(userHome, fmt.Sprintf(".config%shd-home", string(os.PathSeparator)))
}
return
}
Expand Down Expand Up @@ -80,6 +81,7 @@ func (f *DefaultFetcher) FetchLatestRepo(provider string, branch string,
return
}

_, _ = fmt.Fprintf(progress, "fetch config into: %s\n", configDir)
if ok, _ := common.PathExists(configDir); ok {
var repo *git.Repository
if repo, err = git.PlainOpen(configDir); err == nil {
Expand Down
12 changes: 11 additions & 1 deletion pkg/installer/types.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
package installer

import "github.com/linuxsuren/http-downloader/pkg/exec"
import (
"fmt"

"github.com/linuxsuren/http-downloader/pkg/exec"
)

// PackagingFormat is used for containing config depending on machine
type PackagingFormat struct {
Windows string `yaml:"windows"`
Linux string `yaml:"linux"`
Format string
}

// String returns a pretty string
func (f PackagingFormat) String() string {
return fmt.Sprintf("Windows: %s, Linux: %s, Format: %s", f.Windows, f.Linux, f.Format)
}

// HDConfig is the config of http-downloader
Expand Down
Loading

0 comments on commit b706d1b

Please sign in to comment.