Commit graph

528 commits

Author SHA1 Message Date
Ilya Grigoriev
b6a9423f38 git export: (almost) no-op refactor to export_refs to use RefName
This follows 3779b45, but in this case the refactor makes the logic more
complicated. The main goal here is to prepare for the next commit.
2023-07-03 11:01:22 -07:00
Yuya Nishihara
a07574a233 git: pass RefName enum to git_ref_filter callback
I think it's slightly better to compare each ref fragment than building
"refs/remotes/{remote}/{branch}" pattern to be matched.
2023-07-02 09:49:07 +09:00
Martin von Zweigbergk
c0ffce781e store: cache tree on write and return it
This matches what we do when writing commits.
2023-06-30 14:12:36 +02:00
Martin von Zweigbergk
134efabcef test_merge_trees: make merge_trees() wrapper's signature match original 2023-06-30 14:12:36 +02:00
Martin von Zweigbergk
779b8ba318 files: replace uses of MergeHunk by Conflict<ContentHunk>
Since `Conflict`s can represent the resolved state, so
`Conflict<ContentHunk>` can represent the states that we use
`MergeHunk` for. `MergeHunk` does force the user to handle the
resolved case, which may be useful. I suppose one could use the same
argument for making `Conflict` an enum, i.e. if we think that
`MergeHunk`'s two variants are beneficial, then we should consider
making `Conflict` an enum with those two variants.
2023-06-28 06:51:37 +02:00
Martin von Zweigbergk
c625e9352d files: make MergeHunk::Conflict be a Conflict<ContentHunk>
The `ConflictHunk` type doesn't add anything over
`Conflict<ContentHunk>`.
2023-06-27 21:06:32 +02:00
Martin von Zweigbergk
b1f2e80349 files: add a newtype around Vec<u8> for content hunks
It's useful to have a more readable `Debug` format for `Vec<u8>`
(`"foo"` is better than `[102, 111, 111]`). It might also make types
in function signatures and elsewhere more readable.
2023-06-27 21:06:32 +02:00
Glen Choo
7afaa2487b git: add .gitmodules parser
This only parses the fields relevant to us, i.e.:

- name: the stable identifier of the submodule
- path: the path to the submodule in the current commit
- url: the remote we can clone the submodule from

The full list of .gitmodules fields can be found at
https://git-scm.com/docs/gitmodules.
2023-06-27 10:07:00 -07:00
Kevin Liao
86b6a11e63 Fix jj init --git-repo fails and leaves broken .jj folder
This commit fixes #1305

Before this commit, running `jj init --git-repo=./` in a folder that
does not have a .git would cause jj to panick and leave an unfinished corrupted jj repo.

This commit fixes that by changing the call chain to return an error
instead of calling .unwrap() and panicking. This commit also adds logic to delete the unfinished jj
repository when the git backend initialization failed.

Before this commit, running the above command would result in the following
```
Running `jj/target/debug/jj init --git-repo=./`
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { code: -3, klass: 2, message: "failed to resolve path '/Users/kevincliao/github/jj/test-repo/.jj/repo/store/../../../.git': No such file or directory" }', lib/src/git_backend.rs:83:75
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```

