Skip to content

Commit 3a0a45a

Browse files
committed
feat: Pull from GitHub instead of npm
- fetch from ICU’s GitHub release instead of npm (ICU v50+) - set env FULL_ICU_PREFER_NPM=1 to prefer npm instead - add .eslint - for ICU 67 and following, fetch from icu4c-___-data-_.zip otherwise fetch from icu4c-src.zip (will only work for little endian) Fixes: #36
1 parent 72ddf0c commit 3a0a45a

File tree

15 files changed

+341
-7
lines changed

15 files changed

+341
-7
lines changed

.eslintrc.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module.exports = {
2+
env: {
3+
commonjs: true,
4+
es6: true,
5+
node: true
6+
},
7+
extends: 'standard',
8+
globals: {
9+
Atomics: 'readonly',
10+
SharedArrayBuffer: 'readonly'
11+
},
12+
parserOptions: {
13+
ecmaVersion: 2018
14+
},
15+
rules: {
16+
}
17+
}

.github/workflows/lint.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: Lint
33
on: [push, pull_request]
44

55
jobs:
6-
build:
6+
lint:
77
runs-on: ubuntu-latest
88
steps:
99
- uses: actions/checkout@v2
@@ -12,3 +12,12 @@ jobs:
1212
node-version: 16
1313
- run: npm i
1414
- run: npm run lint
15+
test:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v2
19+
- uses: actions/setup-node@v1
20+
with:
21+
node-version: 16
22+
- run: npm i
23+
- run: npm t

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ node_modules
22
*.dat
33
npm-debug.log
44
/yarn.lock
5+
package-lock.json
6+
/.nyc_output

.npmignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
node_modules
33
.svn
44
.git
5-
npm-debug.log
5+
npm-debug.log
6+
/test

.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package-lock=false

.travis.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
language: node_js
2+
node_js:
3+
- '8'
4+
- '10'
5+
- '11'
6+
- '12'
7+
script:
8+
- npm install
9+
- npm t
10+
cache:
11+
directories:
12+
- node_modules
13+
- ".nvm"
14+
# this is a comment

install-gh-data.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright (C) 2015-2016 IBM Corporation and Others. All Rights Reserved.
2+
3+
// Install by fetching ICU source tarball
4+
// This will only work for little endian systems, but will work for ancient ICU (back to v50)
5+
6+
const fs = require('fs');
7+
const { URL } = require('url')
8+
const process = require('process')
9+
const myFetch = require('./myFetch')
10+
const yauzl = require('yauzl');
11+
12+
// var isglobal = process.env.npm_config_global === 'true';
13+
14+
module.exports = async function installFromGithub (fullIcu, advice) {
15+
// const icupkg = fullIcu.icupkg
16+
const { icudat, icuend } = fullIcu
17+
if(fs.existsSync(icudat)) {
18+
console.log(` √ ${icudat} (exists)`);
19+
return;
20+
}
21+
22+
// var cmdPath = nodePath = process.env.npm_node_execpath;
23+
24+
// var npmPath = process.env.npm_execpath;
25+
26+
// var args;
27+
// https://github.com/unicode-org/icu/releases/download/release-51-3/icu4c-51_3-src.zip
28+
const _baseUrl = process.env.FULL_ICU_BASEURL || 'https://github.com/unicode-org/icu/releases/'
29+
const baseUrl = new URL(_baseUrl)
30+
const versionsAsHyphen = fullIcu.icuver.replace(/\./g, '-')
31+
const versionsAsUnderscore = fullIcu.icuver.replace(/\./g, '_')
32+
const tag = `release-${versionsAsHyphen}`
33+
const file = `icu4c-${versionsAsUnderscore}-data-bin-${icuend}.zip`
34+
const fullUrl = new URL(`./download/${tag}/${file}`, baseUrl)
35+
console.log(fullUrl.toString())
36+
const [srcZip, tmpd] = await myFetch(fullUrl)
37+
38+
console.log(srcZip, tmpd)
39+
// now, unpack it
40+
41+
console.log(`Looking for ${icudat}`);
42+
return new Promise((resolve, reject) =>
43+
yauzl.open(srcZip, {lazyEntries: true}, (err, zipfile) => {
44+
if (err) return reject(err);
45+
zipfile.readEntry();
46+
zipfile.on("end", () => reject(`Not found in zipfile: ${icudat}`));
47+
zipfile.on("entry", (entry) => {
48+
if (entry.fileName.endsWith('/')) {
49+
zipfile.readEntry();
50+
} else if (entry.fileName.endsWith(icudat) || entry.fileName.endsWith('/' + icudat)) {
51+
console.log('found ' + entry.fileName);
52+
zipfile.openReadStream(entry, (err, readStream) => {
53+
if (err) return reject(err);
54+
// if entry.file
55+
readStream.on("end", () => zipfile.readEntry());
56+
const pipeOut = fs.createWriteStream(icudat);
57+
readStream.pipe(pipeOut);
58+
console.log(` √ ${icudat} (from ICU binary data tarball)`);
59+
return resolve();
60+
});
61+
} else {
62+
zipfile.readEntry(); // get next
63+
}
64+
});
65+
}));
66+
}

