Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MSBuild] Fixed trailing garbage #2739

Merged
merged 14 commits into from
Oct 29, 2023

Conversation

0x53A
Copy link
Contributor

@0x53A 0x53A commented Mar 10, 2023

fixes #2738


The previous use of appendQuotedIfNotNull doesn't make any sense, it passes Some as a function as the first parameter, which then get's formatted through %A into a string like <fun:quoteString@686>. The intention was probably (Some str), but this again doesn't work.

image

Just wrapping it in quotes is probably not strictly correct, we would also need to escape existing quotes inside the string, but it quickly fixes the code without a regression.

@0x53A 0x53A closed this Mar 10, 2023
@0x53A 0x53A reopened this Mar 10, 2023
@yazeedobaid
Copy link
Collaborator

Thanks for the PR. I think append with an object formatting gives extra options for parameters passed. For example, passing objects with custom toString methods. I'm not aware of the history of this function. But as it is used in MSBuild and AppVeyor modules yes it doesn't make sense. In TypeScript module it is used with a string passed as the first parameter.

For the use case, as you said it should also account for nested quotes, so can you please include that in PR. I digged more into legacy process module and found a similar helper that did this (legacy process module):

/// Adds quotes around the string
/// [omit]
[<System.Obsolete("FAKE0001 Use the Fake.Core.Process module instead")>]
let quote (str:string) = "\"" + str.Replace("\"","\\\"") + "\""

/// Adds quotes around the string if needed
/// [omit]
[<System.Obsolete("FAKE0001 Use the Fake.Core.Process module instead")>]
let quoteIfNeeded str =
    if isNullOrEmpty str then ""
    elif str.Contains " " then quote str
    else str

@0x53A
Copy link
Contributor Author

0x53A commented Mar 13, 2023

Unfortunately, just quoting isn't enough, see https://learn.microsoft.com/en-us/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way for the mess that is command line parsing.

Fortunately, the process module of Fake already implements this, and by using fromRawCommand instead of fromRawCommandLine we can pass the arg array down to that level instead of having to escape it ourselves.

@0x53A
Copy link
Contributor Author

0x53A commented Mar 13, 2023

I'll leave it at this for today - I believe it should be more or less correct, but I have not done any manual tests

@0x53A 0x53A closed this Mar 14, 2023
@0x53A 0x53A reopened this Mar 14, 2023
@0x53A
Copy link
Contributor Author

0x53A commented Mar 15, 2023

uhhh, how much do y'all trust the unit/integration test coverage? From my side I believe it's ready, but I have (still) not done any manual testing.

Comment on lines 1159 to 1168
addBinaryLogger msBuildArgs.DisableInternalBinLog (args + " " + argString) common
addBinaryLogger msBuildArgs.DisableInternalBinLog (args @ argString) common
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why space has been removed here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before, args and argString were plain strings, which were just concated with a space between them.

Now, args and argString are both string list, which get combined into a single list with the @ operator.

The later code then uses either Args.toWindowsCommandLine (or CreateProcess.fromRawCommand) to convert the string list into a single, properly quoted, string.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with all that said I should also rename the variable from argString to argList

Comment on lines 57 to 58
/// Adds quotes around the string
/// [omit]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please change the function documentation to XML format?

Comment on lines 61 to 62
/// Adds quotes around the string if needed
/// [omit]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also here

options

run cmdArgs options

/// the 'exec' above with args as a single string is public and therefore can't be changed, create a second overload with takes a string list
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please change the function documentation to XML format?

let p = MSBuildParams.Create() |> setParams
p, fromCliArguments p.CliArguments |> Args.toWindowsCommandLine

/// [omit]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to omit comment, if the function will not make it to documentation then u can use visibility modified, maybe change it to internal? Also, can you come up with another name instead of buildArgs2. While reading this, I had to search if buildArgs exists and compare both of them to see the difference.

options

run cmdArgs options

/// the 'exec' above with args as a single string is public and therefore can't be changed, create a second overload with takes a string list
let private exec2 (buildOptions: Options -> Options) (command: string) (args: string list) =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as with buildArgs2, can you come up with a descriptive name instead of exec2

@yazeedobaid
Copy link
Collaborator

Thanks for the new changes. I have added some comments about them.

Regarding handling the other cases in addition to just escaping quotes, that was discussed recently in #2735.
@matthid could you please advise on this and the changes made in this PR to replace fromRawCommandLine with fromRawCommand?

@@ -140,7 +140,7 @@ type FilePath = string
module Args =
/// <summary>
/// Convert the given argument list to a conforming windows command line string, escapes parameter in quotes if
/// needed (currently always but this might change).
/// needed.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this just corrects the comment, the function already did only quote and escape if required.

StringBuilder()
|> StringBuilder.appendQuotedIfNotNull Some str
|> StringBuilder.toText
/// quote and escape the single argument, if required.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all other functions in this file use simple non-xml comments, and it's private anyway

/// <param name="buildOptions">build common execution options</param>
/// <param name="command">the sdk command to execute <c>test</c>, <c>new</c>, <c>build</c>, ...</param>
/// <param name="args">command arguments</param>
let private execArgsList (buildOptions: Options -> Options) (command: string) (args: string list) =
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renamed exec2 to execArgsList


/// [omit]
let buildArgs (setParams: MSBuildParams -> MSBuildParams) =
let buildArgs (setParams: MSBuildParams -> MSBuildParams) : MSBuildParams * string =
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added explicit return type annotation (: MSBuildParams * string) to both variants

@0x53A 0x53A closed this Mar 17, 2023
@0x53A 0x53A reopened this Mar 17, 2023
@0x53A 0x53A closed this Mar 20, 2023
@0x53A 0x53A reopened this Mar 20, 2023
@voronoipotato
Copy link
Contributor

voronoipotato commented May 26, 2023

Who has the rights to merge this? @yazeedobaid do you or is it just @matthid ? If it's just @matthid maybe we could get a secondary on this? I'd be open to being a temporary secondary (I use F# and Fake daily at work) until we can find someone who is a regular contributor.

@kantora
Copy link

kantora commented Jul 30, 2023

Any hints when this could be merged? Can something to be done to push this? As I can understand - without this fix Fake.MSBuild is totally unusable.

kantora added a commit to kantora/KlusterKite that referenced this pull request Jul 30, 2023
Still waiting for fsprojects/FAKE#2739 for the proper workflow
@voronoipotato
Copy link
Contributor

maybe we should fork and call it fmake.

@xperiandri xperiandri changed the title msbuild: fix trailing garbage [MSBuild] Fixed trailing garbage Oct 1, 2023
@xperiandri
Copy link
Collaborator

Have we finished all the discussions and are confident to merge?

@xperiandri
Copy link
Collaborator

@0x53A you may press a merge button now, I suppose it is available

@0x53A
Copy link
Contributor Author

0x53A commented Oct 29, 2023

image

@xperiandri xperiandri merged commit 2de6216 into fsprojects:master Oct 29, 2023
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

MSBuild.build adds a bad string at the end of properties
5 participants