Apple has broken Aliases.
Well, at least for us working with 4D and until 4D supports the new OS X aliases that now are more like bookmarks.
So, what can a developer do?
Copy all Plugins and Components into the appropriate folders and overtime a component changes, copy it again to all destinations, hoping you don’t forget one…
Tedious huh?
But aren’t we developers?
Let’s solve this in code:
First you will need to create a folder that contains the master copies of all your components and one folder with all your reference copies of the plugins you need. The simplest way to do this for your components is to simply set the target folder for the build to that folder.
Now create Aliases to these 2 folders and place the components and plugin folders of your application, renaming the aliases to _Plugins and _Components.
Now all you have to do is call
DEVUTIL_CheckComponents
and/or
DEVUTIL_CheckPlugins aufrufen
at startup and/or shutdown and your components and plugins will be kept up to date.
Whenever changes are found, you will be promoted for what to do, and if you decide to update, you will need to restart your application afterwards.
Now, either download the little component I created with (among others) these methods:
or copy the following Methods:
You will need the Methods for recursive Folder operations as well, these are linked to further down.
Here are the raw methods used:
// ---------------------------------------------------- // Method: DEVUTIL_CheckComponents // ---------------------------------------------------- // Call: DEVUTIL_CheckComponents({Aks}) // ---------------------------------------------------- // UserName (OS): Alexander Heintz // Date and Time: 28.10.14, 14:50:40 // ---------------------------------------------------- // Does: // will check the components for updates, the base repository // is identified by an Alias in the Components folder // that must be named _Components // ---------------------------------------------------- // Parameters: // -> $1 boolean TRUE if the application should ask to update // ---------------------------------------------------- // Parameter Definition C_BOOLEAN($1) // ---------------------------------------------------- // Local Variable Definition C_BOOLEAN($b_Ask) C_BOOLEAN($b_HasUpdate) C_BOOLEAN($b_NeedsUpdate) C_LONGINT($l) C_TEXT($t_BaseFolder) C_TEXT($t_ComList) C_TEXT($t_CompLocal) C_TEXT($t_CompLocalItem) C_TEXT($t_CompRef) C_TEXT($t_CompRefItem) // ---------------------------------------------------- // Parameter Assignment If (Count parameters>0) $b_Ask:=$1 End if // ---------------------------------------------------- $t_BaseFolder:=Get 4D folder(Database folder;*) $t_CompLocal:=$t_BaseFolder+"Components"+Folder separator If (Test path name($t_CompLocal)=Is a folder) $t_CompRef:=$t_CompLocal+"_Components" If (Test path name($t_CompRef)=Is a document) RESOLVE ALIAS($t_CompRef;$t_CompRef) ARRAY TEXT($at_Folder;0) FOLDER LIST($t_CompLocal;$at_Folder) For ($l;1;Size of array($at_Folder)) $t_CompLocalItem:=$t_CompLocal+$at_Folder{$l}+Folder separator $t_CompRefItem:=$t_CompRef+$at_Folder{$l}+Folder separator If (Test path name($t_CompRefItem)=Is a folder) If (DEVUTIL_CompareFolder ($t_CompLocalItem;$t_CompRefItem)) If (Not($b_Ask)) DEVUTIL_CopyFolder ($t_CompRefItem;$t_CompLocal;True) $t_ComList:=$t_ComList+$at_Folder{$l}+"\r" $b_HasUpdate:=True Else $t_ComList:=$t_ComList+$at_Folder{$l}+"\r" $b_NeedsUpdate:=True End if End if End if End for End if End if Case of : ($b_NeedsUpdate) CONFIRM("Updated Components found!\r"+$t_ComList+"do you want to sync the list?\rYou will need to restart you development environment afterards") If (OK=1) DEVUTIL_CheckComponents End if : ($b_HasUpdate) CONFIRM("Components updated:\r"+$t_ComList+"\rRestart now?") If (OK=1) OPEN DATABASE(Structure file(*)) End if End case
Same for PlugIns
// ---------------------------------------------------- // Method: DEVUTIL_CheckPlugins // ---------------------------------------------------- // Call: DEVUTIL_CheckPlugins({Aks}) // ---------------------------------------------------- // UserName (OS): Alexander Heintz // Date and Time: 28.10.14, 14:50:40 // ---------------------------------------------------- // Does: // will check the components for updates, the base repository // is identified by an Alias in the Components folder // that must be named _Components // ---------------------------------------------------- // Parameters: // -> $1 boolean TRUE if the application should ask to update // ---------------------------------------------------- // Parameter Definition C_BOOLEAN($1) // ---------------------------------------------------- // Local Variable Definition C_BOOLEAN($b_Ask) C_BOOLEAN($b_HasUpdate) C_BOOLEAN($b_NeedsUpdate) C_LONGINT($l) C_TEXT($t_BaseFolder) C_TEXT($t_ComList) C_TEXT($t_CompLocal) C_TEXT($t_CompLocalItem) C_TEXT($t_CompRef) C_TEXT($t_CompRefItem) // ---------------------------------------------------- // Parameter Assignment If (Count parameters>0) $b_Ask:=$1 End if // ---------------------------------------------------- $t_BaseFolder:=Get 4D folder(Database folder;*) $t_CompLocal:=$t_BaseFolder+"Plugins"+Folder separator If (Test path name($t_CompLocal)=Is a folder) $t_CompRef:=$t_CompLocal+"_Plugins" If (Test path name($t_CompRef)=Is a document) RESOLVE ALIAS($t_CompRef;$t_CompRef) ARRAY TEXT($at_Folder;0) FOLDER LIST($t_CompLocal;$at_Folder) For ($l;1;Size of array($at_Folder)) $t_CompLocalItem:=$t_CompLocal+$at_Folder{$l}+Folder separator $t_CompRefItem:=$t_CompRef+$at_Folder{$l}+Folder separator If (Test path name($t_CompRefItem)=Is a folder) If (ACFT_CompareFolder ($t_CompLocalItem;$t_CompRefItem)) If (Not($b_Ask)) ACFT_CopyFolder ($t_CompRefItem;$t_CompLocal;True) $t_ComList:=$t_ComList+$at_Folder{$l}+"\r" $b_HasUpdate:=True Else $t_ComList:=$t_ComList+$at_Folder{$l}+"\r" $b_NeedsUpdate:=True End if End if End if End for End if End if Case of : ($b_NeedsUpdate) CONFIRM("Updated Plugins found!\r"+$t_ComList+"do you want to sync the list?\rYou will need to restart you development environment afterards") If (OK=1) DEVUTIL_CheckPlugins End if : ($b_HasUpdate) CONFIRM("Plugins updated:\r"+$t_ComList+"\rRestart now?") If (OK=1) OPEN DATABASE(Structure file(*)) End if End case
As 4D cannot recursively delete/copy or compare folders, you will need the methods mentioned in this post:
Copy, delete and compare folders recursively
Just add this code snippet to OnStartup and OnExit:
If (Not(Is compiled mode)) ARRAY TEXT($at_Components;0) COMPONENT LIST($at_Components) If (Find in array($at_Components;"AC_DevEssentials")>0) EXECUTE FORMULA("DEVUTIL_CheckComponents(True)") EXECUTE FORMULA("DEVUTIL_CheckPlugins(True)") End if End if
Or use this if you do intend to remove the component from the final application:
If (Not(Is compiled mode)) ARRAY TEXT($at_Components;0) COMPONENT LIST($at_Components) If (Find in array($at_Components;"AC_DevEssentials")>0) EXECUTE FORMULA("DEVUTIL_CheckComponents(True)") EXECUTE FORMULA("DEVUTIL_CheckPlugins(True)") End if End if
I created a macro for this:
<macro name="CheckPlugComp"> <text>If (Not(Is compiled mode)) ARRAY TEXT($at_Components;0) COMPONENT LIST($at_Components) If (Find in array($at_Components;"AC_DevEssentials")>0) EXECUTE FORMULA("DEVUTIL_CheckComponents(True)") EXECUTE FORMULA("DEVUTIL_CheckPlugins(True)") End if End if</text> </macro>