install-gh.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright (C) 2015-2016 IBM Corporation and Others. All Rights Reserved.
2+
3+
// Install by fetching ICU source tarball
4+
// This will only work for little endian systems, but will work for ancient ICU (back to v50)
5+
6+
const fs = require('fs');
7+
const { URL } = require('url')
8+
const process = require('process')
9+
const myFetch = require('./myFetch')
10+
const yauzl = require('yauzl');
11+
12+
// var isglobal = process.env.npm_config_global === 'true';
13+
14+
module.exports = async function installFromGithub (fullIcu, advice) {
15+
const {icupkg, icudat, icuend} = fullIcu
16+
17+
if(fs.existsSync(icudat)) {
18+
console.log(` √ ${icudat} (exists)`);
19+
return;
20+
}
21+
22+
if (icuend != 'l') {
23+
// Should not hit this, as versions 67 and prior are already in NPM
24+
console.error('Warning: this method probably will fail, because the ICU source tarball only contains little endian data.');
25+
}
26+
27+
// var cmdPath = nodePath = process.env.npm_node_execpath;
28+
29+
// var npmPath = process.env.npm_execpath;
30+
31+
// var args;
32+
// https://github.com/unicode-org/icu/releases/download/release-51-3/icu4c-51_3-src.zip
33+
const _baseUrl = process.env.FULL_ICU_BASEURL || 'https://github.com/unicode-org/icu/releases/'
34+
const baseUrl = new URL(_baseUrl)
35+
const versionsAsHyphen = fullIcu.icuver.replace(/\./g, '-')
36+
const versionsAsUnderscore = fullIcu.icuver.replace(/\./g, '_')
37+
const tag = `release-${versionsAsHyphen}`
38+
const file = `icu4c-${versionsAsUnderscore}-src.zip`
39+
const fullUrl = new URL(`./download/${tag}/${file}`, baseUrl)
40+
console.log(fullUrl.toString())
41+
const [srcZip, tmpd] = await myFetch(fullUrl)
42+
43+
console.log(srcZip, tmpd)
44+
// now, unpack it
45+
46+
console.log(`Looking for ${icudat}`);
47+
return new Promise((resolve, reject) =>
48+
yauzl.open(srcZip, {lazyEntries: true}, (err, zipfile) => {
49+
if (err) return reject(err);
50+
zipfile.readEntry();
51+
zipfile.on("end", () => reject(`Not found in zipfile: ${icudat}`));
52+
zipfile.on("entry", (entry) => {
53+
if (entry.fileName.endsWith('/')) {
54+
zipfile.readEntry();
55+
} else if(entry.fileName.endsWith('/'+icudat)) {
56+
console.log('found ' + entry.fileName);
57+
zipfile.openReadStream(entry, (err, readStream) => {
58+
if (err) return reject(err);
59+
// if entry.file
60+
readStream.on("end", () => zipfile.readEntry());
61+
const pipeOut = fs.createWriteStream(icudat);
62+
readStream.pipe(pipeOut);
63+
console.log(` √ ${icudat} (from ICU source tarball)`);
64+
return resolve();
65+
});
66+
} else {
67+
zipfile.readEntry(); // get next
68+
}
69+
});
70+
}));
71+
}

