func run()

in devtools/cmd/populate_firestore/populate_firestore.go [53:112]


func run(ctx context.Context) error {
	client, err := firestore.NewClient(ctx, *project)
	if err != nil {
		return err
	}
	defer client.Close()
	repo, err := gitrepo.Open(ctx, *localRepoPath)
	if err != nil {
		return err
	}
	nsDoc := client.Collection(namespaceCollection).Doc(*namespace)

	commitTimeCache := map[string]time.Time{}

	getCommitTime := func(hash string) (time.Time, error) {
		if t, ok := commitTimeCache[hash]; ok {
			return t, nil
		}
		commit, err := repo.CommitObject(plumbing.NewHash(hash))
		if err != nil {
			return time.Time{}, fmt.Errorf("CommitObject(%s): %w", hash, err)
		}
		ct := commit.Committer.When.In(time.UTC)
		fmt.Printf("repo commit %s at %s\n", hash, ct)
		commitTimeCache[hash] = ct
		return ct, nil
	}

	q := nsDoc.Collection(cveCollection).Query
	if *startAfter != "" {
		q = q.OrderBy(firestore.DocumentID, firestore.Asc).StartAfter(*startAfter)
	}
	if *limit != 0 {
		q = q.Limit(*limit)
	}
	iter := q.Documents(ctx)
	defer iter.Stop()
	lastID, err := updateDB(ctx, client, iter, func(ds *firestore.DocumentSnapshot, wb *firestore.WriteBatch) (bool, error) {
		_, err := ds.DataAt("CommitTime")
		if err != nil && strings.Contains(err.Error(), "no field") {
			ch, err := ds.DataAt("CommitHash")
			if err != nil {
				return false, fmt.Errorf(`%s.DataAt("CommitHash"): %w`, ds.Ref.ID, err)
			}
			ct, err := getCommitTime(ch.(string))
			if err != nil {
				return false, err
			}
			wb.Update(ds.Ref, []firestore.Update{{Path: "CommitTime", Value: ct}})
			return true, nil
		} else {
			return false, err
		}
	})
	if err != nil {
		return err
	}
	fmt.Printf("last ID = %s\n", lastID)
	return nil
}