Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Project Roots #5041

Draft
wants to merge 164 commits into
base: trunk
Choose a base branch
from
Draft

[WIP] Project Roots #5041

wants to merge 164 commits into from

Conversation

ChrisPenner
Copy link
Contributor

@ChrisPenner ChrisPenner commented Jun 3, 2024

Overview

Major changes:

  • Loose code is gone from UCM, any code you had in your local loose-code will be automatically migrated to a project called legacy (or legacy1, legacy2, etc. if any name is taken). Note: you can still pull from loose code (for now).
  • The single global root is gone. Every project branch is loaded by its own root. Only one project-branch is loaded at a time.
  • Absolute paths now resolve to the root of the project-branch
  • Some commands can now accept paths/names from other branches of the form /branch:.path.in.project
  • You shouldn't EVER see another project UUID in a path 🎉
  • New reflog commands!
    • reflog, branch.reflog or reflog.branch shows the changes for the current branch head
    • project.reflog or reflog.project shows changes to any branches in the current project
    • reflog.global shows changes across all project-branches in any project.
  • reset will correctly set only the current project-branch head.
  • undo rewinds one node in the history of the current project-branch, and will no longer cause any corruption or weirdness to your projects

Implementation notes

  • Adds new ProjectPath data type which is a fully-qualified path containing a project, branch, and absolute path within it. This is used pretty much everywhere.
  • There's no longer an in-memory Branch in Loop State, it was primarily removed to make it easier to pre-load other projects and keep them cached to speed up project-switching, but as a nice side-effect it's now impossible to get your memory branch out of sync with Sqlite from a ctrl-c.
  • I kept the old reflog around behind a deprecated.root-reflog command, but it's not scoped to projects, so probably isn't terribly useful.
    • the old reflog is never written to anymore, but supposing you upgraded your codebase from an earlier UCM than this PR, and still wanted to reference some hashes that had been in its reflog, you can still read them here.
  • New Project-based reflog allows listing the reflog by project-branch, project, or global, and shows the hash for the head of the branch rather than the global root.
  • Removes "mostRecentNamespace" in favour of "currentProjectPath" in sqlite, but this otherwise behaves the same.
  • I had to refactor the migration module because this migration requires disabling foreign keys (temporarily, and I do a foreign key check after re-enabling), but unfortunately you can't do this inside a transaction, so I had to refactor the migrations to take a connection instead.
  • Moves createSchema from U.Codebase.Sqlite.Queries to Unison.Codebase.SqliteCodebase.Operations to prevent cyclic imports
  • Adds a new codebase migration which:
    • Adds the new project reflog table
    • Adds the project-branch head as a causal-hash-id column on the project-branch table, and populates it from all the projects in the project root.
    • Makes a new legacy project from the existing root branch (minus .__projects)
    • Adds a new scratch/main project
    • Adds a currentProjectPath table to replace the most-recent-path functionality.

Interesting/controversial decisions

  • I ended up changing the branch relative syntax from /branch:path.to.thing into /branch:.path.to.thing because it seemed more consistent now that absolute paths are project relative, we can talk about changing it back if we like :)

  • transcripts run by transcripts (not ucm transcript) won't print timestamps in the reflog output

Test coverage

  • I ported most of the transcripts to projects on trunk, but obviously there are still a LOT of transcript changes to reflect the new behaviours, so please read through the transcript changes and transcript output.
  • Added an undo transcript, we didn't seem to have one

Loose ends

  • names.global, view.global, find.global are currently disabled until we decide how to address them, but we do plan to bring them back (and hopefully faster than before?)
  • Maybe improve caching of multiple branches so you can swap back-and-forth between them quickly
  • It's now pretty easy to add branch-relative-path support to more commands, so we should do a pass on that, not as part of this PR though.

More loose ends:

  • actual root namespace table still exists
  • Ensure newly updated/put branches get into the branch cache.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is now inexpressible since we can't cd into subnamespaces in projects with the transcript parser, and cd'ing is deprecated anyways.




□ 1. #sg60bvjo91 (start of history)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notably you can no longer have an actually "empty" history, the project-branch-head has to be set to something, in this case the empty branch.

We could possibly check for equivalence to the empty hash and call it out in the output if we want.

