Commit Graph

174 Commits

Author SHA1 Message Date
Martin von Zweigbergk
f05a12d301 index: make CompositeIndex non-public and add new IndexRef enum instead
We're getting close to finally having a `RepoRef::index()` method.
2021-02-13 13:56:26 -08:00
Martin von Zweigbergk
face4d637f index: define methods from CompositeIndex directly on {Readonly,Mutable}Index
This is one step towards making `CompositeIndex` non-public (and maybe
deleting it). Next, we'll add an `IndexRef` enum similar to `RepoRef`
etc.
2021-02-13 13:46:58 -08:00
Martin von Zweigbergk
8dda4b05e4 index: add "segment_" prefix to methods in IndexSegment
I'm about to move the functions from `CompositeIndex` to an new
`Index` trait implemeted by `ReadonlyIndex` and `MutableIndex`. Since
those types already implement `IndexSegment`, the names would conflict
and it would get annoying to have to disambiguate them. This commit
therefore prepares for that by adding a `segment_` prefix to the
functions in `IndexSegment`.
2021-02-13 13:45:31 -08:00
Martin von Zweigbergk
3066381d57 transaction: add accessors for view and evolution directly on transaction 2021-02-13 13:43:48 -08:00
Martin von Zweigbergk
72aebc9da3 view: replace View trait by enum with Readonly and Mutable variants 2021-02-13 08:31:41 -08:00
Martin von Zweigbergk
d1e5f46969 evolution: replace Evolution trait by enum with Readonly and Mutable variants 2021-02-13 08:31:41 -08:00
Martin von Zweigbergk
f1666375bd repo: replace Repo trait by enum with readonly and mutable variants
I want to keep the index updated within the transaction. I tried doing
that by adding a `trait Index`, implemented by `ReadonlyIndex` and
`MutableIndex`. However, `ReadonlyRepo::index` is of type
`Mutex<Option<Arc<IndexFile>>>` (because it is lazily initialized),
and we cannot get a `&dyn Index` that lives long enough to be returned
from a `Repo::index()` from that. It seems the best solution is to
instead create an `Index` enum (instead of a trait), with one readonly
and one mutable variant. This commit starts the migration to that
design by replacing the `Repo` trait by an enum. I never intended for
there there to be more implementations of `Repo` than `ReadonlyRepo`
and `MutableRepo` anyway.
2021-02-13 08:31:23 -08:00
Martin von Zweigbergk
a1983ebe96 git: add a ref to each commit we create
I just learned that attaching a git note is not enough to keep a
commit from being GC'd. I had read `git help gc` before but it was
quite misleading (I just sent a patch to clarify it). Since the git
note is not enough, we need to create some other reference. This patch
makes it so we write refs in `refs/jj/keep/` for every commit we
create. We will probably want to remove unnecessary refs (ancestors of
commits pointed to by other refs) once we have a `jj gc` command.
2021-02-13 08:16:18 -08:00
Martin von Zweigbergk
dd98f0564e git: remove git note pointing to conflicts
We store conflicts as blobs with JSON data and with a git note
pointing to them to prevent GC. These are stored in the git tree as
regular files. The only thing that distinguishes them is that their
filename ends with `.jjconflict`. Since they are referenced from the
tree, there's no need for the git note to prevent GC (which doesn't
work anyway, as I just learned), and we don't store any additional
data in the note either, so let's just remove it.
2021-02-13 08:15:12 -08:00
Martin von Zweigbergk
fa30cf768f index: rename UnsavedIndexData to MutableIndex 2021-02-07 23:35:37 -08:00
Martin von Zweigbergk
8170c06573 index: rename IndexFile to ReadonlyIndex 2021-02-07 23:35:22 -08:00
Martin von Zweigbergk
51373b75ff index: use correct per-level file name in stats (previously always top-level) 2021-02-07 23:34:57 -08:00
Martin von Zweigbergk
302c66825f working_copy: preserve executable bit on Windows
Windows doesn't support recording the executable bit in the file
system. Before this commit, the code for reading and writing the
executable wouldn't even compile on Windows. This commit at least
makes it so we preserve whatever bit has been recorded in the repo.
At least I hope that's what it does -- I don't have access to a
Windows machine right now.
2021-02-07 00:50:21 -08:00
Martin von Zweigbergk
d4aed83aa6 working_copy: correct comment about stat accuracy
We don't take a write lock when writing a file; other processes can
modify the file.
2021-02-07 00:48:50 -08:00
Martin von Zweigbergk
3d679de022 working_copy: print warning about ignored symlinks instead of failing build
The project doesn't currently build on Windows. One reason is because
we had a `unimplemented!()` when trying to write a symlink. Let's
print a warning instead, so the project can start building on
Windows. (The next patch will fix another build problem on Windows.)
2021-02-07 00:46:17 -08:00
Martin von Zweigbergk
e0112a4be0 transaction: report failure to close transaction only in debug builds
When a transaction gets dropped without being committed or explicitly
discarded, we currently raise an assertion error. I added that check
because I kept forgetting to commit transactions. However, it's quite
normal to want to drop transactions in error cases. The current
assertion means that we panic and don't report the actual error to the
user in such cases. We should probably audit the code paths where we
commit transactions and decide for each if we simply want to to
discard the transaction or not. In some cases, we may want to commit
the transaction without integrating it in the operation log
(i.e. without creating a file entry in .jj/views/op_heads/). However,
we can do that later. For now, let's just make sure we don't panic
when dropping the transaction in release builds.
2021-02-07 00:11:42 -08:00
Martin von Zweigbergk
4ecbd89378 repo: move MutableRepo from transaction module to repo module 2021-01-31 18:15:32 -08:00
Martin von Zweigbergk
2d03b514fc transaction: move construction of MutableRepo out of Transaction::new()
I'm about to move `MutableRepo` to the `repo` module and it will make
more sense to have the construction of it there then.
2021-01-31 18:15:32 -08:00
Martin von Zweigbergk
bf53c6c506 transaction: add factory function to MutableRepo
This helps finish the encapsulate of the `evolution` field.
2021-01-31 18:15:32 -08:00
Martin von Zweigbergk
5604303954 transaction: avoid direct access to members of MutableRepo
I'm about to move `MutableRepo` to the `repo` module so it becomes
more important to encapsulate access. Besides, the new functions
introduced in this commit reduces some duplication.

