Commit graph

1011 commits

Author SHA1 Message Date
Scott Taylor
2dd75b5c53 revset: add tracked/untracked_remote_branches()
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.
2024-07-13 10:43:21 -05:00
Tim Janik
11f56800fa test_gpg: fix warnings ending up on stdout
Signed-off-by: Tim Janik <timj@gnu.org>
2024-07-12 10:32:13 +09:00
Yuya Nishihara
415c831e30 revset: flatten union nodes in AST to save recursion stack
Maybe it'll also be good to keep RevsetExpression::Union(_) flattened, but
that's not needed to get around stack overflow. The constructed expression
tree is balanced.

test_expand_symbol_alias() is slightly adjusted since there are more than
one representation for "a|b|c" now.

Fixes #4031
2024-07-11 11:20:25 +09:00
Emily
93d76e5d8f str_util: support case‐insensitive string patterns
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).
2024-07-10 05:58:34 +01:00
Emily
a146145adb revset: fix mine() test comments 2024-07-10 05:58:34 +01:00
Emily
3567cba8c9 revset: fix email matching tests
The comments say “Can find a unique match by either name or email”,
but these weren’t checking for an email match.
2024-07-10 05:58:34 +01:00
Scott Taylor
54877e1f79 workspace: abandon discardable working copy on forget
Forgetting a workspace removes its working-copy commit, so it makes
sense for it to be abandoned if it is discardable just like editing a
new commit will cause the old commit to be abandoned if it is
discardable.
2024-07-04 19:37:56 -05:00
Scott Taylor
622b606bfb repo: abandon working copy only if no other workspaces reference it
Currently, if two workspaces are editing the same discardable commit and
one of them switches to editing a different commit, it is abandoned even
though the other workspace is still editing it. This commit treats
workspaces as referencing their working-copy commits so that they won't
be abandoned.
2024-07-04 19:37:56 -05:00
Ilya Grigoriev
1b658ea80e lib id_prefix: look for divergent changes outside short prefix set
Fixes #2476.

Previously, if there was a change id match within the short prefix
lookup set, `jj` would not look for commits with that same change id
outside the short prefix set. So, it wouldn't find the conflicted
commits for a commit with a divergent (AKA conflicted) change id.
2024-06-29 11:44:26 -07:00
Ilya Grigoriev
360a2b6a8b lib id_prefix: demo bug #2476 in a test 2024-06-29 11:44:26 -07:00
Scott Taylor
1eebbe57c0 commit_builder: reset author timestamp on discardable commits
It's common to create empty working-copy commits while using jj, and
currently the author timestamp for a commit is only set when it is first
created. If you create an empty commit, then don't work on a repo for a
few days, and then start working on a new feature without abandoning the
working-copy commit, the author timestamp will remain as the time the
commit was created rather than being updated to the time that work began
or finished.

This commit changes the behavior so that discardable commits (empty
commits with no description) by the current user have their author
timestamps reset when they are rewritten, meaning that the author
timestamp will become finalized whenever a commit is given a description
or becomes non-empty.
2024-06-29 08:35:53 -05:00
Yuya Nishihara
c240313c4b view: remove has_branch() which is called only from tests
Since we've split (local, remotes) branches to (locals, remotes { branches }),
.has_branch() API no longer makes much sense. Callers often need to check if
a remote branch is tracked.
2024-06-28 10:29:06 +09:00
Martin von Zweigbergk
f8a5ad0c7a conflicts: propagate error from conflict materialization 2024-06-17 14:33:29 +09:00
Matt Kulukundis
8aa71f58f3 feat: add an option to monitor the filesystem asynchronously
- 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>
2024-06-16 23:24:22 -04:00
Benjamin Tan
716ec37560 test_local_working_copy: add test for snapshotting of edited materialized simplified conflict 2024-06-15 06:05:06 +08:00
Benjamin Tan
9be33724dc conflicts: materialize simplified file conflicts 2024-06-15 06:05:06 +08:00
Benjamin Tan
7106f6fd49 conflicts: handle parsing of simplified conflicts 2024-06-15 06:05:06 +08:00
Benjamin Tan
f74991c2e1 tests: add tests showing that individual file conflicts are not simplified/deduplicated 2024-06-15 06:05:06 +08:00
Kyle J Strand
03a0921e12 give descendants a range arg 2024-06-13 18:54:57 -06:00
Martin von Zweigbergk
bfa0573cab repo/workspace: drop support for old repo formats
It's been more than 6 months since we added support for dynamically
selecting the working copy implementation. This patch drops support
for selecting the default implementation of that and other stores.
2024-06-11 22:03:20 +09:00
Martin von Zweigbergk
65a988e3d2 merged_tree: make tree builder attempt to resolve conflicts
As we discovered in the `jj fix` tests,
`MergedTreeBuilder::write_tree()` doesn't try to resolve conflicts,
not even trivial ones. This patch fixes that.
2024-06-08 20:29:30 +09:00
Martin von Zweigbergk
776b2d981f merged_tree: make resolve() return a MergedTree
It seems like a method on `MergedTree` should return another
`MergedTree` when reasonable. I'm not sure why I made it return a
`Merge<Tree>` instead.
2024-06-08 20:29:30 +09:00
Yuya Nishihara
5e7cb3435e git: unset unborn HEAD ref on export
Otherwise, newly created default branch would be re-imported as a new Git HEAD.
This could be addressed by cmd_git_init(), but the same situation can be
crafted by using "git checkout -b".
2024-06-01 11:01:16 +09:00
Martin von Zweigbergk
404f31cbc1 backend: add error variant for access denied, handle when diffing
Some backends, like the one we have at Google, can restrict access to
certain files. For such files, if they return a regular
`BackendError::ReadObject`, then that will terminate iteration in many
cases (e.g. when diffing or listing files). This patch adds a new
error variant for them to return instead, plus handling of such errors
in diff output and in the working copy.

In order to test the feature, I added a new commit backend that
returns the new `ReadAccessDenied` error when the caller tries to read
certain objects.
2024-05-30 18:27:38 -07:00
Benjamin Tan
e0e123873b revset_graph: rename to graph and make generic over graph node type 2024-05-31 02:39:34 +08:00
Martin von Zweigbergk
3090adfd5c repo: consider empty and undescribed merge commits as discardable 2024-05-29 06:54:30 -07:00
Martin von Zweigbergk
5d2c0347a2 MutableRepo: add test of updating away from empty merge commit
Merge commits are very similar to non-merge commits in jj. An empty
merge commit with no description is not really different from an empty
non-merge commit with no description. As we discussed on
https://github.com/martinvonz/jj/issues/2859, we should not treat
merge commits differently when updating away from them. This patch
adds test for the current behavior (which is to leave the merge commit
in place).
2024-05-29 06:54:30 -07:00
Martin von Zweigbergk
28050e9da1 repo: update some stale mentions of MutableRepo::check_out() 2024-05-29 06:54:30 -07:00
Martin von Zweigbergk
e02622b143 repo: when abandoning a working copy that a merge, recreate it
I recently needed to test something on top of a two branches at the
same time, so I created a new commit on top of both of them (i.e. a
merge commit). I then ran tests and made some adjustments to the
code. These adjustments belonged in one of the parent branches, so I
used `jj squash --into` to squash it in there. Unfortunately, that
meant that my working copy became a single-parent commit based on one
of the branches only. We already had #2859 for tracking this issue.

