step fifty nine: download missing objects pointed by remote refs
This commit is contained in:
parent
70a660e2f5
commit
416061a632
49
src/base.rs
49
src/base.rs
|
@ -159,6 +159,53 @@ pub fn iter_commits_and_parents(mut oids: VecDeque<String>) -> Vec<String> {
|
||||||
return oid_sequence;
|
return oid_sequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn copy_objects_in_commits_and_parents(mut oids: Vec<&String>, remote_path: String) {
|
||||||
|
// This one is a little be different than the functions in the tutorial
|
||||||
|
// But the end result is the same, copy all missing objects from the remote
|
||||||
|
// repository
|
||||||
|
let mut visited: HashSet<String> = HashSet::new();
|
||||||
|
let mut commits = oids
|
||||||
|
.into_iter()
|
||||||
|
.map(|oid| oid.clone())
|
||||||
|
.rev()
|
||||||
|
.collect::<VecDeque<String>>();
|
||||||
|
|
||||||
|
while !commits.is_empty() {
|
||||||
|
let oid = commits.pop_front().unwrap();
|
||||||
|
if oid == "" || visited.contains(&oid) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
data::fetch_object_if_missing(oid.clone(), remote_path.clone());
|
||||||
|
visited.insert(oid.clone());
|
||||||
|
|
||||||
|
let commit = get_commit(oid.clone());
|
||||||
|
copy_tree_objects(commit.tree, &mut visited, remote_path.clone());
|
||||||
|
|
||||||
|
let parent1 = commit.parents[0].clone();
|
||||||
|
// Deal with parent next
|
||||||
|
commits.push_front(parent1);
|
||||||
|
// Deal with other parents later
|
||||||
|
if commit.parents.len() > 1 {
|
||||||
|
let parent2 = commit.parents[1].clone();
|
||||||
|
commits.push_back(parent2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn copy_tree_objects(oid: String, visited: &mut HashSet<String>, remote_path: String) {
|
||||||
|
// get_tree already walks recursively the provided tree. Lets use that instead.
|
||||||
|
visited.insert(oid.clone());
|
||||||
|
data::fetch_object_if_missing(oid.clone(), remote_path.clone());
|
||||||
|
|
||||||
|
for (path, object_id) in get_tree(oid, "./".to_owned()).iter() {
|
||||||
|
if visited.contains(object_id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
data::fetch_object_if_missing(object_id.clone(), remote_path.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn checkout(name: String) {
|
pub fn checkout(name: String) {
|
||||||
let oid = get_oid(name.clone());
|
let oid = get_oid(name.clone());
|
||||||
let commit = get_commit(oid.clone());
|
let commit = get_commit(oid.clone());
|
||||||
|
@ -206,7 +253,7 @@ pub fn get_oid(mut name: String) -> String {
|
||||||
for reference in refs_to_try.iter() {
|
for reference in refs_to_try.iter() {
|
||||||
let found = data::get_ref(reference.clone(), false);
|
let found = data::get_ref(reference.clone(), false);
|
||||||
if found.value != "" {
|
if found.value != "" {
|
||||||
return found.value;
|
return data::get_ref(reference.clone(), true).value;
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
20
src/data.rs
20
src/data.rs
|
@ -159,3 +159,23 @@ pub fn get_ref_internal(reference: String, deref: bool) -> (String, RefValue) {
|
||||||
|
|
||||||
return (reference, RefValue { value, symbolic });
|
return (reference, RefValue { value, symbolic });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn fetch_object_if_missing(oid: String, remote_git_dir: String) {
|
||||||
|
if object_exists(oid.clone()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let dir = RGIT_DIR.lock().unwrap().to_owned();
|
||||||
|
let rgit_remote = remote_git_dir + "/.rgit";
|
||||||
|
fs::copy(
|
||||||
|
format!("{}/objects/{}", rgit_remote, oid.clone()),
|
||||||
|
format!("{}/objects/{}", dir, oid),
|
||||||
|
)
|
||||||
|
.expect(format!("Failed to fetch {}", oid).as_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn object_exists(oid: String) -> bool {
|
||||||
|
let dir = RGIT_DIR.lock().unwrap().to_owned();
|
||||||
|
let path = format!("{}/objects/{}", dir.clone(), oid.clone());
|
||||||
|
return Path::new(path.as_str()).exists();
|
||||||
|
}
|
||||||
|
|
|
@ -3,12 +3,18 @@ use std::collections::HashMap;
|
||||||
#[path = "data.rs"]
|
#[path = "data.rs"]
|
||||||
mod data;
|
mod data;
|
||||||
|
|
||||||
|
#[path = "base.rs"]
|
||||||
|
mod base;
|
||||||
|
|
||||||
static REMOTE_REFS_BASE: &'static str = "refs/heads/";
|
static REMOTE_REFS_BASE: &'static str = "refs/heads/";
|
||||||
static LOCAL_REFS_BASE: &'static str = "refs/remote/";
|
static LOCAL_REFS_BASE: &'static str = "refs/remote/";
|
||||||
|
|
||||||
pub fn fetch(path: String) {
|
pub fn fetch(path: String) {
|
||||||
// Get refs from server
|
// Get refs from server
|
||||||
let refs = get_remote_refs(path, REMOTE_REFS_BASE);
|
let refs = get_remote_refs(path.clone(), REMOTE_REFS_BASE);
|
||||||
|
|
||||||
|
let commit_oids: Vec<&String> = refs.values().collect();
|
||||||
|
base::copy_objects_in_commits_and_parents(commit_oids, path.clone());
|
||||||
|
|
||||||
// Update local refs to match server
|
// Update local refs to match server
|
||||||
for (remote_name, value) in refs.iter() {
|
for (remote_name, value) in refs.iter() {
|
||||||
|
|
Loading…
Reference in New Issue