func (cmd *PluginInstall) Execute(c flags.FlagContext) {
	if !cmd.confirmWithUser(
		c,
		T("**Attention: Plugins are binaries written by potentially untrusted authors. Install and use plugins at your own risk.**\n\nDo you want to install the plugin {{.Plugin}}? (y or n)", map[string]interface{}{"Plugin": c.Args()[0]}),
	) {
		cmd.ui.Failed(T("Plugin installation cancelled"))
	}

	fileDownloader := fileutils.NewDownloader(os.TempDir())

	removeTmpFile := func() {
		err := fileDownloader.RemoveFile()
		if err != nil {
			cmd.ui.Say(T("Problem removing downloaded binary in temp directory: ") + err.Error())
		}
	}
	defer removeTmpFile()

	deps := &plugin_installer.PluginInstallerContext{
		Checksummer:    cmd.checksum,
		GetPluginRepos: cmd.config.PluginRepos,
		FileDownloader: fileDownloader,
		PluginRepo:     cmd.pluginRepo,
		RepoName:       c.String("r"),
		Ui:             cmd.ui,
	}
	installer := plugin_installer.NewPluginInstaller(deps)
	pluginSourceFilepath := installer.Install(c.Args()[0])

	cmd.ui.Say(fmt.Sprintf(T("Installing plugin {{.PluginPath}}...", map[string]interface{}{"PluginPath": pluginSourceFilepath})))

	_, pluginExecutableName := filepath.Split(pluginSourceFilepath)

	pluginDestinationFilepath := filepath.Join(cmd.pluginConfig.GetPluginPath(), pluginExecutableName)

	cmd.ensurePluginBinaryWithSameFileNameDoesNotAlreadyExist(pluginDestinationFilepath, pluginExecutableName)

	pluginMetadata := cmd.runBinaryAndObtainPluginMetadata(pluginSourceFilepath)

	cmd.ensurePluginIsSafeForInstallation(pluginMetadata, pluginDestinationFilepath, pluginSourceFilepath)

	cmd.installPlugin(pluginMetadata, pluginDestinationFilepath, pluginSourceFilepath)

	cmd.ui.Ok()
	cmd.ui.Say(fmt.Sprintf(T("Plugin {{.PluginName}} v{{.Version}} successfully installed.", map[string]interface{}{"PluginName": pluginMetadata.Name, "Version": fmt.Sprintf("%d.%d.%d", pluginMetadata.Version.Major, pluginMetadata.Version.Minor, pluginMetadata.Version.Build)})))
}
예제 #2
0
func (cmd *PluginInstall) Run(c *cli.Context) {
	downloader := fileutils.NewDownloader(os.TempDir())

	removeTmpFile := func() {
		err := downloader.RemoveFile()
		if err != nil {
			cmd.ui.Say(T("Problem removing downloaded binary in temp directory: ") + err.Error())
		}
	}
	defer removeTmpFile()

	pluginSourceFilepath := c.Args()[0]

	repoName := c.String("r")

	if repoName != "" {
		targetPluginName := strings.ToLower(c.Args()[0])

		cmd.ui.Say(T("Looking up '{{.filePath}}' from repository '{{.repoName}}'", map[string]interface{}{"filePath": pluginSourceFilepath, "repoName": repoName}))

		repoModel, err := cmd.getRepoFromConfig(repoName)
		if err != nil {
			cmd.ui.Failed(err.Error() + "\n" + T("Tip: use 'add-plugin-repo' to register the repo"))
		}

		pluginList, repoAry := cmd.pluginRepo.GetPlugins([]models.PluginRepo{repoModel})
		if len(repoAry) != 0 {
			cmd.ui.Failed(T("Error getting plugin metadata from repo: ") + repoAry[0])
		}

		found := false
		sha1 := ""
		for _, plugin := range findRepoCaseInsensity(pluginList, repoName) {
			if strings.ToLower(plugin.Name) == targetPluginName {
				found = true
				pluginSourceFilepath, sha1 = cmd.downloadBinary(plugin, downloader)

				cmd.checksum.SetFilePath(pluginSourceFilepath)
				if !cmd.checksum.CheckSha1(sha1) {
					cmd.ui.Failed(T("Downloaded plugin binary's checksum does not match repo metadata"))
				}
			}

		}
		if !found {
			cmd.ui.Failed(pluginSourceFilepath + T(" is not available in repo '") + repoName + "'")
		}
	} else {
		if filepath.Dir(pluginSourceFilepath) == "." {
			pluginSourceFilepath = "./" + filepath.Clean(pluginSourceFilepath)
		}

		cmd.ui.Say("")
		if strings.HasPrefix(pluginSourceFilepath, "https://") || strings.HasPrefix(pluginSourceFilepath, "http://") ||
			strings.HasPrefix(pluginSourceFilepath, "ftp://") || strings.HasPrefix(pluginSourceFilepath, "ftps://") {
			cmd.ui.Say(T("Attempting to download binary file from internet address..."))
			pluginSourceFilepath = cmd.tryDownloadPluginBinaryfromGivenPath(pluginSourceFilepath, downloader)
		} else if !cmd.ensureCandidatePluginBinaryExistsAtGivenPath(pluginSourceFilepath) {
			cmd.ui.Failed(T("File not found locally, make sure the file exists at given path ..."))
		}

	}

	cmd.ui.Say(fmt.Sprintf(T("Installing plugin {{.PluginPath}}...", map[string]interface{}{"PluginPath": pluginSourceFilepath})))

	_, pluginExecutableName := filepath.Split(pluginSourceFilepath)

	pluginDestinationFilepath := filepath.Join(cmd.pluginConfig.GetPluginPath(), pluginExecutableName)

	cmd.ensurePluginBinaryWithSameFileNameDoesNotAlreadyExist(pluginDestinationFilepath, pluginExecutableName)

	pluginMetadata := cmd.runBinaryAndObtainPluginMetadata(pluginSourceFilepath)

	cmd.ensurePluginIsSafeForInstallation(pluginMetadata, pluginDestinationFilepath, pluginSourceFilepath)

	cmd.installPlugin(pluginMetadata, pluginDestinationFilepath, pluginSourceFilepath)

	cmd.ui.Ok()
	cmd.ui.Say(fmt.Sprintf(T("Plugin {{.PluginName}} v{{.Version}} successfully installed.", map[string]interface{}{"PluginName": pluginMetadata.Name, "Version": fmt.Sprintf("%d.%d.%d", pluginMetadata.Version.Major, pluginMetadata.Version.Minor, pluginMetadata.Version.Build)})))
}
예제 #3
0
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Downloader", func() {
	var (
		downloader fileutils.Downloader
		tempDir    string
	)

	BeforeEach(func() {
		var err error
		tempDir, err = ioutil.TempDir("", "file-download-test")
		Expect(err).NotTo(HaveOccurred())
		downloader = fileutils.NewDownloader(tempDir)
	})

	AfterEach(func() {
		os.RemoveAll(tempDir)
	})

	Describe("DownloadFile", func() {
		var server *ghttp.Server

		BeforeEach(func() {
			server = ghttp.NewServer()
		})

		AfterEach(func() {
			server.Close()