"request failed with status code: 401" 尝试使用 git2-rs / libgit2 推送到远程时出错

"request failed with status code: 401" error when trying to push to remote using git2-rs / libgit2

我有一个本地 git 存储库,正在通过 git2-rs, a pretty much one-to-one Rust wrapper around the C library libgit2 进行维护。我已经设法使用该库进行并提交更改。但是,我无法设法将更改推送到远程存储库。当我尝试连接到遥控器时,出现以下消息的错误:

request failed with status code: 401

这是我的代码:

let repo: Repository = /* get repository */;
let mut remote = repo.find_remote("origin").unwrap();
// connect returns Err, and so this panics.
remote.connect(Direction::Push).unwrap();

我也试过通过各种凭据,但出现同样的错误:

let mut callbacks = RemoteCallbacks::new();
callbacks.credentials(|str, str_opt, cred_type| {
    Ok(Cred::userpass_plaintext("natanfudge", env!("GITHUB_PASSWORD")).unwrap())
});
remote
    .connect_auth(Direction::Push, Some(callbacks), None)
    .unwrap();
let mut callbacks = RemoteCallbacks::new();
callbacks.credentials(|str, str_opt, cred_type| {
    // This line does not panic, only the connect_auth!
    Ok(Cred::ssh_key_from_agent("natanfudge").expect("Could not get ssh key from ssh agent"))
});
remote
    .connect_auth(Direction::Push, Some(callbacks), None)
    .unwrap();

我错过了什么?

好的,我解决了问题。需要完成 3 件事情才能使其正常工作:

  • 使用 connect_authcredentials 是正确的。

  • 需要指定与remote.push相同的凭据。

  • 您必须在 remote.push 中指定与 remote_add_push 中相同的 refspec 字符串。

所以这段代码有效:

fn create_callbacks<'a>() -> RemoteCallbacks<'a>{
    let mut callbacks = RemoteCallbacks::new();
    &callbacks.credentials(|str, str_opt, cred_type| {
        Cred::userpass_plaintext("your-username",env!("GITHUB_PASSWORD"))
    });
    callbacks
}

fn main() {
    let repo = /* get repository */

    let mut remote = repo.find_remote("origin").unwrap();

    remote.connect_auth(Direction::Push, Some(create_callbacks()), None).unwrap();
    repo.remote_add_push("origin", "refs/heads/<branch-name>:refs/heads/<branch-name>").unwrap();
    let mut push_options = PushOptions::default();
    let mut callbacks = create_callbacks();
    push_options.remote_callbacks(callbacks);

    remote.push(&["refs/heads/<branch-name>:refs/heads/<branch-name>"], Some(&mut push_options)).unwrap();

    std::mem::drop(remote);

    Ok(())
}

对于调试,使用 push_update_reference 回调很有用。如果推送有问题,它会说。

    let mut push_options = PushOptions::default();
    let mut callbacks = create_callbacks();
    callbacks.push_update_reference(|ref,error|{
       println!("ref = {}, error = {:?}", ref, error);
       Ok(())
    });

    remote.push(&["refs/heads/<branch-name>:refs/heads/<branch-name>"], Some(&mut 
    push_options)).unwrap();