pinning binary exts

This commit is contained in:
meiji163 2022-03-01 15:01:04 -08:00
parent eaa64df801
commit fe5eca1dd5
5 changed files with 90 additions and 40 deletions

View file

@ -70,10 +70,12 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command {
return t.Render()
},
},
&cobra.Command{
Use: "install <repository>",
Short: "Install a gh extension from a repository",
Long: heredoc.Doc(`
func() *cobra.Command {
var pinFlag string
cmd := &cobra.Command{
Use: "install <repository>",
Short: "Install a gh extension from a repository",
Long: heredoc.Doc(`
Install a GitHub repository locally as a GitHub CLI extension.
The repository argument can be specified in "owner/repo" format as well as a full URL.
@ -84,41 +86,44 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command {
See the list of available extensions at <https://github.com/topics/gh-extension>
`),
Example: heredoc.Doc(`
Example: heredoc.Doc(`
$ gh extension install owner/gh-extension
$ gh extension install https://git.example.com/owner/gh-extension
$ gh extension install .
`),
Args: cmdutil.MinimumArgs(1, "must specify a repository to install from"),
RunE: func(cmd *cobra.Command, args []string) error {
if args[0] == "." {
wd, err := os.Getwd()
Args: cmdutil.MinimumArgs(1, "must specify a repository to install from"),
RunE: func(cmd *cobra.Command, args []string) error {
if args[0] == "." {
wd, err := os.Getwd()
if err != nil {
return err
}
return m.InstallLocal(wd)
}
repo, err := ghrepo.FromFullName(args[0])
if err != nil {
return err
}
return m.InstallLocal(wd)
}
repo, err := ghrepo.FromFullName(args[0])
if err != nil {
return err
}
if err := checkValidExtension(cmd.Root(), m, repo.RepoName()); err != nil {
return err
}
if err := checkValidExtension(cmd.Root(), m, repo.RepoName()); err != nil {
return err
}
if err := m.Install(repo, pinFlag); err != nil {
return err
}
if err := m.Install(repo); err != nil {
return err
}
if io.IsStdoutTTY() {
cs := io.ColorScheme()
fmt.Fprintf(io.Out, "%s Installed extension %s\n", cs.SuccessIcon(), args[0])
}
return nil
},
},
if io.IsStdoutTTY() {
cs := io.ColorScheme()
fmt.Fprintf(io.Out, "%s Installed extension %s\n", cs.SuccessIcon(), args[0])
}
return nil
},
}
cmd.Flags().StringVar(&pinFlag, "pin", "", "pin extension to a release tag or commit sha")
return cmd
}(),
func() *cobra.Command {
var flagAll bool
var flagForce bool

View file

@ -112,3 +112,37 @@ func fetchLatestRelease(httpClient *http.Client, baseRepo ghrepo.Interface) (*re
return &r, nil
}
// fetchRelease finds release by tag name for a repository
func fetchReleaseFromTag(httpClient *http.Client, baseRepo ghrepo.Interface, tagName string) (*release, error) {
fullRepoName := fmt.Sprintf("%s/%s", baseRepo.RepoOwner(), baseRepo.RepoName())
path := fmt.Sprintf("repos/%s/releases/tags/%s", fullRepoName, tagName)
url := ghinstance.RESTPrefix(baseRepo.RepoHost()) + path
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
resp, err := httpClient.Do(req)
defer resp.Body.Close()
if err != nil {
return nil, err
}
if resp.StatusCode > 299 {
return nil, api.HandleHTTPError(resp)
}
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var r release
err = json.Unmarshal(b, &r)
if err != nil {
return nil, err
}
return &r, nil
}

View file

@ -320,13 +320,13 @@ type binManifest struct {
Path string
}
func (m *Manager) Install(repo ghrepo.Interface) error {
func (m *Manager) Install(repo ghrepo.Interface, targetCommitish string) error {
isBin, err := isBinExtension(m.client, repo)
if err != nil {
return fmt.Errorf("could not check for binary extension: %w", err)
}
if isBin {
return m.installBin(repo)
return m.installBin(repo, targetCommitish)
}
hs, err := hasScript(m.client, repo)
@ -341,9 +341,14 @@ func (m *Manager) Install(repo ghrepo.Interface) error {
return m.installGit(ghrepo.FormatRemoteURL(repo, protocol), m.io.Out, m.io.ErrOut)
}
func (m *Manager) installBin(repo ghrepo.Interface) error {
func (m *Manager) installBin(repo ghrepo.Interface, targetCommitish string) error {
var r *release
r, err := fetchLatestRelease(m.client, repo)
var err error
if targetCommitish == "" {
r, err = fetchLatestRelease(m.client, repo)
} else {
r, err = fetchReleaseFromTag(m.client, repo, targetCommitish)
}
if err != nil {
return err
}
@ -498,7 +503,7 @@ func (m *Manager) upgradeExtension(ext Extension, force bool) error {
if err != nil {
return fmt.Errorf("failed to migrate to new precompiled extension format: %w", err)
}
return m.installBin(repo)
return m.installBin(repo, "")
}
err = m.upgradeGitExtension(ext, force)
}
@ -525,7 +530,7 @@ func (m *Manager) upgradeBinExtension(ext Extension) error {
if err != nil {
return fmt.Errorf("failed to parse URL %s: %w", ext.url, err)
}
return m.installBin(repo)
return m.installBin(repo, "")
}
func (m *Manager) Remove(name string) error {