Port is a VCS-agnostic Caché Studio utility to export or import Caché files based on projects instead of namespaces.
It's recommended to use Port locally, which makes it ideal for Studio users and quick open-source projects.
Its name origins from 'portability', 'export' and 'import'.
NOTE: Although you can use Port for a shared instance, keep in mind that if two users are working in the same project their changes could overlap each other, this would cause an extremely undesired result. So if you plan on using Port for a single shared instance, then make sure that only one person works exclusively for a single project.
Since it uses a project based approach to handle the source code, we can consider the following advantages:
In order to install Port, you just need to import the file port.xml with the compile flag enabled and restart your Studio.
After installing Port, it'll define a set of default configurations. However sometimes these settings might not be adequate for you.
You can re-configure these settings using the class Port.Configuration
. You can also check what you can configure by running ##class(Port.Configuration).Help()
or using the wizard: Wizard^Port
.
It also includes settings that allow you more per-project customizations.
NOTE: Some configurations are not available when using the Wizard. For such cases, use the
Port.Configuration
class.
Port will act whenever a file is saved (not compiled), as long as you're working on some project that isn't the 'Default'. You can see if Port is working correctly by checking the Studio's Output window.
When installed, Port adds a Source Control menu, composed with the following options:
Sometimes you might want to ignore paths that aren't related to Caché but must be kept inside, files like a README.md to describe a package are a good example. You can do this by creating a file called .portignore
in the root of the repository and putting the paths to ignore
inside it, one per line. Note that you MUST provide the folder that indicates the item type since the paths are relative to the repository root.
In the example below, notice that cls and int folders are included. These are the item types.
cls/Package/ignoreme <- This ignores the folder called ignoreme and anything inside it.
int/ignoreme <- This also ignores the folder called ignoreme but only if it's inside the int folder.
When using Port you'll notice the usage of the term workspace. This is basically the path where the project's source code is exported. There're two types of workspaces: primary workspace and custom workspaces.
Whenever a new project is exported by Port it will use the primary workspace configuration pattern to 'seed' the path to the project being exported for the first time. After this, the resulting path will be always used for this project, this path is called a custom workspace.
You can modify that path by using the Wizard or the method SetCustomWorkspace
from the Port.Configuration
class. Modifying it will cause the project you selected to be exported to a new location. Port will detect a path change and warn the user about exporting the whole project again.
NOTE: This'll not move any of the existing source code from your old path, but instead it'll export the project straight from your instance again.
You can also modify the primary workspace by using the Wizard or the method SetPrimaryWorkspace
from the Port.Configuration
class. However this will affect only the projects that weren't exported by Port yet or had their custom workspace removed by calling the method RemoveCustomWorkspace
.
Extended hooks allows another source control class to take over the Studio event (hook) cycle and execute specific tasks. In order to create extended hooks, you need to create a class that implements one or more of the following hooks:
You can check what each hook does by reading %Studio.Extension.Base
documentation.
Unlike %Studio.Extension.Base
, each hook should be implemented as class method and receive the %Studio.Extension.Base
as the first parameter: consider a case where you need to do some validation before the file is saved, you would use OnBeforeSave.
You must consider modifying the method signature from %Studio.Extension.Base
:
Method OnBeforeSave(InternalName As %String, Location As %String = "", Object As %RegisteredObject = {$$$NULLOREF}) As %Status
to:
ClassMethod OnBeforeSave(SourceControl As %Studio.Extension.Base,__ InternalName As %String, Location As %String = "", Object As %RegisteredObject = {$$$NULLOREF}) As %Status
Finally, after implementing your hooks you need to register the class with:
do ##class(Port.Configuration).RegisterExtendedHooks("Your.Implementer.Class")
If you want to remove it, just call the same method with an empty string.
NOTE: Using extended hooks means that all output will be redirect to Port. That makes the class you specified responsible for whatever it writes. Port will attempt to capture its output and display it cleanly, but the class still must take care of messages that break into new lines.
WARNING! Make sure you know what you're doing! Bad hook implementations can cause Port and even the Source Control API to go awry thus resulting in code loss.
This project started before Atelier was released, and it's still useful for developers that prefer using the Studio instead of installing Eclipse. The original idea was to bring to the developers the capability to export the source code using a scaffolding that is easy to manage, which is pretty much what Atelier does today, however Atelier is not made for working with the Studio's projects. Leaving that task for the Eclipse platform.
The deal is: you might want something simplier to do something simple.
Make sure to check the output and check for a 'All Done' message. After this message, there should have a note requesting you to restart the Studio. Follow this instruction, now see if the Source Control menu appears, if it's there then you're good to go.
This might be caused due to your current Caché language which is not supported by Port yet, try executing the following method and see check if it fixes the issue:
do ##class(%MessageDictionary).SetSessionLanguage("en-us")
If it does, you are encouraged to open a PR and add your language.
Whenever you export the project Port will check for any files that aren't related to it in your instance. If there's any files that doesn't corresponds to the project, these are considered an orphans and as such they'll be removed in order to keep the workspace synchronized. The're two circustances that can cause the purge: when you remove the item or when you delete the item.
As long as you REMOVE and don't DELETE the source from your instance you can simply re-add this item to the project and export it again, you might need to force export or edit the item though.
If you want to avoid this kind of issue, remember to commit your changes before purging these files.
If the file you're trying to import failed or you didn't noticed any message warning you about it, then you must check if:
For number 3, remember that Port doesn't check the source code but instead their modified date. So if you attempt to import an item whose last-modified attribute is older than your project's last change, this item will be skipped. This is a by-design limitation introduced to improve the performance for projects with many items, but you can remediate it by using the Import (forced)
option. However be warned that it'll import the project as whole.
This can be caused due to Port working with UTF-8 by default. You can use the following methods to try and fix it:
SetRoutineInputTranslateTable
, this includes class items.SetRoutineOutputTranslateTable
, this also includes class items.SetPublicFileInputTranslateTable
.SetPublicFileOutputTranslateTable
.NOTE: All the methods accept only a single parameter which is a string representing the charset. If you don't want to apply any translation, you can pass "RAW" to all methods.
Yes, Port supports exporting only source codes, which is mostly plain-text. Anything binary-related is usually associated to the the public folder, e.g. an image. That being said, you can export the project XML that include binary files.
That's because saving an item is not the same as saving the project. So even though the item was created and added to the current project, since the project wasn't saved as well the item entry is not persisted yet. If you create a new item always remember to save the project it belongs to before saving the item itself.
If you're working with big projects, you'll mostly face this issue. And the solution for that is: wait. Because the Source Control process runs in the same as the Studio itself, exporting or importing a big project will cause the Studio to become inoperable. However this is only visually, because the Source Control process still would be running.
The time it takes to finish depends on the amount of items the project has so don't attempt to interrupt the process because you would risk corrupting the project and the sources themselves.
Even though implemented, the support for MVB routine types is highly bugged due to it using an obscure API, as long as this API keeps this way, I don't plan on improving the support for it as well.
However, working with MVI routines seems to be fine as long as you know the syntax for them.
Here.