Skip to content

Commit

Permalink
Show information about updated plugin during update command
Browse files Browse the repository at this point in the history
  • Loading branch information
artmello committed Jan 5, 2020
1 parent f92c9d7 commit 9e65c53
Show file tree
Hide file tree
Showing 3 changed files with 186 additions and 13 deletions.
151 changes: 151 additions & 0 deletions cmd/krew/cmd/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,31 @@ package cmd
import (
"fmt"
"os"
"path/filepath"
"sort"

"github.com/pkg/errors"
"github.com/spf13/cobra"
"k8s.io/klog"

"sigs.k8s.io/krew/internal/gitutil"
"sigs.k8s.io/krew/internal/index/indexscanner"
"sigs.k8s.io/krew/internal/installation"
"sigs.k8s.io/krew/pkg/constants"
)

type newPlugin struct {
name string
version string
}

type newVersionPlugin struct {
name string
installed bool
oldVersion string
newVersion string
}

// updateCmd represents the update command
var updateCmd = &cobra.Command{
Use: "update",
Expand All @@ -41,12 +57,147 @@ Remarks:
RunE: ensureIndexUpdated,
}

func retrieveUpdatedPluginList() ([]string, error) {
modifiedFiles, err := gitutil.ListModifiedFiles(constants.IndexURI, paths.IndexPluginsPath())
if err != nil {
return []string{}, err
}

var plugins []string
for _, f := range modifiedFiles {
filename := filepath.Base(f)
extension := filepath.Ext(filename)
name := filename[0 : len(filename)-len(extension)]
plugins = append(plugins, name)
}

return plugins, nil
}

func retrievePluginNameVersionMap(names []string) map[string]string {
m := make(map[string]string, len(names))
for _, n := range names {
plugin, err := indexscanner.LoadPluginByName(paths.IndexPluginsPath(), n)
if err != nil {
continue
}

m[n] = plugin.Spec.Version
}

return m
}

func retrieveInstalledPluginMap() (map[string]bool, error) {
plugins, err := installation.ListInstalledPlugins(paths.InstallReceiptsPath())
if err != nil {
return map[string]bool{}, err
}
m := make(map[string]bool, len(plugins))
for name := range plugins {
m[name] = true
}

return m, nil
}

func filterAndSortUpdatedPlugins(old, updated map[string]string, installed map[string]bool) ([]newPlugin, []newVersionPlugin) {
var newPluginList []newPlugin
var newVersionList []newVersionPlugin

for name, version := range updated {
oldVersion, ok := old[name]
if !ok {
newPluginList = append(newPluginList, newPlugin{
name: name,
version: version,
})
continue
}

if version != oldVersion {
_, installed := installed[name]
newVersionList = append(newVersionList, newVersionPlugin{
name: name,
installed: installed,
oldVersion: oldVersion,
newVersion: version,
})
continue
}
}

sort.Slice(newPluginList, func(i, j int) bool {
return newPluginList[i].name < newPluginList[j].name
})

sort.Slice(newVersionList, func(i, j int) bool {
if newVersionList[i].installed && !newVersionList[j].installed {
return true
}

if !newVersionList[i].installed && newVersionList[j].installed {
return false
}

return newVersionList[i].name < newVersionList[j].name
})

return newPluginList, newVersionList
}

func showUpdatedPlugins(newPluginList []newPlugin, newVersionList []newVersionPlugin) {
if len(newPluginList) > 0 {
fmt.Fprintln(os.Stderr, " New plugins available:")
for _, np := range newPluginList {
fmt.Fprintf(os.Stderr, " * %s %s\n", np.name, np.version)
}
}

if len(newVersionList) > 0 {
fmt.Fprintln(os.Stderr, " The following plugins have new version:")
for _, np := range newVersionList {
if np.installed {
fmt.Fprintf(os.Stderr, " * %s %s -> %s (!)\n", np.name, np.oldVersion, np.newVersion)
continue
}
fmt.Fprintf(os.Stderr, " * %s %s -> %s\n", np.name, np.oldVersion, np.newVersion)
}
}
}