There's still one access of `MutableRepo::evolution` in
`Transaction::new()`. I'll address that next by adding a factory
function to `MutableRepo`.
2021-01-31 18:15:32 -08:00
Martin von Zweigbergk
a28fe7b388 transaction: slightly simplify write_commit() by using store() 2021-01-31 18:15:22 -08:00
Martin von Zweigbergk
49d386931d tests: fix smoke test broken by bad23cda74
I apparently didn't run tests on that commit :(
2021-01-24 23:02:17 -08:00
Martin von Zweigbergk
bea399640b commands: don't leave color on after printing error
E.g. `jj log` outside a repo would print the message with red color
and then not turn off the color after the message.
2021-01-23 23:52:13 -08:00
Martin von Zweigbergk
37a2fbce65 commands: add -m to jj merge and jj close 2021-01-23 23:48:47 -08:00
Martin von Zweigbergk
c459c61cdb merge: ask user for commit description
The command would leave the description blank until now.
2021-01-23 23:32:16 -08:00
Martin von Zweigbergk
bad23cda74 describe: rename --text argument to more standard --message
I'm about to add the argument to `jj merge` and `jj close` as
well. For those, I think `--description` would have made more sense
than `--text`, but I don't like the idea of having the short form be
`-d` (sounds too much like `--destination` or `--delete`). It's
unfortunate that `jj describe` set the "commit description" but the
argument is called "message". That still seems better than calling the
command `jj message`.
2021-01-23 23:32:04 -08:00
Martin von Zweigbergk
9ffd35caf8 transaction: when checking out open commit with conflicts, create child commit
I've been confused twice that rebasing an open commit so it results in
conflicts doesn't show the conflicts in the log output. That's because
we create a successor instead if a commit with conflicts is open. I
guess I thought it would be expected that a child commit was not
created. Since it seems surprising in practice, let's change it and
we'll see if the new behavior is more or less surprising.
2021-01-22 11:41:52 -08:00
Martin von Zweigbergk
bb730d8a2b merge: rewrite code for 3-way merge of files to handle not just trivial cases
The most annoying remaining bug is that 3-way merge frequently panics
with "unhandled merge case". This commit fixes that by rewriting the
merge code. The new code is based on the algorithm used in Mercurial
(which was in turn copied from Bazaar):

 1. Find "sync" regions, which are regions that are the unchanged in
    the base and two sides. Note their start end end positions in each
    version.

 2. Produce the output by taking the sync regions and inserting the
    result of merging the regions between the sync regions. These
    regions can either be changed on only one side, in which case we
    use that version, or it can be changed on both sides, in which
    case we indicate a conflict in the output.

