| 126 | } |
| 127 | |
| 128 | func refreshRun(opts *RefreshOptions) error { |
| 129 | plainHTTPClient, err := opts.PlainHttpClient() |
| 130 | if err != nil { |
| 131 | return err |
| 132 | } |
| 133 | |
| 134 | cfg, err := opts.Config() |
| 135 | if err != nil { |
| 136 | return err |
| 137 | } |
| 138 | authCfg := cfg.Authentication() |
| 139 | |
| 140 | candidates := authCfg.Hosts() |
| 141 | if len(candidates) == 0 { |
| 142 | return fmt.Errorf("not logged in to any hosts. Use 'gh auth login' to authenticate with a host") |
| 143 | } |
| 144 | |
| 145 | hostname := opts.Hostname |
| 146 | if hostname == "" { |
| 147 | if len(candidates) == 1 { |
| 148 | hostname = candidates[0] |
| 149 | } else { |
| 150 | selected, err := opts.Prompter.Select("What account do you want to refresh auth for?", "", candidates) |
| 151 | if err != nil { |
| 152 | return fmt.Errorf("could not prompt: %w", err) |
| 153 | } |
| 154 | hostname = candidates[selected] |
| 155 | } |
| 156 | } else if !slices.Contains(candidates, hostname) { |
| 157 | return fmt.Errorf("not logged in to %s. use 'gh auth login' to authenticate with this host", hostname) |
| 158 | } |
| 159 | |
| 160 | if src, writeable := shared.AuthTokenWriteable(authCfg, hostname); !writeable { |
| 161 | fmt.Fprintf(opts.IO.ErrOut, "The value of the %s environment variable is being used for authentication.\n", src) |
| 162 | fmt.Fprint(opts.IO.ErrOut, "To refresh credentials stored in GitHub CLI, first clear the value from the environment.\n") |
| 163 | return cmdutil.SilentError |
| 164 | } |
| 165 | |
| 166 | additionalScopes := set.NewStringSet() |
| 167 | |
| 168 | if !opts.ResetScopes { |
| 169 | if oldToken, _ := authCfg.ActiveToken(hostname); oldToken != "" { |
| 170 | if oldScopes, err := shared.GetScopes(plainHTTPClient, hostname, oldToken); err == nil { |
| 171 | for s := range strings.SplitSeq(oldScopes, ",") { |
| 172 | s = strings.TrimSpace(s) |
| 173 | if s != "" { |
| 174 | additionalScopes.Add(s) |
| 175 | } |
| 176 | } |
| 177 | } |
| 178 | } |
| 179 | } |
| 180 | |
| 181 | credentialFlow := &shared.GitCredentialFlow{ |
| 182 | Prompter: opts.Prompter, |
| 183 | HelperConfig: &gitcredentials.HelperConfig{ |
| 184 | SelfExecutablePath: opts.MainExecutable, |
| 185 | GitClient: opts.GitClient, |