Skip to content

Commit 468e355

Browse files
authored
Merge pull request #5684 from unisonweb/25-04-03-merge-db
bugfix: track merge branch parents in database to fix nameless dependency bug
2 parents 52643fd + 7f8d723 commit 468e355

File tree

14 files changed

+880
-71
lines changed

14 files changed

+880
-71
lines changed

codebase2/codebase-sqlite/U/Codebase/Sqlite/Queries.hs

Lines changed: 204 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,14 @@ module U.Codebase.Sqlite.Queries
134134
expectProjectBranchHead,
135135
setMostRecentBranch,
136136
loadMostRecentBranch,
137+
loadProjectBranchParent,
138+
loadMergeBranchParents,
139+
insertMergeBranchLocal,
140+
insertMergeBranchRemote,
141+
insertMergeBranchLooseCode,
142+
loadNamespaceUniqueTypeGuids,
143+
existsAnyNamespaceUniqueTypeGuidForNamespace,
144+
insertNamespaceUniqueTypeGuid,
137145

138146
-- ** remote projects
139147
loadRemoteProject,
@@ -257,6 +265,7 @@ module U.Codebase.Sqlite.Queries
257265
addProjectBranchReflogTable,
258266
addProjectBranchCausalHashIdColumn,
259267
addProjectBranchLastAccessedColumn,
268+
addMergeBranchTables,
260269

261270
-- ** schema version
262271
currentSchemaVersion,
@@ -303,11 +312,13 @@ import Control.Monad.Writer qualified as Writer
303312
import Data.Aeson qualified as Aeson
304313
import Data.Aeson.Text qualified as Aeson
305314
import Data.Bitraversable (bitraverse)
315+
import Data.ByteString.Lazy (LazyByteString)
306316
import Data.Bytes.Put (runPutS)
307317
import Data.Foldable qualified as Foldable
308318
import Data.List qualified as List
309319
import Data.List.Extra qualified as List
310320
import Data.List.NonEmpty (NonEmpty)
321+
import Data.List.NonEmpty qualified as List.NonEmpty
311322
import Data.List.NonEmpty qualified as Nel
312323
import Data.List.NonEmpty qualified as NonEmpty
313324
import Data.Map qualified as Map
@@ -401,6 +412,8 @@ import Unison.Hash qualified as Hash
401412
import Unison.Hash32 (Hash32)
402413
import Unison.Hash32 qualified as Hash32
403414
import Unison.Hash32.Orphans.Sqlite ()
415+
import Unison.Name (Name)
416+
import Unison.Name qualified as Name
404417
import Unison.NameSegment.Internal (NameSegment (NameSegment))
405418
import Unison.NameSegment.Internal qualified as NameSegment
406419
import Unison.Prelude
@@ -421,7 +434,7 @@ type TextPathSegments = [Text]
421434
-- * main squeeze
422435

423436
currentSchemaVersion :: SchemaVersion
424-
currentSchemaVersion = 18
437+
currentSchemaVersion = 19
425438

426439
runCreateSql :: Transaction ()
427440
runCreateSql =
@@ -491,6 +504,10 @@ addProjectBranchLastAccessedColumn :: Transaction ()
491504
addProjectBranchLastAccessedColumn =
492505
executeStatements $(embedProjectStringFile "sql/015-add-project-branch-last-accessed.sql")
493506

507+
addMergeBranchTables :: Transaction ()
508+
addMergeBranchTables =
509+
executeStatements $(embedProjectStringFile "sql/016-add-merge-branch-tables.sql")
510+
494511
schemaVersion :: Transaction SchemaVersion
495512
schemaVersion =
496513
queryOneCol
@@ -4328,6 +4345,192 @@ loadMostRecentBranch projectId =
43284345
project_id = :projectId
43294346
|]
43304347

