When read/writing commits from the git-backend, populate the git commit
header with a backwards hash of the `change-id`. This should enable
preserving change identity across various git remotes assuming a
cooperative git server that doesn't strip the git header.
This feature is behind a `git.write-change-id-header` configuration flag
at least to start.
This uses `zlib-rs`, a native Rust library that is comparable in
performance to `zlib-ng`. Since there’s no complicated C build
and gitoxide only has one hashing backend now, this lets us drop our
`packaging` feature without adding any awkward build requirements.
`zlib-rs` is generally faster at decompression than
`zlib-ng`, and faster at compression on levels 6 and 9; see
<https://trifectatech.org/blog/zlib-rs-is-faster-than-c/>
for details.
I couldn’t get reliable‐looking benchmark results out of my
temperamental laptop; `hyperfine` seemed to think that some random
`jj` workloads I tested might be slightly slower than with `zlib-ng`,
but it wasn’t unambiguously distinguishable from noise, so I’d
like to see measurements from others.
It’s certainly a lot faster than the previous default, and I
think it’s likely that `zlib-rs` will continue to get faster
and that it’s more than worth avoiding the headaches of a native
library with a CMake build dependency. (Though on the other hand,
if distributions move in the direction of shipping `zlib-ng` by
default, maybe there will be more motivation to make `libz-ng-sys`
support system libraries.)
The version that returns Merge<_> will be used in diff functions. The added
helper functions will also be used in order to apply word-level merging.
Since we cannot express FnOnce(impl IntoIterator<..>) where the argument type is
controlled by callee, this patch adds helper trait to bridge collect_*()
functions.
This helps implement variants of file::merge() that return Merge<BString> or
Option<BString>. collect_hunks() could be implemented as FromIterator for
MergeResult. It would enable .collect(), but I don't think this abstraction
would generally be useful. The other types to which we want to collect the
outcome is Option<BString> and Merge<BString>. They could technically implement
FromIterator, but it would be weird if .collect() into Merge<BString> panicked
because of incompatible merge shapes.
Merge::resolved() is marked as const fn to clarify it is a trivial constructor.
We haven't updated `prost` in a while, and the reason for that is
probably because the code generation output slightly changed, which
would have caused dependabot to exclude that package from its updates as
a failure. (At least, I suspect that's what happened.)
This lets us drop a dependency on `itertools 0.12.x` because the prost
0.13.5 release weakened its constraints, allowing `itertools 0.13.x`.
Now we only depend on two major versions of itertools (0.10 + 0.12)
instead of three (previously four).
Signed-off-by: Austin Seipp <aseipp@pobox.com>
It can be useful for fixers to record some information about the
inputs they processed. For example, the `FileFixer` we use in our
server at Google get more detailed error information back from its
formatter tools. We may want to record these errors in our
`FileFixer`'s state so we can then return that to the client.
This function is similar to `transform_descendants_with_options`, but
only rewrites the given commits and not their descendants. This will
allow `rewrite::move_commits` to transform a given set of commits
without iterating through their descendants twice (once when computing
new parents and once when rewriting commits).
The `new_parents_map` will allow the parents of each commit to be
customized before the `transform_descendents` callback is invoked. This
is useful when the order of commits needs to be changed, whereby setting
the new parents in the default callback might lead to repeated rebasing
and cycles if the new parent has not been visited in the reverse
topological order traversal.
Fix GHSA-794x-2rpg-rfgr.
`gix::Repository::work_dir` was renamed to `workdir` (though strangely
not the `gix::ThreadSafeRepository` version), and `lossy_config`
is now off by default in all configurations.
Previously, this was calling `git_repository_open()`,
which is equivalent to `git_repository_open_ext()` with
`flags = GIT_REPOSITORY_OPEN_NO_SEARCH` and `ceiling_dirs =
NULL`. This changes `ceiling_dirs` to an empty string, and adds
`GIT_REPOSITORY_OPEN_FROM_ENV` to `flags` when we’re in test code.
`GIT_REPOSITORY_OPEN_FROM_ENV` is used to respect the Git configuration
path environment variables, which is what we want for the test
hermeticity code. It works like this:
* `config_path_system` will use `$GIT_CONFIG_SYSTEM` because `use_env`
will be set.
* `config_path_global` will use `$GIT_CONFIG_GLOBAL` because `use_env`
will be set.
* `git_config__find_xdg` and `git_config__find_programdata` will find
impure system paths and load them even when `$GIT_CONFIG_GLOBAL` is
set, contrary to Git behaviour, so we need to set `$XDG_CONFIG_HOME`
and `$PROGAMDATA`.
It has a few other effects, which I will exhaustively enumerate to
show that they are benign:
* It respects `$GIT_WORK_TREE` and `$GIT_COMMON_DIR`. These would
already break our tests, I think, so we’re assuming they’re
not set. (Possibly we should set them explicitly.)
* When opening a repository, it will:
* Set the starting path for the search to `$GIT_DIR` if it’s
`NULL`, but we do set it, so no change.
* Initialize `ceiling_dirs` to `$GIT_CEILING_DIRECTORIES` if it’s
`NULL`, but we do set it, so no change.
* Respect `$GIT_DISCOVERY_ACROSS_FILESYSTEM` and set the
`GIT_REPOSITORY_OPEN_CROSS_FS` flag appropriately. However,
this is only checked on subsequent iterations of the loop in
`find_repo_traverse`, and we set `GIT_REPOSITORY_OPEN_NO_SEARCH`
which causes it to never enter a second iteration.
* Use `ceiling_dirs` in `find_ceiling_dir_offset`, but the result is
ignored when `GIT_REPOSITORY_OPEN_NO_SEARCH` is set, so changing
from `NULL` to the empty string doesn’t affect behaviour. (It
also would always return the same result for either value, anyway.)
If a commit needs fixing but its descendant does not, we currently
skip rewriting the descendant, which means it will instead be rebased
when the transactions finished. That usually results in
conflicts. This adds a test case for that case.
This reverts commit b8ca9ae and adds a comment.
In commit 4d42604 (a year ago), we started writing the trees involved in
conflicted commits to the Git commit object in addition to the proto
storage. We validated that the two record matched when reading commits
until as recently as f7b14be (about a week ago). Just after that, in
commit b8ca9ae, we stopped writing the tree ids to the proto storage.
That means that any version of jj between 4d42604 and f7b14be would
error fail when reading a conflicted commit created by new versions.
While we don't guarantee forward compatibility, it's easy to do so here,
so let's be friendly to older versions by rolling back b8ca9ae so we
continue to write the conflicted tree ids to both places for a while
more.
(Thanks to Martin for the detailed explanation!)
Fixes https://github.com/jj-vcs/jj/issues/6185
I think this makes more sense because WorkspaceId is currently a human-readable
name. In error/status messages, workspace names are now printed in revset
syntax.
New WorkspaceId types do not implement Default. It would be weird if string-like
type had non-empty Default::default(). The DEFAULT constant is provided instead.
Wrapped errors are usually displayed after "Failed to import refs ...", etc., so
the context is obvious. I also removed "Internal"/"Error" for consistency.
This allows callers to mutate RevsetParseContext if needed.
RevsetParseContext was changed to an opaque struct at 4e0abf0631 "revset: make
RevsetParseContext opaque." I think the intent there was to hide implementation
details from revset extension functions. This is now achieved by opaque
LoweringContext.
Another reason of this change is that aliases_map is no longer needed when
transforming AST to UserRevsetExpression.
I tried to minimize this patch, but it seemed rather complicated than porting
most callers all at once. Remote management functions in git.rs are unchanged.
They'll be ported separately.
With this change, many non-template bookmark/remote name outputs should be
rendered in revset syntax.
It's a bit weird that Deref is required, but this helps deduce the query type.
Maybe we can add typed StringPattern wrapper, but I'm not sure if that's a good
idea.
Alternatively, RefNameBuf could implement Borrow<str>, but that means the map
could be looked up by weakly-typed string keys.
These types are akin to ObjectId types, but for refs. Perhaps, WorkspaceId can
be ported to impl_name_type!().
These types don't implement Display because it would be source of subtle bugs
if a string-like type could be formatted differently. For example, we would
have to be careful to not format!("refs/heads/{name}") if the name implemented
a default Display in revset syntax.
We've been finding that a lot of bug reports on `jj git push` come from
sub-standard error reporting on the reasons the failure happens.
It can come from a number of places:
- hook failure
- remote branch protection
- git config
This commit forwards the reason as explained by the ouptut of git push
to help users figure out what is happening.
We need to report more complicated errors on push.
Firstly, we can have a mix of unexpected ref locations and remote
rejections. We should report both at the same time.
Second, git gives us a reason for why a push failed.
For this to work, it's relevant to refactor the current error reporting
path to allow us to inject this information.
In colocated repos, we set up the Git index to make `git diff` closely
match `jj diff`. However, `git diff` will not include new files. We're
long talked about using the `git add --intent-to-add` feature to make
the match closer. This patch implements that. It does so both after
updating the working copy and after snapshotting. After updating the
working copy, the new file in the working-copy commit (compared to the
parent(s)) are marked as intent-to-add. After snapshotting, newly
snapshotted files are marked as intent-to-add, and deleted ones that
were previously marked as intent-to-add are removed from the index.
Closes#6122