This patch changes the behavior so we create a new working-copy commit
with all of the previous parents.
2024-05-29 06:54:30 -07:00
Ilya Grigoriev
12081166f6 test_git.rs: delete now-useless test 2024-05-28 21:38:26 -07:00
Ilya Grigoriev
777da99533 jj git push: always force-push, all safety logic now in push_negotiation
This should be a no-op, though that is not necessarily obvious in corner
cases.

Note that libgit2 already performs the push negotiation even when
pushing without force (without `+` in the refspec).
2024-05-28 21:38:26 -07:00
Ilya Grigoriev
8d3dd17b51 jj git push: safety checks in push negotiation, "force-with-lease"
As explained in the commit, our logic is a bit more complicated than
that of `git push --force-with-lease`. This is to match the behavior of
`jj git fetch` and branch conflict resolution rules.
2024-05-28 21:38:26 -07:00
Ilya Grigoriev
b0306eb742 jj git push: no-op push negotiation, plumb data to it
Hopefully, splitting the no-op portion will make the following commits
easier to review.
2024-05-28 21:38:26 -07:00
Ilya Grigoriev
b54d962d58 test_git.rs: add two more commits to PushSetup, rename them
The new names are a bit clearer. Soem tests already use a
`sideways_commit`, `parent_of_main_commit` will be needed in
an upcoming test.
2024-05-28 21:38:26 -07:00
Martin von Zweigbergk
1e3b49abf5 revset: use FsRepoPathUiConverter in RevsetWorkspaceContext 2024-05-28 21:36:40 -07:00
Martin von Zweigbergk
7e6a968415 conflicts: consider the empty tree a non-legacy tree
Since we no longer depend on legacy trees being preserved when we
build new trees or merge trees, we can consider the root tree a
non-legacy tree.
2024-05-27 06:25:27 -07:00
mlcui
a075a5c6ca git: Only reset Git index if non-empty
In chromium/src.git, this gives an approximate ~0.83s speedup for
commands if the Git index is empty, and a ~0.14s slowdown if the Git
index is non-empty.

As most users using jj will likely be using jj to write to a colocated
repo - and therefore avoid modifying the Git index - this should be a
general speedup for most colocated checkouts.
2024-05-27 11:35:13 +10:00
Martin von Zweigbergk
07bb1d81b7 tree_builder: propagate errors from write_tree() 2024-05-22 06:46:38 -07:00
Martin von Zweigbergk
1970ddef15 tree: propagate errors from sub_tree()/path_value() 2024-05-22 06:46:38 -07:00
Martin von Zweigbergk
facfb71f7b test_merged_tree: reduce duplication and wrapping with helper lambdas
I'm about to make `[Merged]Tree::path_value()` return a `Result`. This
will help even more then.
2024-05-22 06:46:38 -07:00
dploch
a49da4ad01 revset: implement a 'reachable(src, domain)' expression
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.
2024-05-21 10:52:31 -04:00
Thomas Castiglione
59d3a2c866 local_working_copy: when all sides of a conflict are executable, materialise the conflicted file as executable
Fixes #3579 and adds a testcase for an executable conflict treevalue.
2024-05-21 14:37:17 +08:00
Ilya Grigoriev
1f7c4ec60a conflicts: label closing delimeter with conflict number
This follows up on https://github.com/martinvonz/jj/pull/3459 and adds a
label to the closing delimeter of each conflict, e.g.  "Conflict 1 of 3
ends".

I didn't initially put any label at the ending delimeter since the
starting delimeter is already marked with "Conflict 1 of 3". However,
I'm now realizing that when I resolve conflicts, I usually go from top
to bottom. The first thing I do is delete the starting conflict
delimeter. It is when I get to the *end* of the conflict that I wonder
whether there are any more conflicts left in the file.
2024-05-20 18:36:51 -07:00
Martin von Zweigbergk
ee9d3271c1 cleanup: propagate errors from Commit::predecessors() 2024-05-13 07:39:14 -07:00
Martin von Zweigbergk
0a758e7024 cleanup: propagate errors from Commit::parents()
The function now returns an iterator over `Result`s, matching
`Operation::parents()`.

I updated callers to also propagate the error where it was trivial.
2024-05-13 07:39:14 -07:00
dploch
4e0abf0631 revset: make RevsetParseContext opaque 2024-05-06 10:42:01 -04:00
Ilya Grigoriev
70b517ca64 conflicts.rs: label conflict number and sides next to conflict markers
For example, 

```
<<<<<<< Conflict 1 of 3
+++++++ Contents of side #1
left 3.1
left 3.2
left 3.3
%%%%%%% Changes from base to side #2
-line 3
+right 3.1
>>>>>>>
```

or

```
<<<<<<< Conflict 1 of 1
%%%%%%% Changes from base to side #1
-line 3
+right 3.1
+++++++ Contents of side #2
left 3.1
left 3.2
left 3.3
>>>>>>>
```

Currently, there is no way to disable these, this is TODO for a future
PR. Other TODOs for future PRs: make these labels configurable. After
that, we could support a `diff3/git`-like conflict format as well, in
principle.

Counting conflicts helps with knowing whether you fixed all the
conflicts while you are in the editor.

While labeling "side #1", etc, does not tell you the commit id or
description as requested in #1176, I still think it's an improvement.
Most importantly, I hope this will make `jj`'s conflict format less
scary-looking for new users.

I've used this for a bit, and I like it. Without the labels, I would see
that the two conflicts have a different order of conflict markers, but I
wouldn't be able to remember what that means. For longer diffs, it can
be tricky for me to quickly tell that it's a diff as opposed to one of
the sides. This also creates some hope of being able to navigate a
conflict with more than 2 sides.

Another not-so-secret goal for this is explained in
https://github.com/martinvonz/jj/pull/3109#issuecomment-2014140627. The
idea is a little weird, but I *think* it could be helpful, and I'd like
to experiment with it.
2024-05-05 18:42:14 -07:00
Ilya Grigoriev
f43a810fe0 conflicts.rs: Teach jj to parse conflict markers that are followed by a label
The format is 7 characters of the separator followed by a space and arbitrary
text, followed by a newline. Separator followed by a newline is also allowed.
E.g.:

