@himamshus06/git-auto 1.3.4 → 1.3.5
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/package.json +1 -1
- package/src/tree.js +128 -124
package/package.json
CHANGED
package/src/tree.js
CHANGED
|
@@ -12,7 +12,17 @@ class TreeParseError extends Error {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* Parse a visual directory tree
|
|
15
|
+
* Parse a visual directory tree.
|
|
16
|
+
*
|
|
17
|
+
* Supported format:
|
|
18
|
+
*
|
|
19
|
+
* my-project/
|
|
20
|
+
* ├── src/
|
|
21
|
+
* │ ├── index.js
|
|
22
|
+
* │ └── utils.js
|
|
23
|
+
* ├── public/
|
|
24
|
+
* │ └── index.html
|
|
25
|
+
* └── package.json
|
|
16
26
|
*/
|
|
17
27
|
function parseTree(text) {
|
|
18
28
|
if (!text || text.trim() === '') {
|
|
@@ -30,46 +40,111 @@ function parseTree(text) {
|
|
|
30
40
|
const line = lines[i];
|
|
31
41
|
const lineNum = i + 1;
|
|
32
42
|
|
|
33
|
-
|
|
43
|
+
let name;
|
|
44
|
+
let depth;
|
|
34
45
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
46
|
+
// --------------------------------------------------
|
|
47
|
+
// ROOT
|
|
48
|
+
// --------------------------------------------------
|
|
49
|
+
|
|
50
|
+
if (i === 0) {
|
|
51
|
+
name = line.trim();
|
|
52
|
+
depth = 0;
|
|
40
53
|
}
|
|
41
54
|
|
|
42
|
-
|
|
55
|
+
// --------------------------------------------------
|
|
56
|
+
// CHILD
|
|
57
|
+
// --------------------------------------------------
|
|
58
|
+
|
|
59
|
+
else {
|
|
60
|
+
/*
|
|
61
|
+
* Match:
|
|
62
|
+
*
|
|
63
|
+
* ├── src/
|
|
64
|
+
* └── package.json
|
|
65
|
+
*
|
|
66
|
+
* │ ├── index.js
|
|
67
|
+
* │ └── utils.js
|
|
68
|
+
*
|
|
69
|
+
* │ │ └── Button.jsx
|
|
70
|
+
*/
|
|
71
|
+
|
|
72
|
+
const match = line.match(
|
|
73
|
+
/^((?:│ | )*)(?:├── |└── |\+-- |`-- )(.*)$/
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
if (!match) {
|
|
77
|
+
throw new TreeParseError(
|
|
78
|
+
`Could not parse line: "${line}"`,
|
|
79
|
+
lineNum
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const indentation = match[1];
|
|
84
|
+
name = match[2].trim();
|
|
85
|
+
|
|
86
|
+
/*
|
|
87
|
+
* Every 4 characters of indentation
|
|
88
|
+
* represents one level.
|
|
89
|
+
*
|
|
90
|
+
* ├── src/ depth 1
|
|
91
|
+
* │ ├── index.js depth 2
|
|
92
|
+
* │ │ └── x.js depth 3
|
|
93
|
+
*/
|
|
43
94
|
|
|
44
|
-
|
|
45
|
-
|
|
95
|
+
depth = indentation.length / 4 + 1;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (!name) {
|
|
46
99
|
throw new TreeParseError(
|
|
47
|
-
'
|
|
100
|
+
'Empty file/directory name',
|
|
48
101
|
lineNum
|
|
49
102
|
);
|
|
50
103
|
}
|
|
51
104
|
|
|
52
|
-
//
|
|
105
|
+
// --------------------------------------------------
|
|
106
|
+
// STACK
|
|
107
|
+
// --------------------------------------------------
|
|
108
|
+
|
|
109
|
+
/*
|
|
110
|
+
* If we're moving back up the tree,
|
|
111
|
+
* remove deeper entries.
|
|
112
|
+
*
|
|
113
|
+
* Example:
|
|
114
|
+
*
|
|
115
|
+
* │ ├── index.js
|
|
116
|
+
* │ └── utils.js
|
|
117
|
+
*
|
|
118
|
+
* When utils.js is processed, index.js
|
|
119
|
+
* must be removed from the stack.
|
|
120
|
+
*/
|
|
121
|
+
|
|
122
|
+
while (stack.length > depth) {
|
|
123
|
+
stack.pop();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/*
|
|
127
|
+
* Make sure we aren't jumping over a level.
|
|
128
|
+
*/
|
|
53
129
|
if (depth > stack.length) {
|
|
54
130
|
throw new TreeParseError(
|
|
55
|
-
`
|
|
131
|
+
`Invalid nesting at depth ${depth}`,
|
|
56
132
|
lineNum
|
|
57
133
|
);
|
|
58
134
|
}
|
|
59
135
|
|
|
60
|
-
//
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
136
|
+
// --------------------------------------------------
|
|
137
|
+
// FILE / DIRECTORY
|
|
138
|
+
// --------------------------------------------------
|
|
64
139
|
|
|
65
|
-
|
|
66
|
-
const isDirectory = detectDirectory(name);
|
|
140
|
+
const isDirectory = name.endsWith('/');
|
|
67
141
|
|
|
68
|
-
const cleanName =
|
|
69
|
-
|
|
70
|
-
|
|
142
|
+
const cleanName = name.replace(/\/$/, '');
|
|
143
|
+
|
|
144
|
+
// --------------------------------------------------
|
|
145
|
+
// PATH
|
|
146
|
+
// --------------------------------------------------
|
|
71
147
|
|
|
72
|
-
// Add current item to stack
|
|
73
148
|
stack.push(cleanName);
|
|
74
149
|
|
|
75
150
|
const fullPath = path.join(...stack);
|
|
@@ -86,117 +161,46 @@ function parseTree(text) {
|
|
|
86
161
|
}
|
|
87
162
|
|
|
88
163
|
/**
|
|
89
|
-
*
|
|
90
|
-
*/
|
|
91
|
-
function parseLine(line) {
|
|
92
|
-
// Root:
|
|
93
|
-
// project/
|
|
94
|
-
if (!/^[│|├└+`]/.test(line)) {
|
|
95
|
-
return {
|
|
96
|
-
name: line.trim(),
|
|
97
|
-
depth: 0
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/*
|
|
102
|
-
* Match tree indentation.
|
|
103
|
-
*
|
|
104
|
-
* Examples:
|
|
105
|
-
*
|
|
106
|
-
* ├── src/
|
|
107
|
-
* └── package.json
|
|
108
|
-
*
|
|
109
|
-
* │ ├── components/
|
|
110
|
-
* │ └── App.jsx
|
|
111
|
-
*
|
|
112
|
-
* │ │ └── Button.jsx
|
|
113
|
-
*/
|
|
114
|
-
|
|
115
|
-
const match = line.match(/^((?:│ | )*)(?:├── |└── |\+-- |`-- )(.*)$/);
|
|
116
|
-
|
|
117
|
-
if (!match) {
|
|
118
|
-
return null;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const indentation = match[1];
|
|
122
|
-
const name = match[2].trim();
|
|
123
|
-
|
|
124
|
-
// Every 4-character indentation block = one level.
|
|
125
|
-
const depth = indentation.length / 4 + 1;
|
|
126
|
-
|
|
127
|
-
return {
|
|
128
|
-
name,
|
|
129
|
-
depth
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Determine whether an item is a directory.
|
|
135
|
-
*
|
|
136
|
-
* Best case: directories end with /.
|
|
137
|
-
*
|
|
138
|
-
* For trees that don't include /, this falls back to
|
|
139
|
-
* extension-based detection.
|
|
140
|
-
*/
|
|
141
|
-
function detectDirectory(name) {
|
|
142
|
-
// Explicit directory marker
|
|
143
|
-
if (name.endsWith('/')) {
|
|
144
|
-
return true;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Hidden files like .gitignore are files
|
|
148
|
-
if (name.startsWith('.')) {
|
|
149
|
-
return false;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Files with extensions are files
|
|
153
|
-
if (path.extname(name) !== '') {
|
|
154
|
-
return false;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Otherwise assume directory
|
|
158
|
-
return true;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Parse tree and create files/directories.
|
|
164
|
+
* Create files and directories from parsed tree.
|
|
163
165
|
*/
|
|
164
166
|
async function parseAndCreateTree(text) {
|
|
165
167
|
const created = [];
|
|
166
168
|
const errors = [];
|
|
167
169
|
|
|
170
|
+
let treeStructure;
|
|
171
|
+
|
|
168
172
|
try {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
for (const item of treeStructure) {
|
|
172
|
-
try {
|
|
173
|
-
if (item.isDirectory) {
|
|
174
|
-
fs.mkdirSync(item.fullPath, {
|
|
175
|
-
recursive: true
|
|
176
|
-
});
|
|
177
|
-
} else {
|
|
178
|
-
const parentDir = path.dirname(item.fullPath);
|
|
179
|
-
|
|
180
|
-
fs.mkdirSync(parentDir, {
|
|
181
|
-
recursive: true
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
fs.writeFileSync(item.fullPath, '');
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
created.push(item.fullPath);
|
|
188
|
-
} catch (err) {
|
|
189
|
-
errors.push(
|
|
190
|
-
`Failed to create ${item.fullPath}: ${err.message}`
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
173
|
+
treeStructure = parseTree(text);
|
|
194
174
|
} catch (err) {
|
|
195
175
|
if (err instanceof TreeParseError) {
|
|
196
176
|
throw err;
|
|
197
177
|
}
|
|
198
178
|
|
|
199
|
-
throw new Error(`Unexpected error: ${err.message}`);
|
|
179
|
+
throw new Error(`Unexpected parsing error: ${err.message}`);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
for (const item of treeStructure) {
|
|
183
|
+
try {
|
|
184
|
+
if (item.isDirectory) {
|
|
185
|
+
fs.mkdirSync(item.fullPath, {
|
|
186
|
+
recursive: true
|
|
187
|
+
});
|
|
188
|
+
} else {
|
|
189
|
+
const parentDir = path.dirname(item.fullPath);
|
|
190
|
+
|
|
191
|
+
fs.mkdirSync(parentDir, {
|
|
192
|
+
recursive: true
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
fs.writeFileSync(item.fullPath, '');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
created.push(item.fullPath);
|
|
199
|
+
} catch (err) {
|
|
200
|
+
errors.push(
|
|
201
|
+
`Failed to create ${item.fullPath}: ${err.message}`
|
|
202
|
+
);
|
|
203
|
+
}
|
|
200
204
|
}
|
|
201
205
|
|
|
202
206
|
return {
|
|
@@ -206,7 +210,7 @@ async function parseAndCreateTree(text) {
|
|
|
206
210
|
}
|
|
207
211
|
|
|
208
212
|
module.exports = {
|
|
209
|
-
parseAndCreateTree,
|
|
210
213
|
parseTree,
|
|
214
|
+
parseAndCreateTree,
|
|
211
215
|
TreeParseError
|
|
212
216
|
};
|