Gulp task publishing only one project - msbuild

When trying to publish projects from a solution using the below gulp task it working fine.
var publish = function (projectPath) {
return gulp.src([projectPath + "/**/*.csproj"])
.pipe(foreach(function (stream, file) {
return publishStream(stream, file);
}));
But when I pass an array with my project name in to gulp.src like below, publishing only one project and the task is exited. (here 'projects' is my array of projects)
return gulp.src(projects)
.pipe(foreach(function (stream, file) {
return publishStream(stream, file);
}));
What may be the reason

You have to provide the root folder as second parameter as shown below.
gulp.src(['bower_components/jquery/jquery.js',
'bower_components/superscrollorama/js/greensock/TweenMax.min.js',
'bower_components/superscrollorama/jquery.superscrollorama.js' ],
{base: 'bower_components/'})
.pipe(...);
Please have a look at Why does gulp.src not like being passed an array of complete paths to files?.

Related

Flutter test - verifying assets exist

I have a flutter app which contains a large list of quotes, each with an associated audio file.
I've written a simple test that verifies all the specified audio files are where they're supposed to be, in case of typos etc:
test('specified audio file should exist for all quotes', () {
ALL_QUOTES.forEach((quote) {
final expectedPath = 'assets/${quote.filename}.wav';
final exists = new File(expectedPath).existsSync();
expect(exists, isTrue, reason: '$expectedPath does not exist');
});
});
This passes fine in IntelliJ, however running from the command line using flutter test it fails on the first thing it looks for.
Is there a way of doing this which will work regardless of how it's run? Why does it pass one way but not the other?
Ok so I got to the bottom of this, and it is something you can do in a unit test.
To diagnose, I added the line print(Directory.current); to the test. Running in IntelliJ, I get /home/project_name. From the command line, it's /home/project_name/test. So just a simple file path thing to resolve.
Edited to include Ovidiu's simpler logic for getting the right asset path
void main() {
test('specified audio file should exist for all quotes', () {
ALL_QUOTES.forEach((quote) {
final expectedPath = 'assets/${quote.filename}.wav';
final exists = _getProjectFile(expectedPath).existsSync();
expect(exists, isTrue, reason: '$expectedPath does not exist');
});
});
}
File _getProjectFile(String path) {
final String assetFolderPath = Platform.environment['UNIT_TEST_ASSETS'];
return File('$assetFolderPath/$path');
}

Exception when listing created sub-directory in documents directory

I am using the official API to list a directory I had created for some purpose and have pushed few files into it. Now I want to list them out.
Here's how I am creating first
final Directory extDir = await getApplicationDocumentsDirectory();
// final String dirPath = '${extDir.path}/Movies/flutter_test';
final String dirPath = '${extDir.path}/mydir';
await new Directory(dirPath).create(recursive: true);
Here's what I am doing to read in a different page.
final Directory extDir = await getApplicationDocumentsDirectory();
// final String dirPath = '${extDir.path}/Pictures/flutter_test';
final String dirPath = '${extDir.path}/mydir';
final String thumbDirPath = '$dirPath/thumbs';
final Directory imgDir = Directory.fromUri(Uri.file(dirPath));
dirExists = imgDir.existsSync();
fileCount = 0;
if(dirExists) {
print("my dir exists");
// thumbDir.list(recursive: false, followLinks: false)
fileCount = await imgDir.list(recursive: false).length;
print('mydir images count $fileCount');
if(fileCount > 1) { // we think one is always the directory itself?
try {
imgDir.list(recursive: false, followLinks: false)
.listen((FileSystemEntity entity) {
The code breaks here giving the following exception message
type '() => Null' is not a subtype of type '(Object) => FutureOr<dynamic>'
I have to also tell you this doesn't happen when I am listing the external storage directory. Am I doing something wrong while creating my directory?
EDIT
I have now upgraded flutter to 0.7.3 on my Mac, and have a new problem altogether. The application won't run at all.
Okay, I found a solution myself. Apparently tinkering with the large provider API has given me different way to list the items, which actually told me I was trying to run listeners twice.
fileCount = await imgDir.list(recursive: false).length;
and
imgDir.list(recursive: false, followLinks: false)
.listen((FileSystemEntity entity) {
from original code cannot be written one after the other, as the first one finishes the listener. This I found out by altering my own code and listing directories this way instead.
Stream<FileSystemEntity> files = imgDir.list(recursive: false, followLinks: false);
will add as many events as many files according to API.. and then create a regular generic list
List<FileSystemEntity> entities = await files.toList();
and then you perform usual iteration using iterator or for() loop like
for(FileSystemEntity entity in entities) {
... // every file now is available

How to get local path for payload in WiX/Burn Managed Bootstrapper Application?

I am currently working in a WiX/Burn Managed Bootstrapper Application and cannot figure out how to get the local path for a payload (MSI).
I let the user select which applications they want to install in my custom UI, and I want to not show applications for which the MSI is missing. I also need to see information in the MSI's database.
I know I can determine missing payloads by handling "ResolveSource" but that doesn't happen until right before the application in installed.
I deserialize the BootstrapperApplicationData.xml file first thing so I have information about which MSIs MIGHT be installed, but it still doesn't help me determine the source of the MSIs.
Does anyone know how to determine the local path to a payload?
EDIT: Here is an example for how I reference all the installers:
<MsiPackage Id="AppName"
SourceFile="$(var.ProjectName.TargetDir)ProjectName.msi"
Name="MSI\ProjectName.msi"
Compressed="no"/>
In the GetLastUsedSourceFolder function in cache.cpp, you can see that the engine gets the source folder from the WixBundleLastUsedSource variable, and the parent directory of the WixBundleOriginalSource variable if WixBundleLastUsedSource isn't set.
You can use this along with the Name attribute of the WixPayloadProperties element in the BootstrapperApplicationData.xml file to predetermine where the engine will look for a payload. Note that the engine will actually look in the cache first.
The MSI files are embedded into the bundle .exe and aren't extracted from the bundle until right before the application is installed, which corresponds to when the ResolveSource event fires. However, if you really want to get this information, you can programatically extract the MSI files yourself and inspect them using the WiX DTF library (wix.dll in the /bin folder of your WiX install).
using Microsoft.Tools.WindowsInstallerXml;
private void ExtractEmbeddedMsiInstallers()
{
var tmpFolder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
var bundlePath = Engine.StringVariables["WixBundleOriginalSource"];
Unbinder unbinder = null;
try
{
unbinder = new Unbinder();
//The next line will extract the MSIs into the tmpFolder in a subfolder named "AttachedContainer"
unbinder.Unbind(bundlePath, OutputType.Bundle, tmpFolder);
}
finally
{
if (null != unbinder)
unbinder.DeleteTempFiles();
}
}
You also mentioned needing to inspect data in the MSI database. Here's a sample of how to do that:
using (var database = new InstallPackage(msiFilePath, DatabaseOpenMode.Transact) { WorkingDirectory = _someTempFolder })
{
if (database.Tables.Contains("CustomAction"))
{
using (View view = database.OpenView("SELECT `Action`, `Type`, `Source`, `Target` FROM `CustomAction`"))
{
view.Execute();
foreach (Record rowRecord in view)
using (rowRecord)
{
var actionName = rowRecord.GetString(1);
var actionType = rowRecord.GetInteger(2);
var binaryName = rowRecord.GetString(3);
var methodName = rowRecord.GetString(4);
//Do something with the values
}
}
}
}

How to pass parameters or arguments into a Gradle task?

I have a Gradle build script into which I am trying to include Eric Wendelin's CSS plugin.
It's easy enough to implement, and because I only want minification (rather than combining and gzipping), I've got the pertinent parts of the build script looking like this:
minifyCss {
source = "src/main/webapp/css/brandA/styles.css"
dest = "${buildDir}/brandA/styles.css"
yuicompressor {
lineBreakPos = -1
}
}
war {
baseName = 'ex-ren'
}
war.doFirst {
tasks.myTask.minifyCss.execute()
}
This is perfect - when I run the gradle war task, it calls the minifyCss task, takes the source css file, and creates a minified version in the buildDir
However, I have a handful of css files which need minify-ing, but not combining into one file (hence I'm not using the combineCss task)
What I'd like to be able to do is make the source and dest properties (assuming that's the correct terminology?) of the minifyCss task reference variables of some sort - either variables passed into the task in the signature, or global variables, or something ...
Something like this I guess (which doesn't work):
minifyCss(sourceFile, destFile) {
source = sourceFile
dest = destFile
yuicompressor {
lineBreakPos = -1
}
}
war {
baseName = 'ex-ren'
}
war.doFirst {
tasks.myTask.minifyCss.execute("src/main/webapp/css/brandA/styles.css", "${buildDir}/brandA/styles.css")
tasks.myTask.minifyCss.execute("src/main/webapp/css/brandB/styles.css", "${buildDir}/brandB/styles.css")
tasks.myTask.minifyCss.execute("src/main/webapp/css/brandC/styles.css", "${buildDir}/brandC/styles.css")
}
This doesn't work either:
def sourceFile = null
def destFile = null
minifyCss {
source = sourceFile
dest = destFile
yuicompressor {
lineBreakPos = -1
}
}
war {
baseName = 'ex-ren'
}
war.doFirst {
sourceFile = "src/main/webapp/css/brandA/styles.css"
destFile = "${buildDir}/brandA/styles.css"
tasks.myTask.minifyCss.execute()
}
For the life of me I cannot work out how to call a task and pass variables in :(
Any help very much appreciated;
You should consider passing the -P argument in invoking Gradle.
From Gradle Documentation :
--project-prop
Sets a project property of the root project, for example -Pmyprop=myvalue. See Section 14.2, “Gradle properties and system properties”.
Considering this build.gradle
task printProp << {
println customProp
}
Invoking Gradle -PcustomProp=myProp will give this output :
$ gradle -PcustomProp=myProp printProp
:printProp
myProp
BUILD SUCCESSFUL
Total time: 3.722 secs
This is the way I found to pass parameters.
If the task you want to pass parameters to is of type JavaExec and you are using Gradle 5, for example the application plugin's run task, then you can pass your parameters through the --args=... command line option. For example gradle run --args="foo --bar=true".
Otherwise there is no convenient builtin way to do this, but there are 3 workarounds.
1. If few values, task creation function
If the possible values are few and are known in advance, you can programmatically create a task for each of them:
void createTask(String platform) {
String taskName = "myTask_" + platform;
task (taskName) {
... do what you want
}
}
String[] platforms = ["macosx", "linux32", "linux64"];
for(String platform : platforms) {
createTask(platform);
}
You would then call your tasks the following way:
./gradlew myTask_macosx
2. Standard input hack
A convenient hack is to pass the arguments through standard input, and have your task read from it:
./gradlew myTask <<<"arg1 arg2 arg\ in\ several\ parts"
with code below:
String[] splitIntoTokens(String commandLine) {
String regex = "(([\"']).*?\\2|(?:[^\\\\ ]+\\\\\\s+)+[^\\\\ ]+|\\S+)";
Matcher matcher = Pattern.compile(regex).matcher(commandLine);
ArrayList<String> result = new ArrayList<>();
while (matcher.find()) {
result.add(matcher.group());
}
return result.toArray();
}
task taskName, {
doFirst {
String typed = new Scanner(System.in).nextLine();
String[] parsed = splitIntoTokens(typed);
println ("Arguments received: " + parsed.join(" "))
... do what you want
}
}
You will also need to add the following lines at the top of your build script:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Scanner;
3. -P parameters
The last option is to pass a -P parameter to Gradle:
./gradlew myTask -PmyArg=hello
You can then access it as myArg in your build script:
task myTask {
doFirst {
println myArg
... do what you want
}
}
Credit to #789 for his answer on splitting arguments into tokens
I would suggest the method presented on the Gradle forum:
def createMinifyCssTask(def brand, def sourceFile, def destFile) {
return tasks.create("minify${brand}Css", com.eriwen.gradle.css.tasks.MinifyCssTask) {
source = sourceFile
dest = destFile
}
}
I have used this method myself to create custom tasks, and it works very well.
task mathOnProperties << {
println Integer.parseInt(a)+Integer.parseInt(b)
println new Integer(a) * new Integer(b)
}
$ gradle -Pa=3 -Pb=4 mathOnProperties
:mathOnProperties
7
12
BUILD SUCCESSFUL
Its nothing more easy.
run command: ./gradlew clean -PjobId=9999
and
in gradle use: println(project.gradle.startParameter.projectProperties)
You will get clue.
I think you probably want to view the minification of each set of css as a separate task
task minifyBrandACss(type: com.eriwen.gradle.css.tasks.MinifyCssTask) {
source = "src/main/webapp/css/brandA/styles.css"
dest = "${buildDir}/brandA/styles.css"
}
etc etc
BTW executing your minify tasks in an action of the war task seems odd to me - wouldn't it make more sense to make them a dependency of the war task?
Here is a solution for Kotlin DSL (build.gradle.kts).
I first try to get the variable as a property and if it was null try to get it from OS environment variables (can be useful in CIs like GitHub Actions).
tasks.create("MyCustomTask") {
val songName = properties["songName"]
?: System.getenv("SONG_NAME")
?: error("""Property "songName" or environment variable "SONG_NAME" not found""")
// OR getting the property with 'by'. Did not work for me!
// For this approach, name of the variable should be the same as the property name
// val songName: String? by properties
println("The song name: $songName")
}
We can then pass a value for the property from command line:
./gradlew MyCustomTask -PsongName="Black Forest"
Or create a file named local.properties at the root of the project and set the property:
songName=Black Forest
We can also add an env variable named SONG_NAME with our desired value and then run the task:
./gradlew MyCustomTask

Write file specific folder inside localFolder

I'm trying to write an image file to the localFolder storage. I want to write it specifically to the images/heroes/ folder inside the localFolder. Is there some way to do this with my existing code?
return WinJS.xhr({ url: fileToDownloadURL, responseType: 'blob' }).then(
function (response) {
var input = response.response.msDetachStream();
var filename = 'ms-appx:///local/images/heroes/image_name.png';
Windows.Storage.ApplicationData.current.localFolder.createFileAsync(filename,
Windows.Storage.CreationCollisionOption.replaceExisting).then(
function (file) {
return file.openAsync(Windows.Storage.FileAccessMode.readWrite).then(
function (output) {
return Windows.Storage.Streams.RandomAccessStream.copyAsync(input, output).then(
function () {
output.flushAsync().then(function () {
input.close();
output.close();
});
});
});
}
}
)};
I get this error message:
0x8007007b - JavaScript runtime error: The filename, directory name, or volume label syntax is incorrect.
WinRT information: The specified name (ms-appx:///local/images/heroes/image_name.png) contains one or more invalid characters.
I figured it out. For anyone wondering, you can call
getFolderAsync('SomeFolderName')
from the
Windows.Storage.ApplicationData.current.localFolder
instance. getFolderAsync() is like any promise function and will return with an error if the folder does not exist. From there you can run
createFolderAsync('SomeFolderName')
to create the folder, and then continue what you were doing. In my case it was better to create a function like writeFileAsync() and then call it depending on whether or not the folder exists first.
Keep in mind getFolderAsync() can only get one folder at a time, so something like
getFolderAsync('along/list/of/folders')
won't work. You'll have to chain together the getFolderAsync() calls together, I believe (correct me if I'm wrong!).