<<<<<<< Random text
%%%%%%% Random text
 line 2
-line 3
+left
 line 4
+++++++ Random text
right
%%%%%%% Random text
 line 2
+forward
 line 3
 line 4
>>>>>>> Random text

This commit only allows reading such conflicts.

I considered allowing longer separators (`<<<<<<<<<<<<<< Random text`), but we
wouldn't currently write them, so let's be strict for now.

7 characters if they are followed by a space and arbitrary text
2024-05-05 18:42:14 -07:00
Martin von Zweigbergk
0d1ff8a150 merged_tree: propagate errors from TreeEntriesIterator
We shouldn't panic if we fail to read a tree from the backend.
2024-05-01 06:10:08 -07:00
Martin von Zweigbergk
dbf2a98903 rewrite: add CommitRewriter::record_abandoned_commit()
We already have two uses for this function and I think we're soon
going to have more.

The function record the old commit as abandoned with the new parents,
which is typically what you want. We could record it as abandoned with
the old parents instead but then we'd have to do an extra iteration to
find the parents when rebasing any children. It would also be
confusing if
`rewriter.set_parents(new_parents).record_abandoned_commit()` didn't
respect the new parents.
2024-04-30 20:03:57 -07:00
dploch
586ab1f076 revset: add a SymbolResolverExtension trait to provide custom resolvers 2024-04-26 10:55:34 -04:00
Yuya Nishihara
9f4a7318c7 tests: compare git refs loaded from disk, not in-memory cache values
This addresses the test instability. The underlying problem still exists, but
it's unlikely to trigger user-facing issues because of that. A repo instance
won't be reused after gc() call.

Fixes #3537
2024-04-22 18:46:28 +09:00
Yuya Nishihara
527713a851 tests: fix potential mtime flakiness in git gc tests
Apparently, these gc() invocations rely on that the previous "git gc" packed
all refs so there are no loose refs to compare mtimes. If there were new (or
remaining) loose refs, mtime comparison could fail. I also added +1sec to
effectively turn off the keep_newer option, which isn't important in these
tests.
2024-04-22 18:46:28 +09:00
Evan Mesterhazy
f9a3021a7a Simplify calls to CommitRewriter::replace_parents()
Now that it takes `IntoIterator` the caller doesn't need to clone
the input `CommitIds`.
2024-04-21 23:31:17 -04:00
Martin von Zweigbergk
87c65ee0f9 rewrite: make CommitRewriter::replace_parents() remove repeats 2024-04-18 21:06:52 -07:00
Martin von Zweigbergk
96f5ca47d4 repo: add method for tranforming descendants, use in rebase_descendants()
There are several existing commands that would benefit from an API
that makes it easier to rewrite a whole graph of commits while
transforming them in some way.

`jj squash` is one example. When squashing into an ancestor, that
command currently rewrites the ancestor, then rebases descendants, and
then rewrites the rewritten source commit. It would be better to
rewrite the source commit (and any descendants) only once.

Another example is the future `jj fix`. That command will want to
rewrite a graph while updating the trees. There's currently no good
API for that; you have to manually iterate over descendants and
rewrite them.

This patch adds a new `MutableRepo::transform_descendants()` method
that takes a callback which gets a `CommitRewriter` passed to it. The
callback can then decide to change the parents, the tree, etc. The
callback is also free to leave the commit in place or to abandon it.

I updated the regular `rebase_descendants()` to use the new function
in order to exercise it. I hope we can replace all of the
`rebase_descendant_*()` flavors later.

I added a `replace_parent()` method that was a bit useful for the test
case. It could easily be hard-coded in the test case instead, but I
think the method will be useful for `jj git sync` and similar in the
future.
2024-04-18 21:06:52 -07:00
Martin von Zweigbergk
2859277941 rewrite: pass CommitRewriter into rebase_commit_with_options()
`CommitRewriter` wraps 3 of the arguments, so I think it makes sense
to pass it instead. More importantly, I hope to continue refactoring
so many of the callers already have a `CommitRewriter`.
2024-04-18 08:08:51 -07:00
Martin von Zweigbergk
b13cb8db26 rewrite: make EmptyBehavior implement Copy 2024-04-18 08:08:51 -07:00
Martin von Zweigbergk
93baff0b8a rewrite: pass just IDs of new parents into rewrite::rebase*()
It's cheap to look up commits again from the cache in `Store` but it
can be expensive to look up commits we didn't end up needing. This
will make it easier to refactor further and be able to cheaply set
preliminary parents for a rewritten commits and then let the caller
update them.
2024-04-17 06:13:54 -07:00
Martin von Zweigbergk
057b7c8d0b rewrite: take commit and new parents by value in rebase_commit()
I'm going to add a helper struct to help with rewriting commits. I
want to make that struct own the old commit and the new parents to
simplify lifetimes. This patch prepares for that by passing the
commits by value to `rebase_commit()`.
2024-04-17 06:13:54 -07:00
Yuya Nishihara
aaa2025dfc git: on fetch, pin visible untracked remote refs
This implements the other workaround described in 57167cefda "git: on
import_refs(), don't abandon ancestors of newly fetched refs":

> I think there are two ways to fix the problem:
>  a. pin non-tracking remote branches just like local refs
>  b. pin newly fetched refs in addition to local refs
> This patch implements (b) because it's simpler and more obvious that the
> fetched commits would never be abandoned immediately.

The idea of (a) is that untracked remote branches are independent read-only
refs, and read-only branches shouldn't be rewritten implicitly. Once the
branch gets rewritten or abandoned by user, these remote refs will be hidden,
and won't be pinned anymore.

Since (a) effectively supersedes (b), this patch also removes the original
workaround.

Fixes #3495
2024-04-14 11:38:21 +09:00
Yuya Nishihara
47150d2bb4 revset: migrate file() predicate to be based on FilesetExpression 2024-04-06 23:59:54 +09:00
Christoph Koehler
7bde6ddc29 revset: add working_copies() function
It includes the working copy commit of every workspace of the repo.

Implements #3384
2024-04-01 19:36:53 -06:00
Martin von Zweigbergk
5e8d7f8c6f rewrite: update references after rewriting all commits 2024-03-25 23:00:44 -07:00
Martin von Zweigbergk
d2043f069e repo: delete record_rewritten_commit()
I don't think we have any callers left that call
`record_rewritten_commit()` multiple times within a transaction and
expect it to result in divergence. I think we should consider it a bug
to do that.
2024-03-25 06:53:14 -07:00
Ilya Grigoriev
02a04d0d37 test_conflicts and test_resolve_command: use indoc! to indent conflict markers in tests
Apart from (IMO) looking nicer, this will also sidestep the potential problem
that if the file contains actual jj conflict markers (`>>>>>>>` in the beginning
of a line, for example), jj would currently have trouble materializing and
subsequently parsing conflicts in the file if it actually became conflicted.

