| 347 | } |
| 348 | |
| 349 | func (h *commandCredentialHelper) exec(subcommand string, input Creds) (Creds, error) { |
| 350 | output := new(bytes.Buffer) |
| 351 | cmd, err := subprocess.ExecCommand("git", "credential", subcommand) |
| 352 | if err != nil { |
| 353 | return nil, errors.New(tr.Tr.Get("failed to find `git credential %s`: %v", subcommand, err)) |
| 354 | } |
| 355 | cmd.Stdin, err = input.buffer(h.protectProtocol) |
| 356 | if err != nil { |
| 357 | return nil, errors.New(tr.Tr.Get("invalid input to `git credential %s`: %v", subcommand, err)) |
| 358 | } |
| 359 | cmd.Stdout = output |
| 360 | /* |
| 361 | There is a reason we don't read from stderr here: |
| 362 | Git's credential cache daemon helper does not close its stderr, so if this |
| 363 | process is the process that fires up the daemon, it will wait forever |
| 364 | (until the daemon exits, really) trying to read from stderr. |
| 365 | |
| 366 | Instead, we simply pass it through to our stderr. |
| 367 | |
| 368 | See https://github.com/git-lfs/git-lfs/issues/117 for more details. |
| 369 | */ |
| 370 | cmd.Stderr = os.Stderr |
| 371 | |
| 372 | err = cmd.Start() |
| 373 | if err == nil { |
| 374 | err = cmd.Wait() |
| 375 | } |
| 376 | |
| 377 | if _, ok := err.(*exec.ExitError); ok { |
| 378 | if h.SkipPrompt { |
| 379 | return nil, errors.New(tr.Tr.Get("change the GIT_TERMINAL_PROMPT env var to be prompted to enter your credentials for %s://%s", |
| 380 | FirstEntryForKey(input, "protocol"), FirstEntryForKey(input, "host"))) |
| 381 | } |
| 382 | |
| 383 | // 'git credential' exits with 128 if the helper doesn't fill the username |
| 384 | // and password values. |
| 385 | if subcommand == "fill" && err.Error() == "exit status 128" { |
| 386 | return nil, nil |
| 387 | } |
| 388 | } |
| 389 | |
| 390 | if err != nil { |
| 391 | return nil, errors.New(tr.Tr.Get("`git credential %s` error: %s", subcommand, err.Error())) |
| 392 | } |
| 393 | |
| 394 | creds := make(Creds) |
| 395 | for _, line := range strings.Split(output.String(), "\n") { |
| 396 | pieces := strings.SplitN(line, "=", 2) |
| 397 | if len(pieces) < 2 || len(pieces[1]) < 1 { |
| 398 | continue |
| 399 | } |
| 400 | if _, ok := creds[pieces[0]]; ok { |
| 401 | creds[pieces[0]] = append(creds[pieces[0]], pieces[1]) |
| 402 | } else { |
| 403 | creds[pieces[0]] = []string{pieces[1]} |
| 404 | } |
| 405 | } |
| 406 | |