node: Improve project init

Improvement doesn't modify the working copy index.

Signed-off-by: Alexis Sellier <self@cloudhead.io>
This commit is contained in:
Alexis Sellier 2022-09-03 18:18:55 +02:00
parent e4e4d9dcaa
commit 910cd74294
No known key found for this signature in database
1 changed files with 34 additions and 36 deletions

View File

@ -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<S: storage::WriteStorage>(
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<S: storage::WriteStorage>(
..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<S: storage::WriteStorage>(
// `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)?;