@@ -20,19 +20,23 @@ import (
2020 "encoding/json"
2121 "log"
2222 "net/http"
23+ "net/url"
2324 "strings"
2425 "time"
2526)
2627
27- // indexer gets a limited list of entries from index.golang.org.
28- type indexer interface {
29- get (prefixes []string , since time.Time ) (entries []indexEntry , last time.Time , err error )
28+ func mustParse (s string ) * url.URL {
29+ u , err := url .Parse (s )
30+ if err != nil {
31+ log .Fatalf ("Failed to parse URL: %q" , s )
32+ }
33+ return u
3034}
3135
3236// indexClient is used to access index.golang.org.
33- type indexClient struct {}
34-
35- var _ indexer = indexClient { }
37+ type indexClient struct {
38+ indexURL string
39+ }
3640
3741// indexEntry represents a line in the output of index.golang.org/index.
3842type indexEntry struct {
@@ -41,47 +45,45 @@ type indexEntry struct {
4145 Timestamp time.Time
4246}
4347
44- // newModules returns the new modules with the given prefix.
48+ // get returns modules with the given prefix that were published since the given timestamp .
4549//
46- // newModules uses index.golang.org/index?since=timestamp to find new module
47- // versions since the given timestamp.
50+ // get uses index.golang.org/index?since=timestamp to find new module versions.
4851//
49- // newModules stores the timestamp of the last successful run with tSaver.
50- func newModules (ctx context.Context , i indexer , tSaver timeSaver , prefixes []string ) ([]indexEntry , error ) {
51- since , err := tSaver .get (ctx )
52- if err != nil {
53- return nil , err
54- }
52+ // get returns the entries and the timestamp of the last seen entry, which may be later
53+ // than the timestamp of the last returned entry.
54+ func (ic indexClient ) get (ctx context.Context , prefixes []string , since time.Time ) ([]indexEntry , time.Time , error ) {
5555 fiveMinAgo := time .Now ().Add (- 5 * time .Minute ).UTC () // When to stop processing.
5656 entries := []indexEntry {}
5757 log .Printf ("Fetching index.golang.org entries since %s" , since .Format (time .RFC3339 ))
58- count := 0
59- for {
60- count ++
58+ pages := 0
59+ lastSeen := since
60+ for ! lastSeen .After (fiveMinAgo ) {
61+ log .Printf ("last seen: %v" , lastSeen .Format (time .RFC3339 ))
62+ pages ++
6163 var cur []indexEntry
62- cur , since , err = i .get (prefixes , since )
64+ var err error
65+ cur , lastSeen , err = ic .getPage (prefixes , lastSeen )
6366 if err != nil {
64- return nil , err
67+ return nil , time. Time {}, err
6568 }
6669 entries = append (entries , cur ... )
67- if since .After (fiveMinAgo ) {
68- break
69- }
70- }
71- log .Printf ("Parsed %d index.golang.org pages up to %s" , count , since .Format (time .RFC3339 ))
72- if err := tSaver .put (ctx , since ); err != nil {
73- return nil , err
7470 }
71+ log .Printf ("Parsed %d index.golang.org pages from %s to %s" , pages , since .Format (time .RFC3339 ), lastSeen .Format (time .RFC3339 ))
7572
76- return entries , nil
73+ return entries , lastSeen , nil
7774}
7875
7976// get fetches a single chronological page of modules from
8077// index.golang.org/index.
81- func (indexClient ) get (prefixes []string , since time.Time ) ([]indexEntry , time.Time , error ) {
78+ func (ic indexClient ) getPage (prefixes []string , since time.Time ) ([]indexEntry , time.Time , error ) {
8279 entries := []indexEntry {}
83- sinceString := since .Format (time .RFC3339 )
84- resp , err := http .Get ("https://index.golang.org/index?since=" + sinceString )
80+
81+ u := mustParse (ic .indexURL )
82+ q := u .Query ()
83+ q .Set ("since" , since .Format (time .RFC3339 ))
84+ u .RawQuery = q .Encode ()
85+ log .Printf ("Fetching %s" , u .String ())
86+ resp , err := http .Get (u .String ())
8587 if err != nil {
8688 return nil , time.Time {}, err
8789 }
0 commit comments