Skip to content

Commit 8fbe86e

Browse files
@jotadevelopersergiohgz
authored andcommitted
fix: migration from main repository merge #306
1 parent 072b7ca commit 8fbe86e

File tree

4 files changed

+102
-30
lines changed

4 files changed

+102
-30
lines changed

plugins/local-storage/package-lock.json

Lines changed: 20 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

plugins/local-storage/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"mkdirp": "0.5.1"
2020
},
2121
"devDependencies": {
22-
"@verdaccio/types": "0.0.3",
22+
"@verdaccio/types": "0.0.4",
2323
"babel-cli": "6.24.1",
2424
"babel-core": "6.25.0",
2525
"babel-eslint": "^7.2.3",

plugins/local-storage/src/local-data.js

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type {ILocalData, LocalStorage, Logger} from '@verdaccio/types';
1414
path: string;
1515
logger: Logger;
1616
data: LocalStorage;
17+
locked: boolean;
1718

1819
/**
1920
* Load an parse the local json database.
@@ -22,34 +23,84 @@ import type {ILocalData, LocalStorage, Logger} from '@verdaccio/types';
2223
constructor(path: string, logger: Logger) {
2324
this.path = path;
2425
this.logger = logger;
26+
this.locked = false;
27+
this.data = this._fetchLocalPackages();
28+
}
29+
30+
/**
31+
* Fetch local packages.
32+
* @private
33+
* @return {Object}
34+
*/
35+
_fetchLocalPackages() {
36+
const emptyDatabase = {list: []};
37+
2538
try {
26-
this.data = JSON.parse(fs.readFileSync(this.path, 'utf8'));
27-
} catch (_) {
28-
this.data = {list: []};
39+
const dbFile = fs.readFileSync(this.path, 'utf8');
40+
41+
if (!dbFile) { // readFileSync is platform specific, FreeBSD might return null
42+
return emptyDatabase;
43+
}
44+
45+
const db = this._parseDatabase(dbFile);
46+
47+
if (!db) {
48+
return emptyDatabase;
49+
}
50+
51+
return db;
52+
} catch (err) {
53+
// readFileSync is platform specific, macOS, Linux and Windows thrown an error
54+
// Only recreate if file not found to prevent data loss
55+
if (err.code !== 'ENOENT') {
56+
this.locked = true;
57+
this.logger.error(
58+
'Failed to read package database file, please check the error printed below:\n',
59+
`File Path: ${this.path}\n\n ${err.message}`
60+
);
61+
}
62+
return emptyDatabase;
63+
}
64+
}
65+
66+
/**
67+
* Parse the local database.
68+
* @param {Object} dbFile
69+
* @private
70+
* @return {Object}
71+
*/
72+
_parseDatabase(dbFile: any) {
73+
try {
74+
return JSON.parse(dbFile);
75+
} catch (err) {
76+
this.logger.error(`Package database file corrupted (invalid JSON), please check the error printed below.\nFile Path: ${this.path}`, err);
77+
this.locked = true;
2978
}
3079
}
3180

3281
/**
3382
* Add a new element.
3483
* @param {*} name
84+
* @return {Error|*}
3585
*/
3686
add(name: string) {
3787
if (this.data.list.indexOf(name) === -1) {
3888
this.data.list.push(name);
39-
this.sync();
89+
return this.sync();
4090
}
4191
}
4292

4393
/**
4494
* Remove an element from the database.
4595
* @param {*} name
96+
* @return {Error|*}
4697
*/
4798
remove(name: string) {
4899
const i = this.data.list.indexOf(name);
49100
if (i !== -1) {
50101
this.data.list.splice(i, 1);
51102
}
52-
this.sync();
103+
return this.sync();
53104
}
54105

55106
/**
@@ -62,16 +113,26 @@ import type {ILocalData, LocalStorage, Logger} from '@verdaccio/types';
62113

63114
/**
64115
* Syncronize {create} database whether does not exist.
116+
* @return {Error|*}
65117
*/
66118
sync() {
119+
if (this.locked) {
120+
this.logger.error('Database is locked, please check error message printed during startup to prevent data loss.');
121+
return new Error('Verdaccio database is locked, please contact your administrator to checkout logs during verdaccio startup.');
122+
}
67123
// Uses sync to prevent ugly race condition
68124
try {
69125
mkdirp.sync(Path.dirname(this.path));
70126
} catch (err) {
71127
// perhaps a logger instance?
72128
/* eslint no-empty:off */
73129
}
74-
fs.writeFileSync(this.path, JSON.stringify(this.data));
130+
131+
try {
132+
fs.writeFileSync(this.path, JSON.stringify(this.data));
133+
} catch (err) {
134+
return err;
135+
}
75136
}
76137

77138
}

plugins/local-storage/src/local-storage.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import Path from 'path';
99
import Stream from 'stream';
1010
import UrlNode from 'url';
1111
import _ from 'lodash';
12+
// $FlowFixMe
1213
import async from 'async';
1314

1415
import LocalFS from './local-fs';
@@ -130,6 +131,12 @@ class Storage implements IStorage {
130131
}
131132
this._normalizePackage(data);
132133

134+
let removeFailed = this.localList.remove(name);
135+
if (removeFailed) {
136+
// This will happen when database is locked
137+
return callback(this.utils.ErrorCode.get422(removeFailed.message));
138+
}
139+
133140
storage.unlink(pkgFileName, function(err) {
134141
if (err) {
135142
return callback(err);
@@ -156,7 +163,6 @@ class Storage implements IStorage {
156163
});
157164
});
158165
});
159-
this.localList.remove(name);
160166
}
161167

162168
/**
@@ -193,7 +199,7 @@ class Storage implements IStorage {
193199
url: version.dist.tarball,
194200
sha: version.dist.shasum,
195201
};
196-
202+
// $FlowFixMe
197203
const upLink: string = version[Symbol.for('__verdaccio_uplink')];
198204

199205
if (_.isNil(upLink) === false) {
@@ -313,7 +319,12 @@ class Storage implements IStorage {
313319

314320
data.versions[version] = metadata;
315321
this.utils.tag_version(data, version, tag);
316-
this.localList.add(name);
322+
323+
let addFailed = this.localList.add(name);
324+
if (addFailed) {
325+
return cb(this.utils.ErrorCode.get422(addFailed.message));
326+
}
327+
317328
cb();
318329
}, callback);
319330
}

0 commit comments

Comments
 (0)