diff --git a/build.psm1 b/build.psm1 index e546506d4d..dc356337c5 100644 --- a/build.psm1 +++ b/build.psm1 @@ -30,6 +30,10 @@ if ($IsLinux) { function Start-PSBuild { [CmdletBinding(DefaultParameterSetName='CoreCLR')] param( + # When specified this switch will stops running dev powershell + # to help avoid compilation error, because file are in use. + [switch]$StopDevPowerShell, + [switch]$NoPath, [switch]$Restore, [string]$Output, @@ -37,6 +41,10 @@ function Start-PSBuild { [switch]$TypeGen, [switch]$Clean, + # this switch will re-build only System.Mangement.Automation.dll + # it's useful for development, to do a quick changes in the engine + [switch]$SMAOnly, + [Parameter(ParameterSetName='CoreCLR')] [switch]$Publish, @@ -66,6 +74,18 @@ function Start-PSBuild { [string]$Configuration ) + function Stop-DevPowerShell + { + Get-Process powershell* | + Where-Object { + $_.Modules | + Where-Object { + $_.FileName -eq (Resolve-Path $script:Options.Output).Path + } + } | + Stop-Process -Verbose + } + if ($Clean) { log "Cleaning your working directory. You can also do it with 'git clean -fdX'" @@ -142,9 +162,22 @@ function Start-PSBuild { } # set output options - $OptionsArguments = @{Publish=$Publish; Output=$Output; FullCLR=$FullCLR; Runtime=$Runtime; Configuration=$Configuration; Verbose=$true} + $OptionsArguments = @{ + Publish=$Publish + Output=$Output + FullCLR=$FullCLR + Runtime=$Runtime + Configuration=$Configuration + Verbose=$true + SMAOnly=[bool]$SMAOnly + } $script:Options = New-PSOptions @OptionsArguments + if ($StopDevPowerShell) + { + Stop-DevPowerShell + } + # setup arguments $Arguments = @() if ($Publish) { @@ -155,6 +188,10 @@ function Start-PSBuild { if ($Output) { $Arguments += "--output", (Join-Path $PSScriptRoot $Output) } + elseif ($SMAOnly) { + $Arguments += "--output", (Split-Path $script:Options.Output) + } + $Arguments += "--configuration", $Options.Configuration $Arguments += "--framework", $Options.Framework $Arguments += "--runtime", $Options.Runtime @@ -215,7 +252,7 @@ function Start-PSBuild { if (-not (Test-Path $Lib)) { throw "Compilation of $Lib failed" } - } elseif ($FullCLR) { + } elseif ($FullCLR -and (-not $SMAOnly)) { log "Start building native powershell.exe" try { @@ -277,7 +314,6 @@ cmd.exe /C cd /d "$location" "&" "$($vcVarsPath)\vcvarsall.bat" "$NativeHostArch } } - function New-PSOptions { [CmdletBinding()] param( @@ -302,7 +338,9 @@ function New-PSOptions { [switch]$Publish, [string]$Output, - [switch]$FullCLR + [switch]$FullCLR, + + [switch]$SMAOnly ) # Add .NET CLI tools to PATH @@ -372,9 +410,19 @@ function New-PSOptions { $Output = [IO.Path]::Combine($Output, $Executable) } + $RealFramework = $Framework + if ($SMAOnly) + { + $Top = "$PSScriptRoot/src/System.Management.Automation" + if ($Framework -match 'netcoreapp') + { + $RealFramework = 'netstandard1.6' + } + } + return @{ Top = $Top; Configuration = $Configuration; - Framework = $Framework; + Framework = $RealFramework; Runtime = $Runtime; Output = $Output } } @@ -721,7 +769,6 @@ function Publish-NuGetFeed } } - function Start-DevPowerShell { param( [switch]$ZapDisable, diff --git a/docs/git/powershell-repository-101.md b/docs/git/powershell-repository-101.md index 193e36d264..785385f782 100644 --- a/docs/git/powershell-repository-101.md +++ b/docs/git/powershell-repository-101.md @@ -45,23 +45,13 @@ Branches Use **git rebase** instead of **git merge** and **git pull**, when you're updating your feature-branch. ```sh -# switch to master branch - # fetch updates all remote branch references in the repo and all submodules # --all : tells it to do it for all remotes (handy, when you use your fork) # -p : tells it to remove obsolete remote branch references (when they are removed from remote) git fetch --all -p -# pull updates your local files -# you should call this command ONLY from master branch -git pull origin master - -``` - -Then switch to your branch and do a rebase - -``` -git rebase master +# rebase on origin/master will rewrite your branch history +git rebase origin/master ``` #### More complex scenarios diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostRawUserInterface.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostRawUserInterface.cs index 2c260fb478..24307ce22d 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostRawUserInterface.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostRawUserInterface.cs @@ -1711,7 +1711,44 @@ namespace Microsoft.PowerShell } } - /// + public void ScrollBuffer(int lines) + { + for (int i=0; i /// This API returns a rectangular region of the screen buffer. In /// this example this functionality is not needed so the method throws /// a NotImplementException exception. @@ -1752,15 +1789,61 @@ namespace Microsoft.PowerShell /// /// This method copies an array of buffer cells into the screen buffer - /// at a specified location. In this example this functionality is - /// not needed so the method throws a NotImplementedException exception. + /// at a specified location. /// - /// The parameter is not used. - /// The parameter is not used. + /// The parameter used to set the origin where the buffer where begin writing to. + /// The parameter used to contain the contents to be written to the buffer. public override void SetBufferContents(Coordinates origin, BufferCell[,] contents) { - throw new NotImplementedException("The method or operation is not implemented."); + //if there are no contents, there is nothing to set the buffer to + if (contents == null) + { + PSTraceSource.NewArgumentNullException("contents"); + } + + //variables to traverse through the buffer + int cursorX = origin.X; + int cursorY = origin.Y; + + //if the cursor is on the last line, we need to make more space to print the specified buffer + if (cursorY == Console.BufferHeight -1 && cursorX >= Console.BufferWidth) + { + //for each row in the buffer, create a new line + int rows = contents.GetLength(0); + for (int i=0; i < rows; i++) + { + ScrollBuffer(1); + } + + //for each row in the buffer, move the cursor y up to the beginning of the created blank space + cursorY -= rows; + } + + //iterate through the buffer to set + foreach (var charitem in contents) + { + //set the cursor to false to prevent cursor flicker + Console.CursorVisible = false; + + //if x is exceeding buffer width, reset to the next line + if (cursorX >= Console.BufferWidth) + { + cursorX = 1; + } + + //write the character from contents + Console.Out.Write(charitem.Character); + + //advance the character one position + cursorX++; + } + + //reset the cursor to the original position + Console.SetCursorPosition(cursorX, cursorY); + //reset the cursor to visible + Console.CursorVisible = true; + } /// diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs index d213381d1b..9d457a1a6d 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs @@ -102,14 +102,33 @@ namespace Microsoft.PowerShell location.X = 0; location.Y = Math.Min(location.Y + 2, bufSize.Height); - // Save off the current contents of the screen buffer in the region that we will occupy - - savedRegion = - rawui.GetBufferContents( - new Rectangle(location.X, location.Y, location.X + cols - 1, location.Y + rows - 1)); + if (System.Management.Automation.Platform.IsWindows) + { + // Save off the current contents of the screen buffer in the region that we will occupy + savedRegion = + rawui.GetBufferContents( + new Rectangle(location.X, location.Y, location.X + cols - 1, location.Y + rows - 1)); + } + //Platform is either OSX or Linux + else + { + // replace the saved region in the screen buffer with our progress display + location.X = rawui.CursorPosition.X; + location.Y = rawui.CursorPosition.Y; + + //set the cursor position back to the beginning of the region to overwrite write-progress + //if the cursor is at the bottom, back it up to overwrite the previous write progress + if (location.Y >= Console.BufferHeight - rows) + { + Console.Out.Write('\n'); + location.Y -= rows; + } + + Console.SetCursorPosition(location.X, location.Y); + } + // replace the saved region in the screen buffer with our progress display - rawui.SetBufferContents(location, tempProgressRegion); } } diff --git a/test/powershell/enginecore/Parser.Test.ps1 b/test/powershell/enginecore/Parser.Test.ps1 index d216989a64..df22e5f143 100644 --- a/test/powershell/enginecore/Parser.Test.ps1 +++ b/test/powershell/enginecore/Parser.Test.ps1 @@ -102,6 +102,7 @@ Describe "ParserTests (admin\monad\tests\monad\src\engine\core\ParserTests.cs)" } AfterEach { $PowerShell.Commands.Clear() + $PowerShell.Streams.Error.Clear() if(Test-Path $testfile) { Remove-Item $testfile @@ -731,14 +732,88 @@ Describe "ParserTests (admin\monad\tests\monad\src\engine\core\ParserTests.cs)" $result | Should be "1" } - It "Newlines are allowed after operators (line 3033)" { - $result = ExecuteCommand "(20 % - 6 * - 4 + - 2) / - 2 - - 3" - $result | should be 2 + It 'Tests accessing using null as index. (line 2648)'{ + ExecuteCommand '$A=$(testcmd-parserBVT -returntype array); $A[$NONEXISTING_VARIABLE];' + $PowerShell.HadErrors | should be $true + $PowerShell.Streams.Error.FullyQualifiedErrorId | should be "NullArrayIndex" + } + + It 'Tests the parser response to ArrayName[. (line 2678)'{ + try { + ExecuteCommand '$A=$(testcmd-parserBVT -returntype array); $A[ ;' + throw "Execution OK" + } + catch { + $_.FullyQualifiedErrorId | Should be "ParseException" + } + } + + It 'Tests the parser response to ArrayName[]. (line 2687)'{ + try { + ExecuteCommand '$A=$(testcmd-parserBVT -returntype array); $A[] ;' + throw "Execution OK" + } + catch { + $_.FullyQualifiedErrorId | Should be "ParseException" + } + } + + #Issue#1430 + It "Tests function scopes in a script. (line 2800)" -Pending{ + " function global:func { 'global' }; " + + " function func { 'default' }; " + + " local:func; " + + " script:func; " + + " global:func; ">$testfile + $result = ExecuteCommand "function func { 'notcalled' };. $testfile" + $result -join "" | should be ("default", "default", "global" -join "") + $result = ExecuteCommand "func" + $result | should be "global" + } + + It 'Test piping arguments to a script block. The objects should be accesible from "$input". (line 2870)'{ + ExecuteCommand '$script = { $input; };$results = @(0,0),-1 | &$script' + $result = ExecuteCommand '$results[0][0]' + $result | Should be "0" + $result = ExecuteCommand '$results[0][1]' + $result | Should be "0" + $result = ExecuteCommand '$results[1]' + $result | Should be "-1" + } + + It 'Test piping null into a scriptblock. The script block should not be passed anything. (line 2903)'{ + $result = ExecuteCommand '$() | &{ $count = 0; foreach ($i in $input) { $count++ }; $count }' + $result | Should be "1" + $result = ExecuteCommand '$() | &{ $input }' + $result | Should BeNullOrEmpty + } + + It 'Test that types in System.dll are found automatically. (line 2951)'{ + $result = ExecuteCommand '[ System.IO.FileInfo]' + $result | Should be "System.IO.FileInfo" + } + + Context "Mathematical Operations Tests (starting at line 2975 to line 3036)" { + $testData = @( + @{ Script = '$a=6; $a -= 2;$a'; Expected = 4 } + @{ Script = "20 % + 6"; Expected = "2" } + @{ Script = "(20 % + 6 * + 4 + + 2 ) / + 2 - + 3"; Expected = "2" } + ) + It "