populate method
Implementation
Map<String, String?> populate() {
final variables = <String, String?>{};
final projectRoot = pubspecYaml.nearest();
variables[Vars.projectRoot] =
projectRoot == null ? null : path.dirname(projectRoot);
final scriptsRoot = scriptsYaml.nearest();
variables[Vars.scriptsRoot] =
scriptsRoot == null ? null : path.dirname(scriptsRoot);
variables[Vars.cwd] = cwd.path;
final definedVariables = scriptsYaml.variables();
for (final MapEntry(:key, :value) in (definedVariables ?? {}).entries) {
if (value is! String) {
Logger.warn('Variable $key is not a string');
continue;
}
if (Vars.values.contains(key)) {
Logger.warn('Variable $key is a reserved keyword');
continue;
}
variables[key] = value;
}
for (final MapEntry(:key, value: variable) in {...variables.entries}) {
if (variable == null) {
continue;
}
final matches = variablePattern.allMatches('$variable');
if (matches.isEmpty) {
continue;
}
final keyToCheckForCircular = {key};
String? resolve(RegExpMatch match, String variable) {
final referencedVariable = match.group(1);
final wholeMatch = match.group(0)!;
if (referencedVariable == null) {
Logger.warn('Variable $referencedVariable is not defined');
return null;
}
if (referencedVariable.startsWith(r'$')) {
Logger.warn(
'Variable $key is referencing a script, this is forbidden',
);
return null;
}
if (referencedVariable.startsWith('-')) {
return variable;
}
keyToCheckForCircular.add(referencedVariable);
final referencedValue = variables[referencedVariable];
if (referencedValue == null) {
Logger.warn('Variable $referencedVariable is not defined');
return null;
}
var almostResolved = variable.replaceAll(wholeMatch, referencedValue);
if (variablePattern.hasMatch(almostResolved)) {
for (final match in variablePattern.allMatches(almostResolved)) {
// check for circular references
if (keyToCheckForCircular.contains(match.group(1))) {
Logger.warn('Circular reference detected for variable $key');
return null;
}
final partialResolved = resolve(match, almostResolved);
if (partialResolved == null) {
return null;
}
almostResolved =
almostResolved.replaceAll(match.group(0)!, partialResolved);
}
}
return almostResolved;
}
for (final match in matches) {
final resolved = resolve(match, '$variable');
variables['$key'] = resolved;
}
}
return variables;
}