@tangelo/tangelo-configuration-toolkit 1.10.3 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -5,10 +5,10 @@ String.prototype.toFws = function(){
5
5
  };
6
6
 
7
7
 
8
- const findUp = require('find-up');
9
- const fs = require('fs-extra');
10
- const {getPath} = require('global-modules-path');
11
- const path = require('path');
8
+ const {execSync} = require('child_process');
9
+ const findUp = require('find-up');
10
+ const fs = require('fs-extra');
11
+ const path = require('path');
12
12
 
13
13
  const execGitCommand = require('./src/lib/exec-git-command');
14
14
 
@@ -57,12 +57,17 @@ _paths.repoconfig = path.join(_paths.repo, appname+'-repoconfig.json');
57
57
  _paths.apply = process.cwd().replace(_paths.repo, '').substr(1);
58
58
 
59
59
 
60
- global._appdata = fs.readJsonSync(_paths.appdata, {throws: false}) || {};
60
+ global._appdata = fs.readJsonSync(_paths.appdata, {throws: false}) || {};
61
+ _appdata._update = (data) => Object.assign(_appdata, data, {_changed: true});
62
+ if (!_appdata.npmPath) {
63
+ _appdata._update({npmPath: execSync('npm config get prefix', {encoding: 'UTF-8'}).replace(/\s$/, '')});
64
+ }
65
+
61
66
  global._packages = {
62
67
  TCT: {name: '@tangelo/tangelo-configuration-toolkit', version: require('./package.json')?.version},
63
68
  FDT: {name: '@fontoxml/fontoxml-development-tools'}
64
69
  }
65
- _packages.FDT.version = fs.readJsonSync(`${getPath(_packages.FDT.name)}/package.json`, {throws: false})?.version;
70
+ _packages.FDT.version = fs.readJsonSync(path.join(_appdata.npmPath, 'node_modules', _packages.FDT.name, 'package.json'), {throws: false})?.version;
66
71
 
67
72
  try { global._appconfig = _paths.appconfig && fs.readJsonSync(_paths.appconfig) || {}; }
68
73
  catch({message}) { _error('Error in '+message); }
