From b12d1e606acb9233a3c44b828fe5baea18bacc19 Mon Sep 17 00:00:00 2001 From: Jeffrey Faer Date: Thu, 4 Apr 2024 11:49:56 -0600 Subject: [PATCH 1/3] refactor(tracing): Move the tracing VCS wrapper into its own file. --- api/api.go | 77 +------------------------------------------------- api/tracing.go | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 76 deletions(-) create mode 100644 api/tracing.go diff --git a/api/api.go b/api/api.go index d682b50..6e9ce85 100644 --- a/api/api.go +++ b/api/api.go @@ -72,7 +72,7 @@ var ( // Register registers a VCS for use by tmux-vcs-sync. func Register(vcs VersionControlSystem) { - registered = append(registered, TracingVersionControlSystem(vcs)) + registered = append(registered, &tracingVersionControlSystem{vcs}) } // Registered is all of the VersionControlSystems added via Register. @@ -80,12 +80,6 @@ func Registered() VersionControlSystems { return slices.Clone(registered) } -// TracingVersionControlSystem wraps the provided VersionControlSystem so that -// it automatically creates trace regions. -func TracingVersionControlSystem(vcs VersionControlSystem) VersionControlSystem { - return &tracingVersionControlSystem{vcs} -} - // CurrentRepository returns a Repository for the current working directory, or an error if one cannot be found. func (all VersionControlSystems) CurrentRepository(ctx context.Context) (Repository, error) { repo, err := all.MaybeCurrentRepository(ctx) @@ -165,72 +159,3 @@ func MaybeFindRepository[T any](ctx context.Context, elems []T, fn func(T) (Repo return nil, fmt.Errorf("multiple Repositories match: %s", strings.Join(s, ", ")) } } - -type tracingVersionControlSystem struct { - vcs VersionControlSystem -} - -func (vcs *tracingVersionControlSystem) Name() string { return vcs.vcs.Name() } -func (vcs *tracingVersionControlSystem) WorkUnitName() string { return vcs.vcs.WorkUnitName() } - -func (vcs *tracingVersionControlSystem) Repository(ctx context.Context, name string) (Repository, error) { - defer trace.StartRegion(ctx, "VCS:"+vcs.Name()).End() - repo, err := vcs.vcs.Repository(ctx, name) - if err != nil { - return nil, err - } - if repo == nil { - return nil, nil - } - return &tracingRepository{repo}, nil -} - -type tracingRepository struct { - repo Repository -} - -func (repo *tracingRepository) VCS() VersionControlSystem { return repo.repo.VCS() } -func (repo *tracingRepository) Name() string { return repo.repo.Name() } -func (repo *tracingRepository) RootDir() string { return repo.repo.RootDir() } - -func (repo *tracingRepository) startRegions(ctx context.Context) func() { - r1 := trace.StartRegion(ctx, "VCS:"+repo.VCS().Name()) - r2 := trace.StartRegion(ctx, "Repo:"+repo.Name()) - return func() { - r2.End() - r1.End() - } -} - -func (repo *tracingRepository) Current(ctx context.Context) (string, error) { - defer repo.startRegions(ctx)() - return repo.repo.Current(ctx) -} -func (repo *tracingRepository) List(ctx context.Context, prefix string) ([]string, error) { - defer repo.startRegions(ctx)() - return repo.repo.List(ctx, prefix) -} -func (repo *tracingRepository) Sort(ctx context.Context, workUnits []string) error { - defer repo.startRegions(ctx)() - return repo.repo.Sort(ctx, workUnits) -} -func (repo *tracingRepository) New(ctx context.Context, workUnitName string) error { - defer repo.startRegions(ctx)() - return repo.repo.New(ctx, workUnitName) -} -func (repo *tracingRepository) Commit(ctx context.Context, workUnitName string) error { - defer repo.startRegions(ctx)() - return repo.repo.Commit(ctx, workUnitName) -} -func (repo *tracingRepository) Rename(ctx context.Context, workUnitName string) error { - defer repo.startRegions(ctx)() - return repo.repo.Rename(ctx, workUnitName) -} -func (repo *tracingRepository) Exists(ctx context.Context, workUnitName string) (bool, error) { - defer repo.startRegions(ctx)() - return repo.repo.Exists(ctx, workUnitName) -} -func (repo *tracingRepository) Update(ctx context.Context, workUnitName string) error { - defer repo.startRegions(ctx)() - return repo.repo.Update(ctx, workUnitName) -} diff --git a/api/tracing.go b/api/tracing.go new file mode 100644 index 0000000..bd73b67 --- /dev/null +++ b/api/tracing.go @@ -0,0 +1,77 @@ +package api + +import ( + "context" + "runtime/trace" +) + +// tracingVersionControlSystem wraps the provided VersionControlSystem so that +// it automatically creates trace regions. +type tracingVersionControlSystem struct { + vcs VersionControlSystem +} + +func (vcs *tracingVersionControlSystem) Name() string { return vcs.vcs.Name() } +func (vcs *tracingVersionControlSystem) WorkUnitName() string { return vcs.vcs.WorkUnitName() } + +func (vcs *tracingVersionControlSystem) Repository(ctx context.Context, name string) (Repository, error) { + defer trace.StartRegion(ctx, "VCS:"+vcs.Name()).End() + repo, err := vcs.vcs.Repository(ctx, name) + if err != nil { + return nil, err + } + if repo == nil { + return nil, nil + } + return &tracingRepository{repo}, nil +} + +type tracingRepository struct { + repo Repository +} + +func (repo *tracingRepository) VCS() VersionControlSystem { return repo.repo.VCS() } +func (repo *tracingRepository) Name() string { return repo.repo.Name() } +func (repo *tracingRepository) RootDir() string { return repo.repo.RootDir() } + +func (repo *tracingRepository) startRegions(ctx context.Context) func() { + r1 := trace.StartRegion(ctx, "VCS:"+repo.VCS().Name()) + r2 := trace.StartRegion(ctx, "Repo:"+repo.Name()) + return func() { + r2.End() + r1.End() + } +} + +func (repo *tracingRepository) Current(ctx context.Context) (string, error) { + defer repo.startRegions(ctx)() + return repo.repo.Current(ctx) +} +func (repo *tracingRepository) List(ctx context.Context, prefix string) ([]string, error) { + defer repo.startRegions(ctx)() + return repo.repo.List(ctx, prefix) +} +func (repo *tracingRepository) Sort(ctx context.Context, workUnits []string) error { + defer repo.startRegions(ctx)() + return repo.repo.Sort(ctx, workUnits) +} +func (repo *tracingRepository) New(ctx context.Context, workUnitName string) error { + defer repo.startRegions(ctx)() + return repo.repo.New(ctx, workUnitName) +} +func (repo *tracingRepository) Commit(ctx context.Context, workUnitName string) error { + defer repo.startRegions(ctx)() + return repo.repo.Commit(ctx, workUnitName) +} +func (repo *tracingRepository) Rename(ctx context.Context, workUnitName string) error { + defer repo.startRegions(ctx)() + return repo.repo.Rename(ctx, workUnitName) +} +func (repo *tracingRepository) Exists(ctx context.Context, workUnitName string) (bool, error) { + defer repo.startRegions(ctx)() + return repo.repo.Exists(ctx, workUnitName) +} +func (repo *tracingRepository) Update(ctx context.Context, workUnitName string) error { + defer repo.startRegions(ctx)() + return repo.repo.Update(ctx, workUnitName) +} From e5bf616a36609574fe6e00010141682686c157bc Mon Sep 17 00:00:00 2001 From: Jeffrey Faer Date: Thu, 4 Apr 2024 11:50:35 -0600 Subject: [PATCH 2/3] test(api): Add a sort test for empty slices. --- api/repotest/tests.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/api/repotest/tests.go b/api/repotest/tests.go index 54abac4..4b32313 100644 --- a/api/repotest/tests.go +++ b/api/repotest/tests.go @@ -350,6 +350,11 @@ func testSort(ctx context.Context, t *testing.T, ctor repoCtor, opts Options) { workUnits: []string{"wxyz"}, wantErr: true, }, + { + name: "Empty", + + workUnits: []string{}, + }, } { t.Run(tc.name, func(t *testing.T) { want := slices.Clone(tc.workUnits) From 3498cb8cc6400a8512160358963cabd865ea0687 Mon Sep 17 00:00:00 2001 From: Jeffrey Faer Date: Thu, 4 Apr 2024 12:00:51 -0600 Subject: [PATCH 3/3] feat(api): Allow for the repo test deadline to be configured. --- api/repotest/tests.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/api/repotest/tests.go b/api/repotest/tests.go index 4b32313..2cdd2aa 100644 --- a/api/repotest/tests.go +++ b/api/repotest/tests.go @@ -27,6 +27,10 @@ type Options struct { ExtraListWorkUnitPrefixes []ListWorkUnitTestCase Parallel bool + + // The deadline to use for test cases. + // Defaults to 5s. + Deadline time.Duration } type ListWorkUnitTestCase struct { @@ -37,6 +41,10 @@ type ListWorkUnitTestCase struct { type repoCtor func(*testing.T) api.Repository func RepoTests(t *testing.T, ctor func(context.Context, *testing.T, string) (api.Repository, error), opts Options) { + if opts.Deadline == 0 { + opts.Deadline = 5 * time.Second + } + for n, tc := range map[string]func(context.Context, *testing.T, repoCtor, Options){ "EmptyRepository": testEmptyRepository, "New": testNew, @@ -50,7 +58,7 @@ func RepoTests(t *testing.T, ctor func(context.Context, *testing.T, string) (api if opts.Parallel { t.Parallel() } - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), opts.Deadline) defer cancel() ctor := func(t *testing.T) api.Repository { repo, err := ctor(ctx, t, t.Name())