2022-11-26 23:57:50 +00:00
|
|
|
// Copyright 2020 The Jujutsu Authors
|
2020-12-12 08:00:42 +00:00
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2021-04-07 06:05:16 +00:00
|
|
|
use std::io;
|
2020-12-12 08:00:42 +00:00
|
|
|
|
2021-06-09 20:57:48 +00:00
|
|
|
use itertools::Itertools;
|
2023-01-25 09:46:38 +00:00
|
|
|
use jujutsu_lib::backend::{ObjectId, Signature, Timestamp};
|
2021-05-15 16:16:31 +00:00
|
|
|
use jujutsu_lib::commit::Commit;
|
2022-02-02 18:14:03 +00:00
|
|
|
use jujutsu_lib::op_store::WorkspaceId;
|
2021-05-15 16:16:31 +00:00
|
|
|
use jujutsu_lib::repo::RepoRef;
|
2023-01-14 10:43:23 +00:00
|
|
|
use jujutsu_lib::rewrite::merge_commit_trees;
|
2020-12-12 08:00:42 +00:00
|
|
|
|
2021-06-02 22:50:08 +00:00
|
|
|
use crate::formatter::Formatter;
|
2023-01-23 02:38:16 +00:00
|
|
|
use crate::time_util;
|
2020-12-12 08:00:42 +00:00
|
|
|
|
|
|
|
pub trait Template<C> {
|
2021-06-02 22:50:08 +00:00
|
|
|
fn format(&self, context: &C, formatter: &mut dyn Formatter) -> io::Result<()>;
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
|
|
|
|
2023-01-23 10:42:57 +00:00
|
|
|
impl<C, T: Template<C> + ?Sized> Template<C> for Box<T> {
|
|
|
|
fn format(&self, context: &C, formatter: &mut dyn Formatter) -> io::Result<()> {
|
|
|
|
<T as Template<C>>::format(self, context, formatter)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-23 02:38:16 +00:00
|
|
|
impl Template<()> for Signature {
|
|
|
|
fn format(&self, _: &(), formatter: &mut dyn Formatter) -> io::Result<()> {
|
2023-01-23 04:11:29 +00:00
|
|
|
write!(formatter.labeled("name"), "{}", self.name)?;
|
2023-01-22 12:16:52 +00:00
|
|
|
write!(formatter, " <")?;
|
|
|
|
write!(formatter.labeled("email"), "{}", self.email)?;
|
|
|
|
write!(formatter, ">")?;
|
|
|
|
Ok(())
|
2023-01-23 02:38:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Template<()> for String {
|
|
|
|
fn format(&self, _: &(), formatter: &mut dyn Formatter) -> io::Result<()> {
|
|
|
|
formatter.write_str(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Template<()> for Timestamp {
|
|
|
|
fn format(&self, _: &(), formatter: &mut dyn Formatter) -> io::Result<()> {
|
|
|
|
formatter.write_str(&time_util::format_absolute_timestamp(self))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Template<()> for bool {
|
|
|
|
fn format(&self, _: &(), formatter: &mut dyn Formatter) -> io::Result<()> {
|
|
|
|
formatter.write_str(if *self { "true" } else { "false" })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-23 10:42:57 +00:00
|
|
|
pub struct LabelTemplate<T> {
|
|
|
|
content: T,
|
2020-12-12 08:00:42 +00:00
|
|
|
labels: Vec<String>,
|
|
|
|
}
|
|
|
|
|
2023-01-23 10:42:57 +00:00
|
|
|
impl<T> LabelTemplate<T> {
|
|
|
|
pub fn new<C>(content: T, labels: Vec<String>) -> Self
|
|
|
|
where
|
|
|
|
T: Template<C>,
|
|
|
|
{
|
2020-12-12 08:00:42 +00:00
|
|
|
LabelTemplate { content, labels }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-23 10:42:57 +00:00
|
|
|
impl<C, T: Template<C>> Template<C> for LabelTemplate<T> {
|
2021-06-02 22:50:08 +00:00
|
|
|
fn format(&self, context: &C, formatter: &mut dyn Formatter) -> io::Result<()> {
|
2020-12-12 08:00:42 +00:00
|
|
|
for label in &self.labels {
|
2023-01-12 08:00:12 +00:00
|
|
|
formatter.push_label(label)?;
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
2021-06-02 22:50:08 +00:00
|
|
|
self.content.format(context, formatter)?;
|
2020-12-12 08:00:42 +00:00
|
|
|
for _label in &self.labels {
|
2023-01-12 08:00:12 +00:00
|
|
|
formatter.pop_label()?;
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
2021-04-07 06:05:16 +00:00
|
|
|
Ok(())
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-23 10:42:57 +00:00
|
|
|
pub struct DynamicLabelTemplate<T, F> {
|
|
|
|
content: T,
|
|
|
|
label_property: F,
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
|
|
|
|
2023-01-23 10:42:57 +00:00
|
|
|
impl<T, F> DynamicLabelTemplate<T, F> {
|
|
|
|
pub fn new<C>(content: T, label_property: F) -> Self
|
|
|
|
where
|
|
|
|
T: Template<C>,
|
|
|
|
F: Fn(&C) -> Vec<String>,
|
|
|
|
{
|
2020-12-12 08:00:42 +00:00
|
|
|
DynamicLabelTemplate {
|
|
|
|
content,
|
|
|
|
label_property,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-23 10:42:57 +00:00
|
|
|
impl<C, T, F> Template<C> for DynamicLabelTemplate<T, F>
|
|
|
|
where
|
|
|
|
T: Template<C>,
|
|
|
|
F: Fn(&C) -> Vec<String>,
|
|
|
|
{
|
2021-06-02 22:50:08 +00:00
|
|
|
fn format(&self, context: &C, formatter: &mut dyn Formatter) -> io::Result<()> {
|
2023-01-23 10:42:57 +00:00
|
|
|
let labels = (self.label_property)(context);
|
2020-12-12 08:00:42 +00:00
|
|
|
for label in &labels {
|
2023-01-12 08:00:12 +00:00
|
|
|
formatter.push_label(label)?;
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
2021-06-02 22:50:08 +00:00
|
|
|
self.content.format(context, formatter)?;
|
2020-12-12 08:00:42 +00:00
|
|
|
for _label in &labels {
|
2023-01-12 08:00:12 +00:00
|
|
|
formatter.pop_label()?;
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
2021-04-07 06:05:16 +00:00
|
|
|
Ok(())
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-23 10:42:57 +00:00
|
|
|
pub struct ListTemplate<T>(pub Vec<T>);
|
2020-12-12 08:00:42 +00:00
|
|
|
|
2023-01-23 10:42:57 +00:00
|
|
|
impl<C, T: Template<C>> Template<C> for ListTemplate<T> {
|
2021-06-02 22:50:08 +00:00
|
|
|
fn format(&self, context: &C, formatter: &mut dyn Formatter) -> io::Result<()> {
|
2020-12-12 08:00:42 +00:00
|
|
|
for template in &self.0 {
|
2021-06-02 22:50:08 +00:00
|
|
|
template.format(context, formatter)?
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
2021-04-07 06:05:16 +00:00
|
|
|
Ok(())
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
templater: turn output parameter of TemplateProperty into associated type
When implementing FormattablePropertyTemplate, I tried a generic 'property: P'
first, and I couldn't figure out how to constrain the output type.
impl<C, O, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C, O>, // 'O' isn't constrained by type
O: Template<()>,
According to the book, the problem is that we can add multiple implementations
of 'TemplateProperty<C, *>'. Since TemplateProperty is basically a function
to extract data from 'C', I think the output parameter shouldn't be freely
chosen.
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
With this change, I can express the type constraint as follows:
impl<C, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C>,
P::Output: Template<()>,
2023-01-23 06:26:27 +00:00
|
|
|
pub trait TemplateProperty<C> {
|
|
|
|
type Output;
|
|
|
|
|
|
|
|
fn extract(&self, context: &C) -> Self::Output;
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
|
|
|
|
2023-01-23 10:42:57 +00:00
|
|
|
impl<C, P: TemplateProperty<C> + ?Sized> TemplateProperty<C> for Box<P> {
|
|
|
|
type Output = <P as TemplateProperty<C>>::Output;
|
|
|
|
|
|
|
|
fn extract(&self, context: &C) -> Self::Output {
|
|
|
|
<P as TemplateProperty<C>>::extract(self, context)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-23 03:03:13 +00:00
|
|
|
/// Adapter to drop template context.
|
|
|
|
pub struct Literal<O>(pub O);
|
|
|
|
|
|
|
|
impl<C, O: Template<()>> Template<C> for Literal<O> {
|
|
|
|
fn format(&self, _context: &C, formatter: &mut dyn Formatter) -> io::Result<()> {
|
|
|
|
self.0.format(&(), formatter)
|
|
|
|
}
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
|
|
|
|
templater: turn output parameter of TemplateProperty into associated type
When implementing FormattablePropertyTemplate, I tried a generic 'property: P'
first, and I couldn't figure out how to constrain the output type.
impl<C, O, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C, O>, // 'O' isn't constrained by type
O: Template<()>,
According to the book, the problem is that we can add multiple implementations
of 'TemplateProperty<C, *>'. Since TemplateProperty is basically a function
to extract data from 'C', I think the output parameter shouldn't be freely
chosen.
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
With this change, I can express the type constraint as follows:
impl<C, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C>,
P::Output: Template<()>,
2023-01-23 06:26:27 +00:00
|
|
|
impl<C, O: Clone> TemplateProperty<C> for Literal<O> {
|
|
|
|
type Output = O;
|
|
|
|
|
2020-12-12 08:00:42 +00:00
|
|
|
fn extract(&self, _context: &C) -> O {
|
2023-01-23 03:03:13 +00:00
|
|
|
self.0.clone()
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-22 23:02:46 +00:00
|
|
|
/// Adapter to extract context-less template value from property for displaying.
|
2023-01-23 10:42:57 +00:00
|
|
|
pub struct FormattablePropertyTemplate<P> {
|
|
|
|
property: P,
|
2023-01-22 23:02:46 +00:00
|
|
|
}
|
|
|
|
|
2023-01-23 10:42:57 +00:00
|
|
|
impl<P> FormattablePropertyTemplate<P> {
|
|
|
|
pub fn new<C>(property: P) -> Self
|
|
|
|
where
|
|
|
|
P: TemplateProperty<C>,
|
|
|
|
P::Output: Template<()>,
|
|
|
|
{
|
2023-01-22 23:02:46 +00:00
|
|
|
FormattablePropertyTemplate { property }
|
|
|
|
}
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
|
|
|
|
2023-01-23 10:42:57 +00:00
|
|
|
impl<C, P> Template<C> for FormattablePropertyTemplate<P>
|
2023-01-22 23:02:46 +00:00
|
|
|
where
|
2023-01-23 10:42:57 +00:00
|
|
|
P: TemplateProperty<C>,
|
|
|
|
P::Output: Template<()>,
|
2023-01-22 23:02:46 +00:00
|
|
|
{
|
2021-06-02 22:50:08 +00:00
|
|
|
fn format(&self, context: &C, formatter: &mut dyn Formatter) -> io::Result<()> {
|
2023-01-22 23:02:46 +00:00
|
|
|
let template = self.property.extract(context);
|
|
|
|
template.format(&(), formatter)
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct DescriptionProperty;
|
|
|
|
|
templater: turn output parameter of TemplateProperty into associated type
When implementing FormattablePropertyTemplate, I tried a generic 'property: P'
first, and I couldn't figure out how to constrain the output type.
impl<C, O, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C, O>, // 'O' isn't constrained by type
O: Template<()>,
According to the book, the problem is that we can add multiple implementations
of 'TemplateProperty<C, *>'. Since TemplateProperty is basically a function
to extract data from 'C', I think the output parameter shouldn't be freely
chosen.
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
With this change, I can express the type constraint as follows:
impl<C, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C>,
P::Output: Template<()>,
2023-01-23 06:26:27 +00:00
|
|
|
impl TemplateProperty<Commit> for DescriptionProperty {
|
|
|
|
type Output = String;
|
|
|
|
|
|
|
|
fn extract(&self, context: &Commit) -> Self::Output {
|
2023-01-14 10:32:01 +00:00
|
|
|
match context.description() {
|
|
|
|
s if s.is_empty() => "(no description set)\n".to_owned(),
|
|
|
|
s if s.ends_with('\n') => s.to_owned(),
|
|
|
|
s => format!("{s}\n"),
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct AuthorProperty;
|
|
|
|
|
templater: turn output parameter of TemplateProperty into associated type
When implementing FormattablePropertyTemplate, I tried a generic 'property: P'
first, and I couldn't figure out how to constrain the output type.
impl<C, O, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C, O>, // 'O' isn't constrained by type
O: Template<()>,
According to the book, the problem is that we can add multiple implementations
of 'TemplateProperty<C, *>'. Since TemplateProperty is basically a function
to extract data from 'C', I think the output parameter shouldn't be freely
chosen.
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
With this change, I can express the type constraint as follows:
impl<C, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C>,
P::Output: Template<()>,
2023-01-23 06:26:27 +00:00
|
|
|
impl TemplateProperty<Commit> for AuthorProperty {
|
|
|
|
type Output = Signature;
|
|
|
|
|
|
|
|
fn extract(&self, context: &Commit) -> Self::Output {
|
2020-12-12 08:00:42 +00:00
|
|
|
context.author().clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct CommitterProperty;
|
|
|
|
|
templater: turn output parameter of TemplateProperty into associated type
When implementing FormattablePropertyTemplate, I tried a generic 'property: P'
first, and I couldn't figure out how to constrain the output type.
impl<C, O, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C, O>, // 'O' isn't constrained by type
O: Template<()>,
According to the book, the problem is that we can add multiple implementations
of 'TemplateProperty<C, *>'. Since TemplateProperty is basically a function
to extract data from 'C', I think the output parameter shouldn't be freely
chosen.
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
With this change, I can express the type constraint as follows:
impl<C, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C>,
P::Output: Template<()>,
2023-01-23 06:26:27 +00:00
|
|
|
impl TemplateProperty<Commit> for CommitterProperty {
|
|
|
|
type Output = Signature;
|
|
|
|
|
|
|
|
fn extract(&self, context: &Commit) -> Self::Output {
|
2020-12-12 08:00:42 +00:00
|
|
|
context.committer().clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-18 21:46:12 +00:00
|
|
|
pub struct WorkingCopiesProperty<'a> {
|
2022-02-03 01:00:05 +00:00
|
|
|
pub repo: RepoRef<'a>,
|
|
|
|
}
|
|
|
|
|
templater: turn output parameter of TemplateProperty into associated type
When implementing FormattablePropertyTemplate, I tried a generic 'property: P'
first, and I couldn't figure out how to constrain the output type.
impl<C, O, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C, O>, // 'O' isn't constrained by type
O: Template<()>,
According to the book, the problem is that we can add multiple implementations
of 'TemplateProperty<C, *>'. Since TemplateProperty is basically a function
to extract data from 'C', I think the output parameter shouldn't be freely
chosen.
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
With this change, I can express the type constraint as follows:
impl<C, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C>,
P::Output: Template<()>,
2023-01-23 06:26:27 +00:00
|
|
|
impl TemplateProperty<Commit> for WorkingCopiesProperty<'_> {
|
|
|
|
type Output = String;
|
|
|
|
|
|
|
|
fn extract(&self, context: &Commit) -> Self::Output {
|
2022-09-18 21:46:12 +00:00
|
|
|
let wc_commit_ids = self.repo.view().wc_commit_ids();
|
|
|
|
if wc_commit_ids.len() <= 1 {
|
2022-02-03 01:00:05 +00:00
|
|
|
return "".to_string();
|
|
|
|
}
|
|
|
|
let mut names = vec![];
|
2022-09-18 21:46:12 +00:00
|
|
|
for (workspace_id, wc_commit_id) in wc_commit_ids.iter().sorted() {
|
|
|
|
if wc_commit_id == context.id() {
|
2022-02-03 01:00:05 +00:00
|
|
|
names.push(format!("{}@", workspace_id.as_str()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
names.join(" ")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-18 21:46:12 +00:00
|
|
|
pub struct IsWorkingCopyProperty<'a> {
|
2021-04-11 16:13:00 +00:00
|
|
|
pub repo: RepoRef<'a>,
|
2022-02-02 18:14:03 +00:00
|
|
|
pub workspace_id: WorkspaceId,
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
|
|
|
|
templater: turn output parameter of TemplateProperty into associated type
When implementing FormattablePropertyTemplate, I tried a generic 'property: P'
first, and I couldn't figure out how to constrain the output type.
impl<C, O, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C, O>, // 'O' isn't constrained by type
O: Template<()>,
According to the book, the problem is that we can add multiple implementations
of 'TemplateProperty<C, *>'. Since TemplateProperty is basically a function
to extract data from 'C', I think the output parameter shouldn't be freely
chosen.
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
With this change, I can express the type constraint as follows:
impl<C, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C>,
P::Output: Template<()>,
2023-01-23 06:26:27 +00:00
|
|
|
impl TemplateProperty<Commit> for IsWorkingCopyProperty<'_> {
|
|
|
|
type Output = bool;
|
|
|
|
|
|
|
|
fn extract(&self, context: &Commit) -> Self::Output {
|
2022-09-18 21:46:12 +00:00
|
|
|
Some(context.id()) == self.repo.view().get_wc_commit_id(&self.workspace_id)
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-15 08:31:48 +00:00
|
|
|
pub struct BranchProperty<'a> {
|
|
|
|
pub repo: RepoRef<'a>,
|
|
|
|
}
|
|
|
|
|
templater: turn output parameter of TemplateProperty into associated type
When implementing FormattablePropertyTemplate, I tried a generic 'property: P'
first, and I couldn't figure out how to constrain the output type.
impl<C, O, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C, O>, // 'O' isn't constrained by type
O: Template<()>,
According to the book, the problem is that we can add multiple implementations
of 'TemplateProperty<C, *>'. Since TemplateProperty is basically a function
to extract data from 'C', I think the output parameter shouldn't be freely
chosen.
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
With this change, I can express the type constraint as follows:
impl<C, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C>,
P::Output: Template<()>,
2023-01-23 06:26:27 +00:00
|
|
|
impl TemplateProperty<Commit> for BranchProperty<'_> {
|
|
|
|
type Output = String;
|
|
|
|
|
|
|
|
fn extract(&self, context: &Commit) -> Self::Output {
|
2021-07-15 08:31:48 +00:00
|
|
|
let mut names = vec![];
|
|
|
|
for (branch_name, branch_target) in self.repo.view().branches() {
|
|
|
|
let local_target = branch_target.local_target.as_ref();
|
|
|
|
if let Some(local_target) = local_target {
|
|
|
|
if local_target.has_add(context.id()) {
|
|
|
|
if local_target.is_conflict() {
|
2023-01-07 01:59:57 +00:00
|
|
|
names.push(format!("{branch_name}??"));
|
2022-11-04 16:39:46 +00:00
|
|
|
} else if branch_target
|
|
|
|
.remote_targets
|
|
|
|
.values()
|
|
|
|
.any(|remote_target| remote_target != local_target)
|
|
|
|
{
|
2022-12-15 02:30:06 +00:00
|
|
|
names.push(format!("{branch_name}*"));
|
2021-07-15 08:31:48 +00:00
|
|
|
} else {
|
|
|
|
names.push(branch_name.clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (remote_name, remote_target) in &branch_target.remote_targets {
|
|
|
|
if Some(remote_target) != local_target && remote_target.has_add(context.id()) {
|
|
|
|
if remote_target.is_conflict() {
|
2022-12-15 02:30:06 +00:00
|
|
|
names.push(format!("{branch_name}@{remote_name}?"));
|
2021-07-15 08:31:48 +00:00
|
|
|
} else {
|
2022-12-15 02:30:06 +00:00
|
|
|
names.push(format!("{branch_name}@{remote_name}"));
|
2021-07-15 08:31:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
names.join(" ")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct TagProperty<'a> {
|
|
|
|
pub repo: RepoRef<'a>,
|
|
|
|
}
|
|
|
|
|
templater: turn output parameter of TemplateProperty into associated type
When implementing FormattablePropertyTemplate, I tried a generic 'property: P'
first, and I couldn't figure out how to constrain the output type.
impl<C, O, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C, O>, // 'O' isn't constrained by type
O: Template<()>,
According to the book, the problem is that we can add multiple implementations
of 'TemplateProperty<C, *>'. Since TemplateProperty is basically a function
to extract data from 'C', I think the output parameter shouldn't be freely
chosen.
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
With this change, I can express the type constraint as follows:
impl<C, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C>,
P::Output: Template<()>,
2023-01-23 06:26:27 +00:00
|
|
|
impl TemplateProperty<Commit> for TagProperty<'_> {
|
|
|
|
type Output = String;
|
|
|
|
|
|
|
|
fn extract(&self, context: &Commit) -> Self::Output {
|
2021-07-15 08:31:48 +00:00
|
|
|
let mut names = vec![];
|
|
|
|
for (tag_name, target) in self.repo.view().tags() {
|
|
|
|
if target.has_add(context.id()) {
|
|
|
|
if target.is_conflict() {
|
2022-12-15 02:30:06 +00:00
|
|
|
names.push(format!("{tag_name}?"));
|
2021-07-15 08:31:48 +00:00
|
|
|
} else {
|
|
|
|
names.push(tag_name.clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
names.join(" ")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-11 16:13:00 +00:00
|
|
|
pub struct GitRefsProperty<'a> {
|
|
|
|
pub repo: RepoRef<'a>,
|
2021-01-03 08:26:57 +00:00
|
|
|
}
|
|
|
|
|
templater: turn output parameter of TemplateProperty into associated type
When implementing FormattablePropertyTemplate, I tried a generic 'property: P'
first, and I couldn't figure out how to constrain the output type.
impl<C, O, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C, O>, // 'O' isn't constrained by type
O: Template<()>,
According to the book, the problem is that we can add multiple implementations
of 'TemplateProperty<C, *>'. Since TemplateProperty is basically a function
to extract data from 'C', I think the output parameter shouldn't be freely
chosen.
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
With this change, I can express the type constraint as follows:
impl<C, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C>,
P::Output: Template<()>,
2023-01-23 06:26:27 +00:00
|
|
|
impl TemplateProperty<Commit> for GitRefsProperty<'_> {
|
|
|
|
type Output = String;
|
|
|
|
|
|
|
|
fn extract(&self, context: &Commit) -> Self::Output {
|
2021-07-11 17:58:01 +00:00
|
|
|
// TODO: We should keep a map from commit to ref names so we don't have to walk
|
|
|
|
// all refs here.
|
|
|
|
let mut names = vec![];
|
|
|
|
for (name, target) in self.repo.view().git_refs() {
|
|
|
|
if target.has_add(context.id()) {
|
|
|
|
if target.is_conflict() {
|
2022-12-15 02:30:06 +00:00
|
|
|
names.push(format!("{name}?"));
|
2021-07-11 17:58:01 +00:00
|
|
|
} else {
|
|
|
|
names.push(name.clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
names.join(" ")
|
2021-01-03 08:26:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-29 05:33:37 +00:00
|
|
|
pub struct IsGitHeadProperty<'a> {
|
|
|
|
repo: RepoRef<'a>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> IsGitHeadProperty<'a> {
|
|
|
|
pub fn new(repo: RepoRef<'a>) -> Self {
|
|
|
|
Self { repo }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
templater: turn output parameter of TemplateProperty into associated type
When implementing FormattablePropertyTemplate, I tried a generic 'property: P'
first, and I couldn't figure out how to constrain the output type.
impl<C, O, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C, O>, // 'O' isn't constrained by type
O: Template<()>,
According to the book, the problem is that we can add multiple implementations
of 'TemplateProperty<C, *>'. Since TemplateProperty is basically a function
to extract data from 'C', I think the output parameter shouldn't be freely
chosen.
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
With this change, I can express the type constraint as follows:
impl<C, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C>,
P::Output: Template<()>,
2023-01-23 06:26:27 +00:00
|
|
|
impl TemplateProperty<Commit> for IsGitHeadProperty<'_> {
|
|
|
|
type Output = bool;
|
|
|
|
|
|
|
|
fn extract(&self, context: &Commit) -> Self::Output {
|
2021-11-29 05:33:37 +00:00
|
|
|
self.repo.view().git_head().as_ref() == Some(context.id())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-25 09:46:38 +00:00
|
|
|
pub struct DivergentProperty<'a> {
|
|
|
|
repo: RepoRef<'a>,
|
2021-10-07 05:50:11 +00:00
|
|
|
}
|
|
|
|
|
2023-01-25 09:46:38 +00:00
|
|
|
impl<'a> DivergentProperty<'a> {
|
|
|
|
pub fn new(repo: RepoRef<'a>) -> Self {
|
|
|
|
DivergentProperty { repo }
|
2021-10-07 05:50:11 +00:00
|
|
|
}
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
|
|
|
|
2023-01-25 09:46:38 +00:00
|
|
|
impl TemplateProperty<Commit> for DivergentProperty<'_> {
|
templater: turn output parameter of TemplateProperty into associated type
When implementing FormattablePropertyTemplate, I tried a generic 'property: P'
first, and I couldn't figure out how to constrain the output type.
impl<C, O, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C, O>, // 'O' isn't constrained by type
O: Template<()>,
According to the book, the problem is that we can add multiple implementations
of 'TemplateProperty<C, *>'. Since TemplateProperty is basically a function
to extract data from 'C', I think the output parameter shouldn't be freely
chosen.
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
With this change, I can express the type constraint as follows:
impl<C, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C>,
P::Output: Template<()>,
2023-01-23 06:26:27 +00:00
|
|
|
type Output = bool;
|
|
|
|
|
|
|
|
fn extract(&self, context: &Commit) -> Self::Output {
|
2023-01-25 09:46:38 +00:00
|
|
|
// The given commit could be hidden in e.g. obslog.
|
|
|
|
let maybe_entries = self.repo.resolve_change_id(context.change_id());
|
|
|
|
maybe_entries.map_or(0, |entries| entries.len()) > 1
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct ConflictProperty;
|
|
|
|
|
templater: turn output parameter of TemplateProperty into associated type
When implementing FormattablePropertyTemplate, I tried a generic 'property: P'
first, and I couldn't figure out how to constrain the output type.
impl<C, O, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C, O>, // 'O' isn't constrained by type
O: Template<()>,
According to the book, the problem is that we can add multiple implementations
of 'TemplateProperty<C, *>'. Since TemplateProperty is basically a function
to extract data from 'C', I think the output parameter shouldn't be freely
chosen.
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
With this change, I can express the type constraint as follows:
impl<C, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C>,
P::Output: Template<()>,
2023-01-23 06:26:27 +00:00
|
|
|
impl TemplateProperty<Commit> for ConflictProperty {
|
|
|
|
type Output = bool;
|
|
|
|
|
|
|
|
fn extract(&self, context: &Commit) -> Self::Output {
|
2020-12-12 08:00:42 +00:00
|
|
|
context.tree().has_conflict()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-23 10:42:57 +00:00
|
|
|
pub struct ConditionalTemplate<P, T, U> {
|
|
|
|
pub condition: P,
|
|
|
|
pub true_template: T,
|
|
|
|
pub false_template: Option<U>,
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
|
|
|
|
2023-01-23 10:42:57 +00:00
|
|
|
impl<P, T, U> ConditionalTemplate<P, T, U> {
|
|
|
|
pub fn new<C>(condition: P, true_template: T, false_template: Option<U>) -> Self
|
|
|
|
where
|
|
|
|
P: TemplateProperty<C, Output = bool>,
|
|
|
|
T: Template<C>,
|
|
|
|
U: Template<C>,
|
|
|
|
{
|
2020-12-12 08:00:42 +00:00
|
|
|
ConditionalTemplate {
|
|
|
|
condition,
|
|
|
|
true_template,
|
|
|
|
false_template,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-23 10:42:57 +00:00
|
|
|
impl<C, P, T, U> Template<C> for ConditionalTemplate<P, T, U>
|
|
|
|
where
|
|
|
|
P: TemplateProperty<C, Output = bool>,
|
|
|
|
T: Template<C>,
|
|
|
|
U: Template<C>,
|
|
|
|
{
|
2021-06-02 22:50:08 +00:00
|
|
|
fn format(&self, context: &C, formatter: &mut dyn Formatter) -> io::Result<()> {
|
2020-12-12 08:00:42 +00:00
|
|
|
if self.condition.extract(context) {
|
2021-06-02 22:50:08 +00:00
|
|
|
self.true_template.format(context, formatter)?;
|
2020-12-12 08:00:42 +00:00
|
|
|
} else if let Some(false_template) = &self.false_template {
|
2021-06-02 22:50:08 +00:00
|
|
|
false_template.format(context, formatter)?;
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
2021-04-07 06:05:16 +00:00
|
|
|
Ok(())
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: If needed, add a ContextualTemplateFunction where the function also
|
|
|
|
// gets the context
|
2023-01-23 10:42:57 +00:00
|
|
|
pub struct TemplateFunction<P, F> {
|
|
|
|
pub property: P,
|
|
|
|
pub function: F,
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
|
|
|
|
2023-01-23 10:42:57 +00:00
|
|
|
impl<P, F> TemplateFunction<P, F> {
|
|
|
|
pub fn new<C, O>(template: P, function: F) -> Self
|
|
|
|
where
|
|
|
|
P: TemplateProperty<C>,
|
|
|
|
F: Fn(P::Output) -> O,
|
|
|
|
{
|
2020-12-12 08:00:42 +00:00
|
|
|
TemplateFunction {
|
|
|
|
property: template,
|
|
|
|
function,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-23 10:42:57 +00:00
|
|
|
impl<C, O, P, F> TemplateProperty<C> for TemplateFunction<P, F>
|
|
|
|
where
|
|
|
|
P: TemplateProperty<C>,
|
|
|
|
F: Fn(P::Output) -> O,
|
|
|
|
{
|
templater: turn output parameter of TemplateProperty into associated type
When implementing FormattablePropertyTemplate, I tried a generic 'property: P'
first, and I couldn't figure out how to constrain the output type.
impl<C, O, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C, O>, // 'O' isn't constrained by type
O: Template<()>,
According to the book, the problem is that we can add multiple implementations
of 'TemplateProperty<C, *>'. Since TemplateProperty is basically a function
to extract data from 'C', I think the output parameter shouldn't be freely
chosen.
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
With this change, I can express the type constraint as follows:
impl<C, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C>,
P::Output: Template<()>,
2023-01-23 06:26:27 +00:00
|
|
|
type Output = O;
|
|
|
|
|
|
|
|
fn extract(&self, context: &C) -> Self::Output {
|
2020-12-12 08:00:42 +00:00
|
|
|
(self.function)(self.property.extract(context))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-19 04:25:18 +00:00
|
|
|
/// Type-erased `CommitId`/`ChangeId`.
|
2023-01-23 06:51:01 +00:00
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct CommitOrChangeId<'a> {
|
|
|
|
repo: RepoRef<'a>,
|
|
|
|
id_bytes: Vec<u8>,
|
|
|
|
}
|
2023-01-02 23:34:54 +00:00
|
|
|
|
2023-01-23 06:51:01 +00:00
|
|
|
impl CommitOrChangeId<'_> {
|
2023-01-18 11:18:57 +00:00
|
|
|
pub fn as_bytes(&self) -> &[u8] {
|
2023-01-23 06:51:01 +00:00
|
|
|
&self.id_bytes
|
2023-01-18 11:18:57 +00:00
|
|
|
}
|
|
|
|
|
2023-01-02 23:34:54 +00:00
|
|
|
pub fn hex(&self) -> String {
|
2023-01-23 06:51:01 +00:00
|
|
|
hex::encode(&self.id_bytes)
|
2023-01-02 23:34:54 +00:00
|
|
|
}
|
|
|
|
|
2023-01-19 04:19:11 +00:00
|
|
|
pub fn short(&self) -> String {
|
2023-01-19 04:42:43 +00:00
|
|
|
let mut hex = self.hex();
|
|
|
|
hex.truncate(12);
|
|
|
|
hex
|
2023-01-02 23:34:54 +00:00
|
|
|
}
|
2020-12-12 08:00:42 +00:00
|
|
|
|
2023-01-23 06:51:01 +00:00
|
|
|
pub fn short_prefix_and_brackets(&self) -> String {
|
|
|
|
highlight_shortest_prefix(self, 12)
|
2023-01-03 00:24:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-23 06:51:01 +00:00
|
|
|
impl Template<()> for CommitOrChangeId<'_> {
|
2023-01-23 02:38:16 +00:00
|
|
|
fn format(&self, _: &(), formatter: &mut dyn Formatter) -> io::Result<()> {
|
|
|
|
formatter.write_str(&self.hex())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-23 06:51:01 +00:00
|
|
|
fn highlight_shortest_prefix(id: &CommitOrChangeId, total_len: usize) -> String {
|
2023-01-24 10:05:27 +00:00
|
|
|
let prefix_len = id.repo.shortest_unique_id_prefix_len(id.as_bytes());
|
2023-01-18 11:18:57 +00:00
|
|
|
let mut hex = id.hex();
|
2023-01-19 04:48:15 +00:00
|
|
|
if prefix_len < total_len - 2 {
|
2023-01-03 00:24:00 +00:00
|
|
|
format!(
|
|
|
|
"{}[{}]",
|
|
|
|
&hex[0..prefix_len],
|
2023-01-19 04:48:15 +00:00
|
|
|
&hex[prefix_len..total_len - 2]
|
2023-01-03 00:24:00 +00:00
|
|
|
)
|
|
|
|
} else {
|
2023-01-19 04:42:43 +00:00
|
|
|
hex.truncate(total_len);
|
|
|
|
hex
|
2023-01-03 00:24:00 +00:00
|
|
|
}
|
2023-01-02 23:34:54 +00:00
|
|
|
}
|
2020-12-12 08:00:42 +00:00
|
|
|
|
2023-01-23 07:43:56 +00:00
|
|
|
pub struct CommitOrChangeIdShort;
|
2023-01-02 23:34:54 +00:00
|
|
|
|
2023-01-23 06:51:01 +00:00
|
|
|
impl TemplateProperty<CommitOrChangeId<'_>> for CommitOrChangeIdShort {
|
templater: turn output parameter of TemplateProperty into associated type
When implementing FormattablePropertyTemplate, I tried a generic 'property: P'
first, and I couldn't figure out how to constrain the output type.
impl<C, O, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C, O>, // 'O' isn't constrained by type
O: Template<()>,
According to the book, the problem is that we can add multiple implementations
of 'TemplateProperty<C, *>'. Since TemplateProperty is basically a function
to extract data from 'C', I think the output parameter shouldn't be freely
chosen.
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
With this change, I can express the type constraint as follows:
impl<C, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C>,
P::Output: Template<()>,
2023-01-23 06:26:27 +00:00
|
|
|
type Output = String;
|
|
|
|
|
|
|
|
fn extract(&self, context: &CommitOrChangeId) -> Self::Output {
|
2023-01-19 04:19:11 +00:00
|
|
|
context.short()
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-23 06:51:01 +00:00
|
|
|
pub struct CommitOrChangeIdShortPrefixAndBrackets;
|
2023-01-03 00:24:00 +00:00
|
|
|
|
2023-01-23 06:51:01 +00:00
|
|
|
impl TemplateProperty<CommitOrChangeId<'_>> for CommitOrChangeIdShortPrefixAndBrackets {
|
templater: turn output parameter of TemplateProperty into associated type
When implementing FormattablePropertyTemplate, I tried a generic 'property: P'
first, and I couldn't figure out how to constrain the output type.
impl<C, O, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C, O>, // 'O' isn't constrained by type
O: Template<()>,
According to the book, the problem is that we can add multiple implementations
of 'TemplateProperty<C, *>'. Since TemplateProperty is basically a function
to extract data from 'C', I think the output parameter shouldn't be freely
chosen.
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
With this change, I can express the type constraint as follows:
impl<C, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C>,
P::Output: Template<()>,
2023-01-23 06:26:27 +00:00
|
|
|
type Output = String;
|
|
|
|
|
|
|
|
fn extract(&self, context: &CommitOrChangeId) -> Self::Output {
|
2023-01-23 06:51:01 +00:00
|
|
|
context.short_prefix_and_brackets()
|
2023-01-03 00:24:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-23 06:51:01 +00:00
|
|
|
pub struct CommitIdProperty<'a> {
|
|
|
|
pub repo: RepoRef<'a>,
|
|
|
|
}
|
2023-01-19 03:17:17 +00:00
|
|
|
|
2023-01-23 06:51:01 +00:00
|
|
|
impl<'a> TemplateProperty<Commit> for CommitIdProperty<'a> {
|
|
|
|
type Output = CommitOrChangeId<'a>;
|
templater: turn output parameter of TemplateProperty into associated type
When implementing FormattablePropertyTemplate, I tried a generic 'property: P'
first, and I couldn't figure out how to constrain the output type.
impl<C, O, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C, O>, // 'O' isn't constrained by type
O: Template<()>,
According to the book, the problem is that we can add multiple implementations
of 'TemplateProperty<C, *>'. Since TemplateProperty is basically a function
to extract data from 'C', I think the output parameter shouldn't be freely
chosen.
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
With this change, I can express the type constraint as follows:
impl<C, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C>,
P::Output: Template<()>,
2023-01-23 06:26:27 +00:00
|
|
|
|
|
|
|
fn extract(&self, context: &Commit) -> Self::Output {
|
2023-01-23 06:51:01 +00:00
|
|
|
CommitOrChangeId {
|
|
|
|
repo: self.repo,
|
|
|
|
id_bytes: context.id().to_bytes(),
|
|
|
|
}
|
2023-01-19 03:17:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-23 06:51:01 +00:00
|
|
|
pub struct ChangeIdProperty<'a> {
|
|
|
|
pub repo: RepoRef<'a>,
|
|
|
|
}
|
2023-01-19 03:17:17 +00:00
|
|
|
|
2023-01-23 06:51:01 +00:00
|
|
|
impl<'a> TemplateProperty<Commit> for ChangeIdProperty<'a> {
|
|
|
|
type Output = CommitOrChangeId<'a>;
|
templater: turn output parameter of TemplateProperty into associated type
When implementing FormattablePropertyTemplate, I tried a generic 'property: P'
first, and I couldn't figure out how to constrain the output type.
impl<C, O, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C, O>, // 'O' isn't constrained by type
O: Template<()>,
According to the book, the problem is that we can add multiple implementations
of 'TemplateProperty<C, *>'. Since TemplateProperty is basically a function
to extract data from 'C', I think the output parameter shouldn't be freely
chosen.
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
With this change, I can express the type constraint as follows:
impl<C, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C>,
P::Output: Template<()>,
2023-01-23 06:26:27 +00:00
|
|
|
|
|
|
|
fn extract(&self, context: &Commit) -> Self::Output {
|
2023-01-23 06:51:01 +00:00
|
|
|
CommitOrChangeId {
|
|
|
|
repo: self.repo,
|
|
|
|
id_bytes: context.change_id().to_bytes(),
|
|
|
|
}
|
2020-12-12 08:00:42 +00:00
|
|
|
}
|
|
|
|
}
|
2022-11-26 01:33:24 +00:00
|
|
|
|
|
|
|
pub struct SignatureTimestamp;
|
|
|
|
|
templater: turn output parameter of TemplateProperty into associated type
When implementing FormattablePropertyTemplate, I tried a generic 'property: P'
first, and I couldn't figure out how to constrain the output type.
impl<C, O, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C, O>, // 'O' isn't constrained by type
O: Template<()>,
According to the book, the problem is that we can add multiple implementations
of 'TemplateProperty<C, *>'. Since TemplateProperty is basically a function
to extract data from 'C', I think the output parameter shouldn't be freely
chosen.
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
With this change, I can express the type constraint as follows:
impl<C, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C>,
P::Output: Template<()>,
2023-01-23 06:26:27 +00:00
|
|
|
impl TemplateProperty<Signature> for SignatureTimestamp {
|
|
|
|
type Output = Timestamp;
|
|
|
|
|
|
|
|
fn extract(&self, context: &Signature) -> Self::Output {
|
2022-11-26 01:33:24 +00:00
|
|
|
context.timestamp.clone()
|
|
|
|
}
|
|
|
|
}
|
2023-01-14 10:43:23 +00:00
|
|
|
|
|
|
|
pub struct EmptyProperty<'a> {
|
|
|
|
pub repo: RepoRef<'a>,
|
|
|
|
}
|
|
|
|
|
templater: turn output parameter of TemplateProperty into associated type
When implementing FormattablePropertyTemplate, I tried a generic 'property: P'
first, and I couldn't figure out how to constrain the output type.
impl<C, O, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C, O>, // 'O' isn't constrained by type
O: Template<()>,
According to the book, the problem is that we can add multiple implementations
of 'TemplateProperty<C, *>'. Since TemplateProperty is basically a function
to extract data from 'C', I think the output parameter shouldn't be freely
chosen.
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
With this change, I can express the type constraint as follows:
impl<C, P> Template<C> for FormattablePropertyTemplate<P>
where
P: TemplateProperty<C>,
P::Output: Template<()>,
2023-01-23 06:26:27 +00:00
|
|
|
impl TemplateProperty<Commit> for EmptyProperty<'_> {
|
|
|
|
type Output = bool;
|
|
|
|
|
|
|
|
fn extract(&self, context: &Commit) -> Self::Output {
|
2023-01-14 10:43:23 +00:00
|
|
|
context.tree().id() == merge_commit_trees(self.repo, &context.parents()).id()
|
|
|
|
}
|
|
|
|
}
|