detached 30815db

fix(gitcli): keep a published repo when the directory sync fails

Also use the zerowrap.FromCtx logger value.
commit
30815db4eeb02e034eb98b1e44669e1bccbc75f6
author
brice · · 2026-10-10 06:41 UTC
parent
b9b6781
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
1 file · +14 -6
M internal/adapters/gitcli/repos.go +14 -6
@@ -49,11 +49,13 @@ func (g *Git) Stage(ctx context.Context) (ports.StagedID, error) {
4949 }
5050 if err != nil {
5151 if rerr := os.RemoveAll(dir); rerr != nil {
52- zerowrap.Ctx(ctx).Error().Err(rerr).Str("dir", dir).Msg("remove failed staging directory")
52+ log := zerowrap.FromCtx(ctx)
53+ log.Error().Err(rerr).Str("dir", dir).Msg("remove failed staging directory")
5354 }
5455 return "", fmt.Errorf("stage repository: %w", err)
5556 }
56- zerowrap.Ctx(ctx).Debug().Str("staged", string(id)).Msg("repository staged")
57+ log := zerowrap.FromCtx(ctx)
58+ log.Debug().Str("staged", string(id)).Msg("repository staged")
5759 return id, nil
5860 }
5961
@@ -71,10 +73,14 @@ func (g *Git) Publish(ctx context.Context, id ports.StagedID, name domain.RepoNa
7173 }
7274 return fmt.Errorf("publish repository %q: %w", name, err)
7375 }
76+ log := zerowrap.FromCtx(ctx)
77+ // The rename succeeded: the repository exists under its final name. A
78+ // failed sync only weakens crash durability; returning an error here
79+ // would make the caller roll back the metadata of a published directory.
7480 if err := syncDir(g.reposDir()); err != nil {
75- return fmt.Errorf("publish repository %q: %w", name, err)
81+ log.Warn().Err(err).Str("repo", name.String()).Msg("sync repositories directory after publish")
7682 }
77- zerowrap.Ctx(ctx).Debug().Str("repo", name.String()).Msg("repository published")
83+ log.Debug().Str("repo", name.String()).Msg("repository published")
7884 return nil
7985 }
8086
@@ -105,7 +111,8 @@ func (g *Git) PurgeStaging(ctx context.Context) error {
105111 if err := os.RemoveAll(filepath.Join(g.stagingDir(), e.Name())); err != nil {
106112 return fmt.Errorf("remove staging leftover %s: %w", e.Name(), err)
107113 }
108- zerowrap.Ctx(ctx).Info().Str("entry", e.Name()).Msg("removed staging leftover")
114+ log := zerowrap.FromCtx(ctx)
115+ log.Info().Str("entry", e.Name()).Msg("removed staging leftover")
109116 }
110117 return nil
111118 }
@@ -160,7 +167,8 @@ func (g *Git) Trash(ctx context.Context, name domain.RepoName) error {
160167 if err := syncDir(g.reposDir()); err != nil {
161168 return fmt.Errorf("trash repository %q: %w", name, err)
162169 }
163- zerowrap.Ctx(ctx).Info().Str("repo", name.String()).Str("trash", filepath.Base(dst)).Msg("repository moved to trash")
170+ log := zerowrap.FromCtx(ctx)
171+ log.Info().Str("repo", name.String()).Str("trash", filepath.Base(dst)).Msg("repository moved to trash")
164172 return nil
165173 }
166174 return fmt.Errorf("trash repository %q: no free name in trash", name)
@@ -49,11 +49,13 @@ func (g *Git) Stage(ctx context.Context) (ports.StagedID, error) {
49 }49 }
50 if err != nil {50 if err != nil {
51 if rerr := os.RemoveAll(dir); rerr != nil {51 if rerr := os.RemoveAll(dir); rerr != nil {
52- zerowrap.Ctx(ctx).Error().Err(rerr).Str("dir", dir).Msg("remove failed staging directory")52+ log := zerowrap.FromCtx(ctx)
53+ log.Error().Err(rerr).Str("dir", dir).Msg("remove failed staging directory")
53 }54 }
54 return "", fmt.Errorf("stage repository: %w", err)55 return "", fmt.Errorf("stage repository: %w", err)
55 }56 }
56- zerowrap.Ctx(ctx).Debug().Str("staged", string(id)).Msg("repository staged")57+ log := zerowrap.FromCtx(ctx)
58+ log.Debug().Str("staged", string(id)).Msg("repository staged")
57 return id, nil59 return id, nil
58 }60 }
59 61
@@ -71,10 +73,14 @@ func (g *Git) Publish(ctx context.Context, id ports.StagedID, name domain.RepoNa
71 }73 }
72 return fmt.Errorf("publish repository %q: %w", name, err)74 return fmt.Errorf("publish repository %q: %w", name, err)
73 }75 }
76+ log := zerowrap.FromCtx(ctx)
77+ // The rename succeeded: the repository exists under its final name. A
78+ // failed sync only weakens crash durability; returning an error here
79+ // would make the caller roll back the metadata of a published directory.
74 if err := syncDir(g.reposDir()); err != nil {80 if err := syncDir(g.reposDir()); err != nil {
75- return fmt.Errorf("publish repository %q: %w", name, err)81+ log.Warn().Err(err).Str("repo", name.String()).Msg("sync repositories directory after publish")
76 }82 }
77- zerowrap.Ctx(ctx).Debug().Str("repo", name.String()).Msg("repository published")83+ log.Debug().Str("repo", name.String()).Msg("repository published")
78 return nil84 return nil
79 }85 }
80 86
@@ -105,7 +111,8 @@ func (g *Git) PurgeStaging(ctx context.Context) error {
105 if err := os.RemoveAll(filepath.Join(g.stagingDir(), e.Name())); err != nil {111 if err := os.RemoveAll(filepath.Join(g.stagingDir(), e.Name())); err != nil {
106 return fmt.Errorf("remove staging leftover %s: %w", e.Name(), err)112 return fmt.Errorf("remove staging leftover %s: %w", e.Name(), err)
107 }113 }
108- zerowrap.Ctx(ctx).Info().Str("entry", e.Name()).Msg("removed staging leftover")114+ log := zerowrap.FromCtx(ctx)
115+ log.Info().Str("entry", e.Name()).Msg("removed staging leftover")
109 }116 }
110 return nil117 return nil
111 }118 }
@@ -160,7 +167,8 @@ func (g *Git) Trash(ctx context.Context, name domain.RepoName) error {
160 if err := syncDir(g.reposDir()); err != nil {167 if err := syncDir(g.reposDir()); err != nil {
161 return fmt.Errorf("trash repository %q: %w", name, err)168 return fmt.Errorf("trash repository %q: %w", name, err)
162 }169 }
163- zerowrap.Ctx(ctx).Info().Str("repo", name.String()).Str("trash", filepath.Base(dst)).Msg("repository moved to trash")170+ log := zerowrap.FromCtx(ctx)
171+ log.Info().Str("repo", name.String()).Str("trash", filepath.Base(dst)).Msg("repository moved to trash")
164 return nil172 return nil
165 }173 }
166 return fmt.Errorf("trash repository %q: no free name in trash", name)174 return fmt.Errorf("trash repository %q: no free name in trash", name)

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 2

Tags 45

↑↓ moveenter openesc close