git2机箱没有执行“git pull”操作的直接方法。
我看到过this question并试着用同样的方法(playground):
use std::fs;
use std::fs::File;
use std::io::{stderr, stdout, Write};
use std::path::Path;
use git2::{Commit, Error, Index, MergeOptions, ObjectType, Repository, ResetType};
struct Repo {
url: &'static str,
path: &'static str,
branch: &'static str,
}
impl Repo {
fn reset(&self, path: &Path) {
let repo = match Repository::open(path) {
Ok(repo) => repo,
Err(e) => panic!("Failed to open: {}", e),
};
repo.reset(
&repo.revparse_single("HEAD").unwrap(),
ResetType::Hard,
None,
)
.unwrap();
}
fn clone(&self) {
let repo = match Repository::clone(self.url, self.path) {
Ok(repo) => repo,
Err(e) => panic!("failed to init: {}", e),
};
}
fn find_last_commit<'repo>(&self, repo: &'repo Repository) -> Result<Commit<'repo>, Error> {
let obj = repo.head()?.resolve()?.peel(ObjectType::Commit)?;
match obj.into_commit() {
Ok(c) => Ok(c),
_ => Err(Error::from_str("commit error")),
}
}
fn pull(&self, path: &Path) -> Result<Index, Error> {
let repo = Repository::open(path)?;
repo.find_remote("origin")?
.fetch(&[self.branch], None, None)?;
let last_commit = self.find_last_commit(&repo)?;
let reference = repo.find_reference("FETCH_HEAD")?;
let fetched_commit = reference.peel_to_commit()?;
let index =
repo.merge_commits(&last_commit, &fetched_commit, Some(&MergeOptions::new()))?;
return Ok(index);
}
pub fn check(&self) {
let repo_path = Path::new(self.path);
if !repo_path.exists() {
self.clone();
return;
}
if repo_path.exists() && repo_path.is_dir() {
self.reset(repo_path);
let idx = match self.pull(repo_path) {
Ok(idx) => idx,
Err(e) => panic!("Failed to pull: {}", e),
};
}
}
}
fn main() {
let currencies = Repo {
url: "https://github.com/datasets/currency-codes",
path: "./resources/currency-codes",
branch: "master",
};
currencies.check();
}
但是当克隆和重置工作时,pull看起来没有。
我做错什么了?
最佳答案
git2-rs
回购协议确实有a pending PR这就添加了一个拉动示例。我在这里稍微修改了一下,以展示如何快速前进,因为这正是您所需要的:
fn fast_forward(&self, path: &Path) -> Result<(), Error> {
let repo = Repository::open(path)?;
repo.find_remote("origin")?
.fetch(&[self.branch], None, None)?;
let fetch_head = repo.find_reference("FETCH_HEAD")?;
let fetch_commit = repo.reference_to_annotated_commit(&fetch_head)?;
let analysis = repo.merge_analysis(&[&fetch_commit])?;
if analysis.0.is_up_to_date() {
Ok(())
} else if analysis.0.is_fast_forward() {
let refname = format!("refs/heads/{}", self.branch);
let mut reference = repo.find_reference(&refname)?;
reference.set_target(fetch_commit.id(), "Fast-Forward")?;
repo.set_head(&refname)?;
repo.checkout_head(Some(git2::build::CheckoutBuilder::default().force()))
} else {
Err(Error::from_str("Fast-forward only!"))
}
}
pub fn check(&self) {
...
if repo_path.exists() && repo_path.is_dir() {
self.reset(repo_path);
if let Err(e) = self.fast_forward(repo_path) {
panic!("Failed to pull: {}", e)
}
}
}
当然是原创作者的功劳。您还可以检查它是否存在非平凡的合并情况,即当本地树变脏时。