func ensureIndexUpdated(_ *cobra.Command, _ []string) error {
updatedPlugins, err := retrieveUpdatedPluginList()
if err != nil {
return errors.Wrap(err, "failed to load the list of updated plugins from the index")
}

var oldMap map[string]string
if len(updatedPlugins) > 0 {
oldMap = retrievePluginNameVersionMap(updatedPlugins)
}

klog.V(1).Infof("Updating the local copy of plugin index (%s)", paths.IndexPath())
if err := gitutil.EnsureUpdated(constants.IndexURI, paths.IndexPath()); err != nil {
return errors.Wrap(err, "failed to update the local index")
}
fmt.Fprintln(os.Stderr, "Updated the local copy of plugin index.")

if len(updatedPlugins) < 0 {
return nil
}

updatedMap := retrievePluginNameVersionMap(updatedPlugins)

installedMap, err := retrieveInstalledPluginMap()
if err != nil {
return errors.Wrap(err, "failed to find all installed versions")
}

newPluginList, newVersionList := filterAndSortUpdatedPlugins(oldMap, updatedMap, installedMap)

showUpdatedPlugins(newPluginList, newVersionList)

return nil
}

Expand Down
12 changes: 6 additions & 6 deletions hack/run-integration-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ if [[ ! -e "${KREW_BINARY}" ]]; then
echo >&2 "Could not find $KREW_BINARY. You need to build krew for ${goos}/${goarch} before running the integration tests."
exit 1
fi
krew_binary_realpath="$(readlink -f "${KREW_BINARY}")"
if [[ ! -x "${krew_binary_realpath}" ]]; then
echo >&2 "krew binary at ${krew_binary_realpath} is not an executable"
exit 1
fi
KREW_BINARY="${krew_binary_realpath}"
# krew_binary_realpath="$(readlink -f "${KREW_BINARY}")"
# if [[ ! -x "${krew_binary_realpath}" ]]; then
# echo >&2 "krew binary at ${krew_binary_realpath} is not an executable"
# exit 1
# fi
# KREW_BINARY="${krew_binary_realpath}"
export KREW_BINARY

go test sigs.k8s.io/krew/integration_test
36 changes: 29 additions & 7 deletions internal/gitutil/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ func EnsureCloned(uri, destinationPath string) error {
if ok, err := IsGitCloned(destinationPath); err != nil {
return err
} else if !ok {
return exec("", "clone", "-v", uri, destinationPath)
_, err := exec("", "clone", "-v", uri, destinationPath)
return err
}
return nil
}
Expand All @@ -49,15 +50,15 @@ func IsGitCloned(gitPath string) (bool, error) {
// and also will create a pristine working directory by removing
// untracked files and directories.
func updateAndCleanUntracked(destinationPath string) error {
if err := exec(destinationPath, "fetch", "-v"); err != nil {
if _, err := exec(destinationPath, "fetch", "-v"); err != nil {
return errors.Wrapf(err, "fetch index at %q failed", destinationPath)
}

if err := exec(destinationPath, "reset", "--hard", "@{upstream}"); err != nil {
if _, err := exec(destinationPath, "reset", "--hard", "@{upstream}"); err != nil {
return errors.Wrapf(err, "reset index at %q failed", destinationPath)
}

err := exec(destinationPath, "clean", "-xfd")
_, err := exec(destinationPath, "clean", "-xfd")
return errors.Wrapf(err, "clean index at %q failed", destinationPath)
}

Expand All @@ -69,7 +70,27 @@ func EnsureUpdated(uri, destinationPath string) error {
return updateAndCleanUntracked(destinationPath)
}

func exec(pwd string, args ...string) error {
// ListModifiedFiles will fetch origin and list modified files
func ListModifiedFiles(uri, destinationPath string) ([]string, error) {
if _, err := exec(destinationPath, "fetch", "-v"); err != nil {
return []string{}, errors.Wrapf(err, "fetch index at %q failed", destinationPath)
}

output, err := exec(destinationPath, "diff", "--name-only", "@{upstream}", "--", ".")
if err != nil {
return []string{}, errors.Wrapf(err, "diff index at %q failed", destinationPath)
}

var modifiedFiles []string
for _, f := range strings.Split(output, "\n") {
if len(f) > 0 {
modifiedFiles = append(modifiedFiles, f)
}
}
return modifiedFiles, nil
}

func exec(pwd string, args ...string) (string, error) {
klog.V(4).Infof("Going to run git %s", strings.Join(args, " "))
cmd := osexec.Command("git", args...)
cmd.Dir = pwd
Expand All @@ -80,7 +101,8 @@ func exec(pwd string, args ...string) error {
}
cmd.Stdout, cmd.Stderr = w, w
if err := cmd.Run(); err != nil {
return errors.Wrapf(err, "command execution failure, output=%q", buf.String())
output := buf.String()
return output, errors.Wrapf(err, "command execution failure, output=%q", output)
}
return nil
return buf.String(), nil
}

0 comments on commit 9e65c53

Please sign in to comment.