4348+
loadProjectBranchParent :: ProjectId -> ProjectBranchId -> Transaction (Maybe ProjectBranchId)
4349+
loadProjectBranchParent projectId projectBranchId =
4350+
queryMaybeCol
4351+
[sql|
4352+
SELECT parent_branch_id
4353+
FROM project_branch_parent
4354+
WHERE project_id = :projectId
4355+
AND branch_id = :projectBranchId
4356+
|]
4357+
4358+
loadMergeBranchParents ::
4359+
ProjectId ->
4360+
ProjectBranchId ->
4361+
Transaction
4362+
( Maybe
4363+
( Maybe ProjectBranchId,
4364+
CausalHashId,
4365+
Maybe ProjectBranchId,
4366+
CausalHashId
4367+
)
4368+
)
4369+
loadMergeBranchParents projectId branchId =
4370+
queryMaybeRow
4371+
[sql|
4372+
SELECT local_source_branch_id, source_causal_hash_id, target_branch_id, target_causal_hash_id
4373+
FROM merge_branch
4374+
WHERE project_id = :projectId
4375+
AND branch_id = :branchId
4376+
|]
4377+
4378+
insertMergeBranchLocal ::
4379+
ProjectId ->
4380+
ProjectBranchId ->
4381+
(ProjectBranchId, CausalHashId) ->
4382+
(ProjectBranchId, CausalHashId) ->
4383+
Transaction ()
4384+
insertMergeBranchLocal
4385+
projectId
4386+
mergeBranchId
4387+
(sourceBranchId, sourceCausalHashId)
4388+
(targetBranchId, targetCausalHashId) =
4389+
execute
4390+
[sql|
4391+
INSERT INTO merge_branch (
4392+
project_id,
4393+
branch_id,
4394+
local_source_project_id,
4395+
local_source_branch_id,
4396+
source_causal_hash_id,
4397+
target_project_id,
4398+
target_branch_id,
4399+
target_causal_hash_id
4400+
)
4401+
VALUES (
4402+
:projectId,
4403+
:mergeBranchId,
4404+
:projectId,
4405+
:sourceBranchId,
4406+
:sourceCausalHashId,
4407+
:projectId,
4408+
:targetBranchId,
4409+
:targetCausalHashId
4410+
)
4411+
|]
4412+
4413+
insertMergeBranchRemote ::
4414+
ProjectId ->
4415+
ProjectBranchId ->
4416+
(RemoteProjectId, RemoteProjectBranchId, URI, CausalHashId) ->
4417+
(ProjectBranchId, CausalHashId) ->
4418+
Transaction ()
4419+
insertMergeBranchRemote
4420+
projectId
4421+
mergeBranchId
4422+
(sourceProjectId, sourceBranchId, sourceHost, sourceCausalHashId)
4423+
(targetBranchId, targetCausalHashId) =
4424+
execute
4425+
[sql|
4426+
INSERT INTO merge_branch (
4427+
project_id,
4428+
branch_id,
4429+
remote_source_project_id,
4430+
remote_source_branch_id,
4431+
remote_source_host,
4432+
source_causal_hash_id,
4433+
target_project_id,
4434+
target_branch_id,
4435+
target_causal_hash_id
4436+
)
4437+
VALUES (
4438+
:projectId,
4439+
:mergeBranchId,
4440+
:sourceProjectId,
4441+
:sourceBranchId,
4442+
:sourceHost,
4443+
:sourceCausalHashId,
4444+
:projectId,
4445+
:targetBranchId,
4446+
:targetCausalHashId
4447+
)
4448+
|]
4449+
4450+
insertMergeBranchLooseCode ::
4451+
ProjectId ->
4452+
ProjectBranchId ->
4453+
CausalHashId ->
4454+
(ProjectBranchId, CausalHashId) ->
4455+
Transaction ()
4456+
insertMergeBranchLooseCode
4457+
projectId
4458+
mergeBranchId
4459+
sourceCausalHashId
4460+
(targetBranchId, targetCausalHashId) =
4461+
execute
4462+
[sql|
4463+
INSERT INTO merge_branch (
4464+
project_id,
4465+
branch_id,
4466+
source_causal_hash_id,
4467+
target_project_id,
4468+
target_branch_id,
4469+
target_causal_hash_id
4470+
)
4471+
VALUES (
4472+
:projectId,
4473+
:mergeBranchId,
4474+
:sourceCausalHashId,
4475+
:projectId,
4476+
:targetBranchId,
4477+
:targetCausalHashId
4478+
)
4479+
|]
4480+
4481+
loadNamespaceUniqueTypeGuids :: BranchHashId -> Transaction (Map Name Text)
4482+
loadNamespaceUniqueTypeGuids namespaceHashId = do
4483+
rows <-
4484+
queryListRow
4485+
[sql|
4486+
SELECT type_name, type_guid
4487+
FROM namespace_unique_type_guid
4488+
WHERE namespace_hash_id = :namespaceHashId
4489+
|]
4490+
4491+
let f :: ByteString -> Name
4492+
f bytes =
4493+
case Aeson.decodeStrict @[Text] bytes of
4494+
Just (segment : segments) ->
4495+
Name.fromSegments (NameSegment segment NonEmpty.:| map NameSegment segments)
4496+
_ ->
4497+
error $
4498+
reportBug
4499+
"E955495"
4500+
( "busted name in namespace_unique_type_guid (namespace hash id = "
4501+
++ show namespaceHashId
4502+
++ ")"
4503+
)
4504+
4505+
pure (Map.fromList (over (Lens.mapped . Lens._1) f rows))
4506+
4507+
existsAnyNamespaceUniqueTypeGuidForNamespace :: BranchHashId -> Transaction Bool
4508+
existsAnyNamespaceUniqueTypeGuidForNamespace namespaceHashId =
4509+
queryOneCol
4510+
[sql|
4511+
SELECT EXISTS (
4512+
SELECT 1
4513+
FROM namespace_unique_type_guid
4514+
WHERE namespace_hash_id = :namespaceHashId
4515+
)
4516+
|]
4517+
4518+
insertNamespaceUniqueTypeGuid :: BranchHashId -> Name -> Text -> Transaction ()
4519+
insertNamespaceUniqueTypeGuid namespaceHashId typeName typeGuid =
4520+
execute
4521+
[sql|
4522+
INSERT INTO namespace_unique_type_guid (namespace_hash_id, type_name, type_guid)
4523+
VALUES (:namespaceHashId, :typeNameJson, :typeGuid)
4524+
|]
4525+
where
4526+
typeNameJson :: LazyByteString
4527+
typeNameJson =
4528+
typeName
4529+
& Name.segments
4530+
& List.NonEmpty.toList
4531+
& map NameSegment.toUnescapedText
4532+
& Aeson.encode
4533+
43314534
-- | Searches for all names within the given name lookup which contain the provided list of segments
43324535
-- in order.
43334536
-- Search is case insensitive.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
create table merge_branch (
2+
project_id uuid not null,
3+
branch_id uuid not null,
4+
local_source_project_id uuid,
5+
local_source_branch_id uuid,
6+
remote_source_project_id uuid,
7+
remote_source_branch_id uuid,
8+
remote_source_host text,
9+
source_causal_hash_id integer not null references hash (id) on delete cascade,
10+
target_project_id uuid,
11+
target_branch_id uuid,
12+
target_causal_hash_id integer not null references hash (id) on delete cascade,
13+
primary key (project_id, branch_id),
14+
foreign key (project_id, branch_id)
15+
references project_branch (project_id, branch_id)
16+
on delete cascade,
17+
foreign key (local_source_project_id, local_source_branch_id)
18+
references project_branch (project_id, branch_id)
19+
on delete set null,
20+
foreign key (remote_source_project_id, remote_source_branch_id, remote_source_host)
21+
references remote_project_branch (project_id, branch_id, host)
22+
on delete set null,
23+
foreign key (target_project_id, target_branch_id)
24+
references project_branch (project_id, branch_id)
25+
on delete set null,
26+
check (
27+
local_source_branch_id is null or
28+
remote_source_branch_id is null
29+
),
30+
check (
31+
(project_id = local_source_project_id or local_source_project_id is null) and
32+
(project_id = target_project_id or target_project_id is null)
33+
)
34+
);
35+
36+
create table namespace_unique_type_guid (
37+
namespace_hash_id integer not null references hash (id) on delete cascade,
38+
type_name jsonb not null,
39+
type_guid text not null
40+
);

