jiri: Maintain "latest" and "second-latest" symlinks in update-history.
And make devtools/postsubmit read the "second-latest" symlink, rather
than try to calculate the second-latest snapshot the hard way.
MultiPart: 1/2
Change-Id: I177c18bbd3ebf0a7546b74d7fc6a5760387ac175
diff --git a/jiri/.api b/jiri/.api
index bbf12c1..f71ff54 100644
--- a/jiri/.api
+++ b/jiri/.api
@@ -15,6 +15,7 @@
pkg jiri, method (*X) RootMetaDir() string
pkg jiri, method (*X) UpdateHistoryDir() string
pkg jiri, method (*X) UpdateHistoryLatestLink() string
+pkg jiri, method (*X) UpdateHistorySecondLatestLink() string
pkg jiri, method (*X) UsageErrorf(string, ...interface{}) error
pkg jiri, method (*X) UsingOldManifests() bool
pkg jiri, method (RelPath) Abs(*X) string
diff --git a/jiri/x.go b/jiri/x.go
index c67a452..09f77f0 100644
--- a/jiri/x.go
+++ b/jiri/x.go
@@ -142,6 +142,12 @@
return filepath.Join(x.UpdateHistoryDir(), "latest")
}
+// UpdateHistorySecondLatestLink returns the path to a symlink that points to
+// the second latest update in the update history directory.
+func (x *X) UpdateHistorySecondLatestLink() string {
+ return filepath.Join(x.UpdateHistoryDir(), "second-latest")
+}
+
// ResolveManifestPath resolves the given manifest name to an absolute path in
// the local filesystem.
//
diff --git a/update.go b/update.go
index aaccb51..36a9877 100644
--- a/update.go
+++ b/update.go
@@ -5,6 +5,7 @@
package main
import (
+ "os"
"path/filepath"
"time"
@@ -44,12 +45,13 @@
}
func runUpdate(jirix *jiri.X, _ []string) error {
+ seq := jirix.NewSeq()
// Create the $JIRI_ROOT/.jiri_root directory if it doesn't already exist.
//
// TODO(toddw): Remove this logic after the transition to .jiri_root is done.
// The bootstrapping logic should create this directory, and jiri should fail
// if the directory doesn't exist.
- if err := jirix.NewSeq().MkdirAll(jirix.RootMetaDir(), 0755).Done(); err != nil {
+ if err := seq.MkdirAll(jirix.RootMetaDir(), 0755).Done(); err != nil {
return err
}
@@ -65,16 +67,34 @@
if err := project.CreateSnapshot(jirix, snapshotFile); err != nil {
return err
}
- // Point the "latest" update history symlink to the new snapshot file. Try to
- // keep the symlink relative, to make it easy to move or copy the entire
- // update_history directory.
- link, latest := jirix.UpdateHistoryLatestLink(), snapshotFile
- if rel, err := filepath.Rel(filepath.Dir(link), latest); err == nil {
- latest = rel
- }
- if err := jirix.NewSeq().RemoveAll(link).Symlink(latest, link).Done(); err != nil {
+
+ latestLink, secondLatestLink := jirix.UpdateHistoryLatestLink(), jirix.UpdateHistorySecondLatestLink()
+
+ // If the "latest" symlink exists, point the "second-latest" symlink to its value.
+ latestLinkExists, err := seq.IsFile(latestLink)
+ if err != nil {
return err
}
+ if latestLinkExists {
+ latestFile, err := os.Readlink(latestLink)
+ if err != nil {
+ return err
+ }
+ if err := seq.RemoveAll(secondLatestLink).Symlink(latestFile, secondLatestLink).Done(); err != nil {
+ return err
+ }
+ }
+
+ // Point the "latest" update history symlink to the new snapshot file. Try
+ // to keep the symlink relative, to make it easy to move or copy the entire
+ // update_history directory.
+ if rel, err := filepath.Rel(filepath.Dir(latestLink), snapshotFile); err == nil {
+ snapshotFile = rel
+ }
+ if err := seq.RemoveAll(latestLink).Symlink(snapshotFile, latestLink).Done(); err != nil {
+ return err
+ }
+
// Only attempt the bin dir transition after the update has succeeded, to
// avoid messy partial states.
return project.TransitionBinDir(jirix)