diff --git a/integration_test.go b/integration_test.go index d05ff68..a7db35a 100644 --- a/integration_test.go +++ b/integration_test.go @@ -52,6 +52,43 @@ func TestFetchWithBranchOption(t *testing.T) { } } +func TestFetchWithStdoutOption(t *testing.T) { + tmpDownloadPath, err := ioutil.TempDir("", "fetch-stdout-test") + require.NoError(t, err) + + repoUrl := "https://github.com/gruntwork-io/fetch-test-public" + releaseTag := "v0.0.4" + releaseAsset := "hello+world.txt" + + cmd := fmt.Sprintf("fetch --repo %s --tag %s --release-asset %s --stdout true %s", repoUrl, releaseTag, releaseAsset, tmpDownloadPath) + t.Logf("Testing command: %s", cmd) + stdoutput, _, err := runFetchCommandWithOutput(t, cmd) + require.NoError(t, err) + + // Ensure the expected file was downloaded + assert.FileExists(t, JoinPath(tmpDownloadPath, releaseAsset)) + + // When --stdout is specified, ensure the file contents are piped to the standard output stream + assert.Contains(t, stdoutput, "hello world") +} + +func TestFetchWithStdoutOptionMultipleAssets(t *testing.T) { + tmpDownloadPath, err := ioutil.TempDir("", "fetch-stdout-test") + require.NoError(t, err) + + repoUrl := SAMPLE_RELEASE_ASSET_GITHUB_REPO_URL + releaseTag := SAMPLE_RELEASE_ASSET_VERSION + releaseAsset := SAMPLE_RELEASE_ASSET_REGEX + + cmd := fmt.Sprintf("fetch --repo %s --tag %s --release-asset %s --stdout true %s", repoUrl, releaseTag, releaseAsset, tmpDownloadPath) + t.Logf("Testing command: %s", cmd) + _, stderr, err := runFetchCommandWithOutput(t, cmd) + require.NoError(t, err) + + // When --stdout is specified, ensure the file contents are piped to the standard output stream + assert.Contains(t, stderr, "Multiple assets were downloaded. Ignoring --stdout") +} + func runFetchCommandWithOutput(t *testing.T, command string) (string, string, error) { stdout := bytes.Buffer{} stderr := bytes.Buffer{} diff --git a/main.go b/main.go index 851cb96..1341200 100644 --- a/main.go +++ b/main.go @@ -30,6 +30,7 @@ type FetchOptions struct { ReleaseAsset string ReleaseAssetChecksums map[string]bool ReleaseAssetChecksumAlgo string + Stdout bool LocalDownloadPath string GithubApiVersion string WithProgress bool @@ -53,6 +54,7 @@ const optionSourcePath = "source-path" const optionReleaseAsset = "release-asset" const optionReleaseAssetChecksum = "release-asset-checksum" const optionReleaseAssetChecksumAlgo = "release-asset-checksum-algo" +const optionStdout = "stdout" const optionGithubAPIVersion = "github-api-version" const optionWithProgress = "progress" const optionLogLevel = "log-level" @@ -117,6 +119,10 @@ func CreateFetchCli(version string, writer io.Writer, errwriter io.Writer) *cli. Name: optionReleaseAssetChecksumAlgo, Usage: "The algorithm Fetch will use to compute a checksum of the release asset. Acceptable values\n\tare \"sha256\" and \"sha512\".", }, + cli.StringFlag{ + Name: optionStdout, + Usage: "If \"true\", the contents of the release asset is sent to standard output so it can be piped to another command.", + }, cli.StringFlag{ Name: optionGithubAPIVersion, Value: "v3", @@ -250,6 +256,25 @@ func runFetch(c *cli.Context, logger *logrus.Logger) error { } } + if options.Stdout { + // Print to stdout only if a single asset was downloaded + if len(assetPaths) == 1 { + dat, err := os.ReadFile(assetPaths[0]) + if err != nil { + return err + } + c.App.Writer.Write(dat) // This should be stdout + } else { + + if len(assetPaths) > 1 { + logger.Warn("Multiple assets were downloaded. Ignoring --stdout") + } else { + logger.Warn("No assets were downloaded. Ignoring --stdout") + } + + } + } + return nil } @@ -282,6 +307,7 @@ func parseOptions(c *cli.Context, logger *logrus.Logger) FetchOptions { ReleaseAsset: c.String(optionReleaseAsset), ReleaseAssetChecksums: assetChecksumMap, ReleaseAssetChecksumAlgo: c.String(optionReleaseAssetChecksumAlgo), + Stdout: c.String(optionStdout) == "true", LocalDownloadPath: localDownloadPath, GithubApiVersion: c.String(optionGithubAPIVersion), WithProgress: c.IsSet(optionWithProgress),