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

Incomplete standard output #18

Open
nicholascross opened this issue Oct 29, 2017 · 2 comments
Open

Incomplete standard output #18

nicholascross opened this issue Oct 29, 2017 · 2 comments
Labels

Comments

@nicholascross
Copy link

I have come across a scenario when not all standard output is returned. This seems to be happening on a non zero exit code, successful termination may or may not be affected.

Background
I was using shellOut to execute fastlane and it was failing for version requirements not being read.

Investigation
I did some tinkering and it seems to be related to how this function reads the output.

private extension Process {
    @discardableResult func launchBash(with command: String, outputHandle: FileHandle? = nil, errorHandle: FileHandle? = nil) throws -> String {
        launchPath = "/bin/bash"
        arguments = ["-c", command]

        var outputData = Data()
        var errorData = Data()

        let outputPipe = Pipe()
        standardOutput = outputPipe

        let errorPipe = Pipe()
        standardError = errorPipe

        #if !os(Linux)
        outputPipe.fileHandleForReading.readabilityHandler = { handler in
            let data = handler.availableData
            outputData.append(data)
            outputHandle?.write(data)
        }

        errorPipe.fileHandleForReading.readabilityHandler = { handler in
            let data = handler.availableData
            errorData.append(data)
            errorHandle?.write(data)
        }
        #endif

        launch()

        #if os(Linux)
        outputData = outputPipe.fileHandleForReading.readDataToEndOfFile()
        errorData = errorPipe.fileHandleForReading.readDataToEndOfFile()
        #endif

        waitUntilExit()

        outputHandle?.closeFile()
        errorHandle?.closeFile()

        #if !os(Linux)
        outputPipe.fileHandleForReading.readabilityHandler = nil
        errorPipe.fileHandleForReading.readabilityHandler = nil
        #endif

        if terminationStatus != 0 {
            throw ShellOutError(
                terminationStatus: terminationStatus,
                errorData: errorData,
                outputData: outputData
            )
        }

        return outputData.shellOutput()
    }
}

This is the output when using the default implementation

[19:08:21]: �[32m-------------------------------------------------�[0m
[19:08:21]: �[32m--- Step: Verifying required fastlane version ---�[0m
[19:08:21]: �[32m-------------------------------------------------�[0m

I noticed the linux only variation and thought I would try it out on macos, I hacked the function as follows.

private extension Process {
    @discardableResult func launchBash(with command: String, outputHandle: FileHandle? = nil, errorHandle: FileHandle? = nil) throws -> String {
        launchPath = "/bin/bash"
        arguments = ["-c", command]

        var outputData = Data()
        var errorData = Data()

        let outputPipe = Pipe()
        standardOutput = outputPipe

        let errorPipe = Pipe()
        standardError = errorPipe

//        #if !os(Linux)
//        outputPipe.fileHandleForReading.readabilityHandler = { handler in
//            let data = handler.availableData
//            outputData.append(data)
//            outputHandle?.write(data)
//        }

//        errorPipe.fileHandleForReading.readabilityHandler = { handler in
//            let data = handler.availableData
//            errorData.append(data)
//            errorHandle?.write(data)
//        }
//        #endif

        launch()

//        #if os(Linux)
        outputData = outputPipe.fileHandleForReading.readDataToEndOfFile()
        errorData = errorPipe.fileHandleForReading.readDataToEndOfFile()
//        #endif

        waitUntilExit()

        outputHandle?.closeFile()
        errorHandle?.closeFile()

        #if !os(Linux)
        outputPipe.fileHandleForReading.readabilityHandler = nil
        errorPipe.fileHandleForReading.readabilityHandler = nil
        #endif

        if terminationStatus != 0 {
            throw ShellOutError(
                terminationStatus: terminationStatus,
                errorData: errorData,
                outputData: outputData
            )
        }

        return outputData.shellOutput()
    }
}

Which produces the following output

[19:04:50]: �[32m-------------------------------------------------�[0m
[19:04:50]: �[32m--- Step: Verifying required fastlane version ---�[0m
[19:04:50]: �[32m-------------------------------------------------�[0m
�[31m
[!] The Fastfile requires a fastlane version of >= 2.47.0. You are on 1.91.0. Please update using `sudo gem update fastlane`.�[0m

Assuming I am not using this wrong it looks like the output is getting cut off early.

@nicholascross
Copy link
Author

I was able to create a small example that can reproduce the problem.

ShellOutput.zip

The following output will not be observed using the default launchBash implementation but will with the hacked version (and when run from terminal).

[!] The Fastfile requires a fastlane version of >= 5000. You are on 2.5.0.

@JohnSundell
Copy link
Owner

@nicholascross Awesome, thanks for this! I'll look into this within the next couple of days if no one else beats me to it 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants