@verdnatura/myt 1.5.19 → 1.5.21

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.
Files changed (69) hide show
  1. package/.dockerignore +2 -2
  2. package/LICENSE +17 -17
  3. package/README.md +284 -278
  4. package/assets/db.ini +5 -5
  5. package/assets/myt.default.yml +28 -11
  6. package/assets/structure.sql +24 -24
  7. package/cli.js +4 -4
  8. package/exporters/event.ejs +18 -18
  9. package/exporters/event.js +31 -31
  10. package/exporters/event.sql +19 -19
  11. package/exporters/function.ejs +17 -17
  12. package/exporters/function.js +27 -27
  13. package/exporters/function.sql +16 -16
  14. package/exporters/procedure.ejs +11 -11
  15. package/exporters/procedure.js +23 -23
  16. package/exporters/procedure.sql +14 -14
  17. package/exporters/trigger.ejs +4 -4
  18. package/exporters/trigger.js +10 -10
  19. package/exporters/trigger.sql +13 -13
  20. package/exporters/view.ejs +7 -7
  21. package/exporters/view.js +29 -29
  22. package/exporters/view.sql +12 -12
  23. package/helpers/local-fixtures.js +79 -0
  24. package/lib/command.js +19 -13
  25. package/lib/conn.js +141 -141
  26. package/lib/docker.js +133 -133
  27. package/lib/dumper.js +104 -83
  28. package/lib/exporter-engine.js +112 -112
  29. package/lib/exporter.js +86 -86
  30. package/lib/repo.js +29 -29
  31. package/lib/server.js +71 -71
  32. package/lib/util.js +7 -7
  33. package/myt-clean.js +58 -58
  34. package/myt-create.js +74 -74
  35. package/myt-dump.js +134 -75
  36. package/myt-fixtures.js +28 -29
  37. package/myt-init.js +36 -36
  38. package/myt-pull.js +183 -183
  39. package/myt-push.js +575 -568
  40. package/myt-run.js +190 -177
  41. package/myt-start.js +54 -54
  42. package/myt-version.js +218 -218
  43. package/myt.js +378 -361
  44. package/package.json +41 -41
  45. package/server/Dockerfile.base +1 -1
  46. package/server/Dockerfile.client +14 -14
  47. package/server/Dockerfile.dump +13 -16
  48. package/server/Dockerfile.server +25 -25
  49. package/server/docker-dump.sh +4 -4
  50. package/server/docker-fixtures.sh +5 -4
  51. package/server/docker-import.sh +10 -6
  52. package/server/docker-init.sh +23 -20
  53. package/server/docker-start.sh +10 -10
  54. package/server/docker.cnf +9 -9
  55. package/template/dump/Dockerfile.base +1 -1
  56. package/template/dump/dump.after.sql +1 -0
  57. package/template/dump/dump.before.sql +1 -0
  58. package/template/dump/fixtures.after.sql +1 -0
  59. package/template/dump/fixtures.before.sql +1 -0
  60. package/template/myt.config.yml +11 -11
  61. package/template/package.json +13 -13
  62. package/template/remotes/docker.ini +4 -4
  63. package/template/remotes/local.ini +5 -5
  64. package/template/routines/README.md +1 -1
  65. package/template/versions/00001-firstVersion/00-firstScript.sql +1 -1
  66. package/template/versions/README.md +1 -1
  67. package/template/dump/afterDump.sql +0 -1
  68. package/template/dump/beforeDump.sql +0 -1
  69. package/template/dump/fixtures.sql +0 -1
