-
My goal would be to clone a private GitHub repository by running my own credential management system that's never stored externally. After much tinkering, I've found the following way to make this possible: use gix::{
credentials::{helper::NextAction, protocol::Outcome},
remote::{Connection, Direction},
sec::identity::Account,
};
#[tokio::main]
async fn main() {
let token = "github_personal_token";
let clone = gix::prepare_clone_bare("https://github.com/user/private_repository", "/path/to/clone").unwrap();
_ = clone
.configure_remote(|remote| {
let connect = remote
.connect(Direction::Fetch, gix::progress::Discard)?
.with_credentials(|action| match action {
gix::credentials::helper::Action::Get(ctx) => Ok(Some(Outcome {
identity: Account {
username: ctx.username.clone().unwrap_or("x-access-token".into()).clone(),
password: token.into(),
},
next: NextAction::from(ctx),
})),
gix::credentials::helper::Action::Store(_) => Ok(None),
gix::credentials::helper::Action::Erase(_) => Ok(None),
});
let out = connect.remote().clone();
_ = connect.prepare_fetch(Default::default())?.receive(&false.into())?;
Ok(out)
}).persist();
} This construct is not very optimal. First, I have little way to influence error handling. After trying to find a better way, however, I've yet to find a good way to achieve what I want. For comparison, the let url = url.to_owned();
let target = target.to_owned();
tokio::task::spawn_blocking(move || {
let options = {
let mut callbacks = RemoteCallbacks::new();
callbacks.credentials(auth);
let mut fo = git2::FetchOptions::new();
fo.remote_callbacks(callbacks);
fo
};
let mut builder = git2::build::RepoBuilder::new();
builder.fetch_options(options);
builder.clone(&url, &target)
})
.await
.expect("git failed")?;
Ok(()) I would appreciate any advice on improving this code. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 7 replies
-
I recommend taking a look at the tests or at the implementation of As for how the above can be improved, I recommend using The configuration of credentials is a bit cumbersome right now as there is no adapter to abstract the interface - right now it's built for credential helper integration. Error handling is possible even though custom errors are harder to deal with - it should be possible to improve that by working on the 'completely customized' authentication use-case. Async is implemented in a way to 'make it work', but inherently most of what's happening in the client is blocking. Async is clearly a second class citizen and goes only as far as there is demand for it. The implementation thus far was completely sponsored for instance and based on the needs of funded applications. I am open to seeing async support improved, but would love to see such improvements around becoming runtime agnostic instead of adding more. Maybe it won't take much to support In the meantime, I recommend integrating I hope that helps. |
Beta Was this translation helpful? Give feedback.
-
One issue that I found trying to call |
Beta Was this translation helpful? Give feedback.
Alright, if you look at the latest
main
you will find some (breaking) changes to support controlling the authentication when cloning.It works like this (even though I didn't try to compile this code):