I'll demo this bug in either this or a subsequent PR. It's the kind of bug that
sounds serious in theory but might never cause a problem in practice.

After this PR, only `docs/tutorial.md` has a conflict marker that's not indented.
There's only one there, so hopefully it won't be too much of a pain to deal with.

I also indented other strings in `test_conflicts.rs`. IMO, this looks nice and
more consistent with the `insta::assert_snapshot` output. I didn't spend the
time to do the same for `test_resolve_command`.
2024-03-22 23:27:25 -07:00
Yuya Nishihara
9207314173 revset: add substitution rule for "::x & ~(::y-)"
Suppose the generation value is usually small, it should be faster to do
bounded range look up first 'y-', then walk ancestors with the unwanted set
'y-..x'.
2024-03-17 14:50:48 +09:00
Yuya Nishihara
699707905c index: reorganize revset_graph_iterator as private module of default_index
The RevsetGraphIterator type is hidden so that the Iterator trait can be
implemented differently.
2024-03-14 10:07:19 +09:00
Yuya Nishihara
243675b793 index: turn CompositeIndex into transparent reference type
This helps to eliminate higher-ranked trait bounds from RevWalkRevset and
RevWalk combinators to be added. Since &CompositeIndex is now a real reference,
it can be passed to functions as index: &T.
2024-03-11 17:24:10 +09:00
Aleksey Kuznetsov
cd3d75ebf6 revset: introduce more performant way to check if a commit is in a revset
Initially we were thinking to have `Revset` return something like
`CachedRevset`:

```
pub trait CachedRevset {
  fn iter(&self) -> Box<dyn Iterator<Item = Commit>>;
  fn contains(&self, &CommitId) -> bool;
}
```

But we weren't sure what use case for `iter` would be, so we dropped the `iter`
method. `CachedRevset` with single `contains` method needed a better name. We
weren't able to come up with one, so we decided instead to have a method on
`Revset` that returns a closure to check if a commit is in a revset.
2024-03-11 08:27:35 +05:00
Yuya Nishihara
f5eb172769 tests: remove last use of walk_revs() from integration tests 2024-03-08 10:07:40 +09:00
Thomas Castiglione
d661f59f9d working_copy: implement symlinks on windows with a helper function
enables symlink tests on windows, ignoring failures due to disabled developer mode,
and updates windows.md
2024-03-05 15:16:38 +08:00
Yuya Nishihara
24868e5192 gpg_signing: handle early termination of gpg command in verify path
Also fixes missing wait() on I/O error. We have the same problem in several
places. I'll fix them in another batch.
2024-03-03 18:35:10 +09:00
Yuya Nishihara
ef9d22887c tests: disable gpg unknown_key() test on Windows as well
Follows up 7552f939c6 "tests: disable most gpg integration tests on Windows."
I couldn't find this test failing in a few samples before, but it does now.
2024-02-27 00:55:06 +09:00
Martin von Zweigbergk
1cbf2b4acf rewrite: allow working-copy to be abandoned
This removes the special handling of the working-copy commit. By
recording when an empty/emptied commit was abanoned, we rebase
descendants correctly and create a new empty working-copy commit on
top.
2024-02-25 16:39:05 -08:00
Yuya Nishihara
7552f939c6 tests: disable most gpg integration tests on Windows
These tests often stuck on Windows CI for unknown reasons. Let's mark them
ignored for the moment. The unknown_key test is allowed because it somehow
appears to pass.

https://github.com/martinvonz/jj/actions/runs/8009950119/job/21879789008?pr=3123#step:7:1487

#3140
2024-02-25 17:07:05 +09:00
Yuya Nishihara
ebf90384f6 operation: add shorthand for .store_operation().metadata 2024-02-25 09:00:56 +09:00
Julien Vincent
f97e929cbf sign: Skip gpg tests if gpg is not installed
This adds a guard to the gpg signing tests which will skip the test if
`gpg` is not installed on the system.

This is done in order to avoid requiring all collaborators to have setup
all the tools on their local machines that are required to test commit
signing.
2024-02-21 13:22:53 +00:00
Yuya Nishihara
9f05aa8c46 tests: fix fun typo "singing" -> "signing" 2024-02-21 22:04:41 +09:00
Austin Seipp
6c31bab0d3 fsmonitor: allow core.fsmonitor = "none" to disable
When doing things like testing snapshot performance differences,
this allows you to turn off the monitor, no matter what the enabled
user or repository configuration has, e.g.

    jj st --config-toml='core.fsmonitor="none"'

Signed-off-by: Austin Seipp <aseipp@pobox.com>
2024-02-20 20:19:47 -06:00
Ilya Grigoriev
106483ad6a clippy: run nightly cargo clippy --fix 2024-02-19 23:38:33 -08:00
Martin von Zweigbergk
11c67cf979 op_store: add metadata flag for ops representing working-copy snapshot
It should be useful at least in the presentation layer to know which
operations correspond to working-copy snapshots. They might be
rendered differently in the graph, for example. Or maybe an undo
command wants to warn if you just undid a snapshot operation. This
patch just introduces a field in the metadata to store the
information.
2024-02-19 22:44:38 -08:00
Julien Vincent
23e5fba737 sign: Add SSH backend tests 2024-02-20 00:02:08 +00:00
Julien Vincent
7c11a61c23 sign: GPG backend tests 2024-02-20 00:02:08 +00:00
Martin von Zweigbergk
a9d0300b11 rewrite: make simplification of ancestor merges optional
I think the conclusion from #2600 is that at least auto-rebasing
should not simplify merge commits that merge a commit with its
ancestor. Let's start by adding an option for that in the library.
2024-02-19 14:20:18 -08:00
Yuya Nishihara
3c7aa75b9b index: switch to persistent change id index
The shortest change id prefix will become a few digits longer, but I think
that's acceptable. Entries included in the "revsets.short-prefixes" set are
unaffected.

The reachable set is calculated eagerly, but this is still faster as we no
longer need to sort the reachable entries by change id. The lazy version will
save another ~100ms in mid-size repos.

