pagan-artifact 0.2.9 → 0.3.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/bin/art.js +15 -2
- package/branching/index.js +13 -7
- package/caches/index.js +55 -81
- package/changes/index.js +16 -7
- package/contributions/index.js +24 -10
- package/index.js +2 -2
- package/package.json +1 -1
- package/setup/index.js +113 -115
- package/utils/getStateByHash/index.js +1 -1
- package/workflow/index.js +11 -4
package/bin/art.js
CHANGED
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* art - Modern version control.
|
|
5
|
-
* CLI (v0.
|
|
5
|
+
* CLI (v0.3.0)
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
const art = require('../index.js');
|
|
9
|
+
const path = require('path');
|
|
9
10
|
|
|
10
11
|
const [,, command, ...args] = process.argv;
|
|
11
12
|
|
|
@@ -69,7 +70,19 @@ async function run() {
|
|
|
69
70
|
|
|
70
71
|
if (ignored && ignored.length > 0) {
|
|
71
72
|
console.log('\nIgnored files:');
|
|
72
|
-
|
|
73
|
+
|
|
74
|
+
const compressedIgnored = new Set();
|
|
75
|
+
|
|
76
|
+
ignored.forEach(f => {
|
|
77
|
+
const parts = f.split(path.sep);
|
|
78
|
+
if (parts.length > 1) {
|
|
79
|
+
compressedIgnored.add(`${parts[0]}${path.sep}`);
|
|
80
|
+
} else {
|
|
81
|
+
compressedIgnored.add(f);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
compressedIgnored.forEach(f => console.log(`${GRAY}\t${f}${RESET}`));
|
|
73
86
|
}
|
|
74
87
|
|
|
75
88
|
if (untracked.length === 0 && modified.length === 0 && staged.length === 0) {
|
package/branching/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* art - Modern version control.
|
|
3
|
-
* Module: Branching (v0.
|
|
3
|
+
* Module: Branching (v0.3.0)
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const fs = require('fs');
|
|
@@ -26,6 +26,7 @@ function branch ({ name, isDelete = false } = {}) {
|
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
const normalizedName = name.toLowerCase();
|
|
29
30
|
const illegalRegExp = /[\/\\]/g;
|
|
30
31
|
const controlRegExp = /[\x00-\x1f\x80-\x9f]/g;
|
|
31
32
|
const reservedRegExp = /^\.+$/;
|
|
@@ -89,20 +90,25 @@ function branch ({ name, isDelete = false } = {}) {
|
|
|
89
90
|
|
|
90
91
|
if (initialCommits.length > 0) {
|
|
91
92
|
const sourceBranchPath = path.join(localHistoryPath, sourceBranchName);
|
|
93
|
+
const sourceRemotePath = path.join(remoteHistoryPath, sourceBranchName);
|
|
92
94
|
|
|
93
95
|
for (const hash of initialCommits) {
|
|
94
|
-
|
|
96
|
+
let masterFile = path.join(sourceBranchPath, `${hash}.json`);
|
|
97
|
+
let currentSrcDir = sourceBranchPath;
|
|
98
|
+
|
|
99
|
+
if (!fs.existsSync(masterFile)) {
|
|
100
|
+
masterFile = path.join(sourceRemotePath, `${hash}.json`);
|
|
101
|
+
currentSrcDir = sourceRemotePath;
|
|
102
|
+
}
|
|
95
103
|
|
|
96
104
|
if (fs.existsSync(masterFile)) {
|
|
97
|
-
// Copy the Master File
|
|
98
105
|
fs.copyFileSync(masterFile, path.join(branchLocalPath, `${hash}.json`));
|
|
99
106
|
|
|
100
|
-
// Detect and copy all Parts
|
|
101
107
|
const commitMaster = JSON.parse(fs.readFileSync(masterFile, 'utf8'));
|
|
102
108
|
|
|
103
109
|
if (commitMaster.parts && Array.isArray(commitMaster.parts)) {
|
|
104
110
|
for (const partName of commitMaster.parts) {
|
|
105
|
-
const srcPart = path.join(
|
|
111
|
+
const srcPart = path.join(currentSrcDir, partName);
|
|
106
112
|
const destPart = path.join(branchLocalPath, partName);
|
|
107
113
|
|
|
108
114
|
if (fs.existsSync(srcPart)) {
|
|
@@ -287,11 +293,11 @@ function checkout (branchName, { force = false } = {}) {
|
|
|
287
293
|
JSON.stringify({ parts: Array.from({ length: partCount }, (_, i) => `part.${i}.json`) }, null, 2)
|
|
288
294
|
);
|
|
289
295
|
|
|
290
|
-
return `Merged ${targetBranch}
|
|
296
|
+
return `Merged ${targetBranch}.`;
|
|
291
297
|
}
|
|
292
298
|
|
|
293
299
|
module.exports = {
|
|
294
|
-
__libraryVersion: '0.
|
|
300
|
+
__libraryVersion: '0.3.0',
|
|
295
301
|
__libraryAPIName: 'Branching',
|
|
296
302
|
branch,
|
|
297
303
|
checkout,
|
package/caches/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* art - Modern version control.
|
|
3
|
-
* Module: Caches (v0.
|
|
3
|
+
* Module: Caches (v0.3.0)
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const fs = require('fs');
|
|
@@ -9,15 +9,16 @@ const path = require('path');
|
|
|
9
9
|
const { checkout } = require('../branching/index.js');
|
|
10
10
|
const getStateByHash = require('../utils/getStateByHash');
|
|
11
11
|
|
|
12
|
+
const MAX_PART_SIZE = 32000000;
|
|
13
|
+
|
|
12
14
|
/**
|
|
13
|
-
* Helper to load all changes from a paginated
|
|
15
|
+
* Helper to load all changes from a paginated directory (Stage or Stash).
|
|
14
16
|
*/
|
|
15
17
|
|
|
16
|
-
function
|
|
17
|
-
const
|
|
18
|
-
const manifestPath = path.join(stageDir, 'manifest.json');
|
|
18
|
+
function getPaginatedChanges(dirPath) {
|
|
19
|
+
const manifestPath = path.join(dirPath, 'manifest.json');
|
|
19
20
|
|
|
20
|
-
if (!fs.existsSync(
|
|
21
|
+
if (!fs.existsSync(dirPath) || !fs.existsSync(manifestPath)) {
|
|
21
22
|
return {};
|
|
22
23
|
}
|
|
23
24
|
|
|
@@ -26,8 +27,7 @@ function getStagedChanges(artPath) {
|
|
|
26
27
|
let allChanges = {};
|
|
27
28
|
|
|
28
29
|
for (const partName of manifest.parts) {
|
|
29
|
-
const partPath = path.join(
|
|
30
|
-
|
|
30
|
+
const partPath = path.join(dirPath, partName);
|
|
31
31
|
if (fs.existsSync(partPath)) {
|
|
32
32
|
const partData = JSON.parse(fs.readFileSync(partPath, 'utf8'));
|
|
33
33
|
|
|
@@ -39,30 +39,28 @@ function getStagedChanges(artPath) {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
|
-
* Helper to write changes to a paginated
|
|
42
|
+
* Helper to write changes to a paginated directory.
|
|
43
43
|
*/
|
|
44
44
|
|
|
45
|
-
function
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (fs.existsSync(stageDir)) {
|
|
50
|
-
fs.rmSync(stageDir, { recursive: true, force: true });
|
|
45
|
+
function savePaginatedChanges (dirPath, changes) {
|
|
46
|
+
if (fs.existsSync(dirPath)) {
|
|
47
|
+
fs.rmSync(dirPath, { recursive: true, force: true });
|
|
51
48
|
}
|
|
52
49
|
|
|
53
|
-
fs.mkdirSync(
|
|
50
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
54
51
|
|
|
55
|
-
const
|
|
52
|
+
const parts = [];
|
|
56
53
|
|
|
57
54
|
let currentPartChanges = {};
|
|
58
55
|
let currentSize = 0;
|
|
59
56
|
|
|
60
57
|
const savePart = () => {
|
|
61
|
-
|
|
58
|
+
if (Object.keys(currentPartChanges).length === 0) return;
|
|
62
59
|
|
|
63
|
-
|
|
64
|
-
stageParts.push(partName);
|
|
60
|
+
const partName = `part.${parts.length}.json`;
|
|
65
61
|
|
|
62
|
+
fs.writeFileSync(path.join(dirPath, partName), JSON.stringify({ changes: currentPartChanges }, null, 2));
|
|
63
|
+
parts.push(partName);
|
|
66
64
|
currentPartChanges = {};
|
|
67
65
|
currentSize = 0;
|
|
68
66
|
};
|
|
@@ -79,14 +77,9 @@ function saveStagedChanges(artPath, changes) {
|
|
|
79
77
|
}
|
|
80
78
|
|
|
81
79
|
savePart();
|
|
82
|
-
|
|
83
|
-
fs.writeFileSync(path.join(stageDir, 'manifest.json'), JSON.stringify({ parts: stageParts }, null, 2));
|
|
80
|
+
fs.writeFileSync(path.join(dirPath, 'manifest.json'), JSON.stringify({ parts }, null, 2));
|
|
84
81
|
}
|
|
85
82
|
|
|
86
|
-
/**
|
|
87
|
-
* Moves changes to a cache folder, or restores the most recent stash.
|
|
88
|
-
*/
|
|
89
|
-
|
|
90
83
|
function stash ({ pop = false, list = false } = {}) {
|
|
91
84
|
const root = process.cwd();
|
|
92
85
|
const artPath = path.join(root, '.art');
|
|
@@ -97,14 +90,14 @@ function stash ({ pop = false, list = false } = {}) {
|
|
|
97
90
|
if (list) {
|
|
98
91
|
if (!fs.existsSync(cachePath)) return [];
|
|
99
92
|
|
|
100
|
-
const
|
|
101
|
-
.filter(
|
|
93
|
+
const stashDirs = fs.readdirSync(cachePath)
|
|
94
|
+
.filter(d => d.startsWith('stash_') && fs.statSync(path.join(cachePath, d)).isDirectory())
|
|
102
95
|
.sort();
|
|
103
96
|
|
|
104
|
-
return
|
|
105
|
-
id: `stash@{${
|
|
106
|
-
date: new Date(parseInt(
|
|
107
|
-
|
|
97
|
+
return stashDirs.map((dirName, index) => ({
|
|
98
|
+
id: `stash@{${stashDirs.length - 1 - index}}`,
|
|
99
|
+
date: new Date(parseInt(dirName.replace('stash_', ''))).toLocaleString(),
|
|
100
|
+
dirName
|
|
108
101
|
}));
|
|
109
102
|
}
|
|
110
103
|
|
|
@@ -112,18 +105,16 @@ function stash ({ pop = false, list = false } = {}) {
|
|
|
112
105
|
if (!fs.existsSync(cachePath)) throw new Error('No stashes found.');
|
|
113
106
|
|
|
114
107
|
const stashes = fs.readdirSync(cachePath)
|
|
115
|
-
.filter(
|
|
108
|
+
.filter(d => d.startsWith('stash_') && fs.statSync(path.join(cachePath, d)).isDirectory())
|
|
116
109
|
.sort();
|
|
117
110
|
|
|
118
|
-
if (stashes.length === 0)
|
|
119
|
-
throw new Error('No stashes found.');
|
|
120
|
-
}
|
|
111
|
+
if (stashes.length === 0) throw new Error('No stashes found.');
|
|
121
112
|
|
|
122
|
-
const
|
|
123
|
-
const latestStashPath = path.join(cachePath,
|
|
124
|
-
const
|
|
113
|
+
const latestStashDirName = stashes[stashes.length - 1];
|
|
114
|
+
const latestStashPath = path.join(cachePath, latestStashDirName);
|
|
115
|
+
const stashChanges = getPaginatedChanges(latestStashPath);
|
|
125
116
|
|
|
126
|
-
for (const [filePath, changeSet] of Object.entries(
|
|
117
|
+
for (const [filePath, changeSet] of Object.entries(stashChanges)) {
|
|
127
118
|
const fullPath = path.join(root, filePath);
|
|
128
119
|
|
|
129
120
|
if (Array.isArray(changeSet)) {
|
|
@@ -146,9 +137,8 @@ function stash ({ pop = false, list = false } = {}) {
|
|
|
146
137
|
}
|
|
147
138
|
}
|
|
148
139
|
|
|
149
|
-
fs.
|
|
150
|
-
|
|
151
|
-
return `Restored changes from ${latestStashName}.`;
|
|
140
|
+
fs.rmSync(latestStashPath, { recursive: true, force: true });
|
|
141
|
+
return `Restored changes from ${latestStashDirName}.`;
|
|
152
142
|
}
|
|
153
143
|
|
|
154
144
|
const artJson = JSON.parse(fs.readFileSync(artJsonPath, 'utf8'));
|
|
@@ -160,12 +150,16 @@ function stash ({ pop = false, list = false } = {}) {
|
|
|
160
150
|
const stashChanges = {};
|
|
161
151
|
|
|
162
152
|
for (const file of allWorkDirFiles) {
|
|
163
|
-
const
|
|
153
|
+
const fullPath = path.join(root, file);
|
|
154
|
+
const currentBuffer = fs.readFileSync(fullPath);
|
|
155
|
+
const isBinary = currentBuffer.includes(0);
|
|
156
|
+
|
|
157
|
+
const currentContent = isBinary ? null : currentBuffer.toString('utf8');
|
|
164
158
|
const previousContent = activeState[file];
|
|
165
159
|
|
|
166
160
|
if (previousContent === undefined) {
|
|
167
|
-
stashChanges[file] = { type: 'createFile', content: currentContent };
|
|
168
|
-
} else if (currentContent !== previousContent) {
|
|
161
|
+
stashChanges[file] = { type: 'createFile', content: isBinary ? currentBuffer.toString('base64') : currentContent };
|
|
162
|
+
} else if (currentContent !== previousContent && !isBinary) {
|
|
169
163
|
let start = 0;
|
|
170
164
|
|
|
171
165
|
while (start < previousContent.length && start < currentContent.length && previousContent[start] === currentContent[start]) {
|
|
@@ -189,7 +183,9 @@ function stash ({ pop = false, list = false } = {}) {
|
|
|
189
183
|
|
|
190
184
|
if (insCont.length > 0) ops.push({ type: 'insert', position: start, content: insCont });
|
|
191
185
|
|
|
192
|
-
if (ops.length > 0)
|
|
186
|
+
if (ops.length > 0) {
|
|
187
|
+
stashChanges[file] = ops;
|
|
188
|
+
}
|
|
193
189
|
}
|
|
194
190
|
}
|
|
195
191
|
|
|
@@ -199,29 +195,21 @@ function stash ({ pop = false, list = false } = {}) {
|
|
|
199
195
|
}
|
|
200
196
|
}
|
|
201
197
|
|
|
202
|
-
if (Object.keys(stashChanges).length === 0)
|
|
203
|
-
return 'No local changes to stash.';
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
if (!fs.existsSync(cachePath)) fs.mkdirSync(cachePath, { recursive: true });
|
|
198
|
+
if (Object.keys(stashChanges).length === 0) return 'No local changes to stash.';
|
|
207
199
|
|
|
208
200
|
const timestamp = Date.now();
|
|
201
|
+
const newStashPath = path.join(cachePath, `stash_${timestamp}`);
|
|
209
202
|
|
|
210
|
-
|
|
203
|
+
savePaginatedChanges(newStashPath, stashChanges);
|
|
211
204
|
|
|
212
205
|
if (fs.existsSync(stageDir)) {
|
|
213
206
|
fs.rmSync(stageDir, { recursive: true, force: true });
|
|
214
207
|
}
|
|
215
|
-
|
|
216
208
|
checkout(artJson.active.branch, { force: true });
|
|
217
209
|
|
|
218
|
-
return `Saved working directory changes to stash_${timestamp}
|
|
210
|
+
return `Saved working directory changes to paginated stash_${timestamp} and reverted to clean state.`;
|
|
219
211
|
}
|
|
220
212
|
|
|
221
|
-
/**
|
|
222
|
-
* Wipes the stage and moves the active parent pointer if a hash is provided.
|
|
223
|
-
*/
|
|
224
|
-
|
|
225
213
|
function reset (hash) {
|
|
226
214
|
const artPath = path.join(process.cwd(), '.art');
|
|
227
215
|
const stageDir = path.join(artPath, 'stage');
|
|
@@ -231,18 +219,14 @@ function reset (hash) {
|
|
|
231
219
|
fs.rmSync(stageDir, { recursive: true, force: true });
|
|
232
220
|
}
|
|
233
221
|
|
|
234
|
-
if (!hash)
|
|
235
|
-
return 'Staging area cleared.';
|
|
236
|
-
}
|
|
222
|
+
if (!hash) return 'Staging area cleared.';
|
|
237
223
|
|
|
238
224
|
const artJson = JSON.parse(fs.readFileSync(artJsonPath, 'utf8'));
|
|
239
225
|
const branch = artJson.active.branch;
|
|
240
226
|
const branchPath = path.join(artPath, 'history/local', branch);
|
|
241
227
|
const commitPath = path.join(branchPath, `${hash}.json`);
|
|
242
228
|
|
|
243
|
-
if (!fs.existsSync(commitPath)) {
|
|
244
|
-
throw new Error(`Commit ${hash} not found in branch ${branch}.`);
|
|
245
|
-
}
|
|
229
|
+
if (!fs.existsSync(commitPath)) throw new Error(`Commit ${hash} not found in branch ${branch}.`);
|
|
246
230
|
|
|
247
231
|
artJson.active.parent = hash;
|
|
248
232
|
fs.writeFileSync(artJsonPath, JSON.stringify(artJson, null, 2));
|
|
@@ -258,34 +242,24 @@ function reset (hash) {
|
|
|
258
242
|
|
|
259
243
|
checkout(branch);
|
|
260
244
|
|
|
261
|
-
return `
|
|
245
|
+
return `Branch is now at ${hash.slice(0, 7)}. Working directory updated.`;
|
|
262
246
|
}
|
|
263
247
|
|
|
264
|
-
/**
|
|
265
|
-
* Marks a file for deletion by adding a "deleteFile" entry to the stage.
|
|
266
|
-
*/
|
|
267
|
-
|
|
268
248
|
function rm (filePath) {
|
|
269
249
|
const artPath = path.join(process.cwd(), '.art');
|
|
270
250
|
const fullPath = path.join(process.cwd(), filePath);
|
|
251
|
+
const stage = getPaginatedChanges(path.join(artPath, 'stage'));
|
|
271
252
|
|
|
272
|
-
|
|
253
|
+
stage[filePath] = { type: 'deleteFile' };
|
|
254
|
+
savePaginatedChanges(path.join(artPath, 'stage'), stage);
|
|
273
255
|
|
|
274
|
-
|
|
275
|
-
type: 'deleteFile'
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
saveStagedChanges(artPath, stage);
|
|
279
|
-
|
|
280
|
-
if (fs.existsSync(fullPath)) {
|
|
281
|
-
fs.unlinkSync(fullPath);
|
|
282
|
-
}
|
|
256
|
+
if (fs.existsSync(fullPath)) fs.unlinkSync(fullPath);
|
|
283
257
|
|
|
284
258
|
return `File ${filePath} marked for removal.`;
|
|
285
259
|
}
|
|
286
260
|
|
|
287
261
|
module.exports = {
|
|
288
|
-
__libraryVersion: '0.
|
|
262
|
+
__libraryVersion: '0.3.0',
|
|
289
263
|
__libraryAPIName: 'Caches',
|
|
290
264
|
stash,
|
|
291
265
|
reset,
|
package/changes/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* art - Modern version control.
|
|
3
|
-
* Module: Changes (v0.
|
|
3
|
+
* Module: Changes (v0.3.0)
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const fs = require('fs');
|
|
@@ -34,8 +34,6 @@ function log () {
|
|
|
34
34
|
|
|
35
35
|
let output = `Branch: ${branch}\n\n`;
|
|
36
36
|
|
|
37
|
-
// Display commits in reverse chronological order
|
|
38
|
-
|
|
39
37
|
for (let i = manifest.commits.length - 1; i >= 0; i--) {
|
|
40
38
|
const hash = manifest.commits[i];
|
|
41
39
|
const commitMasterPath = path.join(branchPath, `${hash}.json`);
|
|
@@ -57,7 +55,7 @@ function log () {
|
|
|
57
55
|
* @returns {object} Formatted diff output and staged file list.
|
|
58
56
|
*/
|
|
59
57
|
|
|
60
|
-
|
|
58
|
+
function diff () {
|
|
61
59
|
const root = process.cwd();
|
|
62
60
|
const artPath = path.join(root, '.art');
|
|
63
61
|
const artJsonPath = path.join(artPath, 'art.json');
|
|
@@ -78,10 +76,13 @@ function log () {
|
|
|
78
76
|
|
|
79
77
|
for (const filePath of currentFiles) {
|
|
80
78
|
const fullPath = path.join(root, filePath);
|
|
81
|
-
const
|
|
79
|
+
const currentBuffer = fs.readFileSync(fullPath);
|
|
80
|
+
const isBinary = currentBuffer.includes(0);
|
|
81
|
+
|
|
82
|
+
const currentContent = isBinary ? null : currentBuffer.toString('utf8');
|
|
82
83
|
const previousContent = lastCommitState[filePath] || '';
|
|
83
84
|
|
|
84
|
-
if (currentContent !== previousContent) {
|
|
85
|
+
if (!isBinary && currentContent !== previousContent) {
|
|
85
86
|
let start = 0;
|
|
86
87
|
|
|
87
88
|
while (start < previousContent.length && start < currentContent.length && previousContent[start] === currentContent[start]) {
|
|
@@ -101,6 +102,12 @@ function log () {
|
|
|
101
102
|
deleted: previousContent.slice(start, oldEnd + 1),
|
|
102
103
|
added: currentContent.slice(start, newEnd + 1)
|
|
103
104
|
});
|
|
105
|
+
} else if (isBinary) {
|
|
106
|
+
const prevHash = lastCommitState[filePath] ? 'exists' : 'null';
|
|
107
|
+
|
|
108
|
+
if (prevHash === 'null') {
|
|
109
|
+
fileDiffs.push({ file: filePath, added: '<Binary Data>', deleted: '' });
|
|
110
|
+
}
|
|
104
111
|
}
|
|
105
112
|
}
|
|
106
113
|
|
|
@@ -115,8 +122,10 @@ function log () {
|
|
|
115
122
|
|
|
116
123
|
for (const partName of manifest.parts) {
|
|
117
124
|
const partPath = path.join(stageDir, partName);
|
|
125
|
+
|
|
118
126
|
if (fs.existsSync(partPath)) {
|
|
119
127
|
const partData = JSON.parse(fs.readFileSync(partPath, 'utf8'));
|
|
128
|
+
|
|
120
129
|
Object.keys(partData.changes).forEach(file => stagedFilesSet.add(file));
|
|
121
130
|
}
|
|
122
131
|
}
|
|
@@ -127,7 +136,7 @@ function log () {
|
|
|
127
136
|
}
|
|
128
137
|
|
|
129
138
|
module.exports = {
|
|
130
|
-
__libraryVersion: '0.
|
|
139
|
+
__libraryVersion: '0.3.0',
|
|
131
140
|
__libraryAPIName: 'Changes',
|
|
132
141
|
log,
|
|
133
142
|
diff
|
package/contributions/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* art - Modern version control.
|
|
3
|
-
* Module: Contributions (v0.
|
|
3
|
+
* Module: Contributions (v0.3.0)
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const fs = require('fs');
|
|
@@ -60,7 +60,10 @@ async function fetchRemote () {
|
|
|
60
60
|
method: 'POST',
|
|
61
61
|
headers: { 'Content-Type': 'application/json' },
|
|
62
62
|
body: JSON.stringify({
|
|
63
|
-
type: 'history',
|
|
63
|
+
type: 'history',
|
|
64
|
+
handle,
|
|
65
|
+
repo,
|
|
66
|
+
branch,
|
|
64
67
|
...(token && { personalAccessToken: token })
|
|
65
68
|
})
|
|
66
69
|
});
|
|
@@ -171,20 +174,22 @@ async function push () {
|
|
|
171
174
|
const handle = remoteParts.pop();
|
|
172
175
|
|
|
173
176
|
const localBranchPath = path.join(artPath, 'history/local', branch);
|
|
177
|
+
const remoteBranchPath = path.join(artPath, 'history/remote', branch);
|
|
174
178
|
const localManifest = JSON.parse(fs.readFileSync(path.join(localBranchPath, 'manifest.json'), 'utf8'));
|
|
175
179
|
|
|
176
180
|
const response = await fetch(`${ARTIFACT_HOST}/manifest`, {
|
|
177
181
|
method: 'POST',
|
|
178
182
|
headers: { 'Content-Type': 'application/json' },
|
|
179
183
|
body: JSON.stringify({
|
|
180
|
-
type: 'history',
|
|
181
|
-
|
|
184
|
+
type: 'history',
|
|
185
|
+
handle,
|
|
186
|
+
repo,
|
|
187
|
+
branch,
|
|
182
188
|
...(token && { personalAccessToken: token })
|
|
183
189
|
})
|
|
184
190
|
});
|
|
185
191
|
|
|
186
192
|
const remoteManifest = await response.json();
|
|
187
|
-
|
|
188
193
|
const missingCommits = localManifest.commits.filter(hash => !remoteManifest.commits.includes(hash));
|
|
189
194
|
|
|
190
195
|
if (missingCommits.length === 0) {
|
|
@@ -208,13 +213,17 @@ async function push () {
|
|
|
208
213
|
}
|
|
209
214
|
}
|
|
210
215
|
|
|
216
|
+
const currentRemoteManifestPath = path.join(remoteBranchPath, 'manifest.json');
|
|
217
|
+
const currentRemoteManifest = fs.existsSync(currentRemoteManifestPath)
|
|
218
|
+
? JSON.parse(fs.readFileSync(currentRemoteManifestPath, 'utf8'))
|
|
219
|
+
: { commits: [] };
|
|
220
|
+
|
|
211
221
|
for (const commitHash of missingCommits) {
|
|
212
222
|
const commitMaster = JSON.parse(fs.readFileSync(path.join(localBranchPath, `${commitHash}.json`), 'utf8'));
|
|
213
223
|
|
|
214
|
-
await fetch(`${ARTIFACT_HOST}/push`, {
|
|
224
|
+
const pushRes = await fetch(`${ARTIFACT_HOST}/push`, {
|
|
215
225
|
method: 'POST',
|
|
216
226
|
headers: { 'Content-Type': 'application/json' },
|
|
217
|
-
|
|
218
227
|
body: JSON.stringify({
|
|
219
228
|
handle, repo, branch, commit: commitMaster,
|
|
220
229
|
|
|
@@ -224,12 +233,14 @@ async function push () {
|
|
|
224
233
|
})
|
|
225
234
|
});
|
|
226
235
|
|
|
236
|
+
if (!pushRes.ok) throw new Error(`Server rejected push for commit ${commitHash}`);
|
|
237
|
+
|
|
227
238
|
rootData = null;
|
|
228
239
|
|
|
229
240
|
for (const partName of commitMaster.parts) {
|
|
230
241
|
const partData = JSON.parse(fs.readFileSync(path.join(localBranchPath, partName), 'utf8'));
|
|
231
242
|
|
|
232
|
-
await fetch(`${ARTIFACT_HOST}/commit/part`, {
|
|
243
|
+
const partRes = await fetch(`${ARTIFACT_HOST}/commit/part`, {
|
|
233
244
|
method: 'POST',
|
|
234
245
|
headers: { 'Content-Type': 'application/json' },
|
|
235
246
|
body: JSON.stringify({
|
|
@@ -237,10 +248,13 @@ async function push () {
|
|
|
237
248
|
...(token && { personalAccessToken: token })
|
|
238
249
|
})
|
|
239
250
|
});
|
|
251
|
+
|
|
252
|
+
if (!partRes.ok) throw new Error(`Server failed to receive part ${partName}`);
|
|
240
253
|
}
|
|
241
|
-
}
|
|
242
254
|
|
|
243
|
-
|
|
255
|
+
currentRemoteManifest.commits.push(commitHash);
|
|
256
|
+
fs.writeFileSync(currentRemoteManifestPath, JSON.stringify(currentRemoteManifest, null, 2));
|
|
257
|
+
}
|
|
244
258
|
|
|
245
259
|
return `Pushed ${missingCommits.length} commits to remote.`;
|
|
246
260
|
}
|
package/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* art - Modern version control.
|
|
3
|
-
* Core Library Entry Point (v0.
|
|
3
|
+
* Core Library Entry Point (v0.3.0)
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const Setup = require('./setup');
|
|
@@ -50,7 +50,7 @@ const art = {
|
|
|
50
50
|
|
|
51
51
|
// Metadata
|
|
52
52
|
|
|
53
|
-
version: '0.
|
|
53
|
+
version: '0.3.0',
|
|
54
54
|
modules: [
|
|
55
55
|
Setup.__libraryAPIName,
|
|
56
56
|
Workflow.__libraryAPIName,
|
package/package.json
CHANGED
package/setup/index.js
CHANGED
|
@@ -1,137 +1,133 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* art - Modern version control.
|
|
3
|
-
* Module: Setup (v0.
|
|
3
|
+
* Module: Setup (v0.3.0)
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const fs = require('fs');
|
|
7
7
|
const path = require('path');
|
|
8
8
|
|
|
9
9
|
const pkg = require('../package.json');
|
|
10
|
-
const { remote } = require('../contributions');
|
|
11
10
|
const shouldIgnore = require('../utils/shouldIgnore');
|
|
12
11
|
|
|
13
12
|
const ARTIFACT_HOST = pkg.artConfig.host || 'http://localhost:1337';
|
|
14
13
|
|
|
15
14
|
/**
|
|
16
|
-
*
|
|
15
|
+
* Internal helper to create the .art directory tree.
|
|
17
16
|
*/
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (!fs.existsSync(fullPath)) {
|
|
40
|
-
fs.mkdirSync(fullPath, { recursive: true });
|
|
41
|
-
}
|
|
42
|
-
}
|
|
18
|
+
function ensureDirStructure(artDirectory) {
|
|
19
|
+
const folders = [
|
|
20
|
+
'',
|
|
21
|
+
'root',
|
|
22
|
+
'history',
|
|
23
|
+
'history/local',
|
|
24
|
+
'history/local/main',
|
|
25
|
+
'history/remote',
|
|
26
|
+
'history/remote/main'
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
for (const folder of folders) {
|
|
30
|
+
const fullPath = path.join(artDirectory, folder);
|
|
31
|
+
|
|
32
|
+
if (!fs.existsSync(fullPath)) {
|
|
33
|
+
fs.mkdirSync(fullPath, { recursive: true });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
43
37
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Initializes the local .art directory structure and indexes current files.
|
|
40
|
+
*/
|
|
47
41
|
|
|
48
|
-
|
|
49
|
-
|
|
42
|
+
function init (directoryPath = process.cwd()) {
|
|
43
|
+
const artDirectory = path.join(directoryPath, '.art');
|
|
50
44
|
|
|
51
|
-
|
|
45
|
+
if (fs.existsSync(artDirectory)) {
|
|
46
|
+
return `Reinitialized existing art repository in ${artDirectory}`;
|
|
47
|
+
}
|
|
52
48
|
|
|
53
|
-
|
|
54
|
-
let currentPartChars = 0;
|
|
49
|
+
ensureDirStructure(artDirectory);
|
|
55
50
|
|
|
56
|
-
|
|
51
|
+
const files = fs.readdirSync(directoryPath, { recursive: true })
|
|
52
|
+
.filter(f => {
|
|
53
|
+
const isInternal = f === '.art' || f.startsWith('.art' + path.sep);
|
|
54
|
+
return !isInternal && !shouldIgnore(f);
|
|
55
|
+
});
|
|
57
56
|
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
const rootMasterManifest = { parts: [] };
|
|
58
|
+
let currentPartFiles = [];
|
|
59
|
+
let currentPartChars = 0;
|
|
60
|
+
const MAX_PART_CHARS = 32000000;
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const partPath = path.join(artDirectory, 'root', partName);
|
|
62
|
+
const saveManifestPart = () => {
|
|
63
|
+
if (currentPartFiles.length === 0) return;
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
);
|
|
65
|
+
const partIndex = rootMasterManifest.parts.length;
|
|
66
|
+
const partName = `manifest.part.${Date.now()}.${partIndex}.json`;
|
|
67
|
+
const partPath = path.join(artDirectory, 'root', partName);
|
|
69
68
|
|
|
70
|
-
|
|
69
|
+
fs.writeFileSync(
|
|
70
|
+
partPath,
|
|
71
|
+
JSON.stringify({ files: currentPartFiles }, null, 2)
|
|
72
|
+
);
|
|
71
73
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
rootMasterManifest.parts.push(partName);
|
|
75
|
+
currentPartFiles = [];
|
|
76
|
+
currentPartChars = 0;
|
|
77
|
+
};
|
|
75
78
|
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
for (const file of files) {
|
|
80
|
+
const fullPath = path.join(directoryPath, file);
|
|
78
81
|
|
|
79
|
-
|
|
80
|
-
|
|
82
|
+
if (fs.lstatSync(fullPath).isFile()) {
|
|
83
|
+
const content = fs.readFileSync(fullPath, 'utf8');
|
|
81
84
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
+
if (currentPartChars + content.length > MAX_PART_CHARS && currentPartFiles.length > 0) {
|
|
86
|
+
saveManifestPart();
|
|
87
|
+
}
|
|
85
88
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
89
|
+
currentPartFiles.push({
|
|
90
|
+
path: file,
|
|
91
|
+
content: content
|
|
92
|
+
});
|
|
90
93
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
+
currentPartChars += content.length;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
94
97
|
|
|
95
|
-
|
|
98
|
+
saveManifestPart();
|
|
96
99
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
100
|
+
fs.writeFileSync(
|
|
101
|
+
path.join(artDirectory, 'root/manifest.json'),
|
|
102
|
+
JSON.stringify(rootMasterManifest, null, 2)
|
|
103
|
+
);
|
|
101
104
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
fs.writeFileSync(
|
|
106
|
+
path.join(artDirectory, 'history/local/main/manifest.json'),
|
|
107
|
+
JSON.stringify({ commits: [] }, null, 2)
|
|
108
|
+
);
|
|
106
109
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
110
|
+
fs.writeFileSync(
|
|
111
|
+
path.join(artDirectory, 'history/remote/main/manifest.json'),
|
|
112
|
+
JSON.stringify({ commits: [] }, null, 2)
|
|
113
|
+
);
|
|
111
114
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
const artFile = {
|
|
116
|
+
active: { branch: 'main', parent: null },
|
|
117
|
+
remote: '',
|
|
118
|
+
configuration: { handle: '', personalAccessToken: '' }
|
|
119
|
+
};
|
|
117
120
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
121
|
+
fs.writeFileSync(
|
|
122
|
+
path.join(artDirectory, 'art.json'),
|
|
123
|
+
JSON.stringify(artFile, null, 2)
|
|
124
|
+
);
|
|
122
125
|
|
|
123
|
-
|
|
124
|
-
|
|
126
|
+
return `Initialized empty art repository in ${artDirectory}.`;
|
|
127
|
+
}
|
|
125
128
|
|
|
126
129
|
/**
|
|
127
|
-
* Clone a repository
|
|
128
|
-
* @param {string} repoSlug - The handle/repo identifier.
|
|
129
|
-
* @param {string} providedToken - Optional token for authentication.
|
|
130
|
-
*/
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* art - Modern version control.
|
|
134
|
-
* Module: Setup (v0.2.9) - Clone logic
|
|
130
|
+
* Clone a repository and replay history.
|
|
135
131
|
*/
|
|
136
132
|
|
|
137
133
|
async function clone (repoSlug, providedToken = null) {
|
|
@@ -148,19 +144,20 @@ async function clone (repoSlug, providedToken = null) {
|
|
|
148
144
|
}
|
|
149
145
|
|
|
150
146
|
fs.mkdirSync(targetPath, { recursive: true });
|
|
151
|
-
|
|
147
|
+
|
|
148
|
+
const artPath = path.join(targetPath, '.art');
|
|
149
|
+
|
|
150
|
+
ensureDirStructure(artPath);
|
|
152
151
|
process.chdir(targetPath);
|
|
153
152
|
|
|
154
153
|
try {
|
|
155
|
-
const artPath = path.join(targetPath, '.art');
|
|
156
154
|
const artJsonPath = path.join(artPath, 'art.json');
|
|
157
|
-
const artJson = JSON.parse(fs.readFileSync(artJsonPath, 'utf8'));
|
|
158
155
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
156
|
+
const artJson = {
|
|
157
|
+
active: { branch: 'main', parent: null },
|
|
158
|
+
remote: `${ARTIFACT_HOST}/${handle}/${repo}`,
|
|
159
|
+
configuration: { handle: '', personalAccessToken: providedToken || '' }
|
|
160
|
+
};
|
|
164
161
|
|
|
165
162
|
fs.writeFileSync(artJsonPath, JSON.stringify(artJson, null, 2));
|
|
166
163
|
|
|
@@ -174,7 +171,6 @@ async function clone (repoSlug, providedToken = null) {
|
|
|
174
171
|
handle,
|
|
175
172
|
repo,
|
|
176
173
|
branch: 'main',
|
|
177
|
-
|
|
178
174
|
...(token && { personalAccessToken: token })
|
|
179
175
|
})
|
|
180
176
|
});
|
|
@@ -191,12 +187,10 @@ async function clone (repoSlug, providedToken = null) {
|
|
|
191
187
|
});
|
|
192
188
|
|
|
193
189
|
const partData = await partRes.json();
|
|
194
|
-
|
|
195
190
|
fs.writeFileSync(path.join(artPath, 'root', partName), JSON.stringify(partData, null, 2));
|
|
196
191
|
|
|
197
192
|
for (const file of partData.files) {
|
|
198
193
|
const workingPath = path.join(targetPath, file.path);
|
|
199
|
-
|
|
200
194
|
fs.mkdirSync(path.dirname(workingPath), { recursive: true });
|
|
201
195
|
fs.writeFileSync(workingPath, file.content);
|
|
202
196
|
}
|
|
@@ -209,7 +203,6 @@ async function clone (repoSlug, providedToken = null) {
|
|
|
209
203
|
});
|
|
210
204
|
|
|
211
205
|
const historyManifest = await historyRes.json();
|
|
212
|
-
|
|
213
206
|
const localHistoryDir = path.join(artPath, 'history/local/main');
|
|
214
207
|
const remoteHistoryDir = path.join(artPath, 'history/remote/main');
|
|
215
208
|
|
|
@@ -217,10 +210,19 @@ async function clone (repoSlug, providedToken = null) {
|
|
|
217
210
|
const commitRes = await fetch(`${ARTIFACT_HOST}/commit`, {
|
|
218
211
|
method: 'POST',
|
|
219
212
|
headers: { 'Content-Type': 'application/json' },
|
|
220
|
-
body: JSON.stringify({
|
|
213
|
+
body: JSON.stringify({
|
|
214
|
+
handle,
|
|
215
|
+
repo,
|
|
216
|
+
branch: 'main',
|
|
217
|
+
hash: commitHash,
|
|
218
|
+
|
|
219
|
+
...(token && { personalAccessToken: token
|
|
220
|
+
})
|
|
221
|
+
})
|
|
221
222
|
});
|
|
222
223
|
|
|
223
224
|
const commitMaster = await commitRes.json();
|
|
225
|
+
|
|
224
226
|
let fullChanges = {};
|
|
225
227
|
|
|
226
228
|
if (commitMaster.parts && commitMaster.parts.length > 0) {
|
|
@@ -232,7 +234,6 @@ async function clone (repoSlug, providedToken = null) {
|
|
|
232
234
|
});
|
|
233
235
|
|
|
234
236
|
const partData = await partRes.json();
|
|
235
|
-
|
|
236
237
|
fs.writeFileSync(path.join(localHistoryDir, partName), JSON.stringify(partData, null, 2));
|
|
237
238
|
fs.writeFileSync(path.join(remoteHistoryDir, partName), JSON.stringify(partData, null, 2));
|
|
238
239
|
|
|
@@ -252,7 +253,6 @@ async function clone (repoSlug, providedToken = null) {
|
|
|
252
253
|
|
|
253
254
|
if (Array.isArray(changeSet)) {
|
|
254
255
|
let content = fs.existsSync(fullPath) ? fs.readFileSync(fullPath, 'utf8') : '';
|
|
255
|
-
|
|
256
256
|
for (const op of changeSet) {
|
|
257
257
|
if (op.type === 'insert') {
|
|
258
258
|
content = content.slice(0, op.position) + op.content + content.slice(op.position);
|
|
@@ -260,7 +260,6 @@ async function clone (repoSlug, providedToken = null) {
|
|
|
260
260
|
content = content.slice(0, op.position) + content.slice(op.position + op.length);
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
|
-
|
|
264
263
|
fs.writeFileSync(fullPath, content);
|
|
265
264
|
} else if (changeSet.type === 'createFile') {
|
|
266
265
|
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
@@ -292,8 +291,7 @@ async function clone (repoSlug, providedToken = null) {
|
|
|
292
291
|
/**
|
|
293
292
|
* Updates the configuration in art.json.
|
|
294
293
|
*/
|
|
295
|
-
|
|
296
|
-
function config (key, value) {
|
|
294
|
+
function config(key, value) {
|
|
297
295
|
const manifestPath = path.join(process.cwd(), '.art', 'art.json');
|
|
298
296
|
|
|
299
297
|
if (!fs.existsSync(manifestPath)) {
|
|
@@ -304,7 +302,6 @@ function config (key, value) {
|
|
|
304
302
|
|
|
305
303
|
if (key && value !== undefined) {
|
|
306
304
|
manifest.configuration[key] = value;
|
|
307
|
-
|
|
308
305
|
fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
|
|
309
306
|
}
|
|
310
307
|
|
|
@@ -316,5 +313,6 @@ module.exports = {
|
|
|
316
313
|
__libraryAPIName: 'Setup',
|
|
317
314
|
init,
|
|
318
315
|
clone,
|
|
319
|
-
config
|
|
316
|
+
config,
|
|
317
|
+
ensureDirStructure
|
|
320
318
|
};
|
package/workflow/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* art - Modern version control.
|
|
3
|
-
* Module: Workflow (v0.
|
|
3
|
+
* Module: Workflow (v0.3.0)
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const fs = require('fs');
|
|
@@ -10,6 +10,8 @@ const crypto = require('crypto');
|
|
|
10
10
|
const getStateByHash = require('../utils/getStateByHash');
|
|
11
11
|
const shouldIgnore = require('../utils/shouldIgnore');
|
|
12
12
|
|
|
13
|
+
const MAX_PART_SIZE = 32000000;
|
|
14
|
+
|
|
13
15
|
/**
|
|
14
16
|
* Helper to load all changes from a paginated stage directory.
|
|
15
17
|
*/
|
|
@@ -27,8 +29,10 @@ function getStagedChanges(artPath) {
|
|
|
27
29
|
|
|
28
30
|
for (const partName of manifest.parts) {
|
|
29
31
|
const partPath = path.join(stageDir, partName);
|
|
32
|
+
|
|
30
33
|
if (fs.existsSync(partPath)) {
|
|
31
34
|
const partData = JSON.parse(fs.readFileSync(partPath, 'utf8'));
|
|
35
|
+
|
|
32
36
|
Object.assign(allChanges, partData.changes);
|
|
33
37
|
}
|
|
34
38
|
}
|
|
@@ -72,6 +76,7 @@ function status () {
|
|
|
72
76
|
|
|
73
77
|
if (isIgnored && !isActive && !isStaged) {
|
|
74
78
|
ignored.push(file);
|
|
79
|
+
|
|
75
80
|
continue;
|
|
76
81
|
}
|
|
77
82
|
|
|
@@ -79,6 +84,7 @@ function status () {
|
|
|
79
84
|
untracked.push(file);
|
|
80
85
|
} else if (!isStaged && isActive) {
|
|
81
86
|
const currentContent = fs.readFileSync(path.join(root, file), 'utf8');
|
|
87
|
+
|
|
82
88
|
if (currentContent !== activeState[file]) {
|
|
83
89
|
modified.push(file);
|
|
84
90
|
}
|
|
@@ -100,14 +106,15 @@ function status () {
|
|
|
100
106
|
*/
|
|
101
107
|
|
|
102
108
|
function add (targetPath) {
|
|
103
|
-
const MAX_PART_SIZE = 32000000;
|
|
104
109
|
const root = process.cwd();
|
|
105
110
|
const artPath = path.join(root, '.art');
|
|
106
111
|
const stageDir = path.join(artPath, 'stage');
|
|
107
112
|
const artJsonPath = path.join(artPath, 'art.json');
|
|
108
113
|
const fullPath = path.resolve(root, targetPath);
|
|
109
114
|
|
|
110
|
-
if (!fs.existsSync(fullPath))
|
|
115
|
+
if (!fs.existsSync(fullPath)) {
|
|
116
|
+
throw new Error(`Path does not exist: ${targetPath}`);
|
|
117
|
+
}
|
|
111
118
|
|
|
112
119
|
const artJson = JSON.parse(fs.readFileSync(artJsonPath, 'utf8'));
|
|
113
120
|
const activeState = getStateByHash(artJson.active.branch, artJson.active.parent) || {};
|
|
@@ -290,7 +297,7 @@ function commit (message) {
|
|
|
290
297
|
}
|
|
291
298
|
|
|
292
299
|
module.exports = {
|
|
293
|
-
__libraryVersion: '0.
|
|
300
|
+
__libraryVersion: '0.3.0',
|
|
294
301
|
__libraryAPIName: 'Workflow',
|
|
295
302
|
status,
|
|
296
303
|
add,
|