2222import * as semver from 'semver' ;
2323import * as Blockly from 'blockly/core' ;
2424
25- import * as mechanismComponentHolder from '../blocks/mrc_mechanism_component_holder' ;
2625import * as commonStorage from './common_storage' ;
2726import * as storageModule from './module' ;
2827import * as storageModuleContent from './module_content' ;
2928import * as storageNames from './names' ;
3029import * as storageProject from './project' ;
31- import { ClassMethodDefBlock , BLOCK_NAME as MRC_CLASS_METHOD_DEF_BLOCK_NAME } from '../blocks/mrc_class_method_def' ;
30+ import { upgrade_001_to_002 } from '../blocks/mrc_mechanism_component_holder' ;
31+ import { upgrade_002_to_003 , upgrade_004_to_005 } from '../blocks/mrc_class_method_def' ;
3232import * as workspaces from '../blocks/utils/workspaces' ;
3333
3434export const NO_VERSION = '0.0.0' ;
35- export const CURRENT_VERSION = '0.0.4 ' ;
35+ export const CURRENT_VERSION = '0.0.5 ' ;
3636
3737export async function upgradeProjectIfNecessary (
3838 storage : commonStorage . Storage , projectName : string ) : Promise < void > {
3939 const projectInfo = await storageProject . fetchProjectInfo ( storage , projectName ) ;
4040 if ( semver . lt ( projectInfo . version , CURRENT_VERSION ) ) {
4141 switch ( projectInfo . version ) {
42+ default :
43+ throw new Error ( 'Unrecognized project version: ' + projectInfo . version ) ;
44+
45+ // Intentional fallthrough after case '0.0.0'
4246 // @ts -ignore
4347 case '0.0.0' :
4448 upgradeFrom_000_to_001 ( storage , projectName , projectInfo )
45- // Intentional fallthrough
49+
50+ // Intentional fallthrough after case '0.0.1'
4651 // @ts -ignore
4752 case '0.0.1' :
4853 upgradeFrom_001_to_002 ( storage , projectName , projectInfo ) ;
49- // Intentional fallthrough
54+
55+ // Intentional fallthrough after case '0.0.2'
5056 // @ts -ignore
5157 case '0.0.2' :
52- upgradeFrom_002_to_003 ( storage , projectName , projectInfo ) ;
58+ upgradeFrom_002_to_003 ( storage , projectName , projectInfo ) ;
59+
60+ // Intentional fallthrough after case '0.0.3'
61+ // @ts -ignore
5362 case '0.0.3' :
5463 upgradeFrom_003_to_004 ( storage , projectName , projectInfo ) ;
55- break ;
56- default :
57- throw new Error ( 'Unrecognized project version: ' + projectInfo . version ) ;
5864
65+ // Intentional fallthrough after case '0.0.4'
66+ // @ts -ignore
67+ case '0.0.4' :
68+ upgradeFrom_004_to_005 ( storage , projectName , projectInfo ) ;
5969 }
6070 await storageProject . saveProjectInfo ( storage , projectName ) ;
6171 }
6272}
6373
64- async function upgradeFrom_000_to_001 (
65- _storage : commonStorage . Storage ,
66- _projectName : string ,
67- projectInfo : storageProject . ProjectInfo ) : Promise < void > {
68- // Project was saved without a project.info.json file.
69- // Nothing needs to be done to upgrade to '0.0.1';
70- projectInfo . version = '0.0.1' ;
71- }
72-
73- async function upgradeFrom_001_to_002 (
74+ async function upgradeBlocksFiles (
7475 storage : commonStorage . Storage ,
7576 projectName : string ,
76- projectInfo : storageProject . ProjectInfo ) : Promise < void > {
77- // Modules were saved without private components.
78- // The Robot's mrc_mechanism_component_holder block was saved without hidePrivateComponents.
77+ preupgradePredicate : ( moduleType : storageModule . ModuleType ) => boolean ,
78+ preupgradeFunc : ( moduleContentText : string ) => string ,
79+ upgradePredicate : ( moduleType : storageModule . ModuleType ) => boolean ,
80+ upgradeFunc : ( w : Blockly . Workspace ) => void
81+ ) : Promise < void > {
7982 const projectFileNames : string [ ] = await storage . list (
8083 storageNames . makeProjectDirectoryPath ( projectName ) ) ;
8184 for ( const projectFileName of projectFileNames ) {
8285 const modulePath = storageNames . makeFilePath ( projectName , projectFileName ) ;
83- let moduleContentText = await storage . fetchFileContentText ( modulePath ) ;
86+ const moduleType = storageNames . getModuleType ( modulePath ) ;
87+ const originalModuleContentText = await storage . fetchFileContentText ( modulePath ) ;
88+ let moduleContentText = originalModuleContentText ;
8489
85- // Add private components to the module content.
86- moduleContentText = storageModuleContent . addPrivateComponents ( moduleContentText ) ;
90+ if ( preupgradePredicate ( moduleType ) ) {
91+ moduleContentText = preupgradeFunc ( moduleContentText ) ;
92+ }
8793
88- if ( storageNames . getModuleType ( modulePath ) === storageModule . ModuleType . ROBOT ) {
89- // If this module is the robot, hide the private components part of the
90- // mrc_mechanism_component_holder block.
94+ if ( upgradePredicate ( moduleType ) ) {
9195 const moduleContent = storageModuleContent . parseModuleContentText ( moduleContentText ) ;
9296 let blocks = moduleContent . getBlocks ( ) ;
9397
9498 // Create a temporary workspace to upgrade the blocks.
95- const headlessWorkspace = workspaces . createHeadlessWorkspace ( storageModule . ModuleType . ROBOT ) ;
99+ const headlessWorkspace = workspaces . createHeadlessWorkspace ( moduleType ) ;
96100
97101 try {
98102 Blockly . serialization . workspaces . load ( blocks , headlessWorkspace ) ;
99- mechanismComponentHolder . hidePrivateComponents ( headlessWorkspace ) ;
103+ upgradeFunc ( headlessWorkspace ) ;
100104 blocks = Blockly . serialization . workspaces . save ( headlessWorkspace ) ;
101105 } finally {
102106 workspaces . destroyHeadlessWorkspace ( headlessWorkspace ) ;
103107 }
108+
104109 moduleContent . setBlocks ( blocks ) ;
105110 moduleContentText = moduleContent . getModuleContentText ( ) ;
106111 }
107112
108- await storage . saveFile ( modulePath , moduleContentText ) ;
113+ if ( moduleContentText !== originalModuleContentText ) {
114+ await storage . saveFile ( modulePath , moduleContentText ) ;
115+ }
109116 }
110- projectInfo . version = '0.0.2' ;
111117}
112118
113- async function upgradeFrom_002_to_003 (
114- storage : commonStorage . Storage ,
115- projectName : string ,
116- projectInfo : storageProject . ProjectInfo ) : Promise < void > {
117- // Opmodes had robot as a parameter to init method
118- const projectFileNames : string [ ] = await storage . list (
119- storageNames . makeProjectDirectoryPath ( projectName ) ) ;
119+ /**
120+ * Predicate function that can be passed to upgradeBlocksFiles indicating that all modules should be
121+ * affected.
122+ */
123+ function anyModuleType ( _moduleType : storageModule . ModuleType ) : boolean {
124+ return true ;
125+ }
120126
121- for ( const projectFileName of projectFileNames ) {
122- const modulePath = storageNames . makeFilePath ( projectName , projectFileName ) ;
127+ /**
128+ * Predicate function that can be passed to upgradeBlocksFiles indicating that only OpMode modules
129+ * should be affected.
130+ */
131+ function isOpMode ( moduleType : storageModule . ModuleType ) : boolean {
132+ return moduleType === storageModule . ModuleType . OPMODE ;
133+ }
123134
124- if ( storageNames . getModuleType ( modulePath ) === storageModule . ModuleType . OPMODE ) {
125- let moduleContentText = await storage . fetchFileContentText ( modulePath ) ;
126- const moduleContent = storageModuleContent . parseModuleContentText ( moduleContentText ) ;
127- let blocks = moduleContent . getBlocks ( ) ;
135+ /**
136+ * Predicate function that can be passed to upgradeBlocksFiles indicating that only Robot modules
137+ * should be affected.
138+ */
139+ function isRobot ( moduleType : storageModule . ModuleType ) : boolean {
140+ return moduleType === storageModule . ModuleType . ROBOT ;
141+ }
128142
129- // Create a temporary workspace to upgrade the blocks.
130- const headlessWorkspace = workspaces . createHeadlessWorkspace ( storageModule . ModuleType . ROBOT ) ;
143+ /**
144+ * Predicate function that can be passed to upgradeBlocksFiles indicating that no modules should be
145+ * affected.
146+ */
147+ function noModuleTypes ( _moduleType : storageModule . ModuleType ) : boolean {
148+ return false ;
149+ }
131150
132- try {
133- Blockly . serialization . workspaces . load ( blocks , headlessWorkspace ) ;
151+ /**
152+ * Preupgrade function that makes no changes to moduleContentText.
153+ */
154+ function noPreupgrade ( moduleContentText : string ) : string {
155+ return moduleContentText ;
156+ }
134157
135- // Method blocks need to be upgraded
136- headlessWorkspace . getBlocksByType ( MRC_CLASS_METHOD_DEF_BLOCK_NAME , false ) . forEach ( block => {
137- ( block as ClassMethodDefBlock ) . upgrade_002_to_003 ( ) ;
138- } ) ;
139- blocks = Blockly . serialization . workspaces . save ( headlessWorkspace ) ;
140- } finally {
141- workspaces . destroyHeadlessWorkspace ( headlessWorkspace ) ;
142- }
158+ async function upgradeFrom_000_to_001 (
159+ _storage : commonStorage . Storage ,
160+ _projectName : string ,
161+ projectInfo : storageProject . ProjectInfo ) : Promise < void > {
162+ // Project was saved without a project.info.json file.
163+ // Nothing needs to be done to upgrade to '0.0.1';
164+ projectInfo . version = '0.0.1' ;
165+ }
143166
144- moduleContent . setBlocks ( blocks ) ;
145- moduleContentText = moduleContent . getModuleContentText ( ) ;
146- await storage . saveFile ( modulePath , moduleContentText ) ;
147- }
148- }
167+ async function upgradeFrom_001_to_002 (
168+ storage : commonStorage . Storage ,
169+ projectName : string ,
170+ projectInfo : storageProject . ProjectInfo ) : Promise < void > {
171+ // Modules were saved without private components.
172+ // The Robot's mrc_mechanism_component_holder block was saved without hidePrivateComponents.
173+ await upgradeBlocksFiles (
174+ storage , projectName ,
175+ anyModuleType , storageModuleContent . preupgrade_001_to_002 ,
176+ isRobot , upgrade_001_to_002 ) ;
177+ projectInfo . version = '0.0.2' ;
178+ }
179+
180+ async function upgradeFrom_002_to_003 (
181+ storage : commonStorage . Storage ,
182+ projectName : string ,
183+ projectInfo : storageProject . ProjectInfo ) : Promise < void > {
184+ // OpModes had robot as a parameter to init method.
185+ await upgradeBlocksFiles (
186+ storage , projectName ,
187+ noModuleTypes , noPreupgrade ,
188+ isOpMode , upgrade_002_to_003 ) ;
149189 projectInfo . version = '0.0.3' ;
150190}
151191
@@ -157,3 +197,15 @@ async function upgradeFrom_003_to_004(
157197 // from loading a project with an older version of software.
158198 projectInfo . version = '0.0.4' ;
159199}
200+
201+ async function upgradeFrom_004_to_005 (
202+ storage : commonStorage . Storage ,
203+ projectName : string ,
204+ projectInfo : storageProject . ProjectInfo ) : Promise < void > {
205+ // mrc_class_method_def blocks that return a value need to have returnType changed from 'Any' to ''.
206+ await upgradeBlocksFiles (
207+ storage , projectName ,
208+ noModuleTypes , noPreupgrade ,
209+ anyModuleType , upgrade_004_to_005 ) ;
210+ projectInfo . version = '0.0.5' ;
211+ }
0 commit comments