cobs: Fix COB drafts to work correctly
This commit is contained in:
parent
e130b4dc06
commit
729a6e057e
|
|
@ -635,11 +635,7 @@ impl<'a, G: Signer> ReviewBuilder<'a, G> {
|
||||||
Brain::new(self.patch_id, signer.public_key(), base, repo)?
|
Brain::new(self.patch_id, signer.public_key(), base, repo)?
|
||||||
};
|
};
|
||||||
let diff = self.diff(&brain.accepted, &tree, repo, opts)?;
|
let diff = self.diff(&brain.accepted, &tree, repo, opts)?;
|
||||||
let drafts = DraftStore::new(*signer.public_key(), self.repo).with(
|
let drafts = DraftStore::new(self.repo, *signer.public_key());
|
||||||
signer.public_key(),
|
|
||||||
&cob::patch::TYPENAME,
|
|
||||||
&patch_id,
|
|
||||||
)?;
|
|
||||||
let mut patches = cob::patch::Cache::no_cache(&drafts)?;
|
let mut patches = cob::patch::Cache::no_cache(&drafts)?;
|
||||||
let mut patch = patches.get_mut(&patch_id)?;
|
let mut patch = patches.get_mut(&patch_id)?;
|
||||||
let mut queue = ReviewQueue::from(diff);
|
let mut queue = ReviewQueue::from(diff);
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ pub enum Create {
|
||||||
Evaluate(Box<dyn std::error::Error + Send + Sync + 'static>),
|
Evaluate(Box<dyn std::error::Error + Send + Sync + 'static>),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
CreateChange(#[from] git::change::error::Create),
|
CreateChange(#[from] git::change::error::Create),
|
||||||
#[error("failed to updated references for during object creation")]
|
#[error("failed to updated references for during object creation: {err}")]
|
||||||
Refs {
|
Refs {
|
||||||
#[source]
|
#[source]
|
||||||
err: Box<dyn std::error::Error + Send + Sync + 'static>,
|
err: Box<dyn std::error::Error + Send + Sync + 'static>,
|
||||||
|
|
@ -40,7 +40,7 @@ pub enum Retrieve {
|
||||||
Evaluate(Box<dyn std::error::Error + Send + Sync + 'static>),
|
Evaluate(Box<dyn std::error::Error + Send + Sync + 'static>),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Git(#[from] git2::Error),
|
Git(#[from] git2::Error),
|
||||||
#[error("failed to get references during object retrieval")]
|
#[error("failed to get references during object retrieval: {err}")]
|
||||||
Refs {
|
Refs {
|
||||||
#[source]
|
#[source]
|
||||||
err: Box<dyn std::error::Error + Send + Sync + 'static>,
|
err: Box<dyn std::error::Error + Send + Sync + 'static>,
|
||||||
|
|
@ -63,7 +63,7 @@ pub enum Update {
|
||||||
NoSuchObject,
|
NoSuchObject,
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
CreateChange(#[from] git::change::error::Create),
|
CreateChange(#[from] git::change::error::Create),
|
||||||
#[error("failed to get references during object update")]
|
#[error("failed to get references during object update: {err}")]
|
||||||
Refs {
|
Refs {
|
||||||
#[source]
|
#[source]
|
||||||
err: Box<dyn std::error::Error + Send + Sync + 'static>,
|
err: Box<dyn std::error::Error + Send + Sync + 'static>,
|
||||||
|
|
|
||||||
|
|
@ -3208,7 +3208,12 @@ mod test {
|
||||||
let alice = test::setup::NodeWithRepo::default();
|
let alice = test::setup::NodeWithRepo::default();
|
||||||
let checkout = alice.repo.checkout();
|
let checkout = alice.repo.checkout();
|
||||||
let branch = checkout.branch_with([("README", b"Hello World!")]);
|
let branch = checkout.branch_with([("README", b"Hello World!")]);
|
||||||
let mut patches = Cache::no_cache(&*alice.repo).unwrap();
|
let mut patches = {
|
||||||
|
let path = alice.tmp.path().join("cobs.db");
|
||||||
|
let db = cob::cache::Store::open(path).unwrap();
|
||||||
|
let store = cob::patch::Patches::open(&*alice.repo).unwrap();
|
||||||
|
cob::patch::Cache::open(store, db)
|
||||||
|
};
|
||||||
let mut patch = patches
|
let mut patch = patches
|
||||||
.create(
|
.create(
|
||||||
"My first patch",
|
"My first patch",
|
||||||
|
|
|
||||||
|
|
@ -324,18 +324,15 @@ pub mod refs {
|
||||||
.with_namespace(remote.into())
|
.with_namespace(remote.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draft collaborative objects of a type.
|
/// All draft collaborative object, identified by `typename` and `object_id`, for all remotes.
|
||||||
///
|
///
|
||||||
/// `refs/namespaces/<remote>/refs/drafts/cobs/<typename>/*`
|
/// `refs/namespaces/*/refs/drafts/cobs/<typename>/<object_id>`
|
||||||
///
|
///
|
||||||
pub fn cobs(remote: &RemoteId, typename: &cob::TypeName) -> PatternString {
|
pub fn cobs(typename: &cob::TypeName, object_id: &cob::ObjectId) -> PatternString {
|
||||||
Qualified::from_components(
|
refspec::pattern!("refs/namespaces/*")
|
||||||
component!("drafts"),
|
.join(refname!("refs/drafts/cobs"))
|
||||||
component!("cobs"),
|
.join(Component::from(typename))
|
||||||
Some(Component::from(typename)),
|
.join(Component::from(object_id))
|
||||||
)
|
|
||||||
.with_namespace(remote.into())
|
|
||||||
.to_pattern(refspec::pattern!("*"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@ pub enum ObjectsError {
|
||||||
Convert(#[from] cob::object::storage::convert::Error),
|
Convert(#[from] cob::object::storage::convert::Error),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Git(#[from] git2::Error),
|
Git(#[from] git2::Error),
|
||||||
|
#[error(transparent)]
|
||||||
|
GitExt(#[from] git_ext::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
|
|
@ -178,38 +180,13 @@ impl cob::object::Storage for Repository {
|
||||||
// which allows for some of the features needed for code review. For
|
// which allows for some of the features needed for code review. For
|
||||||
// example, users can draft comments and later decide to publish them.
|
// example, users can draft comments and later decide to publish them.
|
||||||
pub struct DraftStore<'a, R> {
|
pub struct DraftStore<'a, R> {
|
||||||
remote: RemoteId,
|
|
||||||
repo: &'a R,
|
repo: &'a R,
|
||||||
}
|
remote: RemoteId,
|
||||||
|
|
||||||
impl<'a, R: storage::WriteRepository> DraftStore<'a, R> {
|
|
||||||
/// Create this draft store with an existing COB from storage, so that changes applied
|
|
||||||
/// to this COB can evaluate properly. This creates a symbolic reference to the COB
|
|
||||||
/// pointing to the public COB reference.
|
|
||||||
pub fn with(
|
|
||||||
self,
|
|
||||||
remote: &RemoteId,
|
|
||||||
typename: &cob::TypeName,
|
|
||||||
id: &ObjectId,
|
|
||||||
) -> Result<Self, git::Error> {
|
|
||||||
let target = git::refs::storage::cob(remote, typename, id);
|
|
||||||
let name = git::refs::storage::draft::cob(remote, typename, id);
|
|
||||||
let repo = self.repo.raw();
|
|
||||||
|
|
||||||
repo.reference_symbolic(
|
|
||||||
name.as_str(),
|
|
||||||
target.as_str(),
|
|
||||||
true, // The reference may already exist, overwrite it if so.
|
|
||||||
format!("Link to COB {id} of type {typename}").as_str(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, R> DraftStore<'a, R> {
|
impl<'a, R> DraftStore<'a, R> {
|
||||||
pub fn new(remote: RemoteId, repo: &'a R) -> Self {
|
pub fn new(repo: &'a R, remote: RemoteId) -> Self {
|
||||||
Self { remote, repo }
|
Self { repo, remote }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -398,33 +375,41 @@ impl<'a, R: storage::WriteRepository> cob::object::Storage for DraftStore<'a, R>
|
||||||
typename: &cob::TypeName,
|
typename: &cob::TypeName,
|
||||||
object_id: &cob::ObjectId,
|
object_id: &cob::ObjectId,
|
||||||
) -> Result<cob::object::Objects, Self::ObjectsError> {
|
) -> Result<cob::object::Objects, Self::ObjectsError> {
|
||||||
// Nb. There can only be one draft per COB, per remote.
|
let mut objs = Objects::default();
|
||||||
let Ok(r) = self.repo.raw().find_reference(
|
|
||||||
git::refs::storage::draft::cob(&self.remote, typename, object_id).as_str(),
|
|
||||||
) else {
|
|
||||||
return Ok(Objects::default());
|
|
||||||
};
|
|
||||||
let r = cob::object::Reference::try_from(r).map_err(Self::ObjectsError::from)?;
|
|
||||||
|
|
||||||
Ok(Objects::new(r))
|
// First get the signed COB tips of all remotes for this object.
|
||||||
|
let signed = self
|
||||||
|
.repo
|
||||||
|
.references_glob(&git::refs::storage::cobs(typename, object_id))?;
|
||||||
|
|
||||||
|
for (r, id) in signed {
|
||||||
|
let r = cob::object::Reference {
|
||||||
|
name: r.to_ref_string(),
|
||||||
|
target: cob::object::Commit { id },
|
||||||
|
};
|
||||||
|
objs.push(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then get the draft COB tip that belongs to us only, if any.
|
||||||
|
let draft_ref = &git::refs::storage::draft::cob(&self.remote, typename, object_id);
|
||||||
|
if let Ok(draft_oid) = self
|
||||||
|
.repo
|
||||||
|
.reference_oid(&self.remote, &draft_ref.strip_namespace())
|
||||||
|
{
|
||||||
|
objs.push(cob::object::Reference {
|
||||||
|
name: draft_ref.to_ref_string(),
|
||||||
|
target: cob::object::Commit { id: draft_oid },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(objs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn types(
|
fn types(
|
||||||
&self,
|
&self,
|
||||||
typename: &cob::TypeName,
|
_typename: &cob::TypeName,
|
||||||
) -> Result<BTreeMap<cob::ObjectId, cob::object::Objects>, Self::TypesError> {
|
) -> Result<BTreeMap<cob::ObjectId, cob::object::Objects>, Self::TypesError> {
|
||||||
let glob = git::refs::storage::draft::cobs(&self.remote, typename);
|
unimplemented!()
|
||||||
let references = self.repo.references_glob(&glob)?;
|
|
||||||
let mut objs = BTreeMap::new();
|
|
||||||
|
|
||||||
for (name, id) in references {
|
|
||||||
let r = cob::object::Reference {
|
|
||||||
name: name.into_refstring(),
|
|
||||||
target: cob::object::Commit { id },
|
|
||||||
};
|
|
||||||
objs.insert(id.into(), Objects::new(r));
|
|
||||||
}
|
|
||||||
Ok(objs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(
|
fn update(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue