尝试使用git2-rs / libgit2推送到远程时出现“请求失败,状态码:401”错误

时间:2019-10-02 12:49:02

标签: git authentication rust push libgit2

我有一个本地git仓库,该仓库通过git2-rs进行维护,这是C库libgit2周围几乎一对一的Rust包装器。我已经设法使用该库暂存并提交更改。但是,我无法将更改推送到远程存储库。当我尝试连接到遥控器时,出现以下错误:

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();

我想念什么?

1 个答案:

答案 0 :(得分:1)

好,我解决了这个问题。要使其正常工作,需要完成三件事:

  • connect_authcredentials一起使用是正确的。

  • 还需要使用remote.push指定相同的凭据。

  • 您必须指定与remote_add_push中的remote.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();