Serialize restore recovery and rebase manifest paths
This commit is contained in:
@@ -114,19 +114,28 @@ func executeRestoreDownloadAction(
|
||||
return err
|
||||
}
|
||||
|
||||
if action.LocalRelativePath == config.PathManifestFile {
|
||||
if isRestoreManifest(action.LocalRelativePath) {
|
||||
file, err := temporary.Open()
|
||||
if err != nil {
|
||||
return fmt.Errorf("open restored manifest: %w", err)
|
||||
}
|
||||
err = validateRestoredManifest(ctx, cfg, current, file)
|
||||
destinationRoot := sessionRoot
|
||||
requireCurrentIdentity := action.LocalRelativePath == config.PathManifestFile
|
||||
if !requireCurrentIdentity {
|
||||
destinationRoot = filepath.Dir(safeLocalPath)
|
||||
}
|
||||
restored, prepareErr := prepareRestoredManifest(ctx, cfg, current, file, destinationRoot, requireCurrentIdentity)
|
||||
closeErr := file.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
if prepareErr != nil {
|
||||
return prepareErr
|
||||
}
|
||||
if closeErr != nil {
|
||||
return fmt.Errorf("close restored manifest: %w", closeErr)
|
||||
}
|
||||
if err := (&manifest.LocalStore{}).Save(ctx, safeLocalPath, restored); err != nil {
|
||||
return fmt.Errorf("install rebased manifest atomically: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := temporary.Install(filepath.Base(safeLocalPath), fileops.WorkspaceFileMode); err != nil {
|
||||
@@ -136,6 +145,11 @@ func executeRestoreDownloadAction(
|
||||
return nil
|
||||
}
|
||||
|
||||
func isRestoreManifest(relativePath string) bool {
|
||||
clean := filepath.ToSlash(filepath.Clean(strings.TrimSpace(relativePath)))
|
||||
return clean == config.PathManifestFile || clean == config.PathPreviousDirSegment+"/"+config.PathManifestFile
|
||||
}
|
||||
|
||||
func verifyRestoredObject(ctx context.Context, store storage.ObjectStore, action RestoreAction, temporary *fileops.DownloadedTempFile) error {
|
||||
if strings.TrimSpace(action.SHA256) == "" && strings.TrimSpace(action.Generation) == "" {
|
||||
return nil
|
||||
@@ -217,38 +231,3 @@ func executeRestoreAudioAction(
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateRestoredManifest(ctx context.Context, cfg *config.Config, current *RemoteCurrentState, source io.Reader) error {
|
||||
manifestStore := &manifest.LocalStore{}
|
||||
m, err := manifestStore.LoadReader(ctx, source)
|
||||
if err != nil {
|
||||
return fmt.Errorf("validate manifest decode: %w", err)
|
||||
}
|
||||
|
||||
requestedSession := strings.TrimSpace(cfg.Session.SessionID)
|
||||
requestedCampaign := strings.TrimSpace(cfg.Session.Campaign)
|
||||
manifestSession := strings.TrimSpace(m.SessionID)
|
||||
manifestCampaign := strings.TrimSpace(m.Campaign)
|
||||
if manifestSession != requestedSession {
|
||||
return fmt.Errorf("manifest session_id %q does not match requested session_id %q", manifestSession, requestedSession)
|
||||
}
|
||||
if manifestCampaign == "" {
|
||||
return fmt.Errorf("manifest campaign is required")
|
||||
}
|
||||
if manifestCampaign != requestedCampaign {
|
||||
return fmt.Errorf("manifest campaign %q does not match requested campaign %q", manifestCampaign, requestedCampaign)
|
||||
}
|
||||
if current != nil {
|
||||
if expected := strings.TrimSpace(current.SessionID); expected != "" && manifestSession != expected {
|
||||
return fmt.Errorf("manifest session_id %q does not match discovered session_id %q", manifestSession, expected)
|
||||
}
|
||||
if expected := strings.TrimSpace(current.Campaign); expected != "" && manifestCampaign != expected {
|
||||
return fmt.Errorf("manifest campaign %q does not match discovered campaign %q", manifestCampaign, expected)
|
||||
}
|
||||
if expected := strings.TrimSpace(current.RunID); expected != "" && strings.TrimSpace(m.RunID) != expected {
|
||||
return fmt.Errorf("manifest run_id %q does not match discovered run_id %q", strings.TrimSpace(m.RunID), expected)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user