|
6 | 6 | "io/fs" |
7 | 7 | "os" |
8 | 8 | "path/filepath" |
| 9 | + "strings" |
9 | 10 | "sync" |
10 | 11 |
|
11 | 12 | "github.com/operator-framework/operator-registry/alpha/declcfg" |
@@ -75,10 +76,15 @@ func (fsc *filesystemCache) Put(catalogName, resolvedRef string, source io.Reade |
75 | 76 | func (fsc *filesystemCache) writeFS(catalogName string, source io.Reader) (fs.FS, error) { |
76 | 77 | cacheDir := fsc.cacheDir(catalogName) |
77 | 78 |
|
| 79 | + if err := fsc.removeOrphanedTempDirs(catalogName); err != nil { |
| 80 | + return nil, err |
| 81 | + } |
| 82 | + |
78 | 83 | tmpDir, err := os.MkdirTemp(fsc.cachePath, fmt.Sprintf(".%s-", catalogName)) |
79 | 84 | if err != nil { |
80 | 85 | return nil, fmt.Errorf("error creating temporary directory to unpack catalog metadata: %v", err) |
81 | 86 | } |
| 87 | + defer os.RemoveAll(tmpDir) |
82 | 88 |
|
83 | 89 | if err := declcfg.WalkMetasReader(source, func(meta *declcfg.Meta, err error) error { |
84 | 90 | if err != nil { |
@@ -164,3 +170,26 @@ func (fsc *filesystemCache) Remove(catalogName string) error { |
164 | 170 | func (fsc *filesystemCache) cacheDir(catalogName string) string { |
165 | 171 | return filepath.Join(fsc.cachePath, catalogName) |
166 | 172 | } |
| 173 | + |
| 174 | +// removeOrphanedTempDirs removes temporary staging directories left behind by a |
| 175 | +// previous writeFS call for the given catalog that was interrupted before the |
| 176 | +// rename (e.g. pod eviction or crash). Temp dirs use the prefix ".{catalogName}-" |
| 177 | +// as created by os.MkdirTemp. This method must be called while the write lock is held. |
| 178 | +func (fsc *filesystemCache) removeOrphanedTempDirs(catalogName string) error { |
| 179 | + entries, err := os.ReadDir(fsc.cachePath) |
| 180 | + if os.IsNotExist(err) { |
| 181 | + return nil |
| 182 | + } |
| 183 | + if err != nil { |
| 184 | + return fmt.Errorf("error reading cache directory: %w", err) |
| 185 | + } |
| 186 | + prefix := fmt.Sprintf(".%s-", catalogName) |
| 187 | + for _, entry := range entries { |
| 188 | + if strings.HasPrefix(entry.Name(), prefix) { |
| 189 | + if err := os.RemoveAll(filepath.Join(fsc.cachePath, entry.Name())); err != nil { |
| 190 | + return fmt.Errorf("error removing orphaned temp directory %q: %w", entry.Name(), err) |
| 191 | + } |
| 192 | + } |
| 193 | + } |
| 194 | + return nil |
| 195 | +} |
0 commit comments