myFetch.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright (C) 2015-2016 IBM Corporation and Others. All Rights Reserved.
2+
3+
const os = require('os')
4+
const path = require('path')
5+
const fs = require('fs')
6+
7+
function getFetcher (u) {
8+
if (u.protocol === 'https:') return require('https')
9+
if (u.protocol === 'http:') return require('http')
10+
return null
11+
}
12+
13+
/**
14+
* @param {URL} fullUrl url to fetch
15+
* @returns {Promse<String[]>} filename, tmpdir
16+
*/
17+
function myFetch (fullUrl) {
18+
return new Promise((resolve, reject) => {
19+
const fetcher = getFetcher(fullUrl)
20+
console.log('Fetch:', fullUrl.toString())
21+
if (!fetcher) {
22+
return reject(Error(`Unknown URL protocol ${fullUrl.protocol} in ${fullUrl.toString()}`))
23+
}
24+
25+
fetcher.get(fullUrl, res => {
26+
const length = res.headers['content-length']
27+
if (res.statusCode === 302 && res.headers.location) {
28+
return resolve(myFetch(new URL(res.headers.location)))
29+
} else if (res.statusCode !== 200) {
30+
return reject(Error(`Bad status code ${res.statusCode}`))
31+
}
32+
const tmpd = fs.mkdtempSync(os.tmpdir())
33+
const tmpf = path.join(tmpd, 'icu-download.zip')
34+
let gotSoFar = 0
35+
console.dir(tmpd)
36+
37+
res.on('data', data => {
38+
gotSoFar += data.length
39+
fs.appendFileSync(tmpf, data)
40+
// console.dir(res.headers);
41+
process.stdout.write(`${gotSoFar}/${length}\r`)
42+
// console.log(`chunk: ${data.length}`);
43+
})
44+
res.on('end', () => {
45+
resolve([tmpf, tmpd])
46+
console.log(`${gotSoFar}/${length}\n`)
47+
})
48+
res.on('error', error => {
49+
fs.unlinkSync(tmpf)
50+
fs.rmdirSync(tmpd)
51+
console.error(error)
52+
return reject(error)
53+
})
54+
})
55+
})
56+
}
57+
58+
module.exports = myFetch

package.json

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
"version": "1.3.5-0",
44
"description": "install 'full-icu' data for your current node",
55
"scripts": {
6-
"lint": "standard",
7-
"postinstall": "node postinstall.js"
6+
"lint": "standard && eslint *.js test/*.js",
7+
"postinstall": "node postinstall.js",
8+
"test": "tap test/*.js"
89
},
910
"keywords": [
1011
"icu4c"
@@ -22,7 +23,17 @@
2223
"bugs": {
2324
"url": "https://github.com/unicode-org/full-icu-npm/issues"
2425
},
26+
"dependencies": {
27+
"yauzl": "^2.10.0"
28+
},
2529
"devDependencies": {
26-
"standard": "^16.0.3"
30+
"eslint": "^7.7.0",
31+
"eslint-config-standard": "^16.0.3",
32+
"eslint-plugin-header": "^3.0.0",
33+
"eslint-plugin-import": "^2.24.2",
34+
"eslint-plugin-node": "^11.1.0",
35+
"eslint-plugin-promise": "^4.2.1",
36+
"standard": "^16.0.3",
37+
"tap": "^15.0.10"
2738
}
2839
}

0 commit comments

Comments
 (0)