1

I've got a simple PowerShell script that I'm calling from Jenkins:

function PerformRepoActions($localRepo)
{
  $startDir = $pwd.path
  cd $localRepo
  hg recover
  hg revert --all
  hg pull -r $branch --rebase
  hg update -r $branch
  cd $startDir
}

$branch = $env:NAMEDBRANCH
PerformRepoActions $pwd.path 

When I run this, it does not show any of the mercurial commands that I'm making. Here's what it shows in the Jenkins output:

no interrupted transaction available
pulling from [repo_location]
no changes found
0 files updated, 0 files merged, 0 files removed, 0 files unresolved

It's giving me the the output of the hg commands, but not showing the commands themselves.

So, I'm looking for something that will make those commands print out, equivalent to the cmd.exe "echo on".

A search tells me that the equivalent in PowerShell is "Set-PSDebug -Trace 1". So I add that to the beginning of the script, and it changes the output to:

DEBUG:   15+  >>>> $branch = $env:NAMEDBRANCH
DEBUG:   16+  >>>> PerformRepoActions $pwd.path
DEBUG:    5+  >>>> {
DEBUG:    6+    >>>> $startDir = $pwd.path
DEBUG:    7+    >>>> cd $localRepo
no interrupted transaction available
pulling from ssh://hg@mercurial.wilcoxassoc.com/PcDmis/QA
no changes found
0 files updated, 0 files merged, 0 files removed, 0 files unresolved

As you can see, while it does give me more output, but it doesn't actually show me the commands that I'm calling.

"Set-PSDebug -Trace 2" gives even more output, but still doesn't show what mercurial commands are being called.

The work-around that I've come up with is to create a function which echoes and the executes a string. It works, but it feels awful kludgey:

function execute($cmd)
{
  echo $cmd
  iex $cmd
}

function PerformRepoActions($localRepo)
{
  $startDir = $pwd.path
  execute "cd $localRepo"
  execute "hg recover"
  execute "hg revert --all"
  execute "hg pull -r $branch --rebase"
  execute "hg update -r $branch"
  execute "cd $startDir"
}
$branch = $env:NAMEDBRANCH
PerformRepoActions $pwd.path

Is there some better way to do this?

It seems that there must be, but I've been surprised before.

edit: This is not a duplicate of PowerShell "echo on". Re-directing the output to a file, the answer to that question, isn't feasible. I need it to display in the Jenkins output, not a file.

Community
  • 1
  • 1
PortMan
  • 4,205
  • 9
  • 35
  • 61
  • Mercurial is not Git – m0skit0 Feb 03 '16 at 17:22
  • Possible duplicate of [PowerShell "echo on"](http://stackoverflow.com/questions/2063995/powershell-echo-on) – m0skit0 Feb 03 '16 at 17:23
  • Oops. I meant to tag this as "powershell" only. Sorry about that. – PortMan Feb 03 '16 at 17:38
  • Like the other answer says, there's no such thing as "echo on" on PowerShell (and most shells I know of). Can't you configure Jenkins to display that file instead? (Maybe with [this](https://wiki.jenkins-ci.org/display/JENKINS/Rich+Text+Publisher+Plugin)?) – m0skit0 Feb 03 '16 at 17:47
  • You could also do the "echo on", then cat the file when it's done. – Eris Feb 03 '16 at 18:03
  • A better question would be; What exactly is 'hg'? Is it a batch file (hg.bat), wrapper (hg.com), executable (hg.exe), powershell script (hg.ps1), or even a powershell function? – Eris Feb 03 '16 at 18:18
  • @Eris I don't see how is that relevant, but `hg` is Mercurial. – m0skit0 Feb 03 '16 at 18:32
  • It matters because every other command in your script is a native powershell function, alias, or cmdlet. `hg` is the only unknown, and the only one behaving badly. – Eris Feb 03 '16 at 21:00
  • 1
    hg == mercurial. It's an external program, and it's not behaving badly. Most command-line programs don't print out the command-line command used to launch them. – PortMan Feb 03 '16 at 21:29
  • Don't you need "&" (call operator) in front of those `hg` commands? – malthe Jan 19 '22 at 08:34

1 Answers1

0

there's a way that you can capture the contents of the current script that you're in, and with a little work you could probably marry that up with the relevant output. (whether that's a need I'm not sure)

As of Powershell v3 you have access to the abstract syntax trees (that's the only link I could find that said anything about it!)

Basically the Ast has access all properties of the current script (or any script you send to it) including its complete source.

running this script (I included notepad to show it running external exe)

Write-Host "before"
$MyInvocation.MyCommand.ScriptBlock.Ast 
Write-Host "after"

notepad 

Will produce this output

before


Attributes           : {}
UsingStatements      : {}
ParamBlock           : 
BeginBlock           : 
ProcessBlock         : 
EndBlock             : Write-Host "before"
                       $MyInvocation.MyCommand.ScriptBlock.Ast 
                       Write-Host "after"

                       notepad
DynamicParamBlock    : 
ScriptRequirements   : 
ImplementingAssembly : 
Extent               : 
                       Write-Host "before"
                       $MyInvocation.MyCommand.ScriptBlock.Ast 
                       Write-Host "after"

                       notepad 
Parent               : 

after

I imagine if you play around with

$MyInvocation.MyCommand.ScriptBlock.Ast 

You should be able to make it produce something like what you want.

edited to add

You could potentially take this a step further by using the Ast to select each Powershell cmdlet and attach a breakpoint to it, then you should have access to the cmdlet names (I don't think that would work with executables - and its only a theory at the moment!) You'd need to run the whole thing through an external script that managed the logging and continuing from the breakpoints. But I think it could work.

Michael B
  • 11,887
  • 6
  • 38
  • 74