@jjrawlins/cdk-git-tagger 0.0.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.
@@ -0,0 +1,338 @@
1
+ 'use strict';
2
+
3
+ const fsBinding = process.binding('fs');
4
+ const statsConstructor = fsBinding.statValues
5
+ ? fsBinding.statValues.constructor
6
+ : Float64Array;
7
+ // Nodejs v18.7.0 changed bigint stats type from BigUint64Array to BigInt64Array
8
+ // https://github.com/nodejs/node/pull/43714
9
+ const bigintStatsConstructor = fsBinding.bigintStatValues
10
+ ? fsBinding.bigintStatValues.constructor
11
+ : BigUint64Array;
12
+
13
+ let counter = 0;
14
+
15
+ /**
16
+ * Permissions.
17
+ * @enum {number}
18
+ */
19
+ const permissions = {
20
+ USER_READ: 256, // 0400
21
+ USER_WRITE: 128, // 0200
22
+ USER_EXEC: 64, // 0100
23
+ GROUP_READ: 32, // 0040
24
+ GROUP_WRITE: 16, // 0020
25
+ GROUP_EXEC: 8, // 0010
26
+ OTHER_READ: 4, // 0004
27
+ OTHER_WRITE: 2, // 0002
28
+ OTHER_EXEC: 1, // 0001
29
+ };
30
+
31
+ function getUid() {
32
+ // force 0 on windows.
33
+ return process.getuid ? process.getuid() : 0;
34
+ }
35
+
36
+ function getGid() {
37
+ // force 0 on windows.
38
+ return process.getgid ? process.getgid() : 0;
39
+ }
40
+
41
+ /**
42
+ * A filesystem item.
43
+ * @class
44
+ */
45
+ function Item() {
46
+ const now = Date.now();
47
+
48
+ /**
49
+ * Access time.
50
+ * @type {Date}
51
+ */
52
+ this._atime = new Date(now);
53
+
54
+ /**
55
+ * Change time.
56
+ * @type {Date}
57
+ */
58
+ this._ctime = new Date(now);
59
+
60
+ /**
61
+ * Birth time.
62
+ * @type {Date}
63
+ */
64
+ this._birthtime = new Date(now);
65
+
66
+ /**
67
+ * Modification time.
68
+ * @type {Date}
69
+ */
70
+ this._mtime = new Date(now);
71
+
72
+ /**
73
+ * Permissions.
74
+ */
75
+ this._mode = 438; // 0666
76
+
77
+ /**
78
+ * User id.
79
+ * @type {number}
80
+ */
81
+ this._uid = getUid();
82
+
83
+ /**
84
+ * Group id.
85
+ * @type {number}
86
+ */
87
+ this._gid = getGid();
88
+
89
+ /**
90
+ * Item number.
91
+ * @type {number}
92
+ */
93
+ this._id = ++counter;
94
+
95
+ /**
96
+ * Number of links to this item.
97
+ */
98
+ this.links = 0;
99
+ }
100
+
101
+ /**
102
+ * Add execute if read allowed
103
+ * See notes in index.js -> mapping#addDir
104
+ * @param {number} mode The file mode.
105
+ * @return {number} The modified mode.
106
+ */
107
+ Item.fixWin32Permissions = (mode) =>
108
+ process.platform !== 'win32'
109
+ ? mode
110
+ : mode |
111
+ (mode & permissions.USER_READ && permissions.USER_EXEC) |
112
+ (mode & permissions.GROUP_READ && permissions.GROUP_EXEC) |
113
+ (mode & permissions.OTHER_READ && permissions.OTHER_EXEC);
114
+
115
+ /**
116
+ * Determine if the current user has read permission.
117
+ * @return {boolean} The current user can read.
118
+ */
119
+ Item.prototype.canRead = function () {
120
+ const uid = getUid();
121
+ const gid = getGid();
122
+ let can = false;
123
+ if (process.getuid && uid === 0) {
124
+ can = true;
125
+ } else if (uid === this._uid) {
126
+ can = (permissions.USER_READ & this._mode) === permissions.USER_READ;
127
+ } else if (gid === this._gid) {
128
+ can = (permissions.GROUP_READ & this._mode) === permissions.GROUP_READ;
129
+ } else {
130
+ can = (permissions.OTHER_READ & this._mode) === permissions.OTHER_READ;
131
+ }
132
+ return can;
133
+ };
134
+
135
+ /**
136
+ * Determine if the current user has write permission.
137
+ * @return {boolean} The current user can write.
138
+ */
139
+ Item.prototype.canWrite = function () {
140
+ const uid = getUid();
141
+ const gid = getGid();
142
+ let can = false;
143
+ if (process.getuid && uid === 0) {
144
+ can = true;
145
+ } else if (uid === this._uid) {
146
+ can = (permissions.USER_WRITE & this._mode) === permissions.USER_WRITE;
147
+ } else if (gid === this._gid) {
148
+ can = (permissions.GROUP_WRITE & this._mode) === permissions.GROUP_WRITE;
149
+ } else {
150
+ can = (permissions.OTHER_WRITE & this._mode) === permissions.OTHER_WRITE;
151
+ }
152
+ return can;
153
+ };
154
+
155
+ /**
156
+ * Determine if the current user has execute permission.
157
+ * @return {boolean} The current user can execute.
158
+ */
159
+ Item.prototype.canExecute = function () {
160
+ const uid = getUid();
161
+ const gid = getGid();
162
+ let can = false;
163
+ if (process.getuid && uid === 0) {
164
+ can = true;
165
+ } else if (uid === this._uid) {
166
+ can = (permissions.USER_EXEC & this._mode) === permissions.USER_EXEC;
167
+ } else if (gid === this._gid) {
168
+ can = (permissions.GROUP_EXEC & this._mode) === permissions.GROUP_EXEC;
169
+ } else {
170
+ can = (permissions.OTHER_EXEC & this._mode) === permissions.OTHER_EXEC;
171
+ }
172
+ return can;
173
+ };
174
+
175
+ /**
176
+ * Get access time.
177
+ * @return {Date} Access time.
178
+ */
179
+ Item.prototype.getATime = function () {
180
+ return this._atime;
181
+ };
182
+
183
+ /**
184
+ * Set access time.
185
+ * @param {Date} atime Access time.
186
+ */
187
+ Item.prototype.setATime = function (atime) {
188
+ this._atime = atime;
189
+ };
190
+
191
+ /**
192
+ * Get change time.
193
+ * @return {Date} Change time.
194
+ */
195
+ Item.prototype.getCTime = function () {
196
+ return this._ctime;
197
+ };
198
+
199
+ /**
200
+ * Set change time.
201
+ * @param {Date} ctime Change time.
202
+ */
203
+ Item.prototype.setCTime = function (ctime) {
204
+ this._ctime = ctime;
205
+ };
206
+
207
+ /**
208
+ * Get birth time.
209
+ * @return {Date} Birth time.
210
+ */
211
+ Item.prototype.getBirthtime = function () {
212
+ return this._birthtime;
213
+ };
214
+
215
+ /**
216
+ * Set change time.
217
+ * @param {Date} birthtime Birth time.
218
+ */
219
+ Item.prototype.setBirthtime = function (birthtime) {
220
+ this._birthtime = birthtime;
221
+ };
222
+
223
+ /**
224
+ * Get modification time.
225
+ * @return {Date} Modification time.
226
+ */
227
+ Item.prototype.getMTime = function () {
228
+ return this._mtime;
229
+ };
230
+
231
+ /**
232
+ * Set modification time.
233
+ * @param {Date} mtime Modification time.
234
+ */
235
+ Item.prototype.setMTime = function (mtime) {
236
+ this._mtime = mtime;
237
+ };
238
+
239
+ /**
240
+ * Get mode (permission only, e.g 0666).
241
+ * @return {number} Mode.
242
+ */
243
+ Item.prototype.getMode = function () {
244
+ return this._mode;
245
+ };
246
+
247
+ /**
248
+ * Set mode (permission only, e.g 0666).
249
+ * @param {Date} mode Mode.
250
+ */
251
+ Item.prototype.setMode = function (mode) {
252
+ this.setCTime(new Date());
253
+ this._mode = mode;
254
+ };
255
+
256
+ /**
257
+ * Get user id.
258
+ * @return {number} User id.
259
+ */
260
+ Item.prototype.getUid = function () {
261
+ return this._uid;
262
+ };
263
+
264
+ /**
265
+ * Set user id.
266
+ * @param {number} uid User id.
267
+ */
268
+ Item.prototype.setUid = function (uid) {
269
+ this.setCTime(new Date());
270
+ this._uid = uid;
271
+ };
272
+
273
+ /**
274
+ * Get group id.
275
+ * @return {number} Group id.
276
+ */
277
+ Item.prototype.getGid = function () {
278
+ return this._gid;
279
+ };
280
+
281
+ /**
282
+ * Set group id.
283
+ * @param {number} gid Group id.
284
+ */
285
+ Item.prototype.setGid = function (gid) {
286
+ this.setCTime(new Date());
287
+ this._gid = gid;
288
+ };
289
+
290
+ /**
291
+ * Get item stats.
292
+ * @param {boolean} bigint Use BigInt.
293
+ * @return {object} Stats properties.
294
+ */
295
+ Item.prototype.getStats = function (bigint) {
296
+ const stats = bigint
297
+ ? new bigintStatsConstructor(36)
298
+ : new statsConstructor(36);
299
+ const convert = bigint ? (v) => BigInt(v) : (v) => v;
300
+
301
+ stats[0] = convert(8675309); // dev
302
+ // [1] is mode
303
+ stats[2] = convert(this.links); // nlink
304
+ stats[3] = convert(this.getUid()); // uid
305
+ stats[4] = convert(this.getGid()); // gid
306
+ stats[5] = convert(0); // rdev
307
+ stats[6] = convert(4096); // blksize
308
+ stats[7] = convert(this._id); // ino
309
+ // [8] is size
310
+ // [9] is blocks
311
+ const atimeMs = +this.getATime();
312
+ stats[10] = convert(Math.floor(atimeMs / 1000)); // atime seconds
313
+ stats[11] = convert((atimeMs % 1000) * 1000000); // atime nanoseconds
314
+ const mtimeMs = +this.getMTime();
315
+ stats[12] = convert(Math.floor(mtimeMs / 1000)); // atime seconds
316
+ stats[13] = convert((mtimeMs % 1000) * 1000000); // atime nanoseconds
317
+ const ctimeMs = +this.getCTime();
318
+ stats[14] = convert(Math.floor(ctimeMs / 1000)); // atime seconds
319
+ stats[15] = convert((ctimeMs % 1000) * 1000000); // atime nanoseconds
320
+ const birthtimeMs = +this.getBirthtime();
321
+ stats[16] = convert(Math.floor(birthtimeMs / 1000)); // atime seconds
322
+ stats[17] = convert((birthtimeMs % 1000) * 1000000); // atime nanoseconds
323
+ return stats;
324
+ };
325
+
326
+ /**
327
+ * Get the item's string representation.
328
+ * @return {string} String representation.
329
+ */
330
+ Item.prototype.toString = function () {
331
+ return '[' + this.constructor.name + ']';
332
+ };
333
+
334
+ /**
335
+ * Export the constructor.
336
+ * @type {function()}
337
+ */
338
+ module.exports = Item;
@@ -0,0 +1,121 @@
1
+ const {fixWin32Permissions} = require('./item.js');
2
+ const path = require('path');
3
+ const FileSystem = require('./filesystem.js');
4
+ const fs = require('fs');
5
+ const bypass = require('./bypass.js');
6
+
7
+ const createContext = ({output, options = {}, target}, newContext) =>
8
+ Object.assign(
9
+ {
10
+ // Assign options and set defaults if needed
11
+ options: {
12
+ recursive: options.recursive !== false,
13
+ lazy: options.lazy !== false,
14
+ },
15
+ output,
16
+ target,
17
+ },
18
+ newContext
19
+ );
20
+
21
+ function addFile(context, stats, isRoot) {
22
+ const {output, target} = context;
23
+ const {lazy} = context.options;
24
+
25
+ if (!stats.isFile()) {
26
+ throw new Error(`${target} is not a valid file!`);
27
+ }
28
+
29
+ const outputPropKey = isRoot ? target : path.basename(target);
30
+
31
+ output[outputPropKey] = () => {
32
+ const content = !lazy ? fs.readFileSync(target) : '';
33
+ const file = FileSystem.file(Object.assign({}, stats, {content}))();
34
+
35
+ if (lazy) {
36
+ Object.defineProperty(file, '_content', {
37
+ get() {
38
+ const res = bypass(() => fs.readFileSync(target));
39
+ Object.defineProperty(file, '_content', {
40
+ value: res,
41
+ writable: true,
42
+ });
43
+ return res;
44
+ },
45
+ set(data) {
46
+ Object.defineProperty(file, '_content', {
47
+ value: data,
48
+ writable: true,
49
+ });
50
+ },
51
+ configurable: true,
52
+ });
53
+ }
54
+
55
+ return file;
56
+ };
57
+
58
+ return output[outputPropKey];
59
+ }
60
+
61
+ function addDir(context, stats, isRoot) {
62
+ const {target, output} = context;
63
+ const {recursive} = context.options;
64
+
65
+ if (!stats.isDirectory()) {
66
+ throw new Error(`${target} is not a valid directory!`);
67
+ }
68
+
69
+ stats = Object.assign({}, stats);
70
+ const outputPropKey = isRoot ? target : path.basename(target);
71
+
72
+ // On windows platforms, directories do not have the executable flag, which causes FileSystem.prototype.getItem
73
+ // to think that the directory cannot be traversed. This is a workaround, however, a better solution may be to
74
+ // re-think the logic in FileSystem.prototype.getItem
75
+ // This workaround adds executable privileges if read privileges are found
76
+ stats.mode = fixWin32Permissions(stats.mode);
77
+
78
+ // Create directory factory
79
+ const directoryItems = {};
80
+ output[outputPropKey] = FileSystem.directory(
81
+ Object.assign(stats, {items: directoryItems})
82
+ );
83
+
84
+ fs.readdirSync(target).forEach((p) => {
85
+ const absPath = path.join(target, p);
86
+ const stats = fs.statSync(absPath);
87
+ const newContext = createContext(context, {
88
+ target: absPath,
89
+ output: directoryItems,
90
+ });
91
+
92
+ if (recursive && stats.isDirectory()) {
93
+ addDir(newContext, stats);
94
+ } else if (stats.isFile()) {
95
+ addFile(newContext, stats);
96
+ }
97
+ });
98
+
99
+ return output[outputPropKey];
100
+ }
101
+
102
+ /**
103
+ * Load directory or file from real FS
104
+ * @param {string} p The path.
105
+ * @param {object} options The options.
106
+ * @return {*} The return.
107
+ */
108
+ exports.load = function (p, options) {
109
+ return bypass(() => {
110
+ p = path.resolve(p);
111
+
112
+ const stats = fs.statSync(p);
113
+ const context = createContext({output: {}, options, target: p});
114
+
115
+ if (stats.isDirectory()) {
116
+ return addDir(context, stats, true);
117
+ } else if (stats.isFile()) {
118
+ return addFile(context, stats, true);
119
+ }
120
+ });
121
+ };
@@ -0,0 +1,153 @@
1
+ 'use strict';
2
+
3
+ const {AbortError} = require('./error.js');
4
+ const {FSReqCallback} = process.binding('fs');
5
+
6
+ /**
7
+ * This is a workaround for getting access to the ReadFileContext
8
+ * prototype, which we need to be able to patch its methods.
9
+ * @return {object} The prototype.
10
+ */
11
+ exports.getReadFileContextPrototype = function () {
12
+ const fs = require('fs');
13
+ const fsBinding = process.binding('fs');
14
+
15
+ const originalOpen = fsBinding.open;
16
+
17
+ let proto;
18
+ fsBinding.open = (_path, _flags, _mode, req) => {
19
+ proto = Object.getPrototypeOf(req.context);
20
+ return originalOpen.apply(fsBinding, [_path, _flags, _mode, req]);
21
+ };
22
+
23
+ fs.readFile('/ignored.txt', () => {});
24
+
25
+ fsBinding.open = originalOpen;
26
+
27
+ return proto;
28
+ };
29
+
30
+ /**
31
+ * This patches the ReadFileContext prototype to use mocked bindings
32
+ * when available. This entire implementation is more or less fully
33
+ * copied over from Node.js's /lib/internal/fs/read_file_context.js
34
+ *
35
+ * This patch is required to support Node.js v16+, where the ReadFileContext
36
+ * closes directly over the internal fs bindings, and is also eagerly loader.
37
+ *
38
+ * See https://github.com/tschaub/mock-fs/issues/332 for more information.
39
+ *
40
+ * @param {object} prototype The ReadFileContext prototype object to patch.
41
+ */
42
+ exports.patchReadFileContext = function (prototype) {
43
+ const origRead = prototype.read;
44
+ const origClose = prototype.close;
45
+
46
+ const kReadFileUnknownBufferLength = 64 * 1024;
47
+ const kReadFileBufferLength = 512 * 1024;
48
+
49
+ function readFileAfterRead(err, bytesRead) {
50
+ const context = this.context;
51
+
52
+ if (err) {
53
+ return context.close(err);
54
+ }
55
+ context.pos += bytesRead;
56
+
57
+ if (context.pos === context.size || bytesRead === 0) {
58
+ context.close();
59
+ } else {
60
+ if (context.size === 0) {
61
+ // Unknown size, just read until we don't get bytes.
62
+ const buffer =
63
+ bytesRead === kReadFileUnknownBufferLength
64
+ ? context.buffer
65
+ : context.buffer.slice(0, bytesRead);
66
+ context.buffers.push(buffer);
67
+ }
68
+ context.read();
69
+ }
70
+ }
71
+
72
+ function readFileAfterClose(err) {
73
+ const context = this.context;
74
+ const callback = context.callback;
75
+ let buffer = null;
76
+
77
+ if (context.err || err) {
78
+ // This is a simplification from Node.js, where we don't bother merging the errors
79
+ return callback(context.err || err);
80
+ }
81
+
82
+ try {
83
+ if (context.size === 0) {
84
+ buffer = Buffer.concat(context.buffers, context.pos);
85
+ } else if (context.pos < context.size) {
86
+ buffer = context.buffer.slice(0, context.pos);
87
+ } else {
88
+ buffer = context.buffer;
89
+ }
90
+
91
+ if (context.encoding) {
92
+ buffer = buffer.toString(context.encoding);
93
+ }
94
+ } catch (err) {
95
+ return callback(err);
96
+ }
97
+
98
+ callback(null, buffer);
99
+ }
100
+
101
+ prototype.read = function read() {
102
+ if (!prototype._mockedBinding) {
103
+ return origRead.apply(this, arguments);
104
+ }
105
+
106
+ let buffer;
107
+ let offset;
108
+ let length;
109
+
110
+ if (this.signal && this.signal.aborted) {
111
+ return this.close(new AbortError());
112
+ }
113
+ if (this.size === 0) {
114
+ buffer = Buffer.allocUnsafeSlow(kReadFileUnknownBufferLength);
115
+ offset = 0;
116
+ length = kReadFileUnknownBufferLength;
117
+ this.buffer = buffer;
118
+ } else {
119
+ buffer = this.buffer;
120
+ offset = this.pos;
121
+ length = Math.min(kReadFileBufferLength, this.size - this.pos);
122
+ }
123
+
124
+ const req = new FSReqCallback();
125
+ req.oncomplete = readFileAfterRead;
126
+ req.context = this;
127
+
128
+ // This call and the one in close() is what we want to change, the
129
+ // rest is pretty much the same as Node.js except we don't have access
130
+ // to some of the internal optimizations.
131
+ prototype._mockedBinding.read(this.fd, buffer, offset, length, -1, req);
132
+ };
133
+
134
+ prototype.close = function close(err) {
135
+ if (!prototype._mockedBinding) {
136
+ return origClose.apply(this, arguments);
137
+ }
138
+
139
+ if (this.isUserFd) {
140
+ process.nextTick(function tick(context) {
141
+ readFileAfterClose.apply({context}, [null]);
142
+ }, this);
143
+ return;
144
+ }
145
+
146
+ const req = new FSReqCallback();
147
+ req.oncomplete = readFileAfterClose;
148
+ req.context = this;
149
+ this.err = err;
150
+
151
+ prototype._mockedBinding.close(this.fd, req);
152
+ };
153
+ };
@@ -0,0 +1,59 @@
1
+ 'use strict';
2
+
3
+ const util = require('util');
4
+ const Item = require('./item.js');
5
+ const constants = require('constants');
6
+
7
+ /**
8
+ * A directory.
9
+ * @class
10
+ */
11
+ function SymbolicLink() {
12
+ Item.call(this);
13
+
14
+ /**
15
+ * Relative path to source.
16
+ * @type {string}
17
+ */
18
+ this._path = undefined;
19
+ }
20
+ util.inherits(SymbolicLink, Item);
21
+
22
+ /**
23
+ * Set the path to the source.
24
+ * @param {string} pathname Path to source.
25
+ */
26
+ SymbolicLink.prototype.setPath = function (pathname) {
27
+ this._path = pathname;
28
+ };
29
+
30
+ /**
31
+ * Get the path to the source.
32
+ * @return {string} Path to source.
33
+ */
34
+ SymbolicLink.prototype.getPath = function () {
35
+ return this._path;
36
+ };
37
+
38
+ /**
39
+ * Get symbolic link stats.
40
+ * @param {boolean} bigint Use BigInt.
41
+ * @return {object} Stats properties.
42
+ */
43
+ SymbolicLink.prototype.getStats = function (bigint) {
44
+ const size = this._path.length;
45
+ const stats = Item.prototype.getStats.call(this, bigint);
46
+ const convert = bigint ? (v) => BigInt(v) : (v) => v;
47
+
48
+ stats[1] = convert(this.getMode() | constants.S_IFLNK); // mode
49
+ stats[8] = convert(size); // size
50
+ stats[9] = convert(Math.ceil(size / 512)); // blocks
51
+
52
+ return stats;
53
+ };
54
+
55
+ /**
56
+ * Export the constructor.
57
+ * @type {function()}
58
+ */
59
+ module.exports = SymbolicLink;
@@ -0,0 +1,49 @@
1
+ # License for mock-fs
2
+
3
+ The mock-fs module is distributed under the MIT license. Find the full source
4
+ here: http://tschaub.mit-license.org/
5
+
6
+ Copyright Tim Schaub.
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
9
+ this software and associated documentation files (the “Software”), to deal in
10
+ the Software without restriction, including without limitation the rights to
11
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
12
+ the Software, and to permit persons to whom the Software is furnished to do so,
13
+ subject to the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be included in all
16
+ copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
20
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
21
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+
25
+
26
+ # Node's license
27
+
28
+ This module includes parts of the Node library itself (specifically, the fs
29
+ module is included from several different versions of Node). Find Node's
30
+ license below:
31
+
32
+ Copyright Joyent, Inc. and other Node contributors. All rights reserved.
33
+ Permission is hereby granted, free of charge, to any person obtaining a copy
34
+ of this software and associated documentation files (the "Software"), to
35
+ deal in the Software without restriction, including without limitation the
36
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
37
+ sell copies of the Software, and to permit persons to whom the Software is
38
+ furnished to do so, subject to the following conditions:
39
+
40
+ The above copyright notice and this permission notice shall be included in
41
+ all copies or substantial portions of the Software.
42
+
43
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
44
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
46
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
47
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
48
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
49
+ IN THE SOFTWARE.