After this commit, the result is the following and the jj repo is deleted:
```
Running `jj/target/debug/jj init --git-repo=./`
Error: Failed to access the repository: Error: Failed to open git repository: failed to resolve path '/Users/kevincliao/github/jj/test-repo/.jj/repo/store/../../../.git': No such file or directory; class=Os (2); code=NotFound (-3)
```
2023-06-20 11:02:06 -07:00
Glen Choo
6621f261cc repo: add submodule_store, default impl
..and other assorted boilerplate. These are just stubs for now, but now
that we've reserved the `submodule_store` subdirectory, we can start
adding more functionality.
2023-06-19 09:48:58 -07:00
Martin von Zweigbergk
82883e648d conflicts: move describe_conflict() etc. onto Conflict
Before we had `conflicts::Conflict`, most of these functions took a
`backend::Conflict`. I think I didn't want to pollute the `backend`
module with this kind of logic, trying to keep it focused on
storage. Now that we have the type in `conflicts`, however, I think it
makes sense to move these functions onto it.
2023-06-19 07:05:02 +02:00
Yuya Nishihara
a67d8b5a65 index: turn CompositeIndex::walk_revs() into position-based API
This gets rid of round-trip conversion from queries like "(main..)-". I have
such expression in my default log/disambiguation revset, and the query could
take ~150ms to convert head positions back and forth if the repository had
tons of unmerged commits.
2023-06-19 13:41:43 +09:00
Martin von Zweigbergk
19fd8a917a conflicts: remove ConflictId from update_conflict_from_content()
For tree-level conflicts (#1624), I plan to remove `ConflictId`
completely. This commit removes `ConflictId` from
`update_conflict_from_content()` by instead making it take a
`Conflict<Option<TreeValue>>` and return a possibly different such
value.

I made the call site in `working_copy` avoid writing the conflict to
the store if it's unchanged, but I didn't make the same optimization
in `merge_tools` becuase it's much more likely to have changed there.
2023-06-13 08:49:46 +02:00
Ilya Grigoriev
096538ba18 revsets: stop jj parsing br as a git_ref refs/heads/br
Use `br@git` instead.

Before, if there is not a local branch `br`, jj tried to resolve
it as a git ref `refs/heads/br`. Unchanged from before, `br` can
still be resolved as a tag `refs/tag/br`.
2023-06-12 14:31:44 -07:00
Ilya Grigoriev
738f99ddf1 test_revset.rs: disable nightly clippy false-positive warning
I opened a bug for the clippy error:
https://github.com/frondeus/test-case/issues/122
2023-06-11 13:11:01 -07:00
Waleed Khan
23a4124d20 feat(revset): suggest similar branch names 2023-06-05 11:11:17 -05:00
Martin von Zweigbergk
29b676f24f store: do conversion to/from backend::Conflict
We now convert to/from `backend::Conflict` right before/after calling
the `Store` methods, so we can simplify by having the `Store` do the
conversion.
2023-06-04 06:48:34 -07:00
Martin von Zweigbergk
c378503991 conflicts: replace remaining uses of backend::Conflict 2023-06-04 06:48:34 -07:00
Martin von Zweigbergk
f4499aa65e conflicts: fix bug when modifying modify/delete conflicts
Currently, if the user modifies a modify/delete conflict, we always
consider the result resolved. That happens because we materialize the
missing side of the conflict as an empty string but when we parse the
conflict, we expect only the number of sides in the input
conflict. For example, if the input is a regular modify/delete
conflict with one remove and one add, the materialized markers will
have one remove and two adds (one of them empty), but when we try to
parse it, we expect one remove and only one add. When we fail to parse
it, we consider it resolved.

This commit fixes the bug by using
`conflicts::Conflict<Option<TreeValue>>` and keeping track of which
sides were supposed to be empty. We could have fixed the bug without
switching to `conflicts::Conflict`, but we want to switch anyway, and
the fix happens naturally when switching.
2023-06-04 06:48:34 -07:00
Yuya Nishihara
78a64edb22 dag_walk: rename bfs() to dfs() because it's depth-first
No callers appear to rely on traversal order, so let's just fix the function
name. Maybe it was a typo.
2023-06-04 11:47:49 +09:00
Yuya Nishihara
3ba544414c dag_walk: unbox bfs() callback, use iter::from_fn() to implement iterator
I just wanted to remove syntactic noise from callers. iter::from_fn() helps
to avoid declaring struct with lots of type parameters.
2023-06-04 11:47:49 +09:00
Yuya Nishihara
3d449c55b7 tree_builder: do not omit file entry which was previously a directory 2023-06-01 09:38:06 +09:00
Yuya Nishihara
ae9f7aba52 tests: add test for file-directory-file transition
TreeBuilder fails to handle directory-file transition right now, and leaves
the dirty file as "clean".
2023-06-01 09:38:06 +09:00
Martin von Zweigbergk
fb17e6a50e revset: use different errors for ambiguous commit/change IDs
I made a typo and got something like this:

```
Error: Commit or change id prefix "wl" is ambiguous
```

Since we can tell commit ids from change ids these days, let's make
the error message say which kind of id it is. Changing that also kind
of forced me to make a special error for empty strings. Otherwise we
would have to arbitrarily say that an empty string is a commit id or
change id. A specific error message for empty strings seems helpful,
so that's probably for the better anyway.
2023-05-31 06:28:32 -07:00
Yuya Nishihara
b7b9b8c88e index: pass only CompositeIndex to default_revset_engine::evaluate() 2023-05-29 08:15:40 +09:00
Yuya Nishihara
cf5cb380bb index: implement Index for CompositeIndex
We can't get rid of the other "impl Index"es because .as_composite() must
return a real reference type. Maybe we could turn CompositeIndex into an
owned wrapper, but I don't know if that would be worth the effort.
2023-05-29 08:15:40 +09:00
Yuya Nishihara
5989bdf781 index: move Index::as_any() to MutableIndex, obtain CompositeIndex from there
It might sound scary to add public .mutable_index() accessor, but I think
it's okay because immutable MutableIndex reference has no more power than
Index.

This allows us to implement Index for lifetime-bound type such as
CompositeIndex<'_>.
2023-05-29 08:15:40 +09:00
Yuya Nishihara
93284a153f index: obtain CompositeIndex from ReadonlyIndexWrapper
I'll remove Index::as_any() so that Index can be implemented for reference
wrapper.
2023-05-29 08:15:40 +09:00
Yuya Nishihara
fb77c55268 index: use as_composite() to access to index stats
The idea is that .as_composite() is equivalent to .as_index(), but for the
implementation type. I'm going to add "impl Index for CompositeIndex" to
clean up index references passed to revset engine.
2023-05-29 08:15:40 +09:00
Martin von Zweigbergk
f838d083d3 tree: add test of merge of executable bit
We didn't seem to have any tests of this, so let's add one before I
change the implementation.
2023-05-24 22:00:38 -07:00
Yuya Nishihara
e24fe817c9 tests: invoke .walk_revs() through CompositeIndex
Prepares for removal of the index trait method.
2023-05-24 01:02:37 +09:00
Yuya Nishihara
b01614bbdd cleanup: leverage scoped thread in tests 2023-05-21 21:02:58 +09:00
Yuya Nishihara
38a7e7fd62 git_backend: on read_commit(), bulk-update extra metadata table of ancestors
Otherwise, "jj init --git-repo ." would create extra table files per commit,
and merge them.

I considered adding an explicit GitBackend method to be called from
git::import_refs(), but the call order matters. The method should be invoked
before calling store.get_commit(..) or mut_repo.add_head(..). Since commits
are likely to be loaded from the head, we can instead make read_commit()
import ancestor metadata at all.

Alternatively, we could make a Git commit hidden until it's inserted into
the extra table. It's rather big change, and I wouldn't like to do that
without thinking more thoroughly.
2023-05-21 08:29:00 +09:00
Yuya Nishihara
a9422460cb git_backend: ensure change id generated from git commit id never reassigned
Fixes #924
2023-05-20 15:53:23 +09:00
Yuya Nishihara
9aa72f6f1d git_backend: add lock to prevent racy change id assignments
My first attempt was to fix up corrupted index when merging, but it turned
out to be not easy because the self side may contain corrupted data. It's
also possible that two concurrent commit operations have exactly the same
view state (because change id isn't hashed into commit id), and only the
table heads diverge.

#924
2023-05-20 15:53:23 +09:00
Yuya Nishihara
3655da4f01 tests: add tests for concurrent git commit/change id assignment
Since non-Git metadata isn't hashed, we can't rely on the consistency
provided by content-addressed storage. The problem is also described in
https://github.com/martinvonz/jj/issues/3#issuecomment-947998487

#924
2023-05-20 15:53:23 +09:00
Ilya Grigoriev
714aff63e6 git.rs: properly abandon commits from moved/deleted branches on remote (#864)
This bug concerns the way `import_refs` that gets called by `fetch` computes
the heads that should be visible after the import.

Previously, the list of such heads was computed *before* local branches were
updated based on changes to the remote branches. So, commits that should have
been abandoned based on this update of the local branches weren't properly
abandoned.

Now, `import_refs` tracks the heads that need to be visible because of some ref
in a mapping keyed by the ref. If the ref moves or is deleted, the
corresponding heads are updated.

Fixes #864
2023-05-17 17:57:58 -07:00
Ilya Grigoriev
cf4a603eb4 Tests demonstrating a similar bug with moved rather than deleted branch 2023-05-17 17:57:58 -07:00
Ilya Grigoriev
a0ee2b0dbd lib/tests/test_git.rs: New test to demonstrate #864's root cause 2023-05-17 17:57:58 -07:00
Ilya Grigoriev
bda3d3e50b test_import_refs_reimport: very minor improvement to a test 2023-05-17 17:57:58 -07:00
Martin von Zweigbergk
87a925d736 git_backend: return timestamps for what was actually written
Now that we return the written commit from `write_commit()`, let's
make the timestamps match what was actually written, accounting for
the whole-second precision and the adjustment we do to avoid
collisions.
2023-05-12 15:20:44 -07:00
Martin von Zweigbergk
e7419e76a1 backend: replace git_repo() by as_any()
This has several advantages:

 * Makes it possible to downcast to non-Git custom backends (might be
   useful at Google, but we haven't needed it yet)

 * Lets us access more specific functionality on the `GitBackend`,
   making it possible to access the `git2::Repository` without
   creating a copy of it.

 * Removes the dependency on Git from the backend
2023-05-12 08:05:09 -07:00
Yuya Nishihara
f58beca760 revset: move resolve_symbol() to tests
It's no longer used in library code.
2023-05-12 21:31:29 +09:00
Martin von Zweigbergk
916b00c33e id_prefix: remove repo field from IdPrefixContext
By passing the repo as argument to the methods instead, we can remove
the `repo` field and the associated lifetime. Thanks to Yuya for the
suggestion.
2023-05-11 23:41:24 -07:00
Martin von Zweigbergk
6a4502cb5d prefixes: allow resolving shorter ids within a revset
In large repos, the unique prefixes can get somewhat long (~6 hex
digits seems typical in the Linux repo), which makes them less useful
for manually entering on the CLI. The user typically cares most about
a small set of commits, so it would be nice to give shorter unique ids
to those. That's what Mercurial enables with its
`experimental.revisions.disambiguatewithin` config. This commit
provides an implementation of that feature in `IdPrefixContext`.

In very large repos, it can also be slow to calculate the unique
prefixes, especially if it involves a request to a server. This
feature becomes much more important in such repos.
2023-05-11 23:41:24 -07:00
Martin von Zweigbergk
efd743339c revset: don't allow symbols in RevsetExpression::resolve()
When creating `RevsetExpression` programmatically, I think we should
use commit ids instead of symbols in the expression. This commit adds
a check for that by using a `SymbolResolver` that always errors
out.
2023-05-11 23:41:24 -07:00
Martin von Zweigbergk
99e9cd70d1 cli: make WorkspaceCommandHelper create SymbolResolver
I would eventually want the `SymbolResolver` to be customizable (in
custom `jj` binaries), so we want to make sure we always use the
customized version of it.

I left `RevsetExpression::resolve()` unchanged. I consider that to be
for programmatically created expressions.
2023-05-11 23:41:24 -07:00
Yuya Nishihara
92cfffd843 git: on external HEAD move, do not abandon old branch
The current behavior was introduced by 20eb9ecec1 "git: don't abandon
HEAD commit when it loses a branch." While the change made HEAD mutation
behavior more consistent with a plain ref operation, HEAD can also move on
checkout, and checkout shouldn't be considered a history rewriting operation.

I'm not saying the new behavior is always correct, but I think it's safer
than losing old HEAD branch. I also think this change will help if we want
to extract HEAD management function from git::import_refs().

Fixes #1042.
2023-05-11 10:15:31 +09:00
Yuya Nishihara
66d405fa5f git: add tests that simulate external checkout/amend in colocated repo
I'm going to change the behavior of _without_ref() case to mitigate #1042.
2023-05-11 10:15:31 +09:00
Benjamin Saunders
ccbb34fddb working_copy: introduce snapshot progress callback 2023-05-06 11:07:46 -07:00