X Tutup
Skip to content

Commit 8dd1e12

Browse files
committed
Merge remote-tracking branch 'origin' into fix-actions-help
2 parents 94c1646 + dd3aac7 commit 8dd1e12

File tree

9 files changed

+564
-95
lines changed

9 files changed

+564
-95
lines changed

README.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,12 @@ GitHub CLI is available for repositories hosted on GitHub.com and GitHub Enterpr
1414

1515
If anything feels off, or if you feel that some functionality is missing, please check out the [contributing page][contributing]. There you will find instructions for sharing your feedback, building the tool locally, and submitting pull requests to the project.
1616

17-
1817
<!-- this anchor is linked to from elsewhere, so avoid renaming it -->
1918
## Installation
2019

2120
### macOS
2221

23-
`gh` is available via [Homebrew][], [MacPorts][], and as a downloadable binary from the [releases page][].
22+
`gh` is available via [Homebrew][], [MacPorts][], [Conda][], and as a downloadable binary from the [releases page][].
2423

2524
#### Homebrew
2625

@@ -34,16 +33,23 @@ If anything feels off, or if you feel that some functionality is missing, please
3433
| ---------------------- | ---------------------------------------------- |
3534
| `sudo port install gh` | `sudo port selfupdate && sudo port upgrade gh` |
3635

