@@ -45,20 +45,33 @@ func (s *Server) listBranches(w http.ResponseWriter, r *http.Request) {
45
45
46
46
branchDetails := make ([]models.BranchView , 0 , len (branches ))
47
47
48
+ // branchRegistry is used to display the "main" branch with only the most recent snapshot.
49
+ branchRegistry := make (map [string ]int , 0 )
50
+
48
51
for _ , branchEntity := range branches {
49
52
snapshotDetails , ok := repo .Snapshots [branchEntity .SnapshotID ]
50
53
if ! ok {
51
54
continue
52
55
}
53
56
54
- branchDetails = append (branchDetails ,
55
- models.BranchView {
56
- Name : branchEntity .Name ,
57
- Parent : findBranchParent (repo .Snapshots , snapshotDetails .ID , branchEntity .Name ),
58
- DataStateAt : snapshotDetails .DataStateAt ,
59
- SnapshotID : snapshotDetails .ID ,
60
- Dataset : snapshotDetails .Dataset ,
61
- })
57
+ branchView := models.BranchView {
58
+ Name : branchEntity .Name ,
59
+ Parent : findBranchParent (repo .Snapshots , snapshotDetails .ID , branchEntity .Name ),
60
+ DataStateAt : snapshotDetails .DataStateAt ,
61
+ SnapshotID : snapshotDetails .ID ,
62
+ Dataset : snapshotDetails .Dataset ,
63
+ }
64
+
65
+ if position , ok := branchRegistry [branchEntity .Name ]; ok {
66
+ if branchView .DataStateAt > branchDetails [position ].DataStateAt {
67
+ branchDetails [position ] = branchView
68
+ }
69
+
70
+ continue
71
+ }
72
+
73
+ branchRegistry [branchView .Name ] = len (branchDetails )
74
+ branchDetails = append (branchDetails , branchView )
62
75
}
63
76
64
77
if err := api .WriteJSON (w , http .StatusOK , branchDetails ); err != nil {
@@ -209,7 +222,12 @@ func (s *Server) createBranch(w http.ResponseWriter, r *http.Request) {
209
222
return
210
223
}
211
224
212
- if err := fsm .SetRoot (createRequest .BranchName , branchSnapshot ); err != nil {
225
+ if err := fsm .SetRoot (createRequest .BranchName , snapshotID ); err != nil {
226
+ api .SendBadRequestError (w , r , err .Error ())
227
+ return
228
+ }
229
+
230
+ if err := fsm .SetRelation (snapshotID , branchSnapshot ); err != nil {
213
231
api .SendBadRequestError (w , r , err .Error ())
214
232
return
215
233
}
@@ -360,6 +378,7 @@ func (s *Server) snapshot(w http.ResponseWriter, r *http.Request) {
360
378
}
361
379
362
380
targetBranchSnap := fmt .Sprintf ("%[1]s@%[1]s" , dataStateAt )
381
+
363
382
targetSnap := fmt .Sprintf ("%s/%s" , fsm .Pool ().BranchName (clone .Snapshot .Pool , clone .Branch ), targetBranchSnap )
364
383
365
384
if err := fsm .Move (currentSnapshotID , snapshotName , targetSnap ); err != nil {
@@ -560,26 +579,47 @@ func (s *Server) deleteBranch(w http.ResponseWriter, r *http.Request) {
560
579
561
580
toRemove := snapshotsToRemove (repo , snapshotID , deleteRequest .BranchName )
562
581
563
- // Pre-check.
564
- for _ , snapshotID := range toRemove {
565
- if cloneNum := s .Cloning .GetCloneNumber (snapshotID ); cloneNum > 0 {
566
- log .Warn (fmt .Sprintf ("cannot delete branch %q because snapshot %q contains %d clone(s)" ,
567
- deleteRequest .BranchName , snapshotID , cloneNum ))
582
+ if len (toRemove ) > 0 {
583
+ // Pre-check.
584
+ preCheckList := make (map [string ]int )
585
+
586
+ for _ , snapshotID := range toRemove {
587
+ if cloneNum := s .Cloning .GetCloneNumber (snapshotID ); cloneNum > 0 {
588
+ preCheckList [snapshotID ] = cloneNum
589
+ }
568
590
}
569
- }
570
591
571
- for _ , snapshotID := range toRemove {
572
- if err := fsm .DestroySnapshot (snapshotID ); err != nil {
573
- log .Warn (fmt .Sprintf ("failed to remove snapshot %q:" , snapshotID ), err .Error ())
592
+ if len (preCheckList ) > 0 {
593
+ errMsg := fmt .Sprintf ("cannot delete branch %q because" , deleteRequest .BranchName )
594
+
595
+ for snapID , cloneNum := range preCheckList {
596
+ errMsg += fmt .Sprintf (" snapshot %q contains %d clone(s)" , snapID , cloneNum )
597
+ }
598
+
599
+ log .Warn (errMsg )
600
+ api .SendBadRequestError (w , r , errMsg )
601
+
602
+ return
603
+ }
604
+
605
+ brName := fsm .Pool ().BranchName (fsm .Pool ().Name , deleteRequest .BranchName )
606
+
607
+ if err := fsm .DestroyBranch (brName ); err != nil {
608
+ log .Warn (fmt .Sprintf ("failed to remove snapshot %q:" , brName ), err )
609
+ api .SendBadRequestError (w , r , fmt .Sprintf ("failed to remove snapshot %q:" , brName ))
610
+
611
+ return
574
612
}
575
- }
576
613
577
- if len (toRemove ) > 0 {
578
614
datasetFull := strings .Split (toRemove [0 ], "@" )
579
615
datasetName , _ := strings .CutPrefix (datasetFull [0 ], fsm .Pool ().Name + "/" )
580
616
581
617
if err := fsm .DestroyClone (datasetName ); err != nil {
582
- log .Warn ("cannot destroy the underlying branch dataset" , err )
618
+ errMsg := fmt .Sprintf ("cannot destroy the underlying branch dataset: %s" , datasetName )
619
+ log .Warn (errMsg , err )
620
+ api .SendBadRequestError (w , r , errMsg )
621
+
622
+ return
583
623
}
584
624
}
585
625
0 commit comments