@@ -71,29 +76,27 @@ _appconfig.sharedConfigPath = path.resolve(_paths.appconfig || '', '..', _appcon
71
76
  _appconfig.shared = fs.readJsonSync(_appconfig.sharedConfigPath, {throws: false}) || {};
72
77
 
73
78
 
74
- global._commit = {
75
- branch: execGitCommand('rev-parse --abbrev-ref HEAD', _paths.repo),
76
- hash: execGitCommand('rev-parse HEAD', _paths.repo),
77
- date: execGitCommand('log -1 --format=%cd --date=iso-strict', _paths.repo)
78
- };
79
- _commit.lastDateRemote = execGitCommand('log -1 --format=%cd --date=iso-strict origin/'+_commit.branch,_paths.repo);
80
-
81
- global._tdiCommit = {
82
- hash: execGitCommand('rev-parse HEAD', path.join(_paths.repo, _paths.tdi)),
83
- after (commitHash) {
84
- return execGitCommand(`merge-base --is-ancestor ${commitHash} ${this.hash}`, path.join(_paths.repo, _paths.tdi), 0);
85
- },
86
- fontoVersions: [ // latest commits first
87
- {commitHash: 'e599766', regex: /^7\.1[45]\./},
88
- {commitHash: '77b8ea9', regex: /^7\.14\./}, // 7.14.x
89
- {commitHash: '8066c44', regex: /^7\.13\./}, // 7.13.x
90
- {commitHash: 'a2b2d4e', regex: /^7\.12\./} // 7.12.x
91
- ],
92
- stopUsingRepoconfigFile: '1f12bff' // release/5.1 10-05-2021
79
+ global._git = {
80
+ user: execGitCommand(`config --get user.email`, _paths.repo),
81
+ commitLocal: execGitCommand(`log -1 --format=%D;%H;%cd --date=iso-strict`, _paths.repo, ['branch', 'hash', 'date']),
82
+ commitLocalTdi: {
83
+ ...execGitCommand(`log -1 --format=%D;%H;%cd --date=short`, path.join(_paths.repo, _paths.tdi),['tags', 'hash', 'date']),
84
+ after (commitHash) {
85
+ return execGitCommand(`merge-base --is-ancestor ${commitHash} ${this.hash}`, path.join(_paths.repo, _paths.tdi), null, 0);
86
+ },
87
+ fontoVersions: [ // latest commits first
88
+ {commitHash: 'e599766', regex: /^7\.1[45]\./},
89
+ {commitHash: '77b8ea9', regex: /^7\.14\./}, // 7.14.x
90
+ {commitHash: '8066c44', regex: /^7\.13\./}, // 7.13.x
91
+ {commitHash: 'a2b2d4e', regex: /^7\.12\./} // 7.12.x
92
+ ],
93
+ stopUsingRepoconfigFile: '1f12bff' // release/5.1 10-05-2021
94
+ }
93
95
  };
96
+ _git.commitRemote = execGitCommand('log -1 --format=%cd --date=iso-strict origin/'+_git.commitLocal.branch, _paths.repo, ['date']);
94
97
 
95
98
 
96
- if (_tdiCommit.after(_tdiCommit.stopUsingRepoconfigFile)) {
99
+ if (_git.commitLocalTdi.after(_git.commitLocalTdi.stopUsingRepoconfigFile)) {
97
100
  global._repoconfig = require('./src/lib/get-repoconfig')();
98
101
  }
99
102
  else {
@@ -111,4 +114,19 @@ global._isPre42 = fs.existsSync(path.join(_paths.repo, _paths.tdi, 'create_new_p
111
114
  global._isPre51 = !fs.existsSync(path.join(_paths.repo, _paths.tdi, 'src')); // folder changed in 5.1 (check new folder because old one could still exist after branch switch)
112
115
 
113
116
 
117
+
118
+ process.on('beforeExit', () => {
119
+ _write(); // print empty line before and after update check
120
+
121
+ require('./src/lib/package-update-check')();
122
+
123
+ if (_appdata._changed) {
124
+ delete _appdata._update;
125
+ delete _appdata._changed;
126
+ fs.writeJsonSync(_paths.appdata, _appdata, {spaces: 2});
127
+ }
128
+
129
+ });
130
+
131
+
114
132
  require('./src/cli.js')();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangelo/tangelo-configuration-toolkit",
3
- "version": "1.10.3",
3
+ "version": "1.11.0",
4
4
  "description": "Tangelo Configuration Toolkit is a command-line toolkit which offers support for developing a Tangelo configuration.",
5
5
  "bin": {
6
6
  "tct": "bin/index.js",
@@ -21,11 +21,11 @@
21
21
  "@babel/preset-env": "^7.16.11",
22
22
  "cli-spinner": "^0.2.10",
23
23
  "compare-versions": "^4.1.1",
24
+ "console-table-printer": "^2.11.1",
24
25
  "del": "^6.0.0",
25
26
  "event-stream": "^4.0.1",
26
27
  "find-up": "^5.0.0",
27
28
  "fs-extra": "^10.0.0",
28
- "global-modules-path": "^2.3.1",
29
29
  "globby": "^6.1.0",
30
30
  "gulp": "^4.0.2",
31
31
  "gulp-babel": "^8.0.0",
package/src/cli.js CHANGED
@@ -1,26 +1,6 @@
1
- const {compare} = require('compare-versions');
2
- const exec = require('util').promisify(require('child_process').exec);
3
- const fs = require('fs-extra');
4
1
  const yargs = require('yargs');
5
2
 
6
3
 
7
- const updateAppdata = (data) => Object.assign(_appdata, data, {_changed: true});
8
-
9
- const checkForPackageUpdate = (package) => (
10
- exec(`npm view -g ${_packages[package].name} version`)
11
- .then(r => {
12
- const versionAvailable = r.stdout.match(/([\d/.]+)/)[1];
13
- if (!_packages[package].version) _warn(`${package} is not installed! Run ` + `npm i -g ${_packages[package].name}`.white);
14
- else if (compare(_packages[package].version, versionAvailable, '<')) {
15
- updateAppdata({[`updateCheck${package}`]: {executed: new Date(), versionAvailable}});
16
- return versionAvailable;
17
- }
18
- else updateAppdata({[`updateCheck${package}`]: {executed: new Date()}});
19
- })
20
- .catch(e => _warn(`Failed checking latest version of ${package}.`))
21
- );
22
-
23
-
24
4
  module.exports = function cli () {
25
5
 
26
6
  _write();
@@ -45,7 +25,7 @@ module.exports = function cli () {
45
25
  init: {alias: 'i', desc: 'Create repository content structure', conflicts: ['p', 's', 'c']},
46
26
  project: {alias: 'p', desc: 'Create project configuration', conflicts: ['i', 's', 'c']},
47
27
  symlinks: {alias: 's', desc: 'Recreate symlinks to TDI', conflicts: ['p', 'i', 'c']},
48
- config: {alias: 'c', desc: 'Create repo-config file', conflicts: ['p', 'i', 's'], hidden: _tdiCommit.after(_tdiCommit.stopUsingRepoconfigFile)},
28
+ config: {alias: 'c', desc: 'Create repo-config file', conflicts: ['p', 'i', 's'], hidden: _git.commitLocalTdi.after(_git.commitLocalTdi.stopUsingRepoconfigFile)},
49
29
  oxygen: {alias: 'x', desc: 'Create or update oXygen project file (.xpr)', conflicts: ['p', 'i', 'c']}
50
30
  },
51
31
  handler: require('./modules/build')
@@ -112,6 +92,15 @@ module.exports = function cli () {
112
92
  remove: {alias: 'r', desc: 'Remove project configuration', conflicts: ['i', 'c', 'g']}
113
93
  },
114
94
  handler: require('./modules/sql')
95
+ }).command({
96
+ command: 'versions',
97
+ aliases: ['v'],
98
+ desc: 'Show version information',
99
+ builder: {
100
+ find: {alias: 'f', desc: `Find all version information [choices: "sort-project"(default),"sort-type"]`},
101
+ server: {alias: 's', desc: 'Pass server name (set in config file)', default: _appconfig.defaultServer}
102
+ },
103
+ handler: require('./modules/version')
115
104
  })
116
105
  .recommendCommands()
117
106
  .option('config', {alias: 'c', desc: 'Show loaded appconfig', global: false})
@@ -143,34 +132,4 @@ module.exports = function cli () {
143
132
 
144
133
  }
145
134
 
146
-
147
- let checkUpdatesDone = false;
148
-
149
- process.on('beforeExit', () => {
150
- _write(); // print empty line before and after update check
151
-
152
- if (!checkUpdatesDone) { // check if updatecheck has ran before because async calls below trigger beforeExit again
153
- checkUpdatesDone = true;
154
-
155
- ['TCT', 'FDT'].forEach(p => {
156
- const updateMsg = (va) => `| Update ${p} to ${va} | ` + `npm i -g ${_packages[p].name}`.white;
157
- const {versionAvailable} = _appdata[`updateCheck${p}`] || {};
158
-
159
- if (new Date() - new Date(_appdata[`updateCheck${p}`]?.executed || 0) > 1000*3600*24*7) { // check every week
160
- checkForPackageUpdate(p).then(r => r && _warn(updateMsg(r)));
161
- }
162
- else if (versionAvailable) {
163
- if (compare(_packages[p].version, versionAvailable, '<')) _warn(updateMsg(versionAvailable));
164
- else updateAppdata({[`updateCheck${p}`]: {executed: new Date()}});
165
- }
166
- });
167
- }
168
-
169
- if (_appdata._changed) {
170
- delete _appdata._changed;
171
- fs.writeJsonSync(_paths.appdata, _appdata, {spaces: 2});
172
- }
173
-
174
- });
175
-
176
135
  }
@@ -1,10 +1,26 @@
1
1
  const {spawnSync} = require('child_process');
2
2
 
3
3
 
4
- module.exports = function execGitCommand(args, path, status) {
4
+ module.exports = function execGitCommand(args, path, returnProperties = [], expectedStatus) {
5
5
 
6
6
  const cmd = spawnSync('git', [args], {cwd: path, shell: true});
7
- const res = status!=undefined ? cmd.status == status : (cmd.stdout||'').toString().trim();
8
- return /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(res) ? new Date(res) : res;
7
+
8
+ if (expectedStatus!=undefined) return cmd.status == expectedStatus;
9
+
10
+ let retObj = (cmd.stdout||'').toString().trim().split(';');
11
+ if (returnProperties[0]) {
12
+ retObj = (
13
+ o = {},
14
+ retObj.forEach((v,i) => {
15
+ o[returnProperties[i]] =
16
+ returnProperties[i] == 'date' ? new Date(v) :
17
+ returnProperties[i] == 'branch' ? v.replace(/HEAD -> ([^,]+).*/, '$1') :
18
+ v
19
+ ;
20
+ }),
21
+ o
22
+ )
23
+ }
24
+ return retObj.length==1 ? retObj[0] : retObj;
9
25
 
10
26
  };
@@ -2,7 +2,7 @@ const fs = require('fs-extra');
2
2
  const globby = require('globby');
3
3
 
4
4
 
5
- module.exports = function getRepoconfig(repoconfigPath) {
5
+ module.exports = function getRepoconfig() {
6
6
 
7
7
  const repoconfig = [];
8
8
 
@@ -0,0 +1,39 @@
1
+ const {compare} = require('compare-versions');
2
+ const exec = require('util').promisify(require('child_process').exec);
3
+
4
+
5
+ const doUpdateCheck = (package) => (
6
+ exec(`npm view -g ${_packages[package].name} version`)
7
+ .then(r => {
8
+ const versionAvailable = r.stdout.match(/([\d/.]+)/)[1];
9
+ if (!_packages[package].version) _warn(`${package} is not installed! Run ` + `npm i -g ${_packages[package].name}`.white);
10
+ else if (compare(_packages[package].version, versionAvailable, '<')) {
11
+ _appdata._update({[`updateCheck${package}`]: {executed: new Date(), versionAvailable}});
12
+ return versionAvailable;
13
+ }
14
+ else _appdata._update({[`updateCheck${package}`]: {executed: new Date()}});
15
+ })
16
+ .catch(e => _warn(`Failed checking latest version of ${package}.`))
17
+ );
18
+
19
+ let checkUpdatesDone = false;
20
+
21
+
22
+ module.exports = function packageUpdateCheck () {
23
+ if (!checkUpdatesDone) { // check if updatecheck has ran before because async calls below trigger beforeExit again
24
+ checkUpdatesDone = true;
25
+
26
+ ['TCT', 'FDT'].forEach(p => {
27
+ const updateMsg = (va) => `| Update ${p} to ${va} | ` + `npm i -g ${_packages[p].name}`.white;
28
+ const {versionAvailable} = _appdata[`updateCheck${p}`] || {};
29
+
30
+ if (new Date() - new Date(_appdata[`updateCheck${p}`]?.executed || 0) > 1000*3600*24*7) { // check every week
31
+ doUpdateCheck(p).then(r => r && _warn(updateMsg(r)));
32
+ }
33
+ else if (versionAvailable) {
34
+ if (compare(_packages[p].version, versionAvailable, '<')) _warn(updateMsg(versionAvailable));
35
+ else _appdata._update({[`updateCheck${p}`]: {executed: new Date()}});
36
+ }
37
+ });
38
+ }
39
+ }
@@ -74,7 +74,7 @@ module.exports = function build (argv) {
74
74
  }
75
75
 
76
76
  if (argv.config) {
77
- if (_tdiCommit.after(_tdiCommit.stopUsingRepoconfigFile)) _error('This option only works for older repo\'s using a repoconfig file.');
77
+ if (_git.commitLocalTdi.after(_git.commitLocalTdi.stopUsingRepoconfigFile)) _error('This option only works for older repo\'s using a repoconfig file.');
78
78
 
79
79
 
80
80
  inquirer
@@ -55,7 +55,7 @@ module.exports = {
55
55
  username: serverConfig.config.username,
56
56
  agent: process.platform=='win32' ? 'pageant' : process.env.SSH_AUTH_SOCK,
57
57
  agentForward: process.platform!='win32',
58
- readyTimeout: 10000,
58
+ readyTimeout: 15000,
59
59
  retries: 1
60
60
  }
61
61
  };
@@ -65,8 +65,8 @@ module.exports = {
65
65
  if (ftpConfig.host && !(ftpConfig.port && ftpConfig.parallel && ftpConfig.username)) _error('Config is incomplete!');
66
66
 
67
67
  this.localTransfer = !ftpConfig.host;
68
- this.envDev = /\.dev\.tangelo\.nl$/.test(ftpConfig.host);
69
68
  this.deliveryPack = serverConfig.mode == 'delivery-pack';
69
+ this.envDev = this.localTransfer && !this.deliveryPack || /\.dev\.tangelo\.nl$/.test(ftpConfig.host);
70
70
 
71
71
  if (this.deliveryPack) {
72
72
  const dateStr = new Date().toISOString().replace(/(.*)T(\d+):(\d+):(\d+).*/g, '$1_$2$3$4');
@@ -129,13 +129,13 @@ module.exports = {
129
129
  }
130
130
  else this.replaceStrings.push(['debugMode>true', 'debugMode>false', '**/xopus/xml/*']);
131
131
 
132
- _info(`Branch: ${_commit.branch}`);
132
+ _info(`Branch: ${_git.commitLocal.branch}`);
133
133
  _info(`Source: ${path.join(process.cwd(), transferPattern)}`);
134
134
  _info(`Server: ${ftpConfig.host ? `${ftpConfig.host}:${ftpConfig.port}` : 'local'}`);
135
135
  _info(`Target: ${this.getRemotePath(transferPattern)}`);
136
136
  _write();
137
137
 
138
- if (_commit.date < _commit.lastDateRemote) {
138
+ if (_git.commitLocal.date < _git.commitRemote.date) {
139
139
  _warn(`You're not deploying from the most recent git commit!\n`)
140
140
  }
141
141
  }
@@ -44,6 +44,7 @@ const remote = {
44
44
  sshI.execCommand(command[0])
45
45
  .then(result => {
46
46
  if (result.stderr) _warn(result.stderr);
47
+ else if (command[1] === '') _write(result.stdout);
47
48
  else _info(command[1] || command[0], true);
48
49
 
49
50
  executing--;
@@ -126,15 +127,19 @@ const transfer = (paths, lrServer) => {
126
127
  const srcset = s.create(paths);
127
128
  const files = [];
128
129
 
130
+ // local git repo must be on latest commit containing fonto changes, and fonto build files must be newer than that commit, unless that commit belongs to the current user
129
131
  const fontoPaths = {outdated: [], uptodate: []};
130
- const removeOutdatedFontoBuild = g_filter(file => { // fonto build files must be newer than the last commit date containing fonto changes
132
+ const removeOutdatedFontoBuild = g_filter(file => {
131
133
  const prPath = 'config\\'+file.relative.replace(/fonto.+$/, '');
132
134
  if (fontoPaths.outdated.includes(prPath)) return false;
133
135
  if (fontoPaths.uptodate.includes(prPath)) return true;
134
136
  if (file.relative.match(/fonto[\\\/]dist/)) {
135
137
  const paths = `${prPath}\\fonto ${prPath}\\schema ${_paths.tdi}`; // only check paths containing fonto sources
136
- const lastFontoCommitDate = execGitCommand(`log -1 --format=%cd --date=iso-strict origin/${_commit.branch} ${paths}`, _paths.repo);
137
- if (fs.statSync(file.relative).mtime < lastFontoCommitDate) {
138
+ const lastFontoCommit = execGitCommand(`log -1 --format=%ae;%cd --date=iso-strict origin/${_git.commitLocal.branch} ${paths}`, _paths.repo, ['author', 'date']);
139
+ if (
140
+ lastFontoCommit.author != _git.user &&
141
+ (lastFontoCommit.date > _git.commitLocal.date || lastFontoCommit.date > fs.statSync(file.relative).mtime)
142
+ ) {
138
143
  fontoPaths.outdated.push(prPath);
139
144
  return false;
140
145
  }
@@ -14,9 +14,9 @@ const allowedFontoVersionRegex = () => {
14
14
  const cfvPath = path.join(_paths.repo, _paths.tdi, 'tct/fonto/compatibleVersions.json');
15
15
  if (fs.pathExistsSync(cfvPath)) return RegExp(fs.readJsonSync(cfvPath).regex);
16
16
 
17
- // old way: a regex for each basecommit is stored in global._tdiCommit
18
- for (const fv of _tdiCommit.fontoVersions) {
19
- if (_tdiCommit.after(fv.commitHash)) return fv.regex;
17
+ // old way: a regex for each basecommit is stored in global._git.commitLocalTdi
18
+ for (const fv of _git.commitLocalTdi.fontoVersions) {
19
+ if (_git.commitLocalTdi.after(fv.commitHash)) return fv.regex;
20
20
  }
21
21
  };
22
22
 
@@ -6,7 +6,7 @@ const path = require('path');
6
6
  module.exports = function migrate (argv) {
7
7
  if (_isPre51) _error('This command only works when using branch release/5.1 and up.');
8
8
 
9
- let filter = path.join(_paths.apply, argv.filter); // Default set filter with filter added to the command argument -f
9
+ let filter = path.join(_paths.apply, argv.filter).toFws(); // Default set filter with filter added to the command argument -f
10
10
 
11
11
  const scripts =
12
12
  globby
@@ -24,10 +24,17 @@ module.exports = function migrate (argv) {
24
24
  value: s
25
25
  }))
26
26
  ;
27
-
27
+
28
+ // Search scriptname set in commandline in scripts and return in cmdlScript if found
29
+ const cmdlScript = Object.values(scripts).filter(s => s.name === `${argv.execute}`)[0];
30
+ if (cmdlScript) {
31
+ _info(`Migration: ${cmdlScript.name}`);
32
+ };
33
+
28
34
  inquirer
29
35
  .prompt([{
30
- message: 'Choose a migration: ', name: 'script', type: 'list', choices: scripts, pageSize: 5, loop: false
36
+ message: 'Choose a migration: ', name: 'script', type: 'list', choices: scripts, pageSize: 5, loop: false,
37
+ when: !(cmdlScript) // Only show choice for migration when no script is set in commandline
31
38
  },{
32
39
  message: 'Choose filter: ', name: 'filter', type: 'list', pageSize: 5, loop: false,
33
40
  choices: [{name: `- All`, value:argv.filter},{name:'- Choose active projects',value:'projects'}],
@@ -41,6 +48,11 @@ module.exports = function migrate (argv) {
41
48
  _write();
42
49
  _info(`Working folder set to: ${_paths.repo}`);
43
50
 
51
+ if (cmdlScript) {
52
+ // Set script to execute to script entered in commandline
53
+ a.script = cmdlScript.value;
54
+ }
55
+
44
56
  if (a.filter === 'projects' && _repoconfig.length > a.projects.length) {
45
57
  // push paths of chosen active documents to projectFolders (only if not all projects are chosen)
46
58
  const projectFolders = [];
@@ -37,7 +37,7 @@ const checkLog = (logFilePath, remove=true) => {
37
37
 
38
38
  module.exports = function sql (argv) {
39
39
 
40
- if ((argv.install || argv.configure) && _commit.date < _commit.lastDateRemote) {
40
+ if ((argv.install || argv.configure) && _git.commitLocal.date < _git.commitRemote.date) {
41
41
  _warn(`You're not deploying from the most recent git commit!\n`)
42
42
  }
43
43
 
@@ -0,0 +1,174 @@
1
+ const {execSync} = require('child_process');
2
+ const fs = require('fs-extra');
3
+ const globby = require('globby');
4
+ const path = require('path');
5
+ const {Table} = require('console-table-printer');
6
+ const execGitCommand = require('../../lib/exec-git-command');
7
+ const c = require('../deploy/config');
8
+ const {remote} = require('../deploy/execute');
9
+
10
+ const getGitInfo = (argv) => {
11
+ // Version info TDI submodule
12
+
13
+ const branchInfo = [];
14
+ const gitSubmoduleInfo = new Table({
15
+ columns: [
16
+ { name: 'property', title: 'TDI - submodule', alignment: 'left'},
17
+ { name: 'value', alignment: 'left'}
18
+ ],
19
+ });
20
+
21
+ // Fetch all
22
+ execGitCommand(`fetch -pf --all`, path.join(_paths.repo, _paths.tdi));
23
+
24
+ // Get branches containing TDI HEAD commit
25
+ const releaseBranches = execGitCommand(`branch --contains ${_git.commitLocalTdi.hash}`, path.join(_paths.repo, _paths.tdi)).match(/release\/[^\s]+/gsm);
26
+ if (releaseBranches) {
27
+ releaseBranches.forEach(b => {
28
+ // Get number of commits behind
29
+ const count = execGitCommand(`rev-list HEAD...origin/${b} --count`, path.join(_paths.repo, _paths.tdi));
30
+ // _info(`debug: [${b}]:${count}`);
31
+ // Push number of commits behind to branchInfo
32
+ branchInfo.push({name:b,commitsBehind:count});
33
+ });
34
+ }
35
+
36
+ // Get the first possible branch; prefer release/5.1 over release/5.2:
37
+ const firstBranch = branchInfo.sort((a, b) => a.name > b.name ? 1 : -1)[0];
38
+
39
+ // Create table rows for TDI submodule info
40
+ gitSubmoduleInfo.addRow({
41
+ property: `Commit date (DD-MM-YYYY)`,
42
+ value: `${_git.commitLocalTdi.date.toLocaleDateString('nl-nl')}`
43
+ });
44
+ if (firstBranch) {
45
+ gitSubmoduleInfo.addRow({
46
+ property: `Branch`,
47
+ value: `${firstBranch.name}`
48
+ });
49
+ gitSubmoduleInfo.addRow({
50
+ property: `Commits behind`,
51
+ value: `${firstBranch.commitsBehind}`
52
+ });
53
+ } else {
54
+ gitSubmoduleInfo.addRow({
55
+ property: `Branch could not be determined`,
56
+ value: ``
57
+ });
58
+ }
59
+
60
+ // Print TDI submodule info
61
+ gitSubmoduleInfo.printTable();
62
+ }
63
+
64
+ const getFileExtractInfo = (argv) => {
65
+ // version info miscellaneous
66
+ const sorting = `${argv.info}`.includes(`sort-type`) ? `type` : `project`;
67
+ const projects = new Set;
68
+ const types = new Set;
69
+ const versionInfoConfigPath = path.join(_paths.repo, _paths.tdi, 'tct/version/versionInfo.js');
70
+ const versionInfo = new Table({
71
+ columns: [
72
+ { name: 'path', alignment: 'left'},
73
+ { name: 'type', alignment: 'left'},
74
+ { name: 'version', alignment: 'left'},
75
+ { name: 'sort'}
76
+ ],
77
+ disabledColumns: ['sort'],
78
+ sort: (a, b) => a.sort.toLowerCase() > b.sort.toLowerCase() ? 1 : -1
79
+ });
80
+
81
+ if (fs.existsSync(versionInfoConfigPath)) {
82
+ const config = require(`${versionInfoConfigPath}`);
83
+
84
+ config.forEach(v => {
85
+ const location = path.join(_paths.repo,v.glob);
86
+
87
+ globby
88
+ .sync(`${location}`)
89
+ .forEach(f => {
90
+ const filePathExtract = f.match(/.*(?<path>(cmscustom|site-stylesheets)\/(?<customer>[^\/]*)\/(?<project>[^\/]*)\/.*)/);
91
+ const path = filePathExtract.groups.path ? filePathExtract.groups.path : '';
92
+ const customer = filePathExtract.groups.customer ? filePathExtract.groups.customer : '';
93
+ const project = filePathExtract.groups.project ? filePathExtract.groups.project : '';
94
+
95
+ const fileContent = fs.readFileSync(f).toString();
96
+ v.extracts.forEach(e => {
97
+ const extract = fileContent.match(e.regex);
98
+ if (extract) {
99
+ projects.add(project); // Store the projects where versioninfo is found
100
+ types.add(e.type); // Store the types for which versioninfo is found
101
+ versionInfo.addRow( // Create row with version information to output
102
+ { path: `${path}`
103
+ , sort: `${sorting==`project` ? project : e.type}_2${sorting==`project` ? e.type : extract.groups.version}` // Output is sorted on project or type: '_2' ensures it is rendered after the empty row and the row with the project name
104
+ , type: `${e.type}`
105
+ , version: `${extract.groups.version}`
106
+ }
107
+ );
108
+ }
109
+ });
110
+ })
111
+ });
112
+
113
+ if (sorting==`project`) {
114
+ /* For projects containing version information */
115
+ projects.forEach(p => {
116
+ /* Add empty row after project */
117
+ versionInfo.addRow(
118
+ { path: ``
119
+ , sort: `${p}_3`
120
+ , type: ``
121
+ , version: ``
122
+ }
123
+ )
124
+ /* Add row with project name */
125
+ versionInfo.addRow(
126
+ { path: `-- ${p}:`
127
+ , sort: `${p}_1`
128
+ , type: ``
129
+ , version: ``
130
+ },
131
+ { color: 'yellow' }
132
+ )
133
+ });
134
+ } else
135
+ if (sorting==`type`) {
136
+ types.forEach(t => {
137
+ /* Add empty row after type */
138
+ versionInfo.addRow(
139
+ { path: ``
140
+ , sort: `${t}_3`
141
+ , type: ``
142
+ , version: ``
143
+ }
144
+ )
145
+ });
146
+ }
147
+ versionInfo.printTable();
148
+ } else {
149
+ _warn(`Version info of miscellaneous items cannot be extracted:\nCannot find required files in TDI submodule. Try updating TDI submodule.`);
150
+ }
151
+ }
152
+
153
+ const getServerInfo = (argv) => {
154
+ // Remote server info
155
+ // common setup
156
+ _write();
157
+ c.setServer(argv.server);
158
+
159
+ if (!c.envDev) {
160
+ _info(`Remote version info for '${c.server.ftpConfig.host}':\n`)
161
+ remote.add('sudo ~root/scripts/version.sh', '').process();
162
+ } else {
163
+ _info(`For development environments no server version information is available. Check rancher / database for this information.\nAdd the --server option with a non-dev environment to see version information for that server.`);
164
+ }
165
+ }
166
+
167
+ module.exports = function version (argv) {
168
+ _info(`Version information of this git repository\n`)
169
+
170
+ getGitInfo(argv);
171
+ getFileExtractInfo(argv);
172
+ getServerInfo(argv);
173
+
174
+ };