Invoking shell scripts on Windows under MSYS using Command - path

I am trying to invoke commands in Rust (1.0 beta 3) on Windows 7 in an MSYS2 environment, but I cannot understand how to do it.
Suppose that you have this very simple script called myls in your home folder:
#!/bin/bash
ls
And now create a simple program in Rust that calls the script:
use std::process::Command;
use std::path::Path;
fn main()
{
let path_linux_style = Path::new("~/myls").to_str().unwrap();
let path_win_style = Path::new("C:\\msys64\\home\\yourname\\myls").to_str().unwrap();
let out_linux = Command::new(path_linux_style).output();
let out_win = Command::new(path_win_style).output();
match out_linux
{
Ok(_) => println!("Linux path is working!"),
Err(e) => println!("Linux path is not working: {}", e)
}
match out_win
{
Ok(_) => println!("Win path is working!"),
Err(e) => println!("Win path is not working: {}", e)
}
}
Now, if you try to execute it, you will get the following output:
Linux path is not working: The system cannot find the file specified.
(os error 2)
Win path is not working: %1 is not a valid Win32 application.
(os error 193)
So I am not able to invoke any command in MSYS environment.
How can I solve it?
EDIT:
I noticed that if I invoke an executable, the problem doesn't happen, so it seems to be related to invocation of bash script. Anyway, it's quite annoying since it makes compiling projects depending on external C/C++ code (that need to launch configure script) tricky to get to work.

