Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 31a5fe1

Browse files
committedNov 9, 2016
Retry merging changes
1 parent 22ffa9f commit 31a5fe1

File tree

1 file changed

+105
-42
lines changed

1 file changed

+105
-42
lines changed
 

‎src/main.rs

Lines changed: 105 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
88

9-
// #![deny(warnings)]
9+
#![deny(warnings)]
1010
extern crate rustc_serialize;
1111
extern crate router;
1212
extern crate iron;
@@ -391,57 +391,120 @@ fn main() {
391391
}
392392

393393

394-
pub fn credentials(_url: &str,
395-
user_from_url: Option<&str>,
396-
_cred: git2::CredentialType)
397-
-> Result<git2::Cred, git2::Error> {
398-
// TODO: allow more options
399-
if let Some(user) = user_from_url {
400-
let r = Cred::ssh_key_from_agent(user);
401-
return r;
394+
fn credentials(url: &str,
395+
user_from_url: Option<&str>,
396+
cred: git2::CredentialType,
397+
origin_config: &OriginConfig)
398+
-> Result<git2::Cred, git2::Error> {
399+
let mut error = git2::Error::from_str(&format!("Failed to find credentials for {}", url));
400+
debug!("credentials");
401+
if cred.contains(CredentialType::from(git2::USER_PASS_PLAINTEXT)) {
402+
match (&origin_config.username, &origin_config.password) {
403+
(&Some(ref u), &Some(ref p)) => {
404+
debug!("from username/password");
405+
match Cred::userpass_plaintext(&u, &p) {
406+
Err(e) => {
407+
debug!("Error: {:?}", e);
408+
error = e;
409+
}
410+
Ok(c) => {
411+
debug!("Ok!");
412+
return Ok(c);
413+
}
414+
}
415+
}
416+
_ => {}
417+
}
418+
}
419+
if cred.contains(CredentialType::from(git2::DEFAULT)) {
420+
let config = try!(git2::Config::open_default());
421+
match Cred::credential_helper(&config, url, user_from_url) {
422+
Err(e) => {
423+
debug!("Error: {:?}", e);
424+
error = e;
425+
}
426+
Ok(c) => {
427+
debug!("Ok!");
428+
return Ok(c);
429+
}
430+
}
402431
}
403-
Err(git2::Error::from_str("no authentication set"))
432+
if cred.contains(CredentialType::from(git2::SSH_KEY)) {
433+
if let Some(user) = user_from_url {
434+
debug!("from ssh agent");
435+
match Cred::ssh_key_from_agent(user) {
436+
Err(e) => {
437+
debug!("Error: {:?}", e);
438+
error = e;
439+
}
440+
Ok(c) => {
441+
debug!("Ok");
442+
return Ok(c);
443+
}
444+
}
445+
}
446+
}
447+
return Err(error);
404448
}
405449

406450
fn poll_index(repo: Repository, config: Config) {
407451

408452
let mut origin = repo.find_remote("origin").unwrap();
409453
loop {
410454
::std::thread::sleep(Duration::from_secs(config.poll_intervall.unwrap_or(60) as u64));
411-
origin.fetch(&["master"], None, None).unwrap();
412-
let head = repo.head().unwrap();
413-
414-
let parent = repo.find_commit(head.target().unwrap()).unwrap();
415-
let remote = repo.find_reference("refs/remotes/origin/master").unwrap();
416-
let c = repo.reference_to_annotated_commit(&remote).unwrap();
417-
let mut checkout = ::git2::build::CheckoutBuilder::new();
418-
let mut merge_option = ::git2::MergeOptions::new();
419-
let mut index = repo.index().unwrap();
420-
let old_tree = repo.find_tree(index.write_tree().unwrap()).unwrap();
421-
repo.merge(&[&c],
422-
Some(merge_option.file_favor(::git2::FileFavor::Theirs)),
423-
Some(checkout.force()))
424-
.unwrap();
425-
index.write().unwrap();
426-
let tree_id = index.write_tree().unwrap();
427-
let tree = repo.find_tree(tree_id).unwrap();
428-
let diff = repo.diff_tree_to_tree(Some(&old_tree), Some(&tree), None).unwrap();
429-
if diff.stats().unwrap().files_changed() > 0 {
430-
431-
let sig = repo.signature().unwrap();
432-
repo.commit(Some("HEAD"), &sig, &sig, "Merge", &tree, &[&parent])
433-
.unwrap();
434-
435-
if let Some(_) = config.registry_config.origin_url.clone() {
436-
let mut callbacks = git2::RemoteCallbacks::new();
437-
callbacks.credentials(credentials);
438-
let mut remote = repo.find_remote("local").unwrap();
439-
let mut opts = git2::PushOptions::new();
440-
opts.remote_callbacks(callbacks);
441-
remote.push(&["refs/heads/master"], Some(&mut opts)).unwrap();
455+
'retry: for i in 0..20 {
456+
match try_merge(&repo, &config, &mut origin) {
457+
Ok(()) => break 'retry,
458+
Err(ref e) if i == 19 => {
459+
panic!("{:?}", e);
460+
}
461+
_ => {
462+
debug!("Retry {}", i);
463+
}
442464
}
443-
info!("updated index");
444465
}
445466
}
446467

447468
}
469+
470+
fn try_merge(repo: &Repository,
471+
config: &Config,
472+
origin: &mut git2::Remote)
473+
-> Result<(), git2::Error> {
474+
try!(origin.fetch(&["master"], None, None));
475+
let head = try!(repo.head());
476+
477+
let parent = try!(repo.find_commit(head.target().unwrap()));
478+
let remote = try!(repo.find_reference("refs/remotes/origin/master"));
479+
let c = try!(repo.reference_to_annotated_commit(&remote));
480+
let mut checkout = ::git2::build::CheckoutBuilder::new();
481+
let mut merge_option = ::git2::MergeOptions::new();
482+
let mut index = try!(repo.index());
483+
let old_tree = try!(repo.find_tree(try!(index.write_tree())));
484+
try!(repo.merge(&[&c],
485+
Some(merge_option.file_favor(::git2::FileFavor::Theirs)),
486+
Some(checkout.force())));
487+
try!(index.write());
488+
let tree_id = try!(index.write_tree());
489+
let tree = try!(repo.find_tree(tree_id));
490+
let diff = try!(repo.diff_tree_to_tree(Some(&old_tree), Some(&tree), None));
491+
if try!(diff.stats()).files_changed() > 0 {
492+
493+
let sig = try!(repo.signature());
494+
try!(repo.commit(Some("HEAD"), &sig, &sig, "Merge", &tree, &[&parent]));
495+
496+
if let Some(_) = config.registry_config.origin_url {
497+
let mut callbacks = git2::RemoteCallbacks::new();
498+
callbacks.credentials(credentials);
499+
let mut remote = try!(repo.find_remote("local"));
500+
let mut opts = git2::PushOptions::new();
501+
opts.remote_callbacks(callbacks);
502+
try!(remote.push(&["refs/heads/master"], Some(&mut opts)));
503+
}
504+
debug!("updated index");
505+
} else {
506+
debug!("Nothing to update");
507+
try!(repo.cleanup_state());
508+
}
509+
Ok(())
510+
}

0 commit comments

Comments
 (0)
Please sign in to comment.