diff options
author | Justin Tobler <jtobler@gitlab.com> | 2023-10-02 21:41:05 +0300 |
---|---|---|
committer | Justin Tobler <jtobler@gitlab.com> | 2023-10-19 21:47:56 +0300 |
commit | 292eba6982e85b1e9967cefb7cd4e7620841c221 (patch) | |
tree | d5266fc0d45532c0185a3b515f972bd0857d4d0c | |
parent | 7b43096ae1894b21fbc7aa3cf65d644bcd7ff73d (diff) |
localrepo: Support porcelain fetch option
When performing `git-fetch(1)` with the `porcelain` option, references
are printed to stdout in an easy-to-parse format. This change introduces
a `localrepo.FetchRemote()` configuration to enabled `porcelain` output.
-rw-r--r-- | internal/git/localrepo/remote.go | 8 | ||||
-rw-r--r-- | internal/git/localrepo/remote_test.go | 31 |
2 files changed, 39 insertions, 0 deletions
diff --git a/internal/git/localrepo/remote.go b/internal/git/localrepo/remote.go index 737ba230d..696512afb 100644 --- a/internal/git/localrepo/remote.go +++ b/internal/git/localrepo/remote.go @@ -52,6 +52,10 @@ type FetchOpts struct { Tags FetchOptsTags // DryRun, if enabled, performs the `git-fetch(1)` command without updating any references. DryRun bool + // Porcelain controls `git-fetch(1)` command output and when enabled prints output in an + // easy-to-parse format. By default, `git-fetch(1)` output is suppressed by the `--quiet` flag. + // Therefore, the Verbose option must also be enabled to receive output. + Porcelain bool // Stdout if set it would be used to redirect stdout stream into it. Stdout io.Writer // Stderr if set it would be used to redirect stderr stream into it. @@ -207,6 +211,10 @@ func (opts FetchOpts) buildFlags() []git.Option { flags = append(flags, git.Flag{Name: "--dry-run"}) } + if opts.Porcelain { + flags = append(flags, git.Flag{Name: "--porcelain"}) + } + // Even if we ask Git to not print any output and to force-update branches it will still // compute whether branches have been force-updated only to discard that information again. // Let's ask it not to given that this check can be quite expensive. diff --git a/internal/git/localrepo/remote_test.go b/internal/git/localrepo/remote_test.go index 25c4e7ddc..138428253 100644 --- a/internal/git/localrepo/remote_test.go +++ b/internal/git/localrepo/remote_test.go @@ -188,6 +188,37 @@ func TestRepo_FetchRemote(t *testing.T) { require.Len(t, refs, 0) }) + t.Run("with porcelain", func(t *testing.T) { + repo, _ := initBareWithRemote(t, "origin") + + // The porcelain fetch option write output to stdout in an easy-to-parse format. By default, + // output is suppressed by the --quiet flag. The Verbose option must also be enabled to + // receive output. + var stdout bytes.Buffer + require.NoError(t, repo.FetchRemote(ctx, "origin", FetchOpts{ + Stdout: &stdout, + Porcelain: true, + Verbose: true, + })) + + hash, err := repo.ObjectHash(ctx) + require.NoError(t, err) + scanner := git.NewFetchPorcelainScanner(&stdout, hash) + + // Scan the output for expected references. + require.True(t, scanner.Scan()) + require.Equal(t, git.RefUpdateTypeFetched, scanner.StatusLine().Type) + require.Equal(t, "refs/remotes/origin/main", scanner.StatusLine().Reference) + require.True(t, scanner.Scan()) + require.Equal(t, git.RefUpdateTypeFetched, scanner.StatusLine().Type) + require.Equal(t, "refs/tags/v1.0.0", scanner.StatusLine().Reference) + + // Since the remote only contains two references, there should be nothing left in the buffer + // to scan. + require.False(t, scanner.Scan()) + require.Nil(t, scanner.Err()) + }) + t.Run("with no tags", func(t *testing.T) { repo, testRepoPath := initBareWithRemote(t, "origin") |