Save saves the cache to disk with sorted entries If the cache is empty, the file is not created or is deleted if it exists Deduplicates entries by keeping only the most precise version reference for each repo+SHA combination Only saves if the cache has been modified (dirty flag is true)
()
| 212 | // Deduplicates entries by keeping only the most precise version reference for each repo+SHA combination |
| 213 | // Only saves if the cache has been modified (dirty flag is true) |
| 214 | func (c *ActionCache) Save() error { |
| 215 | // Skip saving if cache hasn't been modified |
| 216 | if !c.dirty { |
| 217 | actionCacheLog.Printf("Cache is clean (no changes), skipping save") |
| 218 | return nil |
| 219 | } |
| 220 | |
| 221 | actionCacheLog.Printf("Saving action cache to: %s with %d entries", c.path, len(c.Entries)) |
| 222 | |
| 223 | // If cache is empty (no entries and no container pins), skip saving and delete the file if it exists |
| 224 | if len(c.Entries) == 0 && len(c.ContainerPins) == 0 { |
| 225 | actionCacheLog.Print("Cache is empty, skipping file creation") |
| 226 | // Remove the file if it exists |
| 227 | if _, err := os.Stat(c.path); err == nil { |
| 228 | actionCacheLog.Printf("Removing existing empty cache file: %s", c.path) |
| 229 | if err := os.Remove(c.path); err != nil { |
| 230 | actionCacheLog.Printf("Failed to remove empty cache file: %v", err) |
| 231 | return err |
| 232 | } |
| 233 | } |
| 234 | c.dirty = false |
| 235 | return nil |
| 236 | } |
| 237 | |
| 238 | // Deduplicate entries before saving |
| 239 | c.deduplicateEntries() |
| 240 | |
| 241 | // Ensure directory exists |
| 242 | dir := filepath.Dir(c.path) |
| 243 | if err := os.MkdirAll(dir, constants.DirPermPublic); err != nil { |
| 244 | actionCacheLog.Printf("Failed to create cache directory: %v", err) |
| 245 | return err |
| 246 | } |
| 247 | |
| 248 | // Marshal with sorted entries |
| 249 | data, err := c.marshalSorted() |
| 250 | if err != nil { |
| 251 | actionCacheLog.Printf("Failed to marshal cache data: %v", err) |
| 252 | return err |
| 253 | } |
| 254 | |
| 255 | // Add trailing newline for prettier compliance |
| 256 | data = append(data, '\n') |
| 257 | |
| 258 | if err := os.WriteFile(c.path, data, constants.FilePermPublic); err != nil { |
| 259 | actionCacheLog.Printf("Failed to write cache file: %v", err) |
| 260 | return err |
| 261 | } |
| 262 | |
| 263 | actionCacheLog.Print("Successfully saved action cache") |
| 264 | c.dirty = false |
| 265 | return nil |
| 266 | } |
| 267 | |
| 268 | // marshalSorted marshals the cache with entries sorted by key |
| 269 | func (c *ActionCache) marshalSorted() ([]byte, error) { |