Skip to content

Commit affa509

Browse files
authored
List command: add update notice (#12)
Add `HAS UPDATES` note to `list` command Minor test fixes
1 parent 10aeb28 commit affa509

File tree

14 files changed

+144
-83
lines changed

14 files changed

+144
-83
lines changed

.github/workflows/main.yaml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,7 @@ jobs:
2929
with:
3030
go-version: "1.24"
3131
cache: true
32-
- name: Install Task
33-
uses: arduino/setup-task@v2
3432
- name: Start tests
3533
env:
3634
GITHUB_TOKEN: ${{ secrets.TEST_GITHUB_TOKEN }}
37-
run: task test
35+
run: go test -v --tags=test -count=1 ./...

app/app.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ func (a *Application) WithConfig(cfg cfg) {
8888

8989
type remoteClient interface {
9090
// GetLatestRelease - retrieves latest repository release.
91-
GetLatestRelease(ctx context.Context, owner, repo string) (*remote.Release, error)
91+
GetLatestRelease(ctx context.Context, repoURL string) (*remote.Release, error)
9292
// DownloadFile downloads binary file.
9393
DownloadFile(ctx context.Context, downloadURL string, writer io.Writer) error
9494
}

app/app_test.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,6 @@ func TestAppWorkflow(t *testing.T) {
4545
expectedConfigPath = "./config.cfg"
4646
expectedLocalFilename = "localFilePath"
4747

48-
expectedTestOwner = "outcatcher"
49-
expectedTestRepo = "asdfasdf"
50-
5148
expectecdDownloadURL = "https://adfsgijnasdfgj.test"
5249
)
5350

@@ -71,7 +68,7 @@ func TestAppWorkflow(t *testing.T) {
7168

7269
mockRemote := mocks.NewMockremoteClient(t)
7370
mockRemote.
74-
On("GetLatestRelease", ctx, expectedTestOwner, expectedTestRepo).
71+
On("GetLatestRelease", ctx, expectecdURL).
7572
Return(&remote.Release{
7673
Name: "123",
7774
Description: "234",

app/list.go

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,45 @@
22
package app
33

44
import (
5-
"github.com/outcatcher/hipapu/internal/config"
5+
"context"
6+
"fmt"
7+
8+
"github.com/outcatcher/hipapu/internal/local"
9+
"github.com/outcatcher/hipapu/internal/remote"
610
)
711

12+
// Installation to be synced.
13+
type Installation struct {
14+
// Remote repo release information
15+
Release *remote.Release
16+
// Local file info
17+
LocalFile *local.FileInfo
18+
}
19+
820
// List lists all existing installations.
921
//
1022
// It would be better to add a type for return, but it's such a waste of code.
11-
func (a *Application) List() []config.Installation {
12-
return a.config.GetInstallations()
23+
func (a *Application) List(ctx context.Context) ([]Installation, error) {
24+
installations := a.config.GetInstallations()
25+
26+
result := make([]Installation, len(installations))
27+
28+
for idx, installation := range installations {
29+
release, err := a.remote.GetLatestRelease(ctx, installation.RepoURL)
30+
if err != nil {
31+
return nil, fmt.Errorf("failed to get release info: %w", err)
32+
}
33+
34+
file, err := a.files.GetFileInfo(installation.LocalPath)
35+
if err != nil {
36+
return nil, fmt.Errorf("failed to get installation file info: %w", err)
37+
}
38+
39+
result[idx] = Installation{
40+
Release: release,
41+
LocalFile: file,
42+
}
43+
}
44+
45+
return result, nil
1346
}

app/mocks/mock_remoteClient.go

Lines changed: 15 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/sync.go

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@ import (
88
"io"
99
"os"
1010
"path/filepath"
11-
"strings"
1211
"time"
1312

14-
"github.com/outcatcher/hipapu/internal/config"
1513
"github.com/schollz/progressbar/v3"
1614
)
1715

@@ -23,7 +21,10 @@ var (
2321

2422
// Synchronize runs synchronization of all new releases replacing local files reporting the progress.
2523
func (a *Application) Synchronize(ctx context.Context) error {
26-
installations := a.config.GetInstallations()
24+
installations, err := a.List(ctx)
25+
if err != nil {
26+
return fmt.Errorf("sync error: %w", err)
27+
}
2728

2829
if len(installations) == 0 {
2930
return ErrEmptyInstallationList
@@ -50,29 +51,18 @@ func (a *Application) Synchronize(ctx context.Context) error {
5051

5152
//nolint:cyclop,funlen // rewriting makes it less readable
5253
func (a *Application) syncInstallation(
53-
ctx context.Context, installation config.Installation,
54+
ctx context.Context, installation Installation,
5455
) error {
55-
file, err := a.files.GetFileInfo(installation.LocalPath)
56-
if err != nil {
57-
return fmt.Errorf("failed to get file info: %w", err)
58-
}
59-
60-
urlParts := strings.Split(installation.RepoURL, "/")
61-
owner, repo := urlParts[len(urlParts)-2], urlParts[len(urlParts)-1]
62-
6356
a.log().InfoContext(ctx,
6457
"Starting sync of installation",
65-
"owner", owner,
66-
"repo", repo,
67-
"local path", installation.LocalPath,
58+
"owner", installation.Release.Owner,
59+
"repo", installation.Release.Repo,
60+
"local path", installation.LocalFile.FilePath,
6861
)
6962

70-
release, err := a.remote.GetLatestRelease(ctx, owner, repo)
71-
if err != nil {
72-
return fmt.Errorf("failed to get release info: %w", err)
73-
}
63+
release, file := installation.Release, installation.LocalFile
7464

75-
if !release.PublishedAt.After(file.LastModified) {
65+
if !release.PublishedAt.After(installation.LocalFile.LastModified) {
7666
a.log().Info(
7767
"Current installation is up to date",
7868
"published at", release.PublishedAt.Format(time.RFC3339),
@@ -140,9 +130,9 @@ func (a *Application) syncInstallation(
140130
}
141131

142132
a.log().Info("Finished sync of installation",
143-
"owner", owner,
144-
"repo", repo,
145-
"local path", installation.LocalPath,
133+
"owner", release.Owner,
134+
"repo", release.Repo,
135+
"local path", file.FilePath,
146136
"download URL", downloadURL,
147137
)
148138

cmd/handlers/actions.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@ import (
66
"fmt"
77

88
"github.com/outcatcher/hipapu/app"
9-
"github.com/outcatcher/hipapu/internal/config"
109
"github.com/urfave/cli/v3"
1110
)
1211

1312
// DefaultCommandName - name of default command.
1413
const DefaultCommandName = commandNameList
1514

1615
type application interface {
17-
List() []config.Installation
16+
List(ctx context.Context) ([]app.Installation, error)
1817
Add(remoteURL, localPath string) error
1918
Synchronize(ctx context.Context) error
2019
}

cmd/handlers/list.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,22 @@ func (h *ActionHandlers) CommandList() *cli.Command {
2121
}
2222
}
2323

24-
func (h *ActionHandlers) list(_ context.Context, cmd *cli.Command) error {
25-
installations := h.app.List()
24+
func (h *ActionHandlers) list(ctx context.Context, cmd *cli.Command) error {
25+
installations, err := h.app.List(ctx)
26+
if err != nil {
27+
return fmt.Errorf("error handling `list` command: %w", err)
28+
}
2629

2730
_, _ = fmt.Fprintln(cmd.Writer, "Installations:")
2831

29-
for i, installation := range installations {
30-
_, _ = fmt.Fprintf(cmd.Writer, " %d) %s <---> %s\n", i+1, installation.RepoURL, installation.LocalPath)
32+
for i, inst := range installations {
33+
statusString := fmt.Sprintf(" %d) %s <---> %s", i+1, inst.Release.RepoURL, inst.LocalFile.FilePath)
34+
35+
if inst.Release.PublishedAt.After(inst.LocalFile.LastModified) {
36+
statusString += " (HAS UPDATES)"
37+
}
38+
39+
_, _ = fmt.Fprintln(cmd.Writer, statusString)
3140
}
3241

3342
return nil

cmd/handlers/list_test.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@ package handlers //nolint:testpackage // don't want to make useless tests overl
88
import (
99
"bytes"
1010
"testing"
11+
"time"
1112

13+
"github.com/outcatcher/hipapu/app"
1214
"github.com/outcatcher/hipapu/cmd/handlers/mocks"
13-
"github.com/outcatcher/hipapu/internal/config"
15+
"github.com/outcatcher/hipapu/internal/local"
16+
"github.com/outcatcher/hipapu/internal/remote"
1417
"github.com/stretchr/testify/require"
1518
)
1619

@@ -24,15 +27,21 @@ func TestList(t *testing.T) {
2427
expectedRepoPath = "test-repo-path-add"
2528
)
2629

27-
expectedInstallations := []config.Installation{
30+
expectedInstallations := []app.Installation{
2831
{
29-
RepoURL: expectedRepoPath,
30-
LocalPath: expectedFilePath,
32+
Release: &remote.Release{
33+
PublishedAt: time.Now(),
34+
RepoURL: expectedRepoPath,
35+
},
36+
LocalFile: &local.FileInfo{
37+
FilePath: expectedFilePath,
38+
LastModified: time.Now().Add(-1 * time.Second),
39+
},
3140
},
3241
}
3342

3443
appMock := mocks.NewMockapplication(t)
35-
appMock.On("List").Once().Return(expectedInstallations)
44+
appMock.On("List", ctx).Once().Return(expectedInstallations, nil)
3645

3746
hdl := &ActionHandlers{app: appMock}
3847

@@ -54,4 +63,5 @@ func TestList(t *testing.T) {
5463

5564
require.Contains(t, line2, expectedRepoPath)
5665
require.Contains(t, line2, expectedFilePath)
66+
require.Contains(t, line2, "HAS UPDATE")
5767
}

0 commit comments

Comments
 (0)