"jj log" without working copy snapshot:
```
% hyperfine --sort command --warmup 3 --runs 20 -L bin jj-0,jj-1,jj-2 \
  -s "target/release-with-debug/{bin} -R ~/mirrors/linux debug reindex" \
  "target/release-with-debug/{bin} -R ~/mirrors/linux \
   --ignore-working-copy log -r.. -l100 --config-toml='revsets.short-prefixes=\"\"'"
Benchmark 1: target/release-with-debug/jj-0 -R ~/mirrors/linux --ignore-working-copy log -r.. -l100 --config-toml='revsets.short-prefixes=""'
  Time (mean ± σ):     353.6 ms ±  11.9 ms    [User: 266.7 ms, System: 87.0 ms]
  Range (min … max):   329.0 ms … 365.6 ms    20 runs

Benchmark 2: target/release-with-debug/jj-1 -R ~/mirrors/linux --ignore-working-copy log -r.. -l100 --config-toml='revsets.short-prefixes=""'
  Time (mean ± σ):     271.3 ms ±   9.9 ms    [User: 183.8 ms, System: 87.7 ms]
  Range (min … max):   250.5 ms … 282.7 ms    20 runs

Relative speed comparison
        1.99 ±  0.16  target/release-with-debug/jj-0 -R ~/mirrors/linux --ignore-working-copy log -r.. -l100 --config-toml='revsets.short-prefixes=""'
        1.53 ±  0.12  target/release-with-debug/jj-1 -R ~/mirrors/linux --ignore-working-copy log -r.. -l100 --config-toml='revsets.short-prefixes=""'
```

"jj status" with working copy snapshot (watchman enabled):
```
% hyperfine --sort command --warmup 3 --runs 20 -L bin jj-0,jj-1,jj-2 \
  -s "target/release-with-debug/{bin} -R ~/mirrors/linux debug reindex" \
  "target/release-with-debug/{bin} -R ~/mirrors/linux \
   status --config-toml='revsets.short-prefixes=\"\"'"
Benchmark 1: target/release-with-debug/jj-0 -R ~/mirrors/linux status --config-toml='revsets.short-prefixes=""'
  Time (mean ± σ):     396.6 ms ±  10.1 ms    [User: 300.7 ms, System: 94.0 ms]
  Range (min … max):   373.6 ms … 408.0 ms    20 runs

Benchmark 2: target/release-with-debug/jj-1 -R ~/mirrors/linux status --config-toml='revsets.short-prefixes=""'
  Time (mean ± σ):     318.6 ms ±  12.6 ms    [User: 219.1 ms, System: 94.1 ms]
  Range (min … max):   294.2 ms … 333.0 ms    20 runs

Relative speed comparison
        1.85 ±  0.14  target/release-with-debug/jj-0 -R ~/mirrors/linux status --config-toml='revsets.short-prefixes=""'
        1.48 ±  0.12  target/release-with-debug/jj-1 -R ~/mirrors/linux status --config-toml='revsets.short-prefixes=""'
```
2024-02-18 09:44:57 +09:00
Yuya Nishihara
8cdf6d752c index: move change ids to sstable, build change-id-to-pos lookup table
This basically means that the change ids are interned. We'll implement binary
search over the sorted change ids table. The table could be sorted differently
for better cache locality, but it is in lexicographical order for simplicity.
With my testing, the cost of the id lookup isn't dominant.

Unlike the parent entries, the size of the per-id overflow items isn't saved.
That's s because the number of the same-change-id commits is either 1 or many.
It doesn't make sense to allocate 8 bytes for each change id. Instead, we'll
pay extra indirection cost to determine the size.
2024-02-18 09:44:57 +09:00
Thomas Castiglione
aaa5d6bc4f working_copy: add Send supertrait
If WorkingCopy: Send, then Workspace is Send, which is useful for long-running
servers. All existing impls are Send already, so this is just a marker.
2024-02-17 15:13:25 +08:00
Yuya Nishihara
5eea88d26a tests: fix concurrent git read/write test to retry on ref lock contention
Apparently, gix has 100ms timeout. Since this test tries to create contended
situation, it's possible that the ref lock can't be acquired. I've added
upper bound to the retry loop at b37293fa68 "tests: add upper bound to
test_concurrent_read_write_commit() loop", so ignoring arbitrary errors
should be okay.

The problem can be reproduced on my Linux machine by inserting 10ms sleep() to
gix and increasing the concurrency.

Fixes #3069
2024-02-17 15:09:27 +09:00
Evan Mesterhazy
e1fd402d39 Fix the ContentHash implementations for std::Option, MergedTreeId, and RemoteRefState
The `ContentHash` documentation specifies that implementations for enums should
hash the ordinal number of the variant contained in the enum as a 32-bit
little-endian number and then hash the contents of the variant, if any.

The current implementations for `std::Option`, `MergedTreeId`, and
`RemoteRefState` are non-conformant since they hash the ordinal number as a u8
with platform specific endianness.


Fixes #3051
2024-02-16 09:27:32 -05:00
Yuya Nishihara
e2c8a8fabd index: fix change id resolution test to not depend on deterministic order
Since IdIndex sorts the entries by using .sort_unstable_by_key(), the order of
the same-key elements is undefined. Perhaps, it's stable for short arrays, and
the test passes because of that.
2024-02-14 23:22:23 +09:00
Yuya Nishihara
2905a70b18 doc, tests: drop use of deprecated revset dag range operator 2024-02-14 10:04:56 +09:00
Yuya Nishihara
b0e8e2a1af index: move segment files to sub directory, add version number
I'm going to introduce breaking changes in index format. Some of them will
affect the file size, so version number or signature won't be needed. However,
I think it's safer to detect the format change as early as possible.

I have no idea if embedded version number is the best way. Because segment
files are looked up through the operation links, the version number could be
stored there and/or the "segments" directory could be versioned. If we want to
support multiple format versions and clients, it might be better to split the
tables into data chunks (e.g. graph entries, commit id table, change id table),
and add per-chunk version/type tag. I choose the per-file version just because
it's simple and would be non-controversial.

As I'm going to introduce format change pretty soon, this patch doesn't
implement data migration. The existing index files will be deleted and new
files will be created from scratch.

Planned index format changes include:
 1. remove unused "flags" field
 2. inline commit parents up to two
 3. add sorted change ids table
2024-02-12 19:38:36 +09:00
Ilya Grigoriev
a9c3af8153 test_local_working_copy: use std::fs:write instead of OpenOptions 2024-02-10 16:06:28 -08:00
Ilya Grigoriev
b2e37d448b clippy: add truncate option as suggested by clippy
In the next commit, I replace the whole thing with
std::fs::write, but I'll leave this here in case
the next commit is somhow incorrect
2024-02-10 16:06:28 -08:00
Ilya Grigoriev
a88c06068e clippy: new nightly fixes
For some reason, clippy also suggested surrounding
`self.value` with parentheses. Not sure whether
that's a clippy bug.

Cc: https://github.com/rust-lang/rust-clippy/issues/12268
2024-02-10 16:06:28 -08:00
dependabot[bot]
6d1faf9b03 Update strsim (changes tests), clap, clap_complete
This is #3002 with tests rerun to account for changes
to `strsim`, as @thoughtpolice noticed in
https://github.com/martinvonz/jj/pull/3002#issuecomment-1936763101