It's both more correct and much easier to follow.
2021-01-22 11:41:50 -08:00
Martin von Zweigbergk
7957feca49 diff: make tokenization return slices instead of making copies 2021-01-21 22:42:55 -08:00
Martin von Zweigbergk
2879d817dd readme: some further touch-up, plus a correction about in-tree conflicts 2021-01-20 00:06:42 -08:00
Martin von Zweigbergk
30939ca686 view: return &HashSet instead of Iterator
We want to be able to be able to do fast `.contains()` checks on the
result, so `Iterator` was a bad type. We probably should hide the
exact type (currently `HashSet` for both readonly and mutable views),
but we can do that later. I actually thought I'd want to use
`.contains()` for indiciting public-phase commits in the log output,
but of course want to also indicate ancestors as public. This still
seem like a step (mostly) in the right direction.
2021-01-16 13:00:05 -08:00
Martin von Zweigbergk
79eecb6119 git: mark imported remote-tracking branches as public 2021-01-16 12:14:42 -08:00
Martin von Zweigbergk
4db3d8d3a6 view: add tracking of "public" heads (copying Mercurial's phase concept)
Mercurial's "phase" concept is important for evolution, and it's also
useful for filtering out uninteresting commits from log
output. Commits are typically marked "public" when they are pushed to
a remote. The CLI prevents public commits from being rewritten. Public
commits cannot be obsolete (even if they have a successor, they won't
be considered obsolete like non-public commits would).

This commits just makes space for tracking the public heads in the
View.
2021-01-16 11:48:35 -08:00
Martin von Zweigbergk
265f90185e tests: simplify transaction tests slightly by using testutils more 2021-01-16 11:31:57 -08:00
Martin von Zweigbergk
f43880381f view: make sure we don't leave a dangling git ref
All commits in the view are supposed to be reachable from its
heads. If a head is removed and there are git refs pointing to
ancestors of it (or to the removed head itself), we should make that
ancestor a head.
2021-01-16 11:05:32 -08:00
Martin von Zweigbergk
1f593a4193 view: create helper for enforcing view's invariants
The only invariant we currently enforce is that the set of heads does
not include any ancestors of other commits in the set. I'm about to
make sure that we don't end up with dangling git refs (pointing to
commits no reachable from the heads). It will be useful to have a
single place to enforce that since we'll need to do the same thing
after updating the view as after merging views.
2021-01-16 10:35:46 -08:00
Martin von Zweigbergk
1f27a78957 view: make remove_head() not add parents as heads
I think it's better to let the caller decide if the parents should be
added. One use case for removing a head is when fetching from a Git
remote where a branch has been rewritten. In that case, it's probably
the best user experience to remove the old head. With the current
semantics of `View::remove_head()`, we would need to walk up the graph
to find a commit that's an ancestor and for each commit we remove as
head, its parents get temporarily added as heads. It's much easier for
callers that want to add the parents as heads to do that.
2021-01-15 01:08:05 -08:00
Martin von Zweigbergk
315818260f git: slightly simplify a few tests 2021-01-11 00:34:04 -08:00
Martin von Zweigbergk
f4a6732d35 git: import refs after pushing to git remote
This makes it so `jj git push` effectively runs `jj git refresh` after
pushing. That's useful so the user sees the updated remote-tracking
branch.
2021-01-11 00:25:50 -08:00
Martin von Zweigbergk
19b542b318 git: simplify error handling by passing git repo into git module functions 2021-01-11 00:25:39 -08:00
Martin von Zweigbergk
b1588afc63 log: include git refs in default templates
They're rendered as a single string created by joining the refs by
spaces because we don't have any support in the template language for
rendering a list.
2021-01-10 20:13:31 -08:00
Martin von Zweigbergk
da0bbbe637 view: start tracking git refs
Git refs are important at least for understanding where the remote
branches are. This commit adds support for tracking them in the view
and makes `git::import_refs()` update them.

When merging views (either because of concurrent operations or when
undoing an earlier operation), there can be conflicts between git ref
changes. I ignored that for now and let the later operation win. That
will probably be good enough for a while. It's not hard to detect the
conflicts, but I haven't yet decided how to handle them. I'm leaning
towards representing the conflicting refs in the view just like how we
represent conflicting files in the tree.
2021-01-10 20:13:22 -08:00
Martin von Zweigbergk
3df6a92df6 view: merge concurrent operations ordered by transaction commit time
This will make it easier to test the result of concurrent operations
(just make sure the operations don't commit during the same
millisecond).
2021-01-10 19:34:52 -08:00
Martin von Zweigbergk
c4cd12e93e view: use the Operation wrapper type in merge_op_heads()
This is partly to prepare for merging the operations in order of
transaction-commit time (currently merged in order of operation id),
so we can get a predictable order in tests (assuming transactions are
not committed the same millisecond).
2021-01-10 19:34:52 -08:00
Martin von Zweigbergk
48e664c716 view: make the View types not store concrete OpStore type 2021-01-10 19:34:52 -08:00
Martin von Zweigbergk
1f53285f64 log: output heads in graph ordered by commit id instead of by hash
It was really annoying that the order kept changing as commits got
rewritten. Also, I prefer to see the latest commits at the top (like
Mercurial does it).
2021-01-10 19:34:50 -08:00
Martin von Zweigbergk
7572a32077 readme: some very minor improvements 2021-01-05 22:39:11 -08:00
Martin von Zweigbergk
a3de39a35a repo: inline init_cycles() now that it's very short
The function used to be larger when we had more reference cycles
between e.g. the `WorkingCopy` and `Repo`. Now there's only
`Evolution` left, so let's inline the function.
2021-01-04 11:18:16 -08:00
Martin von Zweigbergk
7494a03081 repo: return error when attempting to load repo where there is none
This commits makes it so that running commands outside a repo results
in an error message instead of a panic.

We still don't look for a `.jj/` directory in ancestors of the current
directory.
2021-01-04 09:18:09 -08:00
Martin von Zweigbergk
86b2c6b464 restore: restore all files by default
I often (try to) use the command for throwing away all working copy
changes. That currently results in a crash on
`submatches.values_of("paths").unwrap()`. Let's make it revert
everything by default instead, since that seems to be my
intuition. Unlike most VCS's, we have a backup of the working copy and
the user can simply do `jj op undo` if they realized it was a mistake.
2021-01-03 23:11:22 -08:00