codebase2/codebase-sqlite/unison-codebase-sqlite.cabal

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
cabal-version: 1.12
22

3-
-- This file has been generated from package.yaml by hpack version 0.37.0.
3+
-- This file has been generated from package.yaml by hpack version 0.36.0.
44
--
55
-- see: https://github.com/sol/hpack
66

@@ -25,6 +25,7 @@ extra-source-files:
2525
sql/013-add-project-branch-reflog-table.sql
2626
sql/014-add-project-branch-causal-hash-id.sql
2727
sql/015-add-project-branch-last-accessed.sql
28+
sql/016-add-merge-branch-tables.sql
2829
sql/create.sql
2930

3031
source-repository head

parser-typechecker/src/Unison/Codebase/SqliteCodebase/Migrations.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ migrations regionVar getDeclType termBuffer declBuffer rootCodebasePath =
8585
sqlMigration 15 Q.addSquashResultTableIfNotExists,
8686
sqlMigration 16 Q.cdToProjectRoot,
8787
(17 {- This migration takes a raw sqlite connection -}, \conn -> migrateSchema16To17 conn),
88-
sqlMigration 18 Q.addProjectBranchLastAccessedColumn
88+
sqlMigration 18 Q.addProjectBranchLastAccessedColumn,
89+
sqlMigration 19 Q.addMergeBranchTables
8990
]
9091
where
9192
runT :: Sqlite.Transaction () -> Sqlite.Connection -> IO ()