The string similarity changes include an example that
seems better and one that seems worse. Decreasing
the threshold definitely makes things worse.
2024-02-10 00:01:47 -08:00
Austin Seipp
5b517b542e rust: bump MSRV to 1.76.0
Signed-off-by: Austin Seipp <aseipp@pobox.com>
2024-02-09 15:48:01 -06:00
Martin von Zweigbergk
6c1aeff7a9 working copy: materialize symlinks on Windows as regular files
I was a bit surprised to learn (or be reminded?) that checking out
symlinks on Windows leads to a panic. This patch fixes the crash by
materializing symlinks from the repo as regular files. It also updates
the snapshotting code so we preserve the symlink-ness of a path. The
user can update the symlink in the repo by updating the regular file
in the working copy. This seems to match Git's behavior on Windows
when symlinks are disabled.
2024-02-09 09:20:24 -08:00
jyn
d66fcf2ca0 compile integration tests as a single binary
this greatly speeds up the time to run all tests, at the cost of slightly larger recompile times for individual tests.

this unfortunately adds the requirement that all tests are listed in `runner.rs` for the crate.
to avoid forgetting, i've added a new test that ensures the directory is in sync with the file.

 ## benchmarks

before this change, recompiling all tests took 32-50 seconds and running a single test took 3.5 seconds:

```
; hyperfine 'touch lib/src/lib.rs && cargo t --test test_working_copy'
  Time (mean ± σ):      3.543 s ±  0.168 s    [User: 2.597 s, System: 1.262 s]
  Range (min … max):    3.400 s …  3.847 s    10 runs
```

after this change, recompiling all tests take 4 seconds:
```
;  hyperfine 'touch lib/src/lib.rs ; cargo t --test runner --no-run'
  Time (mean ± σ):      4.055 s ±  0.123 s    [User: 3.591 s, System: 1.593 s]
  Range (min … max):    3.804 s …  4.159 s    10 runs
```
and running a single test takes about the same:
```
; hyperfine 'touch lib/src/lib.rs && cargo t --test runner -- test_working_copy'
  Time (mean ± σ):      4.129 s ±  0.120 s    [User: 3.636 s, System: 1.593 s]
  Range (min … max):    3.933 s …  4.346 s    10 runs
```

about 1.4 seconds of that is the time for the runner, of which .4 is the time for the linker. so
there may be room for further improving the times.
2024-02-06 18:19:41 -08:00
Martin von Zweigbergk
b343289238 working_copy: make reset() take a commit instead of a tree
Our virtual file system at Google (CitC) would like to know the commit
so it can scan backwards and find the closest mainline tree based on
it. Since we always record an operation id (which resolves to a
working-copy commit) when we write the working-copy state, it doesn't
seem like a restriction to require a commit.
2024-02-06 12:41:09 -08:00
Ilya Grigoriev
d439de073d rewrite.rs: revert commits cfcc7c5e and becbc889
This mostly reverts https://github.com/martinvonz/jj/pull/2901 as well as its
fixup https://github.com/martinvonz/jj/pull/2903. The related bug is reopened,
see https://github.com/martinvonz/jj/issues/2869#issuecomment-1920367932.

The problem is that while the fix did fix #2869 in most cases, it did
reintroduce the more severe bug https://github.com/martinvonz/jj/issues/2760
in one case, if the working copy is the commit being rebased.

For example, suppose you have the tree

```
root -> A -> B -> @ (empty) -> C
```

### Before this commit

#### Case 1

`jj rebase -s B -d root --skip-empty` would work perfectly before this
commit, resulting in

```
root -> A
  \-------B -> C
           \- @ (new, empty)
```

#### Case 2

Unfortunately, if you run `jj rebase -s @ -d A --skip-empty`, you'd have the
following result (before this commit), which shows the reintroduction of #2760:

```
root -> A @ -> C
         \-- B
```

with the working copy at `A`. The reason for this is explained in
https://github.com/martinvonz/jj/pull/2901#issuecomment-1920043560.

### After this commit

After this commit, both case 1 and case 2 will be wrong in the sense of #2869,
but it will no longer exhibit the worse bug #2760 in the second case.

Case 1 would result in:

```
root -> A
  \-------B -> @ (empty) -> C
```

Case 2 would result in:

```
root -> A -> @ -> C
         \-- B
```

with the working copy remaining a descendant of A
2024-02-03 15:56:44 -08:00
Ilya Grigoriev
cfcc7c5e34 test_rewrite: Fixup test comment after becbc88 2024-01-30 23:43:05 -08:00
Ilya Grigoriev
becbc88915 rewrite.rs: fix working copy position after jj rebase --abandon-empty
Fixes #2869
2024-01-30 22:53:55 -08:00
Yuya Nishihara
3d0b3d57d8 git_backend: on gc(), remove unreachable no-gc refs and compact them
With my jj repo, the number of jj/keep refs went down from 87887 to 27733.
The .git directory size is halved, but we'll need to clean up extra and index
files to save disk space. "git gc --prune=now && jj debug reindex" passed, so
the repo wouldn't be corrupted.

#12
2024-01-27 10:18:11 +09:00
Yuya Nishihara
fc114ef217 git: extract Git HEAD handling bits from import_some_refs()
I'm going to make WorkspaceCommandHelper::maybe_snapshot() snapshot the working
copy before importing refs. git::import_some_refs() can rebase the working copy
branch and therefore @ can be moved. git::import_head() doesn't, and it should
be invoked before snapshotting.

git::import_head() is inserted to some of the git:import_refs() callers where
HEAD seems to matter. I feel it's a bit odd that the HEAD ref is imported to
non-colocated repo, but "jj init --git-repo" relies on that, and I think the
existence of HEAD@git is harmless. It's merely a ref to the revision checked
out somewhere else.
2024-01-27 00:01:59 +09:00
Daniel Ploch
cb889f0b45 workspace: combine working copy functions into a trait 2024-01-25 11:46:07 -08:00
Yuya Nishihara
5a7d8ac596 working_copy: don't follow symlinks when visiting files in gitignored directory
Fixes #2878
2024-01-24 16:38:48 +09:00
Yuya Nishihara
d0d4496258 tests: add executable files and symlinks to gitignored directory test 2024-01-24 16:38:48 +09:00
Martin von Zweigbergk
502150b2f4 conflicts: test materialization with with negative snapshots
We didn't have any tests with negative snapshots (after a `-------`
line). I initially thought we couldn't produce such conflict markers
anymore. I'm not sure we want to render conflicts like the one in the
test like this. I don't think I intended for `add_index` in the code
to be able to be two steps ahead of the remove. Maybe we should
rewrite the algorithm to not do that and thus never produce negative
snapshots.
2024-01-23 07:18:54 -08:00
Ilya Grigoriev
d168fd2b09 test_rebase_abandoning_empty: add children of an empty @ to the test case
This demonstrates the minor bug discussed in
https://github.com/martinvonz/jj/pull/2766#discussion_r1442365389
AKA https://github.com/martinvonz/jj/issues/2869.