The Windows example doesn't work because Windows isn't a Unix. On Unix-like systems, the #! at the beginning of a script is recognized, and it invokes the executable at the given path as the interpreter. Windows doesn't have this behavior; and even if it did, it wouldn't recognize the path name to the /bin/bash, as that path name is one that msys2 emulates, it is not a native path name.
Instead, you can explicitly execute the script you want using the msys2 shell, by doing something like the following (alter the path as appropriate, I have msys32 installed since it's a 32 bit VM)
let out_win = Command::new("C:\\msys32\\usr\\bin\\sh.exe")
.arg("-c")
.arg(path_win_style)
.output();

Related

FZF and NeoVim how to get files list

I try to use neovim with fzf plugins. Part of my init.lua is
-- Plugin imstallation section
local install_path = fn.stdpath('data')..'/site/pack/paqs/opt/paq-nvim'
if fn.empty(fn.glob(install_path)) > 0 then
cmd('!git clone --depth 1 https://github.com/savq/paq-nvim.git '..install_path)
end
-- Load the plugin manager
cmd 'packadd paq-nvim'
-- Set the short hand
local plug = require('paq-nvim').paq
-- Make paq manage it self
plug {'savq/paq-nvim', opt=true}
plug {'scrooloose/nerdtree', opt=true}
plug {'vim-airline/vim-airline', opt=true}
plug {'vijaymarupudi/nvim-fzf', opt=false}
plug {'ibhagwan/fzf-lua', opt=false}
require('paq-nvim').install()
require('paq-nvim').clean()
When I try to use command FzfLua files I observe message
fzf error 2 : unknown option: --headless
I work under Windows 10 and I use lua plugins : fzf-lua and nvim-fzf
fzf binary was installed and reachable
I cannot understand why rzr run with this strange option
What I did wrong?
Fzf-lua uses nvim-fzf actions for previews (and other functions) which calls lua functions by running neovim —headless … <lua function id>.
It seems that your neovim version does not support the headless option, I know of other users running fzf-lua on WSL, try with the official 0.5.1 appimage

How to find path to the package directory when the script is running with `pub run` command

I am writing a package that loads additional data from the lib directory and would like to provide an easy way to load this data with something like this:
const dataPath = 'mypackage/data/data.json';
initializeMyLibrary(dataPath).then((_) {
// library is ready
});
I've made two separate libraries browser.dart and standalone.dart, similar to how it is done in the Intl package.
It is quite easy to load this data from the "browser" environment, but when it comes to the "standalone" environment, it is not so easy, because of the pub run command.
When the script is running with simple $ dart myscript.dart, I can find a package path using dart:io.Platform Platform.script and Platform.packageRoot properties.
But when the script is running with $ pub run tool/mytool, the correct way to load data should be:
detect that the script is running from the pub run command
find the pub server host
load data from this server, because there could be pub transformers and we can't load data directly from the file system.
And even if I want to load data directly from the file system, when the script is running with pub run, Platform.script returns /mytool path.
So, the question is there any way to find that the script is running from pub run and how to find server host for the pub server?
I am not sure that this is the right way, but when I am running script with pub run, Package.script actually returns http://localhost:<port>/myscript.dart. So, when the scheme is http, I can download using http client, and when it is a file, load from the file system.
Something like this:
import 'dart:async';
import 'dart:io';
import 'package:path/path.dart' as ospath;
Future<List<int>> loadAsBytes(String path) {
final script = Platform.script;
final scheme = Platform.script.scheme;
if (scheme.startsWith('http')) {
return new HttpClient().getUrl(
new Uri(
scheme: script.scheme,
host: script.host,
port: script.port,
path: 'packages/' + path)).then((req) {
return req.close();
}).then((response) {
return response.fold(
new BytesBuilder(),
(b, d) => b..add(d)).then((builder) {
return builder.takeBytes();
});
});
} else if (scheme == 'file') {
return new File(
ospath.join(ospath.dirname(script.path), 'packages', path)).readAsBytes();
}
throw new Exception('...');
}

Debugging Jest test cases using node-inspector

Is there a way to use node-inspector to debug unit tests with Jest? It would be nice to step through sometimes to see why tests are failing
I have tried a few ways
node-debug jest --runInBand
from the as well as starting up the inspector first eg
$ node-inspector
$ node --debug-brk .\node_modules\jest-cli --runInBand
and then navigate to http://127.0.0.1:8080/debug?port=5858
I have found that occasionally (1 in 10 or so times), the debugger opens the jest src files and its possible to debug them. Generally though, the scripts in the debugger only contain a 'no domain' folder and another irrelevant folder.
Also the test scripts themselves are never loaded in the debugger.
Has anyone tried this before?
Looks like the issue is that jest is using harmonize, which spawns a child process to ensure that the --harmony option is used.
harmonize/harmonize.js, lines 30-35
var node = child_process.spawn(process.argv[0], ['--harmony'].concat(process.argv.slice(1)), {});
node.stdout.pipe(process.stdout);
node.stderr.pipe(process.stderr);
node.on("close", function(code) {
process.exit(code);
});
I was able to successfully debug jest tests (although tests that use JSX transforms are incredibly slow) by commenting out the code that jest is using to spawn the harmonized process.
node_modules/jest-cli/bin/jest.js, last lines of the file:
if (require.main === module) {
//harmonize(); <--- comment out
_main(function (success) {
process.exit(success ? 0 : 1);
});
}
Then you can run:
$ node-debug --nodejs --harmony ./node_modules/jest-cli/bin/jest.js --runInBand
Jest relies on the --harmony flag being there, so that's why we need to add it back with --nodejs --harmony. We also add --runInBand so that the tests run in sequence, not in parallel.
This opens up the web debugger, and you can debug the tests, although it can be pretty slow to get to the test you want. Please comment if anyone knows a way to make this faster, and I'll update my answer.
You can add this to your package.json to make it easier to kick off:
...
scripts: {
"test": "jest",
"test-debug": "node-debug --nodejs --harmony ./node_modules/jest-cli/bin/jest.js --runInBand"
}
...
Of course, main concern with this solution is the editing of the jest source code. Will think about how to make a pull request to make this stick.
Created Github Issue Here: https://github.com/facebook/jest/issues/152
This is now officially supported with Node >= 6.3.
Quoting Jest documentation:
Place a debugger; statement in any of your tests, and then, in your project's directory, run:
node --debug-brk --inspect ./node_modules/.bin/jest -i [any other arguments here]
This will output a link that you can open in Chrome. After opening that link, the Chrome Developer Tools will be displayed, and a breakpoint will be set at the first line of the Jest CLI script (this is done simply to give you time to open the developer tools and to prevent Jest from executing before you have time to do so). Click the button that looks like a "play" button in the upper right hand side of the screen to continue execution. When Jest executes the test that contains the debugger statement, execution will pause and you can examine the current scope and call stack.
Note: the -i cli option makes sure Jest runs test in the same process rather than spawning processes for individual tests. Normally Jest parallelizes test runs across processes but it is hard to debug many processes at the same time.
More information on the V8 inspector can be found here: https://nodejs.org/api/debugger.html#debugger_v8_inspector_integration_for_node_js
Using Node 7.4.0, Jest 18.x, and the jest-environment-node-debug package (from this comment), it's now possible to use the chrome devtools to debug Jest tests:
$ npm install -D jest-environment-node-debug
$ node --inspect-brk ./node_modules/.bin/jest -i --env jest-environment-node-debug
Here's a Gruntfile.js config to automate #Sean's answer with Grunt.
grunt testd
OR
grunt testd --tests=MyTestName
OR
grunt testd --tests=MyTestName,AnotherTestName
Requires "node-inspector" (must be installed globally to get the node-debug bin in your path), "lodash", "jest-cli" and "grunt-shell" node modules.
var _ = require('lodash');
var commaSplitToRegex = function(input) {
return _.map(input.split(','), function(part) {
return '(' + part + ')';
}).join('|');
};
var getTestRegex = function(tests) {
if (tests) {
return '.*' + commaSplitToRegex(tests) + '.*';
}
return '.*';
}
module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-shell');
grunt.initConfig({
shell: {
jestd: {
command: function() {
var testsRegex = getTestRegex(grunt.option('tests'));
var cmd = 'node-debug --nodejs --harmony ./node_modules/jest-cli/bin/jest.js --runInBand --config="test_utils/jest.json"';
if (testsRegex) {
cmd += ' "' + testsRegex + '"';
}
return cmd;
}
},
monkeypatchjest: {
command: 'sed -i.bak s\\/harmonize\\(\\)\\;\\/\\\\/\\\\/wtf\\/g ./node_modules/jest-cli/bin/jest.js'
},
unmonkeypatchjest: {
command: 'sed -i.bak s\\/\\\\/\\\\/wtf\\/harmonize\\(\\)\\;\\/g ./node_modules/jest-cli/bin/jest.js'
}
}
});
grunt.registerTask('testd', 'Run tests with debugger.', ['shell:monkeypatchjest', 'shell:jestd']);
};

