// buildDiff creates a Diff for the given intermediate. func buildDiff(test, digest string, e *expstorage.Expectations, tile *tiling.Tile, testTally map[string]tally.Tally, blamer *blame.Blamer, diffStore diff.DiffStore, paramset *paramsets.Summary, includeIgnores bool) *Diff { ret := &Diff{ Diff: math.MaxFloat32, Pos: nil, Neg: nil, } if blamer != nil { ret.Blame = blamer.GetBlame(test, digest, tile.Commits) } t := testTally[test] if t == nil { t = tally.Tally{} } ret.Pos = &DiffDigest{ Closest: digesttools.ClosestDigest(test, digest, e, t, diffStore, types.POSITIVE), } ret.Pos.ParamSet = paramset.Get(test, ret.Pos.Closest.Digest, includeIgnores) ret.Neg = &DiffDigest{ Closest: digesttools.ClosestDigest(test, digest, e, t, diffStore, types.NEGATIVE), } ret.Neg.ParamSet = paramset.Get(test, ret.Neg.Closest.Digest, includeIgnores) if pos, neg := ret.Pos.Closest.Diff, ret.Neg.Closest.Diff; pos < neg { ret.Diff = pos } else { ret.Diff = neg } return ret }
// searchTile queries across a tile. func searchTile(q *Query, e *expstorage.Expectations, parsedQuery url.Values, storages *storage.Storage, tile *tiling.Tile, tallies *tally.Tallies, blamer *blame.Blamer, paramset *paramsets.Summary) ([]*Digest, []*tiling.Commit, error) { // TODO Use CommitRange to create a trimmed tile. traceTally := tallies.ByTrace() lastCommitIndex := tile.LastCommitIndex() // Loop over the tile and pull out all the digests that match // the query, collecting the matching traces as you go. Build // up a set of intermediate's that can then be used to calculate // Digest's. // map [test:digest] *intermediate inter := map[string]*intermediate{} for id, tr := range tile.Traces { if tiling.Matches(tr, parsedQuery) { test := tr.Params()[types.PRIMARY_KEY_FIELD] // Get all the digests digests := digestsFromTrace(id, tr, q.Head, lastCommitIndex, traceTally) for _, digest := range digests { cl := e.Classification(test, digest) if q.excludeClassification(cl) { continue } // Fix blamer to make this easier. if q.BlameGroupID != "" { if cl == types.UNTRIAGED { b := blamer.GetBlame(test, digest, tile.Commits) if q.BlameGroupID != blameGroupID(b, tile.Commits) { continue } } else { continue } } key := fmt.Sprintf("%s:%s", test, digest) if i, ok := inter[key]; !ok { inter[key] = newIntermediate(test, digest, id, tr, digests) } else { i.addTrace(id, tr, digests) } } } } // Now loop over all the intermediates and build a Digest for each one. ret := make([]*Digest, 0, len(inter)) for key, i := range inter { parts := strings.Split(key, ":") ret = append(ret, digestFromIntermediate(parts[0], parts[1], i, e, tile, tallies, blamer, storages.DiffStore, paramset, q.IncludeIgnores)) } return ret, tile.Commits, nil }
// buildDiff creates a Diff for the given intermediate. func buildDiff(test, digest string, e *expstorage.Expectations, tile *tiling.Tile, testTally map[string]tally.Tally, blamer *blame.Blamer, diffStore diff.DiffStore, paramset *paramsets.Summary, includeIgnores bool) *Diff { ret := &Diff{ Diff: math.MaxFloat32, Pos: nil, Neg: nil, } if blamer != nil { ret.Blame = blamer.GetBlame(test, digest, tile.Commits) } t := testTally[test] if t == nil { t = tally.Tally{} } var diffVal float32 = 0 if closest := digesttools.ClosestDigest(test, digest, e, t, diffStore, types.POSITIVE); closest.Digest != "" { ret.Pos = &DiffDigest{ Closest: closest, } ret.Pos.ParamSet = paramset.Get(test, ret.Pos.Closest.Digest, includeIgnores) diffVal = closest.Diff } if closest := digesttools.ClosestDigest(test, digest, e, t, diffStore, types.NEGATIVE); closest.Digest != "" { ret.Neg = &DiffDigest{ Closest: closest, } ret.Neg.ParamSet = paramset.Get(test, ret.Neg.Closest.Digest, includeIgnores) if (ret.Pos == nil) || (closest.Diff < diffVal) { diffVal = closest.Diff } } ret.Diff = diffVal return ret }
// Search returns a slice of Digests that match the input query, and the total number of Digests // that matched the query. It also returns a slice of Commits that were used in the calculations. func Search(q *Query, storages *storage.Storage, tallies *tally.Tallies, blamer *blame.Blamer, paramset *paramsets.Summary) ([]*Digest, int, []*tiling.Commit, error) { tile, err := storages.GetLastTileTrimmed(q.IncludeIgnores) if err != nil { return nil, 0, nil, fmt.Errorf("Couldn't retrieve tile: %s", err) } // TODO Use CommitRange to create a trimmed tile. parsedQuery, err := url.ParseQuery(q.Query) if err != nil { return nil, 0, nil, fmt.Errorf("Failed to parse Query in Search: %s", err) } e, err := storages.ExpectationsStore.Get() if err != nil { return nil, 0, nil, fmt.Errorf("Couldn't get expectations: %s", err) } traceTally := tallies.ByTrace() lastCommitIndex := tile.LastCommitIndex() // Loop over the tile and pull out all the digests that match // the query, collecting the matching traces as you go. Build // up a set of intermediate's that can then be used to calculate // Digest's. // map [test:digest] *intermediate inter := map[string]*intermediate{} for id, tr := range tile.Traces { if tiling.Matches(tr, parsedQuery) { test := tr.Params()[types.PRIMARY_KEY_FIELD] // Get all the digests digests := digestsFromTrace(id, tr, q.Head, lastCommitIndex, traceTally) for _, digest := range digests { cl := e.Classification(test, digest) switch { case cl == types.NEGATIVE && !q.Neg: continue case cl == types.POSITIVE && !q.Pos: continue case cl == types.UNTRIAGED && !q.Unt: continue } // Fix blamer to make this easier. if q.BlameGroupID != "" { if cl == types.UNTRIAGED { b := blamer.GetBlame(test, digest, tile.Commits) if q.BlameGroupID != blameGroupID(b, tile.Commits) { continue } } else { continue } } key := fmt.Sprintf("%s:%s", test, digest) if i, ok := inter[key]; !ok { inter[key] = newIntermediate(test, digest, id, tr, digests) } else { i.addTrace(id, tr, digests) } } } } // Now loop over all the intermediates and build a Digest for each one. ret := make([]*Digest, 0, len(inter)) for key, i := range inter { parts := strings.Split(key, ":") ret = append(ret, digestFromIntermediate(parts[0], parts[1], i, e, tile, tallies, blamer, storages.DiffStore, paramset, q.IncludeIgnores)) } sort.Sort(DigestSlice(ret)) fullLength := len(ret) if fullLength > q.Limit { ret = ret[0:q.Limit] } return ret, fullLength, tile.Commits, nil }