It's also interesting whether changing the definition of "discardable" commit
would affect this test, see
https://github.com/martinvonz/jj/issues/2859#issuecomment-1903275884

(I think it won't, but still)
2024-01-22 18:36:49 -08:00
Yuya Nishihara
fb3e006a45 op_store: add special case for root id resolution 2024-01-16 21:46:54 +09:00
Yuya Nishihara
660806ffed tests: set up unparented operations for id prefix tests
Otherwise we can't easily pick i to create operation id starting with "0".
2024-01-16 21:46:54 +09:00
Yuya Nishihara
df1be14aa8 tests: split op id resolution tests, don't require merged op for prefix tests
This makes it easy to set up crafted environment for prefix resolution tests.
2024-01-16 21:46:54 +09:00
Martin von Zweigbergk
6e302bb3a2 op_store: add a virtual root operation, similar to root commit
It seems obvious in hindsight to have a virtual root operation just
like we have a virtual root commit. It removes the same kind of
problems by making sure there's always a common ancestor (or multiple)
between any two commits.

I think the reason I didn't add a root operation from the beginning
was that there used to be a mandatory working-copy commit in the view
(this was before support for multiple workspaces).

Perhaps we should remove the "initialize repo" operation now. The only
difference between their view objects is that the "initialize repo"
operation adds the root commit as a head. We could add that to the
root operation, but then the root operation's value depends on the
commit backend.
2024-01-14 10:15:14 -08:00
Martin von Zweigbergk
c9af8bf43a view: drop tracking of public heads
We've had the public_heads for as long as we've had the View object,
IIRC (I didn't check), but we still don't use it for anything. I don't
have any concrete plans for using it either. Maybe our config for
immutable commits is good enough, or maybe we'll want something more
generic (like Mercurial's phases). For now, I think we should simplify
by removing it the storage for public heads.
2024-01-13 22:23:57 -08:00
Yuya Nishihara
b7eb551cf7 index: fix reindexing to scan all referenced commits such as hidden remote refs
Since hidden commits can be looked up by remote_branches() revset for example,
reindexing should traverse ancestors from all named refs in addition to the
visible heads.
2024-01-12 12:53:16 +09:00
Yuya Nishihara
83ede241e3 op_walk: don't resolve heads beyond @ operation
Since `jj undo --at-op=OP @` resolves @ to OP, I think OP should be the head
in that context, and the descendants of OP shouldn't be accessible by @+.
2024-01-12 08:01:13 +09:00
Yuya Nishihara
d5a98df046 git_backend: teach "format.tree-level-conflicts" config by constructor
Since GitBackend constructors now depend on &UserSettings, it makes sense to
initialize the formatting options there.
2024-01-10 08:57:51 +09:00
Yuya Nishihara
e5286aed08 index: move lifetimed change_id_index() to MutableIndex, rename 'static version
change_id_index() is only used by Readonly/MutableRepo, so we don't need an
abstraction at Index. evaluate_revset() is somewhat similar, but the callers
rely on &dyn Repo.
2024-01-09 10:38:00 +09:00
Yuya Nishihara
dc68f1eeb2 revset: remove unused lifetime parameter from Revset<'index> 2024-01-09 10:37:43 +09:00
Yuya Nishihara
e9d31177cb op_store: implement GC of unreachble operations and views
Since new operations and views may be added concurrently by another process,
there's a risk of data corruption. The keep_newer parameter is a mitigation
for this problem. It's set to preserve files modified within the last 2 weeks,
which is the default of "git gc". Still, a concurrent process may replace an
existing view which is about to be deleted by the gc process, and the view
file would be lost.

#12
2024-01-09 10:37:03 +09:00
Yuya Nishihara
5894f3dfba operation: add shorthand for &store_operation().view_id 2024-01-09 10:37:03 +09:00
Martin von Zweigbergk
c98b0d76af index: move Revset::change_id_index() to Index
We current have `Revset::change_id_index()` for creating a
`ChangeIdIndex` for a given revset. I think it will be hard to make it
performant for general revsets, especially in very large repos and
with custom index implementations, like the one we have at Google. If
we instead restrict it to including all ancestors of a set of heads, I
think it will be much easier to implement. We only use
`Revset::change_id_index()` with revsets including all visible commits
today, so we won't lose any current functionality by making it more
restricted.
2024-01-08 06:06:47 -08:00
Martin von Zweigbergk
2f4594540a tests: move ChangeIdIndex test from test_revset to test_index 2024-01-08 06:06:47 -08:00
Martin von Zweigbergk
1508f28567 tests: update ChangeIdIndex test to include ancestors in set
I plan to replace `Revset::change_id_index()` by
`Index::change_id_index(heads)`, but one of the tests currently uses a
set of commits that does not include ancestors. This patch updates it
to include ancestors (and changes the set of heads to keep the set
small enough for the test).
2024-01-08 06:06:47 -08:00
Martin von Zweigbergk
f0182ad4b8 default_index: adopt revset engine and graph iterator modules
The revset engine and the graph iterator are specific to the default
index implementation, so they belong in the same module.
2024-01-07 05:37:47 -08:00
Yuya Nishihara
a6616e9cea object_id: don't allow ObjectId::from_hex() a dynamically allocated string
This isn't technically needed, but it prevents API misuse. Another option
is to do some compile-time substitution, but most callers are tests and the
runtime performance wouldn't matter.
2024-01-06 00:26:36 +09:00
Yuya Nishihara
95d83cbfe5 object_id: make ObjectId constructors non-trait methods
I'm going to add try_from_hex(), which requires Self: Sized. Such trait bound
could be added, but I don't think we'll need abstracted ObjectId constructors
at all.
2024-01-05 23:36:57 +09:00
Yuya Nishihara
31b236a70d object_id: move HexPrefix and PrefixResolution from index module 2024-01-05 10:20:57 +09:00
Yuya Nishihara
fa5e40719c object_id: extract ObjectId trait and macros to separate module
I'm going to add a prefix resolution method to OpStore, but OpStore is
unrelated to the index. I think ObjectId, HexPrefix, and PrefixResolution can
be extracted to this module.
2024-01-05 10:20:57 +09:00
Yuya Nishihara
e5255135bb op_walk: add function that reparents (and abandons) operation range
This will be used in "jj op abandon ..op_id" command. The "op_id..@" range will
be reparented onto the root operation.

The current implementation is good enough for local repos, but it won't scale.
We might want to extract it as a trait method or introduce OpIndex for
efficient DAG operation.
2024-01-04 11:44:36 +09:00
Matt Stark
3f0a49dafe Ensure you never drop the working commit with --skip-empty
See #2766 for discussions
2024-01-04 13:33:24 +11:00
Matt Stark
a4aed2391f Rewrite instead of abandoning empty commits.
Fixes #2760


Given the tree:
```
A-B-C
 \
  B2
```
And the command `jj rebase -s B -d B2`

We were previously marking B as abandoned, despite the comment stating that we were marking it as being succeeded by B2. This resulted in a call to `rewrite(rewrites={}, abandoned={B})` instead of `rewrite(rewrites={B=>B2}, abandoned={})`, which then made the new parent of `C` into `A` instead of `B2`
2024-01-04 13:33:24 +11:00
Ilya Grigoriev
45cd0bf11b test_rewrite.rs: stop using DescendantRebaser when testing EmptyBehavior
This completes the process of removing DescendantRebaser-related APIs from
tests. It requires creating some new test utils and a new
`rebase_descendants_with_option_return_map`.
2024-01-01 18:51:36 -08:00
Ilya Grigoriev
4461d61254 test_rewrite: test branches of descendants of divergent commits
A TODO left over from a previous PR
2024-01-01 18:51:36 -08:00
Ilya Grigoriev
b2abba07e9 tests: (mostly) stop using soon-to-be-private DescendantRebaser-related APIs
This removes uses of `DescendantRebaser::new` or
`MutRepo::create_descendant_rebaser` from most tests. The exceptions  are the
tests having to do with abandoning empty commits on rebase, since adjusting
those is a bit more elaborate (see follow-up commits).
2024-01-01 18:51:36 -08:00
Yuya Nishihara
3eafca65ea op_walk: add support for op_id+ (children) operator
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.
2024-01-02 10:30:08 +09:00
Yuya Nishihara
51691ea22c tests: add lib tests for op id resolution, migrate some from cli
CLI testing is slow and harder to set up crafted environment.
2024-01-02 10:30:08 +09:00
Yuya Nishihara
f9e9058b9b index: show bad operation id if commit lookup failed during reindexing
My jj repo contains such head commits, and "jj debug reindex" fails. To address
this problem, we'll probably need to implement GC, and the user will discard
operations before the first bad op id.
2023-12-29 13:05:58 +09:00
Ilya Grigoriev
1fb9df252b split.rs: stop using DescendantRebaser::new
This requires creating a new public API as a substitute. I took the opportunity
to also add some comments to the
`MutRepo::record_rewritten_commit`/`record_abandoned_commit` functions.

I imade the simplest possible addition to the API; it is not a very elegant
one. Eventually, the entire `record_rewritten_commit` API should probably be
refactored again.

I also added some comments explaining what these functions do.
2023-12-24 19:25:16 -08:00
Yuya Nishihara
b954bab0ca index: fix partial reindexing to not lose commits only reachable from one side
Spotted while adding error propagation there. This wouldn't likely be a real
problem because "jj debug reindex" removes all of the operation links.

The "} else {" condition is removed because it doesn't make sense to exclude
only the exact parent_op_id operation. This can be optimized to not walk
ancestors of the parent_op_id operation, but I don't see a motivation to add
tests covering such scenarios. It's pretty rare that an intermediate operation
link is missing.
2023-12-24 23:31:16 +09:00
Yuya Nishihara
55b4f69fb6 repo: propagate store error from add_heads() 2023-12-24 00:22:30 +09:00
Yuya Nishihara
6971ec239a tests: set git_settings.auto_local_branch where it matters 2023-12-17 08:30:24 +09:00
Yuya Nishihara
d9e8297059 index: add 'static version of evaluate_revset() to ReadonlyIndex
We'll probably need a better abstraction, but a separate method is good
enough to remove unsafe code from ReadonlyRepo.

I'm not sure if this is feasible for the other backends, but I guess there
would be less lifetimed variables than DefaultReadonlyIndex.
2023-12-15 16:10:28 +09:00
Yuya Nishihara
2ba50c76c7 revset: abstract evaluated RevsetImpl over owned/borrowed index types 2023-12-15 16:10:28 +09:00
Yuya Nishihara
72d9cd019b index: extract as_composite() to trait method
The revset engine will accept abstract AsCompositeIndex type, and the
evaluated revset can be 'static if the index is behind Arc<T>.
2023-12-15 16:10:28 +09:00
Martin von Zweigbergk
60fae3114e transaction: take description at end instead of start
It seems better to have the caller pass the transaction description
when we finish the transaction than when we start it. That way we have
all the information we want to include more readily available.
2023-12-13 08:12:49 -08:00
Ilya Grigoriev
316ab8efb8 rewrite.rs: refactor new_parents to depend only on parent_mapping
Previously, the function relied on both the `self.parent_mapping` and
`self.rebased`. If `(A,B)` was in `parent_mapping` and `(B,C)` was in `rebased`,
`new_parents` would map `A` to `C`.

Now, `self.rebased` is ignored by `new_parents`. In the same situation,
DescendantRebaser is changed so that both `(A,B)` and `(B,C)` are in
`parent_mapping` before. `new_parents` now applies `parent_mapping` repeatedly,
and will map `A` to `C` in this situation.

## Cons

- The semantics are changed; `new_parents` now panics if `self.parent_mapping`
  contain cycles. AFAICT, such cycles never happen in `jj` anyway, except for
one test that I had to fix. I think it's a sensible restriction to live with;
if you do want to swap children of two commits, you can call
`rebase_descendants` twice.

## Pros

- I find the new logic much easier to reason about. I plan to extract it into a
function, to be used in refactors for `jj rebase -r` and `jj new --after`. It
will make it much easier to have a correct implementation of `jj rebase -r
--after`, even when rebasing onto a descendant.

- The de-duplication is no longer O(n^2). I tried to keep the common case fast.

## Alternatives

- We could make `jj rebase` and `jj new` use a separate function with the
algorithm shown here, without changing DescendantRebaser. I believe that the new
algorithm makes DescendatRebaser easier to understand, though, and it feels more
elegant to reduce code duplication.

- The de-duplication optimization here is independent of other changes, and
could be used on its own.
2023-12-12 19:35:51 -08:00
Yuya Nishihara
cdcd465c79 index: move default_index_store.rs to sub directory named default_index
default_index_store.rs is relatively big, and it contains types and impls in
arbitrary order. Let's split them into sub modules. After everything moved,
mod.rs will only contain tests.
2023-12-12 08:07:52 +09:00