Add home directory expansion for SSH key filepaths. This allows the
`signing.key` configuration value to work more universally across both
Linux and macOS without requiring an absolute path.
This moved and renamed the previous `expand_git_path` function to a more
generic location, and the prior use was updated accordingly.
Author dates and committer dates can be filtered like so:
committer_date(before:"1 hour ago") # more than 1 hour ago
committer_date(after:"1 hour ago") # 1 hour ago or less
A date range can be created by combining revsets. For example, to see any
revisions committed yesterday:
committer_date(after:"yesterday") & committer_date(before:"today")
The high level changes include:
- Reworking `fix_file_ids()` to loop over multiple candidate tools per file,
piping file content between them. Only the final file content is written to
the store, and content is no longer read for changed files that don't match
any of the configured patterns.
- New struct `ToolsConfig` to represent the parsed/validated configuration.
- New function `get_tools_config()` to create a `ToolsConfig` from a `Config`.
- New tests; the only old behavior that has changed is that we don't require
`fix.tool-command` if `fix.tools` defines one or more tools. The general
approach to validating the config is to fail early if anything is weird.
Co-Authored-By: Josh Steadmon <steadmon@google.com>
This implements a building block of "signed-off-by line" #1399 and "commit
--verbose" #1946. We'll probably need an easy way to customize the diff part,
but I'm not sure if it can be as simple as a template alias function. User
might want to embed diffs without "JJ: " prefixes?
Perhaps, we can deprecate "ui.default-description", but it's not addressed in
this patch. It could be replaced with "default_description" template alias,
but we might want to configure default per command. Suppose we add a default
"backout_description" template, it would have to be rendered against the
source commit, not the newly-created backout commit.
The template key is named as "draft_commit_description" because it is the
template to generate an editor template. "templates.commit_description_template"
sounds a bit odd.
There's one minor behavior change: the default description is now terminated
by "\n".
Closes#1354
The user can define the setting `git.private-commits` as they desire. For
example:
git.private-commits = 'description(glob:"wip:*")'
If any commits are in this revset, then the push is aborted.
If a commit would be private but already exists on the remote, then it does
not block pushes, nor do its descendents block pushes unless they are also
contained in `git.private-commits`.
Closes#3376
It's inconvenient that we have to quote glob patterns as 'glob:"*.rs"'. Suppose
filesets are usually specified in shell, it's better to allow unquoted strings
if possible. This change also means we'll probably abandon #2101 "make the
parsing of string arguments stricter."
Note that we can no longer introduce ? operator or [] subscript syntax in
filesets.
Closes#4053
The text pattern is applied prior to comparison as we do in Mercurial. This
might affect hunk selection, but is much faster than computing diff of full
file contents. For example, the following hunk wouldn't be caught by
diff_contains("a") because the line "b\n" is filtered out:
- a
b
+ a
Closes#2933
This patch adds TreeDiff template type to host formatting options. The main
reason of this API design is that diff formats have various incompatible
parameters, so a single .diff(files, format[, options..]) method would become
messy pretty quickly. Another reason is that we can probably add custom
summary templating support as diff.files().map(|file| file.path()..).
RepoPathUiConverter is passed to templater explicitly because the one stored
in RevsetParseContext is behind Option<_>.
Since fileset and revset languages are syntactically close, we can reparse
revset expression as a fileset. This might sound a bit scary, but helps
eliminate nested quoting like file("~glob:'*.rs'"). One oddity exists in alias
substitution, though. Another possible problem is that we'll need to add fake
operator parsing rules if we introduce incompatibility in fileset, or want to
embed revset expressions in a fileset.
Since "file(x, y)" is equivalent to "file(x|y)", the former will be deprecated.
I'll probably add a mechanism to collect warnings during parsing.
I used to use "remote_branches() & ~mine()" to exclude "their" branches from
the default log, and I don't think that's uncommon requirement. Suppose
untracked branches are usually read-only, it's probably okay to make them
immutable by default.
Adds support for revset functions `tracked_remote_branches()` and
`untracked_remote_branches()`. I think this would be especially useful
for configuring `immutable_heads()` because rewriting untracked remote
branches usually wouldn't be desirable (since it wouldn't update the
remote branch). It also makes it easy to hide branches that you don't
care about from the log, since you could hide untracked branches and
then only track branches that you care about.
Partially resolve a 1.5‐year‐old TODO comment.
Add opt‐in syntax for case‐insensitive matching, suffixing the
pattern kind with `-i`. Not every context supports case‐insensitive
patterns (e.g. Git branch fetch settings). It may make sense to make
this the default in at least some contexts (e.g. the commit signature
and description revsets), but it would require some thought to avoid
more confusing context‐sensitivity.
Make `mine()` match case‐insensitively unconditionally, since email
addresses are conventionally case‐insensitive and it doesn’t take
a pattern anyway.
This currently only handles ASCII case folding, due to the complexities
of case‐insensitive Unicode comparison and the `glob` crate’s lack
of support for it. This is unlikely to matter for email addresses,
which very rarely contain non‐ASCII characters, but is unfortunate
for names and descriptions. However, the current matching behaviour is
already seriously deficient for non‐ASCII text due to the lack of any
normalization, so this hopefully shouldn’t be a blocker to adding the
interface. An expository comment has been left in the code for anyone
who wants to try and address this (perhaps a future version of myself).
The output looks somewhat similar to color-words diffs. Unified diffs are
verbose, but are easier to follow if adjacent lines are added/removed + modified
for example.
Word-level diffing is forcibly enabled. We can also add a config knob (or
!color condition) to turn it off to save CPU time.
I originally considered disabling highlights in block insertion/deletion, but
that wasn't always great. This can be addressed separately as it also applies
to color-words diffs. #3958
The default style is compatible with various terminal emulators, but I suspect
that many people wouldn't like underlines. Let's add an example to override it.
This adds the basic outline of _when_ a Design Doc should be written. See the next
commit in the stack for the blueprint.
By adding this we hopefully can prevent unnecessary churn from new and longtime contributors,
when they want to add a major feature or rewrite a core part of Jujutsu. The text is written
as a guideline, not a rule.
- make an internal set of watchman extensions until the client api gets
updates with triggers
- add a config option to enable using triggers in watchman
Co-authored-by: Waleed Khan <me@waleedkhan.name>
There's been a lot of questions about the subtle differences between
`..` and `::`. I hope these examples will help with that.
We should also add examples to the revset functions (e.g. `heads()` is
not obvious how it works), but that can come later.
`..` is shorthand for `root()..visible_head()`, for example. We don't
seem to explain that anywhere. I hope mentioning that will help
readers understand the relationship between the shorthands and the
full `x..y`, and also to see the correspondence between `..` and `::`
(in how their default left and right operands are the same).
I am currently not aware of any severe differences between the generated
markdown and `jj help`, though this could change if we look over the
text carefully or if we start using `clap` features we weren't using
before.
Still alias function shadows builtin function (of any arity) by name. This
allows to detect argument error as such, but might be a bit inconvenient if
user wants to overload heads() for example. If needed, maybe we can add some
config/revset syntax to import builtin function to alias namespace.
The functions table is keyed by name, not by (name, arity) pair. That's mainly
because std collections require keys to be Borrow, and a pair of borrowed
values is incompatible with owned pair. Another reason is it makes easy to look
up overloads by name.
Alias overloading could also be achieved by adding default parameters, but that
will complicate the implementation a bit more, and can't prevent shadowing of
0-ary immutable_heads().
Closes#2966
I just added "can be empty" since it seems obvious when it becomes empty if it
can be empty. AFAICT, the confusion in #3821 is whether or not "no parents"
falls back to root().
We can add a separate precedence/associativity table, but I think the ordered
list is good enough. Nullary :: and .. have no binding, but inserted after the
infix versions for brevity.
On Windows `code` works in the shell, but not when specified to jj, because the
executable is actually named `code.cmd`! This is a feature of Windows, where
certain file extensions (defined by the PATHEXT environment variable) are
automatically treated as executable and can have their extensions omitted.
Presumably, jj doesn't support this feature on Windows, though perhaps it
should. For now, avoid adding an explanation of PATHEXT so as to not clutter
things too much, and just suggest `code.cmd` on Windows. Most readers should be
able to put two and two together from there.
I feel like recommending people install Poetry via a package manager was
a mistake. Poetry only supports its latest version, and while newer
versions are sort-of backward-compatible, they print warnings in
different situations and have different bugs. Installing `pipx` via a
package manager, OTOH, works fine, and its older versions work fine.
Using Poetry 1.8+ allows us to use Poetry's new "non-package" mode,
which would no longer print warnings if the user does `poetry install`
instead of `poetry install --no-root`. It's likely that in newer
versions of Poetry, it will become an error.
I add them as aliases, since a user may instead choose to define `immutable_heads()`, for example, as `heads(immutable())`, and the define `immutable()` instead.
This revset correctly implements "reachability" from a set of source commits following both parent and child edges as far as they can go within a domain set. This type of 'bfs' query is currently impossible to express with existing revset functions.
When using `ui.color = "debug"`, changes in the output style
additionally include delimiters << and >>, as well as all active labels
at this point separated by ::. The output is otherwise unformatted and
the delimiters and labels inherit the style of the content they apply
to.
More tests will be added later as "branch list" templates.
In "log" template, we might want to see the number of "local" commits ahead
of any tracked remotes. It can be implemented later in a similar way (or as a
nested remote_refs list.)
We'll probably add binary comparison operators at some point, but this patch
also adds size_hint.zero() method. Otherwise, we'll have to write
"if(x.upper() && x.upper() == 0, ..)" to deal with None.
The resulting "branch list" template will look like:
```
separate(", ",
if(!ref.tracking_ahead_count().zero(),
if(ref.tracking_ahead_count().exact(),
"ahead by " ++ ref.tracking_ahead_count().exact() ++ " commits",
"ahead by at least " ++ ref.tracking_ahead_count().lower() ++ " commits")),
if(!ref.tracking_behind_count().zero(),
if(ref.tracking_behind_count().exact(),
"behind by " ++ ref.tracking_behind_count().exact() ++ " commits",
"behind by at least " ++ ref.tracking_behind_count().lower() ++ " commits")),
)
```
This is instead of https://github.com/martinvonz/jj/pull/3292, which would make
`diffedit3` built into `jj`. I still have some hope of eventually making
`diffedit3` into the default diff editor that is available without any
configuration, which probably requires building it into `jj`, but this may not
happen, and it wouldn't hurt to test `diffedit3` first. Some examples of
concerns (see also the discussion in that PR):
- It is only a guess on my part that this would make a good default. The editor
might not be polished enough, and most users are not used to 3-pane diff
editing. I think most users would like it if they tried it, but this might be
plain wrong.
- There are concerns about adding a heavyweight dependency on `jj`. While I
tried to make it as lightweight as possible, it still unavoidably includes a web
server.
- There may be ways to bundle `diffedit3` with `jj` without combining them in a
single binary.
I wanted to have a reference point for the built-in revsets,
but `jj config get revsets.log` doesn't turn anything up since
it has special handling for the legacy config key
`ui.default-revset`. So I had to dig into the source code of jj
to get it.
I think it might help others to be able to reason about revsets
to have the log default shown in the settings documentation.
I considered adding RefTarget template type, but some of the methods naturally
fit to RefName. For example, a conflicted branch name is decorated as "??", so
it makes sense to add branch.conflict() instead of branch.target().conflict().
I'm not pretty sure how many RefName methods we'll need to add to port the
current branch listing, but there will be .tracked(), .tracking_local_present(),
.ahead_by(), and .behind_by().
Since fileset/revset/template expressions are specified as command-line
arguments, it's sometimes convenient to use single quotes instead of double
quotes. Various scripting languages parse single-quoted strings in various ways,
but I choose the TOML rule because it's simple and practically useful. TOML is
our config language, so copying the TOML syntax would be less surprising than
borrowing it from another language.
https://github.com/toml-lang/toml/issues/188
While I like strict parsing, it's not uncommon that we have to deal with file
names containing spaces, and doubly-quoted strings such as '"Foo Bar"' look
ugly. So, this patch adds an exception that accepts top-level bare strings.
This parsing rule is specific to command arguments, and won't be enabled when
loading fileset aliases.
Mercurial appears to resolve cwd-relative path first, so "glob:*.c" could be
parsed as "**/*.c" if cwd was literally "**". It wouldn't practically matter,
but isn't correct. Instead, jj's parser first splits glob into literal part
and pattern. That's mainly because we want to parse the user input texts into
type-safe objects, and (RepoPathBuf, glob::Pattern) pairs are the simplest
ones. The current parser can't handle patterns like "foo/*/.." (= "foo" ?),
and errors out. I believe this restriction is acceptable.
Unlike literal paths, the 'glob:' pattern anchors to the whole file path. I
don't think "prefix"-matching glob is useful, and making it the default would
be rather confusing.
The Pijul maintainer has opinions that I don't understand about how we
mention Pijul (they consider the current mentions offensive as
"bashing Pijul"). Let's just remove the references so we don't have to
deal with it. I think the references to Darcs we already had in most
of these places are sufficient.
If this doesn't work out, maybe we can try one of these:
a. fall back to bare file name if expression doesn't contain any operator-like
characters (e.g. "f(x" is an error, but "f x" can be parsed as bare string)
b. introduce command-line flag to opt in (e.g. -e FILESET)
c. introduce pattern prefix to opt in (e.g. set:FILESET)
Closes#3239, #2915, #2286
This command checks not only whether Watchman works, but also whether
it's enabled in the config. Also, the output is easier to understand
than that of the other `jj debug watchman` commands.
It would be nice if `jj debug watchman` called `jj debug watchman
status`, but it's not trivial in `clap` to have a default subcommand.
Expose the information we now record, to allow changing the default "snapshot
working copy" message or to make snapshots more compact/less distracting in
the log
There are no more callers of parse_function_argument_to_string(), so it's
removed. This function was a thin wrapper of literal parser, and can be
easily reintroduced if needed.
This lets users use "large" revsets in commands such as `jj rebase`, without
needing the `all:` modifier.
Signed-off-by: Austin Seipp <aseipp@pobox.com>
Change-Id: Ica80927324f3d634413d3cc79fbc73057ccefd8a
This can be used to flatten nested "if()"s. It's not exactly the same as "case"
or "switch" expression, but works reasonably well in template. It's not uncommon
to show placeholder text in place of an empty content, and a nullish value
(e.g. empty string, list, option) is usually rendered as an empty text.
I think Option<Commit> is the simplest encoding of the log node.
The behavior of an Option type is closer to nullable types rather than the
Option in Rust. I don't think we would want to write opt.map(|x| x.f()) or
opt.unwrap().f(). We can of course add opt?.f() syntax, but it will be a short
for "if(opt, opt.f())"?
As discussed in #2900, the milliseconds are rarely useful, and it can
be confusing with different timezones because it makes harder to
compare timestamps.
I added an environment variable to control the timestamp in a
cross-platform way. I didn't document because it exists only for tests
(like `JJ_RANDOMNESS_SEED`).
Closes#2900
`jj rebase -r C -d A; rebase -s B -d C` is missing the second jj.
Although it would be cool if jj had syntax to chain commands like this, so I could write a "swap" alias.
Changes the formatter to accept not only existing color names (such as "red" or
"green") but also those in the form #rrggbb, where rr, gg, and bb are two-digit
hexadecimal numbers. This allows much finer control over colors used.
In the FAQ question "How do I integrate Jujutsu with Gerrit?", the link
to the glossary entry for "co-located repos" was pointing to the entry
for "change-id".
The `amend/unamend` aliases exist for smoothen onboarding for
Git/Mercurial users; I don't think we should recommend that users use
them, so I think it's fine if users override them as they
like. Therefore, I think they belong in the config.
There was a question on Discord about why using Difftastic wasn't working as the
diff tool. The root cause was putting `ui.diff.tool` in the wrong toml section,
when the `ui.` component actually refers to the `[ui]` section itself.
This reads kind of weirdly too because _immediately_ after this, the alternative
option of using the `merge-tools` section is suggested; except it uses `[merge-
tools.<name>]` which makes it immediately clear it's a section on its own.
This simply these two examples more consistent with each other, by using `[ui]`
instead of `ui.` to make it clear `ui.` is a top-level section.
Signed-off-by: Austin Seipp <aseipp@pobox.com>
This is something which should've been written down long ago. This is a follow-up upon
another question from Julia Evans in Discord.
Thank you again for asking such good questions.
I'm going to add string.len() method which will return a length in bytes. The
number of the UTF-8 code points is useless metrics, and strings here are often
ASCII bytes, so let's simply use byte indices in substr().
If the given index is not at a char boundary, it will be rounded. I considered
making it an error, but that would be annoying. I would want to see something
printed by author.name().substr() even if it contained latin characters.
I've extracted index normalization function which might be used by other string
methods. The remaining part of substr() is trivial, so inlined it.
Add an option to list tracked branches only
This option keeps most of the current `--all` printing logic, but:
- Omits local Git-tracking branches by default (can be extended to
support filtering by remote).
- Skip over the branch altogether if it doesn't contain tracked remotes
- Don't print the untracked_remote_refs at the end
Usage:
`jj branch list -t`
`jj branch list --tracked`
`jj branch list --tracked <branch name>`
Show our positive reviews to the world. It's also not completly serious, in a similar fashion to
Phabricator.
Co-Authored-By: Austin Seipp <aseipp@pobox.com>
This allows us to call alias function with the top-level object.
For convenience, all self.<method>()s are available as keywords. I don't think
we'll want to deprecate them. It would be tedious if we had to specify
-T'self.commit_id()' instead of -Tcommit_id.
The legacy parsing rules are turned into compatibility errors. The x:y rule
is temporarily enabled when parsing string patterns. It's weird, but we can't
isolate the parsing function because a string pattern may be defined in an
alias.
The main goal is to avoid having a symlink in our source tree. Currently, there
is no good way to work with the `jj` repo with `jj` on Windows. Currently `jj`
just crashes with symlinks. This is being worked on, see e.g. #2939, but it will
always depend on whether Developer Mode is enabled in Windows or whether
symlinks are materialized as text files with symlinks. Finally, MkDocs has
trouble following symlinks on Windows, so building docs wouldn't work there.
Another advantage is that, previously, we were lucky that MkDocs treats `insta`
header in `cli-reference@.md.snap` as a Markdown header and follows symlinks at
all. Now, we no longer depend on that.
i did the following things:
1. make some changes to the working copy
2. run `jj commit`
3. before i added a description, i decided i didn't want to commit yet. in git, the way to do this is to delete the contents of the editor; git sees that it is blank and aborts the commit. in jj, this doesn't work, because descriptions are allowed to be empty.
now i have the following jj state:
```
; jj log --stat
@ pokrsyvs github@jyn.dev 2024-02-06 21:48:17.000 -05:00 ddd6217f
│ (empty) (no description set)
│ 0 files changed, 0 insertions(+), 0 deletions(-)
◉ lqqmzmku github@jyn.dev 2024-02-06 21:48:02.000 -05:00 HEAD@git b03bf3de
│ (no description set)
│ config/jj.toml | 2 +-
│ 1 file changed, 1 insertion(+), 1 deletion(-)
◉ xqkmwvwp github@jyn.dev 2024-02-06 21:47:08.000 -05:00 master b673f97b
```
i want to undo the most recent commit, `lqqmzmku`. i'm used to doing this with `git reset --soft HEAD~`, which makes the parent `xqkmwvwp` and leaves the change to `config/jj.toml` on disk while removing it from the git history; basically `lqqmzmku` would go back to being the working copy.
i found that `jj move` does what i want, but it took a lot of trawling the options, it wasn't obvious, and i couldn't find `git reset` mentioned in the docs.
Follows up 9702a425e5 "Allow negative numbers in the template grammar."
Since we've added parsing rules for operator expressions, it makes sense to
parse unary '-' as operator.
I enabled automerge for #2994, but forgot to actually *push* my changes
before resolving all the conversations, so GitHub insta-merged it.
This just addresses Ilya and Philip's final comments on #2994.
Signed-off-by: Austin Seipp <aseipp@pobox.com>
Someone on Discord asked this exact question, but these options apparently
weren't documented when they were added in the `0.7.0` release.
Signed-off-by: Austin Seipp <aseipp@pobox.com>
We want to avoid conflicts of interest (both real and
apparent). Better to document this before it happens.
By the way, Ilya and I both work for Google and we have approved lots
of each others' PRs, but we work in very different parts of the
company and I don't think any of the PRs have been specific to
Google's interests.
I'll probably add infix logical operators later, but the surround() function
is still useful because we don't have to repeat the condition:
if(x || y, "<" ++ separate(" ", x, y) ++ ">")
surround("<", ">", separate(" ", x, y))
It can't be used if we want to add placeholder text, though:
if(x || y, "<" ++ separate(" ", x, y) ++ ">", "(none)")
Closes#2924