In Install4j, How to set a relative path in varfile? - install4j

I have an install4j project that I'm running from both GUI and command line.
As you might know it is possible to pass installer parameters in varfile.
I would like to know if there is a simple way to give a relative path in the varfile in the form:
my.variable=${installer:installerDir}\a.txt
I can see a workaround where I can ask the user to specify the file name only and I will put the directory path in the code. but I would still like to know if this is possible.
Thanks.
Ika.

You cannot use installer variables in the variable file. That file is read at startup before any other installer variables are defined, so you would not have a chance to set up the "installerDir" variable first.
The only option I see here is to use your own token, say
my.variable=#installerDir#\a.txt
and use a "Run script" action in the "Startup" node to replace that token with a particular directory. Here's some which checks all defined variables:
String installerDir = null;
InstallerContext context = null;
for (Object o : context.getVariableNames()) {
String variableName = (String)o;
Object variableValue = context.getVariable(variableName);
if (variableValue instanceof String) {
String replacedValue = ((String)variableValue).replaceAll("#installerDir#", installerDir);
if (!replacedValue.equals(variableValue)) {
context.setVariable(variableName, replacedValue);
}
}
}

Related

VSCode extension API: simple local Quick Diff

Trying to understand how to implement simple source control management in my language extension.
I need to show a Quick Diff for a single file (my extension doesn't work with folders) compared with some special one.
Let's say i have this TextDocumentContentProvider and QuickDiffProvider:
class MyLangDocumentContentProvider implements vscode.TextDocumentContentProvider
{
provideTextDocumentContent(uri: vscode.Uri)
{
return getFileText(uri); // returns text of provided file uri
}
}
class MyLangRepository implements vscode.QuickDiffProvider
{
provideOriginalResource(uri: vscode.Uri)
{
return getOriginalFileUri(uri); // returns uri of the special file to compare with
}
}
Then in activate method of extension i initialize them:
const docProvider = new MyLangDocumentContentProvider();
const gitSCM = vscode.scm.createSourceControl('git', 'Git');
gitSCM.quickDiffProvider = new MyLangRepository();
const workingTree = gitSCM.createResourceGroup('workingTree', 'Changes');
workingTree.resourceStates = [
{ resourceUri: vscode.window.activeTextEditor.document.uri }
];
Then i need to call registerTextDocumentContentProvider with some custom uri scheme. So why do i need custom uri scheme? And what else should i do to track changes of current file relative to the special one?
I was looking at vscode-extension-samples/source-control-sample, but it looks more complicated then my case.
Thanks for any advices!
Though my question was rather sily, let me save here some kind of instruction, how I've done this.
to make QuickDif work you don't need neither ResourceGroups nor TextDocumentContentProvider, this is a separate functionality.
SourceControl (and also its quickDiffProvider) will work if you pass some root directory in constructor (I've got no luck without thoug I don't need it for my purpose).

NetSuite SuiteScript - Constants And Inclusion

I have a NetSuite SuiteScript file (2.0) in which I want to include a small library of utilities I've built. I can do that fine, and access the functions in the included library. But I can't access the constants I've defined in that library - I have to re-declare them in the main file.
Here's the main file:
define(['N/record', 'N/search', './utils.js'],
function (record, search, utils) {
function pageInit(scriptContext) {
isUserAdmin = isCurrentUserAdmin(contextRecord);
if (isUserAdmin) {
alert('Administrator Role ID is ' + ADMINISTRATOR_ROLE);
// Do something for Admin users
}
return;
}
return {
pageInit: pageInit
};
});
You can see I include the file ./utils.js in it. Here's utils.js:
const ADMINISTRATOR_ROLE = 11;
function isCurrentUserAdmin(currentRecord) {
return ADMINISTRATOR_ROLE == nlapiGetRole();
}
That's the entire file - nothing else.
In the main file, the call to the function isCurrentUserAdmin works fine. It correctly tells me whether the current user is an admin. Note that I don't have to preface the call to isCurrentUserAdmin with utils. (utils.isCurrentUserAdmin doesn't work - it gives me the error JS_EXCEPTION TypeError utils is undefined). But when the code gets to the line that uses ADMINSTRATOR_ROLE, I get the error JS_EXCEPTION ReferenceError ADMINISTRATOR_ROLE is not defined. BTW, if I put the constant definition of ADMINISTRATOR_ROLE in the main file instead of utils.js, I get the same error when utils.js tries to use it. The only way I can get it to work is if I have the line defining the constant in both files.
Why does the inclusion work for the function, but not the constant? Am I including the library wrongly? I thought I'd have to use it as utils.isCurrentUserAdmin rather than just isCurrentUserAdmin, but to my surprise that's not the case, as I say above.
If you have utils.js like below, you can use utils.ADMINISTRATOR_ROLE and utils.isCurrentUserAdmin() in your main file.
/**
*#NApiVersion 2.0
*/
define ([],
function() {
const ADMINISTRATOR_ROLE = 11;
function isCurrentUserAdmin() {
// check here
}
return {
ADMINISTRATOR_ROLE: ADMINISTRATOR_ROLE,
isCurrentUserAdmin: isCurrentUserAdmin
};
});
Try
define(['N/record', 'N/search', 'SuiteScripts/utils']
You need to make sure any member you need to access in another module needs to be exported in the source module using the return statement

Use same method to get env vironment in flutter from build command than from .env file

I am using this package to set environment variables in flutter in a .env .
To read the variables I have to have this is my main.dart
Future main() async {
await DotEnv().load('.env');
runApp(MyApp());
}
And then read like this
print(DotEnv().env['VAR_NAME']);
From this question, I can also add variables in the build command like this
flutter run --dart-define=APP_VERSION=0.1.2
And then to read the ones set in the build command, I have to do this
const appVersion = String.fromEnvironment('APP_VERSION', defaultValue: 'development');
Is there please a way that I can read variables set in either the .env file or the build command the same way?
I will have the variables in my .env file for local development, and the in dev and prod environments they will be set via commands. So how can I find a way that works for both cases?
Thank you
I am not familiar with the package you mentioned, but a fairly safe bet would be as follows:
Create a singleton class that is responsible for handling environment variables:
final env = Env._();
class Env {
Env._(); // private constructor to prevent accidental initialization
}
Create a method that gets an environment variable from its string, and choose something to default to. IMO I would give precedence to command line args, but that is a matter of taste:
String get(String key, {String defaultValue}) {
final fromFile = DotEnv().env[key];
final fromArgs = String.fromEnvironment(key);
// return the value from command line if it exists
// if not, return the value from .env file
// if still null, return a default
return fromArgs ?? fromFile ?? defaultValue;
}
You can then access the data globally using:
env.get('MY_VARIABLE_NAME', defaultValue: 'hello');
For even more brevity, you can use Dart's callable classes, by renaming get() to call(), and then consume it using:
env('MY_VARIABLE_NAME', defaultValue: 'hello');

Choosing from a list of predefined variables for build pipelines

I'm creating an Azure Pipeline that will have some complex variables, but all of the variable values are one of four possible values. Is it somehow possible to choose variable values from a list when running the pipeline, or would I need to create an extension to accomplish this?
You could make use of powershell script to split the values firstly.
For example, there has a variable names var, and its value is one, two, three, four. And during the pipeline, I just want the value one be used.
Step1:
Write a ps1 file which contain below script to split out those values.
Param(
[string]$a
)
[array]$b = $a.split('.')
[string]$ma = $b[0]
Note: I split the variable based on .. So I store values as one.two.three.four.
Step2:
Since the value should be split first before others, here add Powershell task in the top and configure as below format:
Result:
Step3:
After we split it successfully, based on the scenario you want, this value should also be available for next tasks.
Just add another script in split.ps1 file which set the variable which store the value we want as output variable.
Then configure the reference name in the Powershell task.
Now, all of the next tasks can call that value by using $(ref.var).
This doesn't seem to be possible, so I used a workaround.
I included config files alongside the project named in the style config-team1.json, config-team2.json, etc. I created a variable that can be edited when the pipeline is run called Config.Name and defaulted it to team1. I then created a PowerShell task for the pipeline that checks for an appropriately-named config file and copies it to config.json. For example, if the variable Config.Name is set to team84, the script looks for config-team84.json and copies it to config.json.
Two other variables are also used, Config.SourceDirectory and Config.DestinationDirectory. These just specify where to look for the config file and where to copy it to.
$SourceFile = "config-$env:CONFIG_NAME.json"
$SourcePath = "$env:CONFIG_SOURCEDIRECTORY\$SourceFile"
$DestinationPath = "$env:CONFIG_DESTINATIONDIRECTORY\config.json"
Write-Host "Verifying that config file $SourceFile exists"
$FileExists = Test-Path -Path $SourcePath -PathType leaf
if (!$FileExists) {
throw "Config file does not exist at $SourcePath, cannot continue."
}
Write-Host "Copying config file"
Copy-Item "$SourcePath" -Destination "$DestinationPath"
This is the end of the Pipelines-specific step, the rest is just additional info for how I'm using this in the actual project.
The project being built is written in .NET Core, so I used Microsoft.Extensions.Configuration.Json. An example config file is:
{
"someKey": "someValue",
"anotherKey": 4,
"yetAnotherKey": true
}
You can get the config data like this:
var configuration = new ConfigurationBuilder()
.AddJsonFile("config.json", false) // false means the file is not optional
.Build();
In the above, configuration will be of type IConfigurationRoot.
You can use this configuration object directly:
var someVal = configuration["someKey"];
Or you can create a strongly-typed class for the config if you put the keys inside a parent key:
{
"myConfig": {
"someKey": "someValue",
"anotherKey": 4,
"yetAnotherKey": true
}
}
The C# class will look like this:
public class TestConfiguration
{
public string SomeKey { get; set; }
public int AnotherKey { get; set; }
public bool YetAnotherKey { get; set; }
}
Instantiate and use the class like this:
var testConfig = configuration.GetSection("myConfig").Get<TestConfiguration>();
var someVal = testConfig.SomeKey;

How to invoke a Eclipse Clean-Up Profile programmatically?

Is there a way to invoke a specific Clean-Up profile (Source->Clean Up) programmatically?
I would like to invoke it on an iterable of ICompilationUnits.
I looked at the declarations in org.eclise.jdt.ui.
The relevant command ID is org.eclipse.jdt.ui.edit.text.java.clean.up and the implementation is org.eclipse.jdt.internal.ui.actions.AllCleanUpsAction. Unfortunately it is an internal action and the command does not support any parameters.
I can see three possible approaches:
create an AllCleanUpsAction and invoke ...run(new StructuredSelection(<compilation units>[])). Problem: the action is internal so you might want to create a fragment to access it...
open the package navigator view. Select the proper files corresponding to the compilation units. Execute the command ID via IHandlerService.executeCommand("org.eclipse.jdt.ui.edit.text.java.clean.up"). Problem: the package navigator is changed... and you might not have all compilation units in visible in the navigator.
set the current selection in your view to new StructuredSelection(<compilation units>[]). Then execute the command as above. Problem: I'm not sure the command is properly enabled..
You can use RefactoringExecutionStarter.startCleanupRefactoring which takes an array of ICompilationUnits to perform the clean up on as one of its parameters. This method also allows you to specify the ICleanUps that you want to perform and allows you to skip showing the clean up wizard if you want.
Here's an example which removes unnecessary parentheses:
ICleanUp[] cleanUps = new ICleanUp[]{new ExpressionsCleanUp(){
#Override
protected boolean isEnabled(String key){
switch(key){
case CleanUpConstants.EXPRESSIONS_USE_PARENTHESES:
case CleanUpConstants.EXPRESSIONS_USE_PARENTHESES_NEVER:
return true;
case CleanUpConstants.EXPRESSIONS_USE_PARENTHESES_ALWAYS:
return false;
default:
return super.isEnabled(key);
}
}
}};
ICompilationUnit[] icus = new ICompilationUnit[]{icu};
Shell shell = HandlerUtil.getActiveEditor(event).getSite().getShell();
try {
RefactoringExecutionStarter.startCleanupRefactoring(
icus, cleanUps, false, shell, false, ActionMessages.CleanUpAction_actionName);
} catch (InvocationTargetException e) {
throw new AssertionError(e);
}