OSX 10.10 Working with components and plugins without aliases

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:

AC_DevEssentials

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>

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.