From 910cd74294dc3f86851c04829bc73a37924caef1 Mon Sep 17 00:00:00 2001 From: Alexis Sellier Date: Sat, 3 Sep 2022 18:18:55 +0200 Subject: [PATCH] node: Improve project init Improvement doesn't modify the working copy index. Signed-off-by: Alexis Sellier --- node/src/rad.rs | 70 ++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/node/src/rad.rs b/node/src/rad.rs index 7d8cdbb0..4c6681b8 100644 --- a/node/src/rad.rs +++ b/node/src/rad.rs @@ -1,4 +1,4 @@ -use std::{fs, io}; +use std::io; use git_url::Url; use nonempty::NonEmpty; @@ -9,7 +9,7 @@ use crate::git; use crate::identity::ProjId; use crate::storage::git::RADICLE_ID_REF; use crate::storage::refs::SignedRefs; -use crate::storage::{BranchName, ReadRepository as _}; +use crate::storage::{BranchName, ReadRepository as _, WriteRepository as _}; use crate::{identity, storage}; pub const REMOTE_NAME: &str = "rad"; @@ -54,38 +54,10 @@ pub fn init( parent: None, delegate: NonEmpty::new(delegate), }; - let sig = repo - .signature() - .or_else(|_| git2::Signature::now("anonymous", user_id.to_string().as_str()))?; let filename = *identity::IDENTITY_PATH; - let path = repo.workdir().ok_or(InitError::BareRepo)?.join(filename); - let file = fs::OpenOptions::new() - .create_new(true) - .write(true) - .open(&path)?; - let id = doc.write(file)?; - - let mut index = repo.index()?; - index.add_path(filename)?; - - let rad_id_ref = RADICLE_ID_REF.as_str(); - let tree_id = index.write_tree()?; - let tree = repo.find_tree(tree_id)?; - let _oid = repo.commit( - Some(rad_id_ref), - &sig, - &sig, - "Initialize Radicle", - &tree, - &[], - )?; - - // Remove identity document from current branch. - // FIXME: We shouldn't have to do this, as the user may have an unrelated file - // called the same name. Ideally we are able to create the file in the id branch. - fs::remove_file(path)?; - + let mut doc_bytes = Vec::new(); + let id = doc.write(&mut doc_bytes)?; let project = storage.repository(&id)?; let url = Url { scheme: git_url::Scheme::File, @@ -94,6 +66,33 @@ pub fn init( ..Url::default() }; + { + // Within this scope, redefine `repo` to refer to the project storage, + // since we're going to create the identity file there, and not in there + // working copy. + // + // You can checkout this branch in your working copy with: + // + // git fetch rad + // git checkout -b radicle/id remotes/rad/radicle/id + // + let repo = project.raw(); + let tree = { + let id_blob = repo.blob(&doc_bytes)?; + let mut builder = repo.treebuilder(None)?; + builder.insert(filename, id_blob, 0o100_644)?; + + let tree_id = builder.write()?; + repo.find_tree(tree_id) + }?; + let sig = repo + .signature() + .or_else(|_| git2::Signature::now("radicle", user_id.to_string().as_str()))?; + + let id_ref = format!("refs/remotes/{user_id}/{}", &*RADICLE_ID_REF); + let _oid = repo.commit(Some(&id_ref), &sig, &sig, "Initialize Radicle", &tree, &[])?; + } + let fetch = format!("+refs/remotes/{user_id}/heads/*:refs/remotes/rad/*"); let push = format!("refs/heads/*:refs/remotes/{user_id}/heads/*"); let mut remote = repo.remote_with_fetch(REMOTE_NAME, url.to_string().as_str(), &fetch)?; @@ -110,10 +109,9 @@ pub fn init( // `push_update_reference` to test whether all the references were pushed // successfully. remote.push::<&str>( - &[ - &format!("refs/heads/{default_branch}:refs/remotes/{user_id}/heads/{default_branch}"), - &format!("{rad_id_ref}:refs/remotes/{user_id}/heads/rad/id"), - ], + &[&format!( + "refs/heads/{default_branch}:refs/remotes/{user_id}/heads/{default_branch}" + )], None, )?; let signed = storage.sign_refs(&project)?;