Now it's ready to split template_parser/templater into base template functions
and "commit" templater. I think Signature and Timestamp are basic types, so
they aren't moved to CommitTemplatePropertyKind. Perhaps, a duration type from
OpTemplate will also be added to CoreTemplatePropertyKind.
The idea is that a derived language will do wrap_<core_type>() as
DerivedProperty::Core(CoreProperty::<Type>(property)). This could be dealt
with some From<CoreProperty> trait impls, but the resulting code looked
a mess, and compile errors would be cryptic. I think this is somewhat similar
to serde::Serializer API.
I also rejected the idea of abstracting property types over Box<dyn>. Maybe
it's okay for method dispatching and extraction of some basic types, but it
wouldn't work if we want to implement comparison operators for any compatible
types.
wrap_commit_or_change_id() and wrap_shortest_id_prefix() will be moved to
the CommitTemplateLanguage. I'll add impl_wrap_fns() macro after splitting
the modules.
The "core" template parser wouldn't know how to dispatch property of types
added by a derived language. For example, CommitOrChangeId/ShortestIdPrefix
will be moved to the "commit" templater.
This trait will provide ways to dispatch keyword/method nodes, and wrap
TemplateProperty object with a dedicated "Property" enum.
build_keyword() and context parameter "I"/"C" have been migrated to it.
The function only needs the `TreeValue` so it makes more sense this
way, I think. That will also let the caller keep the rest of the
`Conflict` value owned (though there is nothing but the `value` field
in it right now).
It took a while before I realized that conflicts could be modeled as
simple algebraic expressions with positive and negative terms (they
were modeled as recursive 3-way conflicts initially). We've been
thinking of them that way for a while now, so let's make the
`ConflictPart` name match that model.
When we materialize modify/delete conflicts, we currently don't
include any context lines. That's because modify/delete conflicts have
only two sides, so there's no common base to compare to. Hunks that
are unchanged on the "modify" side are therefore not considered
conflicting, and since they they don't contribute new changes, they're
simply skipped (here:
3dfedf5814/lib/src/files.rs (L228-L230)).
It seems more useful to instead pretend that the missing side is an
empty file. That way we'll get a conflict in the entire file.
We can still decide later to make e.g. `jj resolve` prompt the user on
modify/delete conflicts just like `hg resolve` does (or maybe it
actually happens earlier there, I don't remember).
Closes#1244.
If I understand correctly, the 'revset lifetimes on `Box<dyn
Revset<'index> + 'revset>` are not constrained by the lifetime of a
revset; we don't have any revsets that borrow data from other
revsets. Instead, they're all about constraining a boxed revset to the
index's lifetime. Without the lifetime annotation, it would default to
'static, and the borrow-checker doesn't like `dyn Revset<'index> +
'static`, since the revset could then live longer than the index it
borrows.
The 0.7.0 release build failed because it didn't find OpenSSL. I don't
know much about musl, but I think we added it in order to get a single
binary without dependencies, so I think vendoring is what we want.
It's been about 10 weeks and 730 commits since 0.6.0, compared to
about 7 weeks and 350 commits between 0.5.0 and 0.6.0, so it's time
for a new release. There's been significant user-visible changes and
code-quality improvements. Thanks, everyone!
Now that we use headers to define `[template-aliases]`, I thought we should explain how they are also equivalent to dotted keys.
Alternatively, we could rewrite them all in the dotted style, but it would look awkward.
This is just a little preparation for extracting a `Repo` trait that's
implemented by both `ReadonlyRepo` and `MutableRepo`. The `index()`
function in that trait will of course have to return the same type in
both implementations, and that type will be `&dyn Index`.
I'm going to remove the corresponding config knobs.
As an example of "brackets" short id, I put a simplified version. It's
unlikely that the "rest()" gets empty for hashes of 12-char long.
It turned out bad idea because EPIPE (or SIGPIPE) is kind of a successful
termination. We could show some warning based on pager exit code, but let's
avoid messing up again.
io::Error occurred in handle_command_result() is still mapped to a BrokenPipe.
panic()-ing there should be wrong.
`jj log | head` consistently prints "Error: Broken pipe" for me. I
don't know how the output gets printed after the pipe has been closed,
but neither `git` nor `hg` prints an error, so I think we shouldn't
either.