Comment on lines -268 to -273
Original Changes
1. ns2.fromJust ┐ 2. ns2.fromJust' (removed)
3. ns2.fromJust' │
4. ns2.yoohoo │
5. ns3.fromJust │
6. ns3.fromJust' ┘
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're running the delete from inside a specific branch now, so it doesn't show Originals from the others.

b#aapqletas7 : ##Nat
b#aapqletas7 = ##Nat.+ a#vrs8gtkl2t 1
a#r3msrbpp1v : Nat
a#r3msrbpp1v = 777
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use the same original value for creating conflicts for both a and b now (777) because we can't yet alias terms from one branch into another.




□ 1. #sg60bvjo91 (start of history)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same note as above, every branch must have a head, so there's no "empty namespace" anymore.

@@ -86,30 +86,33 @@ scratch/a2> view A NeedsA f f2 f3 g
= NeedsA (A a b Nat Nat)
| Zoink Text

f : A Nat Nat Nat Nat -> Nat
f : #re3rf9cedk Nat Nat Nat Nat -> Nat
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs looking into 🤔

Comment on lines 83 to 93
-- We can search by suffix and find all definitions in the codebase named 'x', and each of their aliases respectively.
.some> names.global x

Terms
Hash: #gjmq673r1v
Names: .some.otherplace.y .some.place.x .somewhere.z

Hash: #pi25gcdv0o
Names: .some.otherplace.x
TODO: swap this back to a 'ucm' block when names.global is re-implemented

```
-- We can search from a different branch and find all names in the codebase named 'x', and each of their aliases respectively.
scratch/other> names.global x
-- We can search by hash, and see all aliases of that hash in the codebase
.some> names.global #gjmq673r1v

Term
Hash: #gjmq673r1v
Names: .some.otherplace.y .some.place.x .somewhere.z

scratch/other> names.global #gjmq673r1v
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Temporarily disabled.

@@ -175,93 +175,3 @@ scratch/main> view preserve.otherTerm
preserve.otherTerm y = someTerm y

```
### Propagation only applies to the local branch
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is inexpressable now that we can't cd into a subnamespace of a project branch.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This transcript got mostly rewritten

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This transcript got mostly rewritten

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brand new transcript

project_id INTEGER NOT NULL,
branch_id INTEGER NOT NULL,
-- A json array like ["foo", "bar"]; the root namespace is represented by the empty array
path TEXT PRIMARY KEY NOT NULL,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the current path in the current project (might go away if cd goes away)

@@ -771,7 +771,7 @@ a |> f = f a
This diff should be empty if the two namespaces are equivalent. If it's nonempty, the diff will show us the hashes that differ.

```ucm
.> diff.namespace a1 a2
scratch/main> diff.namespace /a1:. /a2:.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would like to be able to diff.namespace /a1 /a2; would that already work?


Done.

```
```ucm
.> diff.namespace b1 b2
scratch/main> diff.namespace /b1: /b2:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this works too, which is nice

@@ -189,26 +184,26 @@ unique type Y a b = Y a b
Added definitions:

8. type Y a b
9. Y.Y : a -> b -> Y a b
9. Y.Y : a -> b -> #md85ksgqel a b
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

broken?

ChrisPenner and others added 7 commits July 10, 2024 14:29
# Conflicts:
#	unison-cli-integration/integration-tests/IntegrationTests/transcript.output.md
#	unison-src/transcripts-round-trip/main.output.md
#	unison-src/transcripts/add-run.output.md
#	unison-src/transcripts/bug-strange-closure.output.md
#	unison-src/transcripts/cycle-update-5.output.md
#	unison-src/transcripts/delete.output.md
#	unison-src/transcripts/diff-namespace.output.md
#	unison-src/transcripts/move-namespace.output.md
#	unison-src/transcripts/name-selection.output.md
#	unison-src/transcripts/names.output.md
#	unison-src/transcripts/namespace-dependencies.output.md
#	unison-src/transcripts/propagate.output.md
#	unison-src/transcripts/reflog.output.md
#	unison-src/transcripts/reset.output.md
#	unison-src/transcripts/tab-completion.output.md
#	unison-src/transcripts/transcript-parser-commands.output.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants