How to Use Version Control with twinBASIC

Integrated vs. External Version Control

At some point, twinBASIC will support integrated version control within the VS Code environment.  As I write this on 6/24/2021, that day has not yet come.

What we do have now is a sensible alternative: external version control support.

With the release of v0.10.2600, twinBASIC now supports exporting and importing from binary .twinproj container files to text files.  What's more, the text files are exported with UTF-8 file encoding, so they will play nicely with modern version control systems like Git and Mercurial.

Export / Import Commands

Here's the announcement from Wayne Philips:

With v0.10.2600, the tB compiler now supports two command line arguments:

twinBASIC_win32.exe export <twinproj_path> <export_folder_path>   --overwrite
twinBASIC_win32.exe import <twinproj_path> <import_folder_path>   --overwrite

The path to the compiler executable is typically:

C:\Users\<username>\.vscode\extensions\twinbasic.twinbasic-0.10.2600\out\bin\

Paths can be surrounded in double-quotes to allow for spaces in paths. The --overwrite flag is optional.

The special root files and folders (Resources / Sources / Settings) need to be preserved after export to ensure the corresponding import works correctly. Any other files in the root folder will be ignored, as they are currently not allowed in the tB virtual file system.

The Export command will continue as far as possible even upon encountering an error, to allow for basic corrupt project recovery.

The Import command creates a default .code-workspace file alongside the generated .twinproj file so that the project is ready to be opened in VS Code.

Let the Fun Begin

This is a real turning point in the twinBASIC project.  Writing code without using version control is like walking on a high wire with no net.  I tried to make version control work with the .twinproj file directly, but that was an exercise in frustration.

To celebrate this milestone, I wrote a batch file to automate the export process.  Simply copy and paste the code below into a file named Export.bat.  Place this file in the same folder as the .twinproj file.  

Export.bat

REM ********************************************************************************************
REM *                             --== Export.bat file ==--                                    *
REM *                                                                                          *
REM * Extracts a twinBASIC project container file into version-control friendly text documents *
REM * Script Author: Mike Wolfe (mike@nolongerset.com)                                         *
REM * Script Source: https://nolongerset.com/version-control-with-twinbasic/                   *
REM ********************************************************************************************

REM Get the folder name of the latest version of the twinBASIC extension
REM   - VS Code normally uninstalls old versions but not always
REM   - https://stackoverflow.com/a/6362922/154439

FOR /F "tokens=* USEBACKQ" %%F IN (`dir %userprofile%\.vscode\extensions\twinbasic* /B`) DO (
SET tb_ver=%%F
)


REM Build the full path to the twinBASIC executable

SET tb_exe=%userprofile%\.vscode\extensions\%tb_ver%\out\bin\twinBASIC_win32.exe


REM Get the name of the .twinproj file

FOR /F "tokens=* USEBACKQ" %%F IN (`dir %~dp0*.twinproj /B`) DO (
SET twinproj=%%F
)


REM Set the destination folder to a \Source\ subfolder in current folder
REM   - you could override this with a different destination path

SET outfolder=%~dp0Source


REM Export to \Source\ subfolder in current folder
REM   - %~dp0 refers to script folder
REM     o see: https://stackoverflow.com/a/4420078/154439
REM   - REM twinBASIC export command uses the following format:
REM     o twinBASIC_win32.exe export <twinproj_path> <export_folder_path>   --overwrite
REM     o see: https://github.com/WaynePhillipsEA/twinbasic/issues/232#issuecomment-866840797

"%tb_exe%" export "%~dp0%twinproj%" "%outfolder%" --overwrite


pause

How it works

The batch file is pretty well documented, so you can refer to that directly for the details.  Here's a high-level overview of what the code is doing:

Step 1. Get the twinBASIC version number

The executable, twinBASIC_win32.exe, is in a versioned subfolder of the VS Code extensions folder.  That means the full path to the executable will change with every release of twinBASIC.  And with the current pace of releases, that's more than once per day.

The batch file uses the dir command to loop through the twinBASIC subfolders and return the latest version of the extension.  Normally, there is only a single version of twinBASIC installed.  However, under certain circumstances you can end up with multiple copies of the extension.  I believe this happens if the twinBASIC_win32.exe executable is running outside of VS Code when the twinBASIC extension is upgraded.

Step 2. Build the full path to the executable

As I'm writing this, the 64-bit version of twinBASIC has not yet been released.  Therefore, I hard-coded the executable name to use the 32-bit version.  If you are reading this after the 64-bit release, you may have to update the batch file accordingly.

Step 3. Get the name of the .twinproj file

The batch file assumes that there is only a single .twinproj file in the directory.  I believe this is a valid assumption as of today, but that is something that also may change in the future.  Be aware that if you have multiple .twinproj files in the same folder, this script will not work as-is.

Step 4. Set the destination folder path

For simplicity, the batch file exports the embedded text files from the .twinproj file to a subfolder of the main directory named \Source\.  If you want to hard-code a different path, you can do that by overriding the SET outfolder line using either an absolute or relative path:

SET outfolder=%~dp0Source

REM To specify an absolute path to a different output folder
SET outfolder=M:\The path\to\my\project\repository

REM To specify a relative path, use %~dp0 to represent the script folder
SET outfolder=%~dp0..\Sibling folder

Step 5. Run the command

The batch file uses the local environment variables that it set in steps 1 - 4 to call the export command.  I use the --overwrite flag so that any existing files are automatically replaced.  This makes perfect sense if you are using this feature to put your twinBASIC project under version control.

Step 6. Pause for debugging

The final line in the batch file is a pause.  This command will keep the batch window from closing on its own.  This is particularly helpful to troubleshoot any problems that you may encounter.  I strongly advise you to leave this on until you verify the script is working as you expect.  You will want to remove this line if you are going to call this batch file as part of a broader automated build process so that it can run entirely unattended.

Notes about deployment

Sample file structure

Create the export.bat file and save it alongside your .twinproj file.  For example:

twinBASIC creates the Build folder the first time you compile your project.   The export.bat batch creates the Source folder the first time it is run.  Here is a typical timeline of what your folder would look like:

1. Initial twinBASIC files; 2. Build the project; 3. Add the export.bat file; 4. Run export.bat

Avoid creating shortcuts to the batch file

Note that this batch file uses the %~dp0 shortcut to get the directory from which the script is running.  There are some quirks to this approach that you should know:

It usually is the directory from which the batch file is started, but if you start the batch file from a shortcut, a different starting directory could be given. Also, when you're in cmd, and your current directory is c:\dir3, you can still start the batch file using c:\dir1\dir2\batch.bat in which case, the current directory will be c:\dir3.

Now go forth and enjoy writing properly version-controlled twinBASIC!