+2015-06-15 Ryosuke Niwa <rniwa@webkit.org>
+
+ Analysis task should show all possible revisions for A/B testing
+ https://bugs.webkit.org/show_bug.cgi?id=145996
+
+ Reviewed by Chris Dumez.
+
+ * public/api/commits.php:
+ (fetch_commits_between): When the time stamp is not available for commits, use revision numbers
+ to find revisions between two ranges. This is necessary for OS X and iOS versions since they don't
+ have a "commit time".
+
+ * public/v2/app.js:
+ (App.AnalysisTaskController.updateRootConfigurations): Fetch commits between two end points.
+ (App.AnalysisTaskController._createConfiguration): Extracted from updateRootConfigurations. List
+ the fetched list of commits if available.
+ (App.AnalysisTaskController._serializeNumbersSkippingConsecutiveEntries): Added. Serializes an list
+ of numbers intelligently. For example, [1, 2, 4, 5] turns into "1-2, 4-5". Without this, some lists
+ of points shown in the A/B testing configurations become too long.
+
+ * public/v2/commits-viewer.js:
+ (App.CommitsViewerComponent.commitsChanged):
+
+ * public/v2/data.js:
+ (CommitLogs.fetchCommits): Renamed from fetchForTimeRange.
+
2015-06-13 Ryosuke Niwa <rniwa@webkit.org>
Add a script to post new OS X builds to perf dashboard
committer_name as "authorName",
committer_account as "authorEmail",
commit_message as "message"
- FROM commits JOIN committers ON commit_committer = committer_id
+ FROM commits LEFT OUTER JOIN committers ON commit_committer = committer_id
WHERE commit_repository = $1 AND commit_reported = true';
$values = array($repository_id);
if ($first && $second) {
- $fitrt_commit = commit_from_revision($db, $repository_id, $first);
+ $first_commit = commit_from_revision($db, $repository_id, $first);
$second_commit = commit_from_revision($db, $repository_id, $second);
- $first = $fitrt_commit['commit_time'];
+ $first = $first_commit['commit_time'];
$second = $second_commit['commit_time'];
+ $column = 'commit_time';
+ if (!$first && !$second) {
+ $first = $first_commit['commit_revision'];
+ $second = $second_commit['commit_revision'];
+ $column = 'commit_revision';
+ }
$in_order = $first < $second;
array_push($values, $in_order ? $first : $second);
- $statements .= ' AND commit_time >= $' . count($values);
+ $statements .= ' AND ' . $column . ' >= $' . count($values);
array_push($values, $in_order ? $second : $first);
- $statements .= ' AND commit_time <= $' . count($values);
+ $statements .= ' AND ' . $column . ' <= $' . count($values);
}
if ($keyword) {
var revisions = point.measurement.formattedRevisions();
for (var repositoryId in revisions) {
if (!repositoryToRevisions[repositoryId])
- repositoryToRevisions[repositoryId] = new Array(analysisPoints.length);
+ repositoryToRevisions[repositoryId] = {commits: null, revisions: []};
var revision = revisions[repositoryId];
- repositoryToRevisions[repositoryId][pointIndex] = {
+ repositoryToRevisions[repositoryId].revisions[pointIndex] = {
label: point.label + ': ' + revision.label,
value: revision.currentRevision,
};
}
});
+ var commitsPromises = [];
+ var repositoryToIndex = {};
+ for (var repositoryId in repositoryToRevisions) {
+ var revisions = repositoryToRevisions[repositoryId].revisions;
+ repositoryToIndex[repositoryId] = commitsPromises.length;
+ console.log(repositoryId)
+ commitsPromises.push(CommitLogs.fetchCommits(repositoryId, revisions[0].value, revisions[revisions.length - 1].value));
+ }
+
var self = this;
this.get('model').get('triggerable').then(function (triggerable) {
if (!triggerable)
return;
-
- self.set('configurations', ['A', 'B']);
- self.set('rootConfigurations', triggerable.get('acceptedRepositories').map(function (repository) {
- var repositoryId = repository.get('id');
- var options = [{label: 'None'}].concat((repositoryToRevisions[repositoryId] || []).map(function (option, index) {
- if (!option || !option['value'])
- return {value: '', label: analysisPoints[index].label + ': None'};
- return option;
+ Ember.RSVP.Promise.all(commitsPromises).then(function (commitsList) {
+ self.set('configurations', ['A', 'B']);
+ self.set('rootConfigurations', triggerable.get('acceptedRepositories').map(function (repository) {
+ return self._createConfiguration(repository, commitsList[repositoryToIndex[repository.get('id')]], analysisPoints);
}));
- return Ember.Object.create({
- repository: repository,
- name: repository.get('name'),
- sets: [
- Ember.Object.create({name: 'A[' + repositoryId + ']',
- options: options,
- selection: options[1]}),
- Ember.Object.create({name: 'B[' + repositoryId + ']',
- options: options,
- selection: options[options.length - 1]}),
- ],
- });
- }));
+ });
});
}.observes('analysisPoints'),
+ _createConfiguration: function(repository, commits, analysisPoints) {
+ var repositoryId = repository.get('id');
+
+ var options = [{label: 'None'}];
+ var revisionToPoints = {};
+ analysisPoints.forEach(function (point, pointIndex) {
+ var revision = point.measurement.revisionForRepository(repositoryId);
+ if (!revision)
+ return;
+ if (!revisionToPoints[revision])
+ revisionToPoints[revision] = [];
+ revisionToPoints[revision].push(pointIndex);
+ });
+
+ if (!commits || !commits.length) {
+ commits = [];
+ for (var revision in revisionToPoints)
+ commits.push({revision: revision});
+ }
+
+ for (var commit of commits) {
+ var revision = commit.revision;
+ var label = Measurement.formatRevisionRange(revision).label;
+ var points = revisionToPoints[revision];
+ if (points) {
+ var serializedPoints = this._serializeNumbersSkippingConsecutiveEntries(revisionToPoints[revision]);
+ label += ' ' + ['(', points.length > 1 ? 'points' : 'point', serializedPoints, ')'].join(' ');
+ }
+ options.push({value: revision, label: label});
+ }
+
+ return Ember.Object.create({
+ repository: repository,
+ name: repository.get('name'),
+ sets: [
+ Ember.Object.create({name: 'A[' + repositoryId + ']',
+ options: options,
+ selection: options[1]}),
+ Ember.Object.create({name: 'B[' + repositoryId + ']',
+ options: options,
+ selection: options[options.length - 1]}),
+ ]});
+ },
+ _serializeNumbersSkippingConsecutiveEntries: function (numbers) {
+ var result = numbers[0];
+ for (var i = 1; i < numbers.length; i++) {
+ if (numbers[i - 1] + 1 == numbers[i]) {
+ while (numbers[i] + 1 == numbers[i + 1])
+ i++;
+ result += '-' + numbers[i];
+ continue;
+ }
+ result += ', ' + numbers[i]
+ }
+ return result;
+ },
actions: {
addBug: function (bugTracker, bugNumber)
{