package/lib/dumper.js CHANGED
@@ -1,83 +1,104 @@
1
- const docker = require('./docker');
2
- const fs = require('fs-extra');
3
- const path = require('path');
4
- const SqlString = require('sqlstring');
5
-
6
- module.exports = class Dumper {
7
- constructor(opts) {
8
- this.opts = opts;
9
- }
10
-
11
- async init(dumpFile) {
12
- const dumpDir = this.opts.dumpDir;
13
- if (!await fs.pathExists(dumpDir))
14
- await fs.mkdir(dumpDir);
15
-
16
- const dumpPath = path.join(dumpDir, dumpFile);
17
-
18
- // FIXME: If it's called after docker.build() statement it creates an
19
- // "invalid" WriteStream
20
- const dumpStream = await fs.createWriteStream(dumpPath);
21
-
22
- const buidDir = path.join(__dirname, '..',)
23
- await docker.build(buidDir, {
24
- tag: 'myt/client',
25
- file: path.join(buidDir, 'server', 'Dockerfile.client')
26
- }, this.opts.debug);
27
-
28
- this.dumpStream = dumpStream;
29
- }
30
-
31
- async use(schema) {
32
- await this.dumpStream.write(
33
- `USE ${SqlString.escapeId(schema, true)};\n`,
34
- 'utf8'
35
- );
36
- }
37
-
38
- async dumpFixtures(tables, replace, args) {
39
- const fixturesArgs = [
40
- '--no-create-info',
41
- '--skip-triggers',
42
- '--skip-extended-insert',
43
- '--skip-disable-keys',
44
- '--skip-add-locks',
45
- '--skip-set-charset',
46
- '--skip-comments',
47
- '--skip-tz-utc'
48
- ].concat(args);
49
-
50
- if (replace)
51
- fixturesArgs.push('--replace');
52
-
53
- for (const schema in tables) {
54
- await this.use(schema);
55
- const args = fixturesArgs.concat([schema], tables[schema]);
56
- await this.runDump('mysqldump', args, this.dumpStream);
57
- }
58
- }
59
-
60
- async runDump(command, args) {
61
- const iniPath = path.join(this.opts.subdir || '', 'remotes', this.opts.iniFile);
62
- const myArgs = [
63
- `--defaults-file=${iniPath}`
64
- ];
65
- const execOptions = {
66
- stdio: [
67
- process.stdin,
68
- this.dumpStream,
69
- process.stderr
70
- ]
71
- };
72
- const commandArgs = [command].concat(myArgs, args);
73
- await docker.run('myt/client', commandArgs, {
74
- addHost: 'host.docker.internal:host-gateway',
75
- volume: `${this.opts.mytDir}:/workspace`,
76
- rm: true
77
- }, execOptions);
78
- }
79
-
80
- async end() {
81
- await this.dumpStream.end();
82
- }
83
- }
1
+ const docker = require('./docker');
2
+ const fs = require('fs-extra');
3
+ const path = require('path');
4
+ const SqlString = require('sqlstring');
5
+
6
+ module.exports = class Dumper {
7
+ constructor(opts) {
8
+ this.opts = opts;
9
+ }
10
+
11
+ async init(dumpDir, dumpFile) {
12
+ if (!await fs.pathExists(dumpDir))
13
+ await fs.mkdir(dumpDir, {recursive: true});
14
+
15
+ const dumpPath = path.join(dumpDir, `${dumpFile}.sql`);
16
+
17
+ // FIXME: If it's called after docker.build() statement it creates an
18
+ // "invalid" WriteStream
19
+ const dumpStream = await fs.createWriteStream(dumpPath);
20
+
21
+ const buidDir = path.join(__dirname, '..',)
22
+ await docker.build(buidDir, {
23
+ tag: 'myt/client',
24
+ file: path.join(buidDir, 'server', 'Dockerfile.client')
25
+ }, this.opts.debug);
26
+
27
+ this.dumpStream = dumpStream;
28
+ }
29
+
30
+ async end() {
31
+ await this.dumpStream.end();
32
+ }
33
+
34
+ async use(schema) {
35
+ await this.dumpStream.write(
36
+ `USE ${SqlString.escapeId(schema, true)};\n`,
37
+ 'utf8'
38
+ );
39
+ }
40
+
41
+ async dumpFixtures(tables, replace, args) {
42
+ let fixturesArgs = [
43
+ '--no-create-info',
44
+ '--skip-triggers',
45
+ '--skip-extended-insert',
46
+ '--skip-disable-keys',
47
+ '--skip-add-locks',
48
+ '--skip-set-charset',
49
+ '--skip-comments',
50
+ '--skip-tz-utc'
51
+ ]
52
+ if (args)
53
+ fixturesArgs = fixturesArgs.concat(args);
54
+ if (replace)
55
+ fixturesArgs.push('--replace');
56
+
57
+ for (const schema in tables) {
58
+ const args = fixturesArgs.concat([schema], tables[schema]);
59
+ await this.use(schema);
60
+ await this.runDump('mysqldump', args);
61
+ }
62
+ }
63
+
64
+ async dumpPrivileges(tables, args, where) {
65
+ let privArgs = [
66
+ '--no-create-info',
67
+ '--skip-triggers',
68
+ '--insert-ignore',
69
+ '--skip-extended-insert',
70
+ '--skip-add-locks',
71
+ '--skip-set-charset',
72
+ '--skip-comments',
73
+ '--skip-tz-utc'
74
+ ];
75
+ if (args)
76
+ privArgs = privArgs.concat(args);
77
+ if (where)
78
+ privArgs.push('--where', where);
79
+ args = privArgs.concat(['mysql'], tables);
80
+
81
+ await this.use('mysql');
82
+ await this.runDump('mysqldump', args);
83
+ }
84
+
85
+ async runDump(command, args) {
86
+ const iniPath = path.join(this.opts.subdir || '', 'remotes', this.opts.iniFile);
87
+ const myArgs = [
88
+ `--defaults-file=${iniPath}`
89
+ ];
90
+ const execOptions = {
91
+ stdio: [
92
+ process.stdin,
93
+ this.dumpStream,
94
+ process.stderr
95
+ ]
96
+ };
97
+ const commandArgs = [command].concat(myArgs, args);
98
+ await docker.run('myt/client', commandArgs, {
99
+ addHost: 'host.docker.internal:host-gateway',
100
+ volume: `${this.opts.mytDir}:/workspace`,
101
+ rm: true
102
+ }, execOptions);
103
+ }
104
+ }
@@ -1,112 +1,112 @@
1
- const shajs = require('sha.js');
2
- const fs = require('fs-extra');
3
- const Exporter = require('./exporter');
4
-
5
- module.exports = class ExporterEngine {
6
- constructor(conn, opts) {
7
- this.conn = conn;
8
- this.opts = opts;
9
- this.pullFile = `${opts.mytDir}/.pullinfo.json`;
10
- this.exporters = [];
11
- this.exporterMap = {};
12
- }
13
-
14
- async init () {
15
- if (await fs.pathExists(this.pullFile)) {
16
- this.pullInfo = JSON.parse(await fs.readFile(this.pullFile, 'utf8'));
17
- const lastPull = this.pullInfo.lastPull;
18
- if (lastPull)
19
- this.pullInfo.lastPull = new Date(lastPull);
20
- } else
21
- this.pullInfo = {
22
- lastPull: null,
23
- shaSums: {}
24
- };
25
-
26
- this.shaSums = this.pullInfo.shaSums;
27
- this.lastPull = this.pullInfo.lastPull;
28
- this.infoChanged = false;
29
-
30
- const types = [
31
- 'function',
32
- 'procedure',
33
- 'view',
34
- 'trigger',
35
- 'event'
36
- ];
37
-
38
- for (const type of types) {
39
- const exporter = new Exporter(type, this.opts.replace);
40
- await exporter.init();
41
-
42
- this.exporters.push(exporter);
43
- this.exporterMap[type] = exporter;
44
- }
45
- }
46
-
47
- async fetchRoutine(type, schema, name) {
48
- const exporter = this.exporterMap[type];
49
- const [row] = await exporter.query(this.conn, schema, name);
50
- return row && exporter.format(row);
51
- }
52
-
53
- async fetchShaSum(type, schema, name) {
54
- const sql = await this.fetchRoutine(type, schema, name);
55
- this.setShaSum(type, schema, name, this.shaSum(sql));
56
- }
57
-
58
- shaSum(sql) {
59
- if (!sql) return null;
60
- return shajs('sha256')
61
- .update(JSON.stringify(sql))
62
- .digest('hex');
63
- }
64
-
65
- getShaSum(type, schema, name) {
66
- try {
67
- return this.shaSums[schema][type][name];
68
- } catch (e) {};
69
-
70
- return null;
71
- }
72
-
73
- setShaSum(type, schema, name, shaSum) {
74
- if (!shaSum) {
75
- this.deleteShaSum(type, schema, name);
76
- return;
77
- }
78
-
79
- const shaSums = this.shaSums;
80
- if (!shaSums[schema])
81
- shaSums[schema] = {};
82
- if (!shaSums[schema][type])
83
- shaSums[schema][type] = {};
84
- shaSums[schema][type][name] = shaSum;
85
- this.infoChanged = true;
86
- }
87
-
88
- deleteShaSum(type, schema, name) {
89
- try {
90
- delete this.shaSums[schema][type][name];
91
- this.infoChanged = true;
92
- } catch (e) {};
93
- }
94
-
95
- deleteSchemaSums(schema) {
96
- delete this.shaSums[schema];
97
- this.infoChanged = true;
98
- }
99
-
100
- async refreshPullDate() {
101
- const [[row]] = await this.conn.query(`SELECT NOW() now`);
102
- this.pullInfo.lastPull = row.now;
103
- this.infoChanged = true;
104
- }
105
-
106
- async saveInfo() {
107
- if (!this.infoChanged) return;
108
- await fs.writeFile(this.pullFile,
109
- JSON.stringify(this.pullInfo, null, ' '));
110
- this.infoChanged = false;
111
- }
112
- }
1
+ const shajs = require('sha.js');
2
+ const fs = require('fs-extra');
3
+ const Exporter = require('./exporter');
4
+
5
+ module.exports = class ExporterEngine {
6
+ constructor(conn, opts) {
7
+ this.conn = conn;
8
+ this.opts = opts;
9
+ this.pullFile = `${opts.mytDir}/.pullinfo.json`;
10
+ this.exporters = [];
11
+ this.exporterMap = {};
12
+ }
13
+
14
+ async init () {
15
+ if (await fs.pathExists(this.pullFile)) {
16
+ this.pullInfo = JSON.parse(await fs.readFile(this.pullFile, 'utf8'));
17
+ const lastPull = this.pullInfo.lastPull;
18
+ if (lastPull)
19
+ this.pullInfo.lastPull = new Date(lastPull);
20
+ } else
21
+ this.pullInfo = {
22
+ lastPull: null,
23
+ shaSums: {}
24
+ };
25
+
26
+ this.shaSums = this.pullInfo.shaSums;
27
+ this.lastPull = this.pullInfo.lastPull;
28
+ this.infoChanged = false;
29
+
30
+ const types = [
31
+ 'function',
32
+ 'procedure',
33
+ 'view',
34
+ 'trigger',
35
+ 'event'
36
+ ];
37
+
38
+ for (const type of types) {
39
+ const exporter = new Exporter(type, this.opts.replace);
40
+ await exporter.init();
41
+
42
+ this.exporters.push(exporter);
43
+ this.exporterMap[type] = exporter;
44
+ }
45
+ }
46
+
47
+ async fetchRoutine(type, schema, name) {
48
+ const exporter = this.exporterMap[type];
49
+ const [row] = await exporter.query(this.conn, schema, name);
50
+ return row && exporter.format(row);
51
+ }
52
+
53
+ async fetchShaSum(type, schema, name) {
54
+ const sql = await this.fetchRoutine(type, schema, name);
55
+ this.setShaSum(type, schema, name, this.shaSum(sql));
56
+ }
57
+
58
+ shaSum(sql) {
59
+ if (!sql) return null;
60
+ return shajs('sha256')
61
+ .update(JSON.stringify(sql))
62
+ .digest('hex');
63
+ }
64
+
65
+ getShaSum(type, schema, name) {
66
+ try {
67
+ return this.shaSums[schema][type][name];
68
+ } catch (e) {};
69
+
70
+ return null;
71
+ }
72
+
73
+ setShaSum(type, schema, name, shaSum) {
74
+ if (!shaSum) {
75
+ this.deleteShaSum(type, schema, name);
76
+ return;
77
+ }
78
+
79
+ const shaSums = this.shaSums;
80
+ if (!shaSums[schema])
81
+ shaSums[schema] = {};
82
+ if (!shaSums[schema][type])
83
+ shaSums[schema][type] = {};
84
+ shaSums[schema][type][name] = shaSum;
85
+ this.infoChanged = true;
86
+ }
87
+
88
+ deleteShaSum(type, schema, name) {
89
+ try {
90
+ delete this.shaSums[schema][type][name];
91
+ this.infoChanged = true;
92
+ } catch (e) {};
93
+ }
94
+
95
+ deleteSchemaSums(schema) {
96
+ delete this.shaSums[schema];
97
+ this.infoChanged = true;
98
+ }
99
+
100
+ async refreshPullDate() {
101
+ const [[row]] = await this.conn.query(`SELECT NOW() now`);
102
+ this.pullInfo.lastPull = row.now;
103
+ this.infoChanged = true;
104
+ }
105
+
106
+ async saveInfo() {
107
+ if (!this.infoChanged) return;
108
+ await fs.writeFile(this.pullFile,
109
+ JSON.stringify(this.pullInfo, null, ' '));
110
+ this.infoChanged = false;
111
+ }
112
+ }
package/lib/exporter.js CHANGED
@@ -1,86 +1,86 @@
1
- const ejs = require('ejs');
2
- const fs = require('fs-extra');
3
- const SqlString = require('sqlstring');
4
-
5
- module.exports = class Exporter {
6
- constructor(objectType, replace) {
7
- Object.assign(this, {
8
- objectType,
9
- replace
10
- });
11
- }
12
-
13
- async init() {
14
- const templateDir = `${__dirname}/../exporters/${this.objectType}`;
15
- this.sql = await fs.readFile(`${templateDir}.sql`, 'utf8');
16
-
17
- const templateFile = await fs.readFile(`${templateDir}.ejs`, 'utf8');
18
- this.template = ejs.compile(templateFile);
19
- this.attrs = require(`${templateDir}.js`);
20
- }
21
-
22
- async query(conn, schema, name) {
23
- const ops = [];
24
- function addOp(col, value) {
25
- ops.push(conn.format('?? = ?', [col, value]));
26
- }
27
- if (schema)
28
- addOp(this.attrs.schemaCol, schema);
29
- if (name)
30
- addOp(this.attrs.nameCol, name);
31
-
32
- const filter = {
33
- toSqlString() {
34
- return ops.join(' AND ');
35
- }
36
- }
37
-
38
- const [res] = await conn.query(this.sql, [filter]);
39
- return res;
40
- }
41
-
42
- format(params) {
43
- const {attrs} = this;
44
- params = Object.assign({}, attrs.defaults, params)
45
- const data = {params};
46
-
47
- if (attrs.formatter)
48
- attrs.formatter(params);
49
-
50
- if (attrs.escapeCols)
51
- for (const escapeCol of attrs.escapeCols) {
52
- if (params[escapeCol])
53
- params[escapeCol] = SqlString.escape(params[escapeCol])
54
- }
55
-
56
- const split = params.definer.split('@');
57
- data.definer =
58
- SqlString.escapeId(split[0], true) + '@' +
59
- SqlString.escapeId(split[1], true);
60
-
61
- data.name =
62
- SqlString.escapeId(params.schema, true) + '.' +
63
- SqlString.escapeId(params.name, true);
64
-
65
- const objectType = this.objectType.toUpperCase();
66
- const delimiter = '$$';
67
- const replace = `CREATE OR REPLACE`;
68
-
69
- let create;
70
- if (this.replace) {
71
- create = `DELIMITER ${delimiter}\n${replace}`
72
- } else {
73
- create =
74
- `DROP ${objectType} IF EXISTS ${data.name};\n`
75
- +`DELIMITER ${delimiter}\n`
76
- +`CREATE`;
77
- }
78
-
79
- data.createOrReplace = `${replace} DEFINER=${data.definer}`
80
- data.begin = `${create} DEFINER=${data.definer}`;
81
- data.typeAndName = `${objectType} ${data.name}`;
82
- data.end = `${delimiter}\nDELIMITER ;`;
83
-
84
- return this.template(data);
85
- }
86
- }
1
+ const ejs = require('ejs');
2
+ const fs = require('fs-extra');
3
+ const SqlString = require('sqlstring');
4
+
5
+ module.exports = class Exporter {
6
+ constructor(objectType, replace) {
7
+ Object.assign(this, {
8
+ objectType,
9
+ replace
10
+ });
11
+ }
12
+
13
+ async init() {
14
+ const templateDir = `${__dirname}/../exporters/${this.objectType}`;
15
+ this.sql = await fs.readFile(`${templateDir}.sql`, 'utf8');
16
+
17
+ const templateFile = await fs.readFile(`${templateDir}.ejs`, 'utf8');
18
+ this.template = ejs.compile(templateFile);
19
+ this.attrs = require(`${templateDir}.js`);
20
+ }
21
+
22
+ async query(conn, schema, name) {
23
+ const ops = [];
24
+ function addOp(col, value) {
25
+ ops.push(conn.format('?? = ?', [col, value]));
26
+ }
27
+ if (schema)
28
+ addOp(this.attrs.schemaCol, schema);
29
+ if (name)
30
+ addOp(this.attrs.nameCol, name);
31
+
32
+ const filter = {
33
+ toSqlString() {
34
+ return ops.join(' AND ');
35
+ }
36
+ }
37
+
38
+ const [res] = await conn.query(this.sql, [filter]);
39
+ return res;
40
+ }
41
+
42
+ format(params) {
43
+ const {attrs} = this;
44
+ params = Object.assign({}, attrs.defaults, params)
45
+ const data = {params};
46
+
47
+ if (attrs.formatter)
48
+ attrs.formatter(params);
49
+
50
+ if (attrs.escapeCols)
51
+ for (const escapeCol of attrs.escapeCols) {
52
+ if (params[escapeCol])
53
+ params[escapeCol] = SqlString.escape(params[escapeCol])
54
+ }
55
+
56
+ const split = params.definer.split('@');
57
+ data.definer =
58
+ SqlString.escapeId(split[0], true) + '@' +
59
+ SqlString.escapeId(split[1], true);
60
+
61
+ data.name =
62
+ SqlString.escapeId(params.schema, true) + '.' +
63
+ SqlString.escapeId(params.name, true);
64
+
65
+ const objectType = this.objectType.toUpperCase();
66
+ const delimiter = '$$';
67
+ const replace = `CREATE OR REPLACE`;
68
+
69
+ let create;
70
+ if (this.replace) {
71
+ create = `DELIMITER ${delimiter}\n${replace}`
72
+ } else {
73
+ create =
74
+ `DROP ${objectType} IF EXISTS ${data.name};\n`
75
+ +`DELIMITER ${delimiter}\n`
76
+ +`CREATE`;
77
+ }
78
+
79
+ data.createOrReplace = `${replace} DEFINER=${data.definer}`
80
+ data.begin = `${create} DEFINER=${data.definer}`;
81
+ data.typeAndName = `${objectType} ${data.name}`;
82
+ data.end = `${delimiter}\nDELIMITER ;`;
83
+
84
+ return this.template(data);
85
+ }
86
+ }
package/lib/repo.js CHANGED
@@ -1,29 +1,29 @@
1
- const nodegit = require('nodegit');
2
-
3
- async function getStaged(repo) {
4
- const head = await repo.getHeadCommit();
5
-
6
- try {
7
- const emptyTree = '4b825dc642cb6eb9a060e54bf8d69288fbee4904';
8
- const headTree = await (head
9
- ? head.getTree()
10
- : nodegit.Tree.lookup(repo, emptyTree)
11
- );
12
- return await nodegit.Diff.treeToIndex(repo, headTree, null);
13
- } catch (err) {
14
- console.warn('Cannot fetch staged changes:', err.message);
15
- }
16
- }
17
-
18
- async function getUnstaged(repo) {
19
- const Diff = nodegit.Diff;
20
- return await Diff.indexToWorkdir(repo, null, {
21
- flags: Diff.OPTION.SHOW_UNTRACKED_CONTENT
22
- | Diff.OPTION.RECURSE_UNTRACKED_DIRS
23
- });
24
- }
25
-
26
- module.exports = {
27
- getStaged,
28
- getUnstaged
29
- };
1
+ const nodegit = require('nodegit');
2
+
3
+ async function getStaged(repo) {
4
+ const head = await repo.getHeadCommit();
5
+
6
+ try {
7
+ const emptyTree = '4b825dc642cb6eb9a060e54bf8d69288fbee4904';
8
+ const headTree = await (head
9
+ ? head.getTree()
10
+ : nodegit.Tree.lookup(repo, emptyTree)
11
+ );
12
+ return await nodegit.Diff.treeToIndex(repo, headTree, null);
13
+ } catch (err) {
14
+ console.warn('Cannot fetch staged changes:', err.message);
15
+ }
16
+ }
17
+
18
+ async function getUnstaged(repo) {
19
+ const Diff = nodegit.Diff;
20
+ return await Diff.indexToWorkdir(repo, null, {
21
+ flags: Diff.OPTION.SHOW_UNTRACKED_CONTENT
22
+ | Diff.OPTION.RECURSE_UNTRACKED_DIRS
23
+ });
24
+ }
25
+
26
+ module.exports = {
27
+ getStaged,
28
+ getUnstaged
29
+ };