parser-typechecker/src/Unison/Codebase/SqliteCodebase/Operations.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ createSchema = do
9898
Q.addProjectBranchReflogTable
9999
Q.addProjectBranchCausalHashIdColumn
100100
Q.addProjectBranchLastAccessedColumn
101+
Q.addMergeBranchTables
101102
(_, emptyCausalHashId) <- emptyCausalHash
102103
(_, ProjectBranch {projectId, branchId}) <- insertProjectAndBranch scratchProjectName scratchBranchName emptyCausalHashId
103104
Q.setCurrentProjectPath projectId branchId []

unison-cli/src/Unison/Cli/MergeTypes.hs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ module Unison.Cli.MergeTypes
77
)
88
where
99

10+
import U.Codebase.Sqlite.Project (Project)
11+
import U.Codebase.Sqlite.ProjectBranch (ProjectBranch)
12+
import Unison.Cli.Share.Projects.Types (RemoteProjectBranch)
1013
import Unison.Codebase.Editor.RemoteRepo (ReadShareLooseCode)
1114
import Unison.Project (ProjectAndBranch, ProjectBranchName, ProjectName)
1215

1316
-- | What are we merging in?
1417
data MergeSource
15-
= MergeSource'LocalProjectBranch !(ProjectAndBranch ProjectName ProjectBranchName)
16-
| MergeSource'RemoteProjectBranch !(ProjectAndBranch ProjectName ProjectBranchName)
18+
= MergeSource'LocalProjectBranch !(ProjectAndBranch Project ProjectBranch)
19+
| MergeSource'RemoteProjectBranch !RemoteProjectBranch
1720
| MergeSource'RemoteLooseCode !ReadShareLooseCode
1821

1922
type MergeTarget =

unison-cli/src/Unison/Cli/Pretty.hs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,10 @@ prettyHash32 = prettyBase32Hex# . Hash32.toBase32Hex
205205

206206
prettyMergeSource :: MergeSource -> Pretty
207207
prettyMergeSource = \case
208-
MergeSource'LocalProjectBranch branch -> prettyProjectAndBranchName branch
209-
MergeSource'RemoteProjectBranch branch -> "remote " <> prettyProjectAndBranchName branch
208+
MergeSource'LocalProjectBranch branch ->
209+
prettyProjectAndBranchName (ProjectAndBranch branch.project.name branch.branch.name)
210+
MergeSource'RemoteProjectBranch branch ->
211+
"remote " <> prettyProjectAndBranchName (ProjectAndBranch branch.projectName branch.branchName)
210212
MergeSource'RemoteLooseCode info -> prettyReadRemoteNamespace (ReadShare'LooseCode info)
211213

212214
prettyMergeSourceOrTarget :: MergeSourceOrTarget -> Pretty

0 commit comments

Comments
 (0)