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
Summary: As discussed in Discord, on GitHub, and elsewhere, this change
deprecates the use of `jj checkout` and suggests users use `jj new` exclusively
instead. The verb `checkout` is a relic of a bygone era the — days of RCS
file locking, before 3-way merge — and is not a good, fitting name for the
functionality it provides.
To further drive the bit home, by default, `jj checkout` (and `jj co`) is now
hidden. This will hopefully stop new users from running into it.
Signed-off-by: Austin Seipp <aseipp@pobox.com>
Change-Id: I7a1adfc9168fce1f25cf5d4c4c313304769e41a1
I couldn't come up with a Git analogue of `jj log`, but I think it's OK
leaving it as a TODO makes the point. Perhaps somebody can figure it
out.
Also, all the correspondences are not completely precise, so I didn't
emphasize it every single time.
I am using a very hacky approach, using `insta` to generate the markdown help.
This is based on a lucky coincidence that `insta` chose to use a header
format for snapshot files that MkDocs interprets as a Markdown header (and
ignores).
I considered several other approaches, but I couldn't resist the facts that:
- This doesn't require new developers to install any extra tools or run any
extra commands.
- There is no need for a new CI check.
- There is no need to compile `jj` in the "Make HTML docs" GitHub action,
which is currently very fast and cheap.
Downside: I'm not sure how well MkDocs will work on Windows, unless the
developer explicitly enables symbolic links (which IIUC is not trivial).
### Possible alternatives
My next favorite approaches (which we could switch to later) would be:
#### `xtask`
Set up a CI check and a [Cargo `xtask`] so that `cargo xtask cli-help-to-md`
essentially runs `cargo run -- util markdown-help > docs/cli-reference.md` from
the project root.
Every developer would have to know to run `cargo xtask cli-help-to-md` if
they change the help text.
Eventually, we could have `cargo xtask preflight` that runs `cargo +nightly
fmt; cargo xtask cli-help-to-md; cargo nextest run`, or `cargo insta`.
#### Only generate markdown for CLI help when building the website, don't track it in Git.
I think that having the file in the repo will be nice to preview changes to
docs, and it'll allow people to consult the file on GitHub or in their repo.
The (currently) very fast job of building the website would now require
installing Rust and building `jj`.
#### Same as the `xtask`, but use a shell script instead of an `xtask`
An `xtask` might seem like overkill, since it's Rust instead of a shell script.
However, I don't want this to be a shell script so that new contributors on
Windows can still easily run it ( since this will be necessary for the CI to
pass) without us having to support a batch file.
#### Cargo Alias
My first attempt was to set up a [cargo alias] to run this, but that doesn't
support redirection (so I had to change the `jj util` command to output to a
file) and, worse, is incapable of executing the command *in the project root*
regardless of where in the project the current directory is. Again, this seems
to be too inconvenient for a command that every new PR author would have to run
to pass CI.
Overall, this just seems a bit ugly. I did file
https://github.com/rust-lang/cargo/issues/13348, I'm not really sure that was
worthwhile, though.
**Aside:** For reference, the alias was:
```toml
# .cargo/config.toml
alias.gen-cli-reference = "run -p jj-cli -- util markdown-help docs/cli-reference.md"
```
### Non-alternatives
#### Clap's new feature
`clap` recently obtained a similarly-sounding feature in
https://github.com/clap-rs/clap/pull/5206. However, it only prints short help
for subcommands and can't be triggered by an option AFAICT, so it won't help us
too much.
[Cargo `xtask`]: https://github.com/matklad/cargo-xtask
[cargo alias]: https://doc.rust-lang.org/cargo/reference/config.html#alias
This follows up on #2625 and updates all sections of `branches.md` to represent
the new default of `git.auto-local-branch=false`.
I realized that the paragraph we discussed for so long with @PhilipMetzger
actually repeats information that was already present a bit earlier in the file.
So, I removed most of it and moved the rest. Sorry I didn't notice this earler.
## The callout
Unfortunately, GitHub and MkDocs use different syntax for admonitions.
The callout looks like this in MkDocs:
https://github.com/martinvonz/jj/assets/4123047/45d79e7a-35db-492e-a227-004b7e3383c1
Use `poetry run -- mkdocs serve` to double-check.
Wol on lwn.net pointed out that our current description in the Git
Comparison doc for why there is no staging area can be interpreted as
saying that it's because it simplifies the CLI. It took me a while to
see that interpretation, but it makes sense to me now. This patch
tries to clarify that we have better tools than the staging area for
manipulating commits.
On my machine, this halves the time taken by `cargo insta test --workspace
--test-runner nextest`.
I don't believe there would be a worthwhile improvement when not
using `nextest`. I also documented how to tell whether using `mold`
is worthwhile.
I was reminded of this by https://github.com/martinvonz/jj/pull/2858.
Sadly, ripgrep won't honor the .gitignore files in the absence of a
.git directory, so we need to pass an annoying flag (for non-colocated
repos).
That seems worth adding despite the existing suggestion, because rg is
faster, and for existing users for rg, it would teach them how to make
rg work as expected.
A possible use case is when doing some archaeology around a certain operation.
The current implementation is quadratic if + is repeated. Suppose op_id is
usually close to the current op heads, I think it'll practically work better
than building a reverse lookup table.
This question is mildly popular on Discord so it's finally time to have an answer.
We should do something better in the future but the current solution is good enough for today.
cc @thoughtpolice
As far as I can see in the chat, there's no objection to changing the default,
and git.auto-local-branch = false is generally preferred.
docs/branches.md isn't updated as it would otherwise conflict with #2625. I
think the "Remotes" section will need a non-trivial rewrite.
#1136, #1862
I originally thought this would be unavoidable, but I was wrong. "jj git clone"
doesn't implicitly create any local branch if git.auto-local-branch is off, and
that's fine because the detached HEAD state is normal in jj.
That being said, Git users would expect that the main/master branch exists.
Since importing the default branch is harmless, let's create and track it no
matter if git.auto-local-branch is off.
This adds an initial `jj util gc` command, which simply calls `git gc`
when using the Git backend. That should already be useful in
non-colocated repos because it's not obvious how to GC (repack) such
repos. In my own jj repo, it shrunk `.jj/repo/store/` from 2.4 GiB to
780 MiB, and `jj log --ignore-working-copy` was sped up from 157 ms to
86 ms.
I haven't added any tests because the functionality depends on having
`git` binary on the PATH, which we don't yet depend on anywhere
else. I think we'll still be able to test much of the future parts of
garbage collection without a `git` binary because the interesting
parts are about manipulating the Git repo before calling `git gc` on
it.
As discussed in Discord, it's less useful if remote_branches() included
Git-tracking branches. Users wouldn't consider the backing Git repo as
a remote.
We could allow explicit 'remote_branches(remote=exact:"git")' query by changing
the default remote pattern to something like 'remote=~exact:"git"'. I don't
know which will be better overall, but we don't have support for negative
patterns anyway.
This adds two MkDocs extensions to make list handling more flexible.
It took some trial-and-error, but it seems this config works OK.
revsets.md: use saner formatting that is now possible.
sapling-comparison.md: this was the one case I saw made worse by the
new plugins. I changed the Markdown formatting, it still looks sane.
Both local and remote refs are backed by the same value type since we'll need
some kind of runtime abstraction to represent "branches" keyword (which is a
list of local + remote branches.) It's tedious to implement separate
local/remote/both ref types.
The "unsynced" flag is inverted just because the positive term is slightly
easier to document.
I'm going to change "branches" to return a list instead of formatted string,
and I don't think "if(branches, ..)" should be invalidated by that. Perhaps,
a container type like String, Vec<T>, Option<T> can implement the cast.
Thanks to @glencbz for noticing that VS Code works fine now as a
merge tool, and thanks to @solson for suggesting
`merge-tool-edits-conflict-markers = true`.
Although this is logically correct, the error message is a bit cryptic. It's
probably better to reject push if non-tracking remote branches exist.
#1136
This means that the commits previously pinned by remote branches are no longer
abandoned. I think that's more correct since "push" is the operation to
propagate local view to remote, and uninteresting commits should have been
locally abandoned.
This patch adds MutableRepo::track_remote_branch() as we'll probably need to
track the default branch on "jj git clone". untrack_remote_branch() is also
added for consistency.
The original idea was to completely replace git_refs with remotes["git"] by
introducing "forgotten" state, but it turned out to break "fetch && undo"
scenario. There are other ways around, but they also have problems:
* Sets tombstone on forgotten/deleted remote refs, exports remote refs without
comparing to the known refs.
* `jj undo` would need to insert tombstone by diffing old/new views.
* `jj branch forget` would need to preserve the @git branch whereas the other
remote branches would be forgotten.
* Always overwrites remote refs on export.
* `jj git export` without importing would discard remote refs.
So, I decided to not remove git_refs. Apparently, it also improves the undo
behavior. In the new model, `jj git fetch && jj undo && jj git fetch` works
even if git_refs isn't rolled back. So we can unify the default of
`jj undo --what`.
This adds a new `revset-aliases.immutable_heads()s` config for
defining the set of immutable commits. The set is defined as the
configured revset, as well as its ancestors, and the root commit
commit (even if the configured set is empty).
This patch also adds enforcement of the config where we already had
checks preventing rewrite of the root commit. The working-copy commit
is implicitly assumed to be writable in most cases. Specifically, we
won't prevent amending the working copy even if the user includes it
in the config but we do prevent `jj edit @` in that case. That seems
good enough to me. Maybe we should emit a warning when the working
copy is in the set of immutable commits.
Maybe we should add support for something more like [Mercurial's
phases](https://wiki.mercurial-scm.org/Phases), which is propagated on
push and pull. There's already some affordance for that in the view
object's `public_heads` field. However, this is simpler, especially
since we can't propagate the phase to Git remotes, and seems like a
good start. Also, it lets you say that commits authored by other users
are immutable, for example.
For now, the functionality is in the CLI library. I'm not sure if we
want to move it into the library crate. I'm leaning towards letting
library users do whatever they want without being restricted by
immutable commits. I do think we should move the functionality into a
future `ui-lib` or `ui-util` crate. That crate would have most of the
functionality in the current `cli_util` module (but in a
non-CLI-specific form).
We are a little weird about which string escapes we support, and we don't
support raw strings. I thought this might be worth documenting.
Inspired by https://github.com/martinvonz/jj/pull/2251
As suggested by @yuja in
https://github.com/martinvonz/jj/issues/1841#issuecomment-1720451152
Thanks to @lazywei for pointing out that `git pack-refs --all` is better, at
least on the first run. I haven't checked, but suspect, that because of the
number of `refs/jj` refs jj creates, it might always be better.
This is essentially a new version, which clarifies multiple statements about
`jj run`. Notably, it cleans up some mistakes which were overlooked or deemed
good enough in the Google Docs version.
This ticks another box in #1869.
Co-Authored-By: arxanas <me@waleedkhan.name>
Co-Authored-By: hooper <hooper@google.com>
Co-Authored-By: martinvonz <martinvonz@google.com>
https://github.com/martinvonz/jj/discussions/2230 indicates a lot of
interest in this, so we'd probably want to support this officially at
some point. Until then, document a script that has worked well-enough
for some of us.
I think the feature is requested by enough users that we should
include it by default, also for people who install from source (we
include it in the `packaging` feature already).
It increases the size of the binary from 16.5 MiB to 17.8 MiB. I
suspect we'd see some of that increase in size soon anyway, as I'm
probably going to use Tokio for making async backend requests.