step sixty: push, naive implementation

This commit is contained in:
Gonçalo Valério 2020-12-06 18:25:41 +00:00
parent 416061a632
commit 8144a96321
4 changed files with 64 additions and 9 deletions

View File

@ -159,10 +159,14 @@ pub fn iter_commits_and_parents(mut oids: VecDeque<String>) -> Vec<String> {
return oid_sequence;
}
pub fn copy_objects_in_commits_and_parents(mut oids: Vec<&String>, remote_path: String) {
pub fn copy_objects_in_commits_and_parents(
mut oids: Vec<&String>,
remote_path: String,
push: bool,
) {
// 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
// But the end result is the same, copy all missing objects from one repo
// to another
let mut visited: HashSet<String> = HashSet::new();
let mut commits = oids
.into_iter()
@ -175,12 +179,15 @@ pub fn copy_objects_in_commits_and_parents(mut oids: Vec<&String>, remote_path:
if oid == "" || visited.contains(&oid) {
continue;
}
data::fetch_object_if_missing(oid.clone(), remote_path.clone());
if push {
data::push_object(oid.clone(), remote_path.clone());
} else {
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());
copy_tree_objects(commit.tree, &mut visited, remote_path.clone(), push);
let parent1 = commit.parents[0].clone();
// Deal with parent next
@ -193,7 +200,7 @@ pub fn copy_objects_in_commits_and_parents(mut oids: Vec<&String>, remote_path:
}
}
fn copy_tree_objects(oid: String, visited: &mut HashSet<String>, remote_path: String) {
fn copy_tree_objects(oid: String, visited: &mut HashSet<String>, remote_path: String, push: bool) {
// 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());
@ -202,7 +209,11 @@ fn copy_tree_objects(oid: String, visited: &mut HashSet<String>, remote_path: St
if visited.contains(object_id) {
continue;
}
data::fetch_object_if_missing(object_id.clone(), remote_path.clone());
if push {
data::push_object(object_id.clone(), remote_path.clone());
} else {
data::fetch_object_if_missing(object_id.clone(), remote_path.clone());
}
}
}

View File

@ -174,6 +174,16 @@ pub fn fetch_object_if_missing(oid: String, remote_git_dir: String) {
.expect(format!("Failed to fetch {}", oid).as_str());
}
pub fn push_object(oid: String, remote_git_dir: String) {
let rgit_remote = remote_git_dir + "/.rgit";
let dir = RGIT_DIR.lock().unwrap().to_owned();
fs::copy(
format!("{}/objects/{}", dir, oid),
format!("{}/objects/{}", rgit_remote, oid.clone()),
)
.expect(format!("Failed to push {}", 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());

View File

@ -98,6 +98,12 @@ fn main() {
.about("Fetch refs and objects from another repository")
.arg(Arg::with_name("remote").index(1).required(true)),
)
.subcommand(
SubCommand::with_name("push")
.about("Push refs and objects to another repository")
.arg(Arg::with_name("remote").index(1).required(true))
.arg(Arg::with_name("branch").index(2).required(true)),
)
.get_matches();
data::set_rgit_dir(".");
@ -120,6 +126,7 @@ fn main() {
Some("merge") => merge(matches),
Some("merge-base") => merge_base(matches),
Some("fetch") => fetch(matches),
Some("push") => push(matches),
_ => println!("unknown sub command"),
}
data::reset_rgit_dir();
@ -357,6 +364,14 @@ fn fetch(matches: ArgMatches) {
}
}
fn push(matches: ArgMatches) {
if let Some(cmd_matches) = matches.subcommand_matches("push") {
let remote_path = cmd_matches.value_of("remote").unwrap().to_owned();
let branch_name = cmd_matches.value_of("branch").unwrap().to_owned();
remote::push(remote_path, format!("refs/heads/{}", branch_name));
}
}
fn print_commit(oid: String, commit: &base::Commit, mut refs: HashMap<String, Vec<String>>) {
let ref_str = if refs.contains_key(&oid) {
refs.get_mut(&oid).unwrap().join(", ")

View File

@ -14,7 +14,7 @@ pub fn fetch(path: String) {
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());
base::copy_objects_in_commits_and_parents(commit_oids, path.clone(), false);
// Update local refs to match server
for (remote_name, value) in refs.iter() {
@ -30,6 +30,25 @@ pub fn fetch(path: String) {
}
}
pub fn push(remote_path: String, reference: String) {
let local_ref = data::get_ref(reference.clone(), true).value;
assert!(local_ref != "".to_string());
let commit_oids = vec![&local_ref];
base::copy_objects_in_commits_and_parents(commit_oids, remote_path.clone(), true);
data::set_rgit_dir(remote_path.as_str());
data::update_ref(
reference,
data::RefValue {
symbolic: false,
value: local_ref,
},
true,
);
data::reset_rgit_dir();
}
fn get_remote_refs(path: String, prefix: &str) -> HashMap<String, String> {
let mut refs = HashMap::new();
data::set_rgit_dir(path.as_str());