Access to user environment variable

In my .bashrc file:
export DART_SDK=/home/nicolas/dart/dart-sdk
In command line, it works when I "echo" it. But I cannot see this user variable from dart with, I just see system variable but not mine:
var env = Platform.environment;
env.forEach((k,v) => print("Key=$k Value=$v"));
I tried:
on windows and it works
on mac but doesn't work
Is my user variable is not well defined? Is my code is bad? It's a bug?
Using the following code:
import 'dart:io'; // Server side / command line only package.
main() {
Map<String, String> env = Platform.environment;
env.forEach((k, v) => print("Key=$k Value=$v"));
}
I was able to override environment variables on both Windows and Mac. On Mac I had to add the line to .bash_profile (.bashrc is not loaded on my Mac).
John
Here is the link to dart docs: https://api.dartlang.org/1.13.0/dart-io/Platform-class.html

How to compile a Delphi 7 project group file (.bpg) using the command line?

I've grouped a lot of projects in a project group. All the info is in the project.bpg. Now I'd like to automatically build them all.
How do I build all the projects using the command line?
I'm still using Delphi 7.
I never tried it myself, but here is a German article describing that you can use make -f ProjectGroup.bpg because *.bpgs essentially are makefiles.
You can also run Delphi from the command line or a batch file, passing the .bpg file name as a parameter.
Edit: Example (for D2007, but can be adjusted for D7):
=== rebuild.cmd (excerpt) ===
#echo off
set DelphiPath=C:\Program Files\CodeGear\RAD Studio\5.0\bin
set DelphiExe=bds.exe
set LibPath=V:\Library
set LibBpg=Library.groupproj
set LibErr=Library.err
set RegSubkey=BDSClean
:buildlib
echo Rebuilding %LibBpg%...
if exist "%LibPath%\%LibErr%" del /q "%LibPath%\%LibErr%"
"%DelphiPath%\%DelphiExe%" -pDelphi -r%RegSubkey% -b "%LibPath%\%LibBpg%"
if %errorlevel% == 0 goto buildlibok
As I said as a comment to Ulrich Gerhardt answer, the make project_group.bpg is useless if your projects are in subdirectories. Make won't use relative paths and the projects won't compile correctly.
I've made a python script to compile all the DPRs in every subdirectory. This is what I really wanted to do, but I'll leave the above answer as marked. Although it didn't worked for me, It really answered my question.
Here is my script to compile_all.py . I believe it may help somebody:
# -*- coding: utf-8 -*-
import os.path
import subprocess
import sys
#put this file in your root dir
BASE_PATH = os.path.dirname(os.path.realpath(__file__))
os.chdir(BASE_PATH)
os.environ['PATH'] += "C:\\Program Files\\Borland\\Delphi7\\Bin" #your delphi compiler path
DELPHI = "DCC32.exe"
DELPHI_PARAMS = ['-B', '-Q', '-$D+', '-$L+']
for root, dirs, files in os.walk(BASE_PATH):
projects = [project for project in files if project.lower().endswith('.dpr')]
if ('FastMM' in root ): #put here projects you don't want to compile
continue
os.chdir(os.path.join(BASE_PATH, root))
for project in projects:
print
print '*** Compiling:', os.path.join(root, project)
result = subprocess.call([DELPHI] + DELPHI_PARAMS + [project])
if result != 0:
print 'Failed for', project, result
sys.exit(result)
Another vantage of this approach is that you don't need to add new projects to your bpg file. If it is in a subdir, it will compile.

Resources