PowerShellThingies icon indicating copy to clipboard operation
PowerShellThingies copied to clipboard

Support inline stdin redirect

Open b1f6c1c4 opened this issue 7 years ago • 5 comments

In sh we can do the following:

echo 'Merge branch doc' | git commit-tree $(git write-tree) -p HEAD -p doc > thecommithash
git reset --soft $(cat thecommithash)
rm -f thecommithash

In PowerShell the following works, but thecommithash has strange encoding:

echo 'Merge branch doc' | git commit-tree $(git write-tree) -p HEAD -p doc > thecommithash
git reset --soft $(cat thecommithash)
rm -fo thecommithash

To take the benefit of Use-RawPipeline, it'd be better to have echo2:

echo2 'Merge branch doc' | run git commit-tree $(git write-tree) -p HEAD -p doc | out2 thecommithash
git reset --soft $(cat thecommithash)
rm -fo thecommithash

Basically, echo2, compared with stdin, should create a raw pipeline stdin from its arguments literally, instead of files specified by the arguments.

b1f6c1c4 avatar Apr 24 '18 07:04 b1f6c1c4

I see what you are trying to do. However, it is not well-defined what you mean by "literally". Pipes in PowerShell pass objects instead of byte streams. Therefore, you might want to specify some encoding here. A cmdlet that converts stream or string (along with an encoding) into ITeedProcessStartInfo seems to be useful.

However, the example doesn't seem to motivate the new functionality. The second snippet gives strange encoding in thecommithash because PowerShell tried to guess the encoding of the output from git and converted it into string, and the string is written to thecommithash with default encoding (UTF16 LE, if I recall correctly). For the third snippet, the first guessing happens in $(cat thecommithash). Even worse, I'm not sure how PowerShell converts the output of Write-Output 'Merge branch doc' into byte stream -- it seems that it is not UTF16 LE, perhaps it is your console encoding. If you don't mind PowerShell guessing it (as it gets it correct, though not guaranteed), you might as well use the following code:

$commithash = 'Merge branch doc' | git commit-tree (git write-tree) -p HEAD -p doc
git reset --soft $commithash

I will work on converting byte stream and string into ITeedProcessStartInfo when I find larger block of free time.

GeeLaw avatar Apr 24 '18 10:04 GeeLaw

Possibly the following is what I desire:

If I want to insert UTF-8 encoded chars in commit message, I have to do the following:

"Merge branch doc: 测试" | sc -Encoding UTF8 thecommitmessage
stdin thecommitmessage | run git commit-tree (git write-tree) -p HEAD -p doc | 2ps
rm -fo thecommitmessage

Would I have a helper function echo2, I can rewrite the ugly code above into this:

echo2 "Merge branch doc: 测试" -Encoding UTF8 | run git commit-tree (git write-tree) -p HEAD -p doc | 2ps

b1f6c1c4 avatar Apr 24 '18 11:04 b1f6c1c4

Sure. I got your idea. BTW, you might want to rewrite it as the following to eliminate encoding guessing:

echo2 'Merge branch doc: 测试' -Encoding UTF8 |
    run git commit-tree `
        (run git write-tree | 2ps -Encoding UTF8) `
        -p HEAD -p doc |
    2ps -Encoding UTF8

GeeLaw avatar Apr 24 '18 14:04 GeeLaw

run git write-tree | 2ps -Encoding UTF8 might be loquacious because git write-tree outputs plain hex chars.

b1f6c1c4 avatar Apr 24 '18 14:04 b1f6c1c4

You could use following to write string to raw pipeline. set/p is to prevent trailing new lines from echo.

function echo2($str) {
  run cmd /c "echo|set/p=$str"
}

Following uses temporary file but works fine with leading/trailing spaces and special characters of windows command line.

echo2 '  %^&<>|''`,;=()!"\[].*? ' | run openssl base64 | 2ps

function echo2($str) {
  $str|Out-File -encoding ascii echo2_temp.txt -NoNewline
  run cmd /c "type echo2_temp.txt && del echo2_temp.txt"
}

expressiveco avatar May 11 '20 15:05 expressiveco