Skip to content

Commit 11c5bb7

Browse files
docs(versions): rework the version info extraction
The docs were relying on the grunt/util module for getting version info but this was unreliable and full of custom regexes. This is moved into a new version-info module that makes much better use of the semver library.
1 parent d6419d0 commit 11c5bb7

File tree

4 files changed

+164
-7
lines changed

4 files changed

+164
-7
lines changed

docs/config/processors/git-data.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
var gruntUtils = require('../../../lib/grunt/utils');
2+
var versionInfo = require('../../../lib/versions/version-info');
23

34
module.exports = {
45
name: 'git-data',
56
runBefore: ['loading-files'],
67
description: 'This processor adds information from the local git repository to the extraData injectable',
78
init: function(config, injectables) {
89
injectables.value('gitData', {
9-
version: gruntUtils.getVersion(),
10-
versions: gruntUtils.getPreviousVersions(),
11-
info: gruntUtils.getGitRepoInfo()
10+
version: versionInfo.currentVersion,
11+
versions: versionInfo.previousVersions,
12+
info: versionInfo.gitRepoInfo
1213
});
1314
},
1415
process: function(extraData, gitData) {

docs/config/templates/indexPage.template.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ <h4 class="search-results-group-heading">{{ key }}</h4>
175175
<div class="container main-grid main-header-grid">
176176
<div class="grid-left">
177177
<div ng-controller="DocsVersionsCtrl" class="picker version-picker">
178-
<select ng-options="v as ('v' + v.full) group by (v.isStable?'Stable':'Unstable') for v in docs_versions"
178+
<select ng-options="v as ('v' + v.version + (v.isSnapshot ? ' (snapshot)' : '')) group by (v.isStable?'Stable':'Unstable') for v in docs_versions"
179179
ng-model="docs_version"
180180
ng-change="jumpToDocsVersion(docs_version)"
181181
class="docs-version-jump">

docs/docs.config.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
var path = require('canonical-path');
2-
var gruntUtils = require('../lib/grunt/utils');
2+
var versionInfo = require('../lib/versions/version-info');
33
var basePath = __dirname;
44

55
var basePackage = require('./config');
66

77
module.exports = function(config) {
88

9-
var version = gruntUtils.getVersion();
10-
var cdnUrl = "//ajax.googleapis.com/ajax/libs/angularjs/" + version.cdn;
9+
var cdnUrl = "//ajax.googleapis.com/ajax/libs/angularjs/" + versionInfo.currentPackage.cdnVersion;
1110

1211
var getVersion = function(component, sourceFolder, packageFile) {
1312
sourceFolder = sourceFolder || '../bower_components';

lib/versions/version-info.js

+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
var fs = require('fs');
2+
var path = require('path');
3+
var shell = require('shelljs');
4+
var semver = require('semver');
5+
var _ = require('lodash');
6+
7+
var currentPackage, previousVersions;
8+
9+
10+
/**
11+
* Load information about this project from the package.json
12+
* @return {Object} The package information
13+
*/
14+
var getPackage = function() {
15+
// Search up the folder hierarchy for the first package.json
16+
var packageFolder = path.resolve('.');
17+
while ( !fs.existsSync(path.join(packageFolder, 'package.json')) ) {
18+
var parent = path.dirname(packageFolder);
19+
if ( parent === packageFolder) { break; }
20+
packageFolder = parent;
21+
}
22+
return JSON.parse(fs.readFileSync(path.join(packageFolder,'package.json'), 'UTF-8'));
23+
};
24+
25+
26+
/**
27+
* Parse the github URL for useful information
28+
* @return {Object} An object containing the github owner and repository name
29+
*/
30+
var getGitRepoInfo = function() {
31+
var GITURL_REGEX = /^https:\/\/github.com\/([^\/]+)\/(.+).git$/;
32+
var match = GITURL_REGEX.exec(currentPackage.repository.url);
33+
var git = {
34+
owner: match[1],
35+
repo: match[2]
36+
};
37+
return git;
38+
};
39+
40+
41+
42+
/**
43+
* Extract the code name from the tagged commit's message - it should contain the text of the form:
44+
* "codename(some-code-name)"
45+
* @param {String} tagName Name of the tag to look in for the codename
46+
* @return {String} The codename if found, otherwise null/undefined
47+
*/
48+
var getCodeName = function(tagName) {
49+
var tagMessage = shell.exec('git cat-file -p '+ tagName +' | grep "codename"', {silent:true}).output;
50+
var codeName = tagMessage && tagMessage.match(/codename\((.*)\)/)[1];
51+
if (!codeName) {
52+
throw new Error("Could not extract release code name. The message of tag "+tagName+
53+
" must match '*codename(some release name)*'");
54+
}
55+
return codeName;
56+
};
57+
58+
59+
/**
60+
* Compute a build segment for the version, from the Jenkins build number and current commit SHA
61+
* @return {String} The build segment of the version
62+
*/
63+
function getBuild() {
64+
var hash = shell.exec('git rev-parse --short HEAD', {silent: true}).output.replace('\n', '');
65+
return 'sha.'+hash;
66+
}
67+
68+
69+
/**
70+
* If the current commit is tagged as a version get that version
71+
* @return {SemVer} The version or null
72+
*/
73+
var getTaggedVersion = function() {
74+
var gitTagResult = shell.exec('git describe --exact-match', {silent:true});
75+
76+
if ( gitTagResult.code === 0 ) {
77+
var tag = gitTagResult.output;
78+
var version = semver.parse(tag);
79+
if ( version ) {
80+
if ( version.satisfies(currentPackage.branchVersion) ) {
81+
version.codeName = getCodeName(tag);
82+
}
83+
version.full = version.version + '+' + version.build;
84+
return version;
85+
}
86+
}
87+
};
88+
89+
/**
90+
* Stable versions have an even minor version and have no prerelease
91+
* @param {SemVer} version The version to test
92+
* @return {Boolean} True if the version is stable
93+
*/
94+
var isStable = function(version) {
95+
return semver.satisfies(version, '1.0 || 1.2') && version.prerelease.length === 0;
96+
};
97+
98+
/**
99+
* Get a collection of all the previous versions sorted by semantic version
100+
* @return {Array.<SemVer>} The collection of previous versions
101+
*/
102+
var getPreviousVersions = function() {
103+
var tagResults = shell.exec('git tag', {silent: true});
104+
if ( tagResults.code === 0 ) {
105+
return _(tagResults.output.trim().split('\n'))
106+
.map(function(tag) {
107+
var version = semver.parse(tag);
108+
return version;
109+
})
110+
.filter()
111+
.map(function(version) {
112+
version.isStable = isStable(version);
113+
114+
version.docsUrl = 'http://code.angularjs.org/' + version.version + '/docs';
115+
// Versions before 1.0.2 had a different docs folder name
116+
if ( version.major < 1 || (version.major === 1 && version.minor === 0 && version.dot < 2 ) ) {
117+
version.docsUrl += '-' + version.version;
118+
}
119+
return version;
120+
})
121+
.sort(semver.compare)
122+
.value();
123+
}
124+
};
125+
126+
127+
/**
128+
* Get the unstable snapshot version
129+
* @return {SemVer} The snapshot version
130+
*/
131+
var getSnapshotVersion = function() {
132+
133+
version = _(previousVersions)
134+
.filter(function(tag) {
135+
return semver.satisfies(tag, currentPackage.branchVersion);
136+
})
137+
.last();
138+
139+
// We need to clone to ensure that we are not modifying another version
140+
version = semver(version.raw);
141+
142+
var jenkinsBuild = process.env.TRAVIS_BUILD_NUMBER || process.env.BUILD_NUMBER;
143+
version.prerelease = jenkinsBuild ? ['build', jenkinsBuild] : ['local'];
144+
version.build = getBuild();
145+
version.codeName = 'snapshot';
146+
version.isSnapshot = true;
147+
version.format();
148+
version.full = version.version + '+' + version.build;
149+
150+
return version;
151+
};
152+
153+
154+
exports.currentPackage = currentPackage = getPackage();
155+
exports.previousVersions = previousVersions = getPreviousVersions();
156+
exports.currentVersion = getTaggedVersion() || getSnapshotVersion();
157+
exports.gitRepoInfo = getGitRepoInfo();

0 commit comments

Comments
 (0)