36+
#### Conda
37+
38+
| Install: | Upgrade: |
39+
|------------------------------------------|-----------------------------------------|
40+
| `conda install gh --channel conda-forge` | `conda update gh --channel conda-forge` |
41+
42+
Additional Conda installation options available on the [gh-feedstock page](https://github.com/conda-forge/gh-feedstock#installing-gh).
43+
3744
### Linux
3845

39-
`gh` is available via [Homebrew](#homebrew), and as downloadable binaries from the [releases page][].
46+
`gh` is available via [Homebrew](#homebrew), [Conda](#Conda), and as downloadable binaries from the [releases page][].
4047

4148
For more information and distro-specific instructions, see the [Linux installation docs](./docs/install_linux.md).
4249

4350
### Windows
4451

45-
`gh` is available via [WinGet][], [scoop][], [Chocolatey][], and as downloadable MSI.
46-
52+
`gh` is available via [WinGet][], [scoop][], [Chocolatey][], [Conda](#Conda), and as downloadable MSI.
4753

4854
#### WinGet
4955

@@ -86,13 +92,13 @@ what an official GitHub CLI tool can look like with a fundamentally different de
8692
tools bring GitHub to the terminal, `hub` behaves as a proxy to `git`, and `gh` is a standalone
8793
tool. Check out our [more detailed explanation][gh-vs-hub] to learn more.
8894

89-
9095
[manual]: https://cli.github.com/manual/
9196
[Homebrew]: https://brew.sh
9297
[MacPorts]: https://www.macports.org
9398
[winget]: https://github.com/microsoft/winget-cli
9499
[scoop]: https://scoop.sh
95100
[Chocolatey]: https://chocolatey.org
101+
[Conda]: https://docs.conda.io/en/latest/
96102
[releases page]: https://github.com/cli/cli/releases/latest
97103
[hub]: https://github.com/github/hub
98104
[contributing]: ./.github/CONTRIBUTING.md

cmd/gh/main.go

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -93,15 +93,6 @@ func mainRun() exitCode {
9393
return exitError
9494
}
9595

96-
if prompt, _ := cfg.Get("", "prompt"); prompt == "disabled" {
97-
cmdFactory.IOStreams.SetNeverPrompt(true)
98-
}
99-
if ghPager, ghPagerExists := os.LookupEnv("GH_PAGER"); ghPagerExists {
100-
cmdFactory.IOStreams.SetPager(ghPager)
101-
} else if pager, _ := cfg.Get("", "pager"); pager != "" {
102-
cmdFactory.IOStreams.SetPager(pager)
103-
}
104-
10596
// TODO: remove after FromFullName has been revisited
10697
if host, err := cfg.DefaultHost(); err == nil {
10798
ghrepo.SetDefaultHost(host)
@@ -181,15 +172,7 @@ func mainRun() exitCode {
181172
// enable `--repo` override
182173
if cmd.Flags().Lookup("repo") != nil {
183174
repoOverride, _ := cmd.Flags().GetString("repo")
184-
if repoFromEnv := os.Getenv("GH_REPO"); repoOverride == "" && repoFromEnv != "" {
185-
repoOverride = repoFromEnv
186-
}
187-
if repoOverride != "" {
188-
// FIXME: reimplement the repo override to avoid having to mutate the factory
189-
cmdFactory.BaseRepo = func() (ghrepo.Interface, error) {
190-
return ghrepo.FromFullName(repoOverride)
191-
}
192-
}
175+
cmdFactory.BaseRepo = cmdutil.OverrideBaseRepoFunc(cmdFactory, repoOverride)
193176
}
194177

195178
return nil

pkg/cmd/factory/default.go

Lines changed: 114 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"net/http"
77
"os"
88

9+
"github.com/cli/cli/api"
10+
"github.com/cli/cli/context"
911
"github.com/cli/cli/git"
1012
"github.com/cli/cli/internal/config"
1113
"github.com/cli/cli/internal/ghrepo"
@@ -14,11 +16,93 @@ import (
1416
)
1517

1618
func New(appVersion string) *cmdutil.Factory {
17-
io := iostreams.System()
19+
f := &cmdutil.Factory{
20+
Config: configFunc(), // No factory dependencies
21+
Branch: branchFunc(), // No factory dependencies
22+
Executable: executable(), // No factory dependencies
23+
}
24+
25+
f.IOStreams = ioStreams(f) // Depends on Config
26+
f.HttpClient = httpClientFunc(f, appVersion) // Depends on Config, IOStreams, and appVersion
27+
f.Remotes = remotesFunc(f) // Depends on Config
28+
f.BaseRepo = BaseRepoFunc(f) // Depends on Remotes
29+
f.Browser = browser(f) // Depends on IOStreams
30+
31+
return f
32+
}
33+
34+
func BaseRepoFunc(f *cmdutil.Factory) func() (ghrepo.Interface, error) {
35+
return func() (ghrepo.Interface, error) {
36+
remotes, err := f.Remotes()
37+
if err != nil {
38+
return nil, err
39+
}
40+
return remotes[0], nil
41+
}
42+
}
43+
44+
func SmartBaseRepoFunc(f *cmdutil.Factory) func() (ghrepo.Interface, error) {
45+
return func() (ghrepo.Interface, error) {
46+
httpClient, err := f.HttpClient()
47+
if err != nil {
48+
return nil, err
49+
}
50+
51+
apiClient := api.NewClientFromHTTP(httpClient)
52+
53+
remotes, err := f.Remotes()
54+
if err != nil {
55+
return nil, err
56+
}
57+
repoContext, err := context.ResolveRemotesToRepos(remotes, apiClient, "")
58+
if err != nil {
59+
return nil, err
60+
}
61+
baseRepo, err := repoContext.BaseRepo(f.IOStreams)
62+
if err != nil {
63+
return nil, err
64+
}
65+
66+
return baseRepo, nil
67+
}
68+
}
69+
70+
func remotesFunc(f *cmdutil.Factory) func() (context.Remotes, error) {
71+
rr := &remoteResolver{
72+
readRemotes: git.Remotes,
73+
getConfig: f.Config,
74+
}
75+
return rr.Resolver()
76+
}
77+
78+
func httpClientFunc(f *cmdutil.Factory, appVersion string) func() (*http.Client, error) {
79+
return func() (*http.Client, error) {
80+
io := f.IOStreams
81+
cfg, err := f.Config()
82+
if err != nil {
83+
return nil, err
84+
}
85+
return NewHTTPClient(io, cfg, appVersion, true), nil
86+
}
87+
}
88+
89+
func browser(f *cmdutil.Factory) cmdutil.Browser {
90+
io := f.IOStreams
91+
return cmdutil.NewBrowser(os.Getenv("BROWSER"), io.Out, io.ErrOut)
92+
}
93+
94+
func executable() string {
95+
gh := "gh"
96+
if exe, err := os.Executable(); err == nil {
97+
gh = exe
98+
}
99+
return gh
100+
}
18101

102+
func configFunc() func() (config.Config, error) {
19103
var cachedConfig config.Config
20104
var configError error
21-
configFunc := func() (config.Config, error) {
105+
return func() (config.Config, error) {
22106
if cachedConfig != nil || configError != nil {
23107
return cachedConfig, configError
24108
}
@@ -30,45 +114,38 @@ func New(appVersion string) *cmdutil.Factory {
30114
cachedConfig = config.InheritEnv(cachedConfig)
31115
return cachedConfig, configError
32116
}
117+
}
33118

34-
rr := &remoteResolver{
35-
readRemotes: git.Remotes,
36-
getConfig: configFunc,
119+
func branchFunc() func() (string, error) {
120+
return func() (string, error) {
121+
currentBranch, err := git.CurrentBranch()
122+
if err != nil {
123+
return "", fmt.Errorf("could not determine current branch: %w", err)
124+
}
125+
return currentBranch, nil
37126
}
38-
remotesFunc := rr.Resolver()
127+
}
39128

40-
ghExecutable := "gh"
41-
if exe, err := os.Executable(); err == nil {
42-
ghExecutable = exe
129+
func ioStreams(f *cmdutil.Factory) *iostreams.IOStreams {
130+
io := iostreams.System()
131+
cfg, err := f.Config()
132+
if err != nil {
133+
return io
43134
}
44135

45-
return &cmdutil.Factory{
46-
IOStreams: io,
47-
Config: configFunc,
48-
Remotes: remotesFunc,
49-
HttpClient: func() (*http.Client, error) {
50-
cfg, err := configFunc()
51-
if err != nil {
52-
return nil, err
53-
}
54-
55-
return NewHTTPClient(io, cfg, appVersion, true), nil
56-
},
57-
BaseRepo: func() (ghrepo.Interface, error) {
58-
remotes, err := remotesFunc()
59-
if err != nil {
60-
return nil, err
61-
}
62-
return remotes[0], nil
63-
},
64-
Branch: func() (string, error) {
65-
currentBranch, err := git.CurrentBranch()
66-
if err != nil {
67-
return "", fmt.Errorf("could not determine current branch: %w", err)
68-
}
69-
return currentBranch, nil
70-
},
71-
Executable: ghExecutable,
72-
Browser: cmdutil.NewBrowser(os.Getenv("BROWSER"), io.Out, io.ErrOut),
136+
if prompt, _ := cfg.Get("", "prompt"); prompt == "disabled" {
137+
io.SetNeverPrompt(true)
73138
}
139+
140+
// Pager precedence
141+
// 1. GH_PAGER
142+
// 2. pager from config
143+
// 3. PAGER
144+
if ghPager, ghPagerExists := os.LookupEnv("GH_PAGER"); ghPagerExists {
145+
io.SetPager(ghPager)
146+
} else if pager, _ := cfg.Get("", "pager"); pager != "" {
147+
io.SetPager(pager)
148+
}
149+
150+
return io
74151
}

0 commit comments

Comments
 (0)
X Tutup