When I recently changed the working copy to not have a commit ID
(e098c01935), I lost the check in `update_working_copy()` in
`commands.rs` that made us not print "Working copy now at: " if the
commit was unchanged. Now we always print, which is unnecessary and
confusing (it makes it seem like the commit changed even if it
didn't). Let's restore the check.
It can be useful in command prompts and scripts to be able to quickly
get e.g. the `jj status` output without spending time committing the
working copy (perhaps because some background process continuously
commits the working copy). One can already do that by passing
`--at-op=<operation ID>`, but then one needs to look up the operation
ID first. That is both extra work for the user/script and it means
there's an extra `jj op log` invocation to get the operation ID. Let's
have a global flag to make it easy and efficient to do.
When running in a working copy collocated with git's, we export the
working copy's commit's parent to git after every command. However, we
forgot to update our own record of git's HEAD. That means that on
subsequent imports from git, it'll look like the user had updated HEAD
using a git command. When we detect that, we trust that the user had
taken care of the changes in the working copy and we simply abandon
our old working copy commit. That led to the bug reported in $54,
where the second commit of a `jj split` got lost.
The fix is to also update our record of where git's HEAD is when we
tell git to update it.
Closes#54.
We no longer need the commit ID, so we shouldn't make the callers pass
it. This lets us simplify several tests, because they no longer to
create commits just to check out a tree in the working copy.
We used to use the value to detect races, but we use the tree ID and
the operation ID these days, so we don't need the commit ID.
By changing this, we can avoid creating some commit IDs in tests,
which is why I tackled this issue now.
There are only two callers of `LockedWorkingCopy::check_out()`. One is
in `commands.rs`. That caller already checks after taking the lock
that the old commit ID is as expected. The other caller is
`WorkingCopy::check_out()`. We can simply move the check to that level
since it's the only caller that cares now.
A few commands (`restore`, `diff`, and `untrack` so far) accept path
arguments, but they only support files. Let's make them work with
directories too.
It's harmless but potentially confusing to have multiple workspaces
with the same ID (it would mean that they always have the same
checkout). Let's just prevent it for now. We can add an override later
if people think of usecases for it.
When you run `jj co abc123` and that commit is already checked out, we
just print a message. The condition for that assumed that the checkout
existed, which it won't if you just ran `jj workspace forget`. Let's
avoid that crash, especially since `jj co` is an easy way to restore
the working copy if you had accidentally run `jj workspace forget`
(though `jj undo` is even easier).
It seems helpful to show in the log output which commit is checked out
in which workspace, so let's try that. I made it only show the
information if there are multiple checkouts for now.
In workspaces added after the initial one, the idea is to have
`.jj/repo` be a file whose contents is a path to the location of the
repo directory in some other workspace.
Because we record each workspace's checkout in the repo view, we can
-- unlike other VCSs -- let the user refer to any workspace's checkout
in revsets. This patch adds syntax for that, so you can show the
contents of the checkout in workspace "foo" with `jj show foo@`. That
won't automatically commit that workspace's working copy, however.
If the workspace is shared with a Git repo, we sometimes update Git's
HEAD ref. We should get the new checkout from the right workspace ID
when doing that (though I'm not sure we'll ever support sharing the
working copy with Git in a non-default workspace).
When importing Git HEAD, we already use the right workspace ID for the
new checkout, but the old checkout we abandon is always the default
workspace's. We should fix that even if we will never support sharing
a working copy with Git in a non-default workspace.
Before committing the working copy, we check if the working copy is
checked out to the commit we expect based on the repo's view. We
always use the default workspace's checkout, so we need to fix that.
We detect concurrent working copy changes by checking that the old
commit matches the repo's view. We should use the current workspace
when looking up the checkout in the view.
This adds a `jj move [--from <rev>] [--to <rev>] [-i]` command, which
lets you move some changes from one commit into another. `jj
squash/amend` is just a special case of this new command. Except for
that command's more specialized help text, instructions, etc., it
could be implemented as simply `jj move --to @-`.
I thought it was a bit unclear which part of the process was
interactive (it's only choosing parts of the diffs that is
interactive, not choosing destination or anything else).
We allow rebasing to a descendant, but that causes divergence because
the old commit remains visible. You could imagine making it work so
`jj rebase -r B -d D` on a linear chain "A-B-C-D" reorders it to
"A-C-D-B", but we don't do that yet, so let's just prevent the
divergence for now.