diff --git a/lib/go/camli/mysqlindexer/search.go b/lib/go/camli/mysqlindexer/search.go index 44e1f0adf..f3fcad11d 100644 --- a/lib/go/camli/mysqlindexer/search.go +++ b/lib/go/camli/mysqlindexer/search.go @@ -397,7 +397,46 @@ func (mi *Indexer) PathsOfSignerTarget(signer, target *blobref.BlobRef) (paths [ return paths, nil } -func (mi *Indexer) PathLookup(signer, base *blobref.BlobRef, suffix string) (paths []*search.Path, err os.Error) { +func (mi *Indexer) PathLookup(signer, base *blobref.BlobRef, suffix string, at *time.Time) (*search.Path, os.Error) { + // TODO: pass along the at time to a new helper function to + // filter? maybe not worth it, since this list should be + // small. + paths, err := mi.PathsLookup(signer, base, suffix); + if err != nil { + return nil, err + } + var ( + newest = int64(0) + atSeconds = int64(0) + best *search.Path + ) + if at != nil { + atSeconds = at.Seconds() + } + for _, path := range paths { + t, err := time.Parse(time.RFC3339, trimRFC3339Subseconds(path.ClaimDate)) + if err != nil { + continue + } + secs := t.Seconds() + if atSeconds != 0 && secs > atSeconds { + // Too new + continue + } + if newest > secs { + // Too old + continue + } + // Just right + newest, best = secs, path + } + if best == nil { + return nil, os.ENOENT + } + return best, nil +} + +func (mi *Indexer) PathsLookup(signer, base *blobref.BlobRef, suffix string) (paths []*search.Path, err os.Error) { keyId, err := mi.keyIdOfSigner(signer) if err != nil { return diff --git a/lib/go/camli/search/search.go b/lib/go/camli/search/search.go index 8ecadbc2c..5e666f66c 100644 --- a/lib/go/camli/search/search.go +++ b/lib/go/camli/search/search.go @@ -96,5 +96,10 @@ type Index interface { PathsOfSignerTarget(signer, target *blobref.BlobRef) ([]*Path, os.Error) - PathLookup(signer, base *blobref.BlobRef, suffix string) ([]*Path, os.Error) + // All Path claims for (signer, base, suffix) + PathsLookup(signer, base *blobref.BlobRef, suffix string) ([]*Path, os.Error) + + // Most recent Path claim for (signer, base, suffix) as of + // provided time 'at', or most recent if 'at' is nil. + PathLookup(signer, base *blobref.BlobRef, suffix string, at *time.Time) (*Path, os.Error) } diff --git a/server/go/camlistored/publish.go b/server/go/camlistored/publish.go index 2ba84af26..fc3822fe0 100644 --- a/server/go/camlistored/publish.go +++ b/server/go/camlistored/publish.go @@ -111,14 +111,12 @@ func (pub *PublishHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) fmt.Fprintf(rw, "I am publish handler at base %q, serving root %q (permanode=%s), suffix %q
", base, pub.RootName, pn, html.EscapeString(suffix)) - paths, err := pub.Search.Index().PathLookup(pub.Search.Owner(), pn, suffix) + path, err := pub.Search.Index().PathLookup(pub.Search.Owner(), pn, suffix, nil) if err != nil { fmt.Fprintf(rw, "Error: %v", err) return } - for _, path := range paths { - fmt.Fprintf(rw, "

Target: %s

", path.Target, path.Target) - } + fmt.Fprintf(rw, "

Target: %s

", path.Target, path.Target) } func (pub *PublishHandler) bootstrapPermanode(jsonSign *JSONSignHandler) os.Error {