jvcs 1.6.9 → 1.7.3
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/controllers/add.js +48 -14
- package/controllers/begin.js +33 -7
- package/controllers/init.js +32 -23
- package/controllers/status.js +126 -70
- package/index.js +1 -1
- package/package.json +2 -2
package/controllers/add.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const { getGlobalConfig, checkforjvcs } = require("./utility")
|
|
2
2
|
const path = require("path")
|
|
3
3
|
const fssync = require("fs")
|
|
4
4
|
const chalk = require("chalk")
|
|
@@ -15,7 +15,7 @@ async function getFileHash(filepath) {
|
|
|
15
15
|
// load .jvcsignore file
|
|
16
16
|
async function loadIgnorePatterns() {
|
|
17
17
|
const ignorePath = path.join(process.cwd(), ".jvcsignore")
|
|
18
|
-
if(!fssync.existsSync(ignorePath)) return []
|
|
18
|
+
if (!fssync.existsSync(ignorePath)) return []
|
|
19
19
|
|
|
20
20
|
const content = await fs.readFile(ignorePath, "utf-8")
|
|
21
21
|
return content
|
|
@@ -61,26 +61,20 @@ async function addCmd(paths) {
|
|
|
61
61
|
|
|
62
62
|
if (!paths || paths.length === 0) {
|
|
63
63
|
console.log(chalk.yellow("Please specify files or folders to add."));
|
|
64
|
-
|
|
64
|
+
process.exit(1);
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
console.log(chalk.red("No existing session found. Please login or signup."))
|
|
69
|
-
console.log(chalk.green("jvcs --help for help"))
|
|
70
|
-
return
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
let configData = getGlobalConfig()
|
|
67
|
+
const configData = getGlobalConfig()
|
|
74
68
|
|
|
75
69
|
if (!configData) {
|
|
76
70
|
console.log(chalk.red("No existing session found. Please login or signup."))
|
|
77
71
|
console.log(chalk.green("jvcs --help for help"))
|
|
78
|
-
|
|
72
|
+
process.exit(1);
|
|
79
73
|
}
|
|
80
74
|
|
|
81
75
|
if (!checkforjvcs()) {
|
|
82
76
|
console.log(chalk.red("Repository is not initialized or is deleted. Please create it."))
|
|
83
|
-
|
|
77
|
+
process.exit(1);
|
|
84
78
|
}
|
|
85
79
|
|
|
86
80
|
const repoPath = path.join(process.cwd(), ".jvcs")
|
|
@@ -99,6 +93,43 @@ async function addCmd(paths) {
|
|
|
99
93
|
// load ignore patterns
|
|
100
94
|
const ignorePatterns = await loadIgnorePatterns()
|
|
101
95
|
|
|
96
|
+
// -------------------------------------------------------------
|
|
97
|
+
// NEW: Handle Deletions sync before adding new files
|
|
98
|
+
// -------------------------------------------------------------
|
|
99
|
+
let deletionHandledFor = new Set();
|
|
100
|
+
|
|
101
|
+
for (const key of Object.keys(hashData)) {
|
|
102
|
+
const cwdPath = path.join(process.cwd(), key);
|
|
103
|
+
|
|
104
|
+
// Check if the staged file falls under any of the target paths
|
|
105
|
+
let isUnderTarget = false;
|
|
106
|
+
if (paths.length === 1 && paths[0] === ".") {
|
|
107
|
+
isUnderTarget = true;
|
|
108
|
+
} else {
|
|
109
|
+
for (const p of paths) {
|
|
110
|
+
const targetPath = path.resolve(process.cwd(), p);
|
|
111
|
+
const relToTarget = path.relative(targetPath, cwdPath);
|
|
112
|
+
// If it's the exact file or inside the target directory
|
|
113
|
+
if (relToTarget === "" || (!relToTarget.startsWith("..") && !path.isAbsolute(relToTarget))) {
|
|
114
|
+
isUnderTarget = true;
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (isUnderTarget && !fssync.existsSync(cwdPath)) {
|
|
121
|
+
// File was deleted from working directory, remove it from staging
|
|
122
|
+
delete hashData[key];
|
|
123
|
+
const stagedTarget = path.join(staging, key);
|
|
124
|
+
if (fssync.existsSync(stagedTarget)) {
|
|
125
|
+
await fs.rm(stagedTarget);
|
|
126
|
+
}
|
|
127
|
+
console.log(chalk.red(`Removed deleted file: ${key}`));
|
|
128
|
+
deletionHandledFor.add(cwdPath);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
|
|
102
133
|
let targets = []
|
|
103
134
|
if (paths.length === 1 && paths[0] === ".") {
|
|
104
135
|
let rootEntries = await fs.readdir(process.cwd(), { withFileTypes: true })
|
|
@@ -114,7 +145,10 @@ async function addCmd(paths) {
|
|
|
114
145
|
try {
|
|
115
146
|
|
|
116
147
|
if (!fssync.existsSync(target)) {
|
|
117
|
-
|
|
148
|
+
// Only warn if we didn't just handle its deletion
|
|
149
|
+
if (!deletionHandledFor.has(target)) {
|
|
150
|
+
console.log(chalk.yellow(`Path not found: ${path.relative(process.cwd(), target)}`));
|
|
151
|
+
}
|
|
118
152
|
continue
|
|
119
153
|
}
|
|
120
154
|
|
|
@@ -155,7 +189,7 @@ async function addCmd(paths) {
|
|
|
155
189
|
}
|
|
156
190
|
}
|
|
157
191
|
catch (error) {
|
|
158
|
-
console.log(chalk.red(`Unexpected error: ${error.message}`));
|
|
192
|
+
console.log(chalk.red(`Unexpected error processing ${target}: ${error.message}`));
|
|
159
193
|
}
|
|
160
194
|
}
|
|
161
195
|
|
package/controllers/begin.js
CHANGED
|
@@ -10,14 +10,24 @@ const fs = require("fs")
|
|
|
10
10
|
|
|
11
11
|
async function beginCmd() {
|
|
12
12
|
|
|
13
|
-
const config = path.join(require("os").homedir(),".jvcs","config.json")
|
|
13
|
+
const config = path.join(require("os").homedir(), ".jvcs", "config.json")
|
|
14
14
|
let isInitialized = false
|
|
15
15
|
let configData = null
|
|
16
|
-
if(fs.existsSync(config)) {
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
if (fs.existsSync(config)) {
|
|
17
|
+
try {
|
|
18
|
+
configData = JSON.parse(fs.readFileSync(config, "utf-8"))
|
|
19
|
+
isInitialized = true
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
// corrupted file, delete it and force re-login
|
|
23
|
+
try {
|
|
24
|
+
fs.unlinkSync(config)
|
|
25
|
+
}
|
|
26
|
+
catch (e) { }
|
|
27
|
+
isInitialized = false
|
|
28
|
+
}
|
|
19
29
|
}
|
|
20
|
-
|
|
30
|
+
|
|
21
31
|
if (isInitialized) {
|
|
22
32
|
console.log(chalk.green(`You are already logged in as ${configData.username} (${configData.email})`))
|
|
23
33
|
console.log(chalk.yellow(`[1] Continue \n[2] Logout \nChoose an option (1/2) : `))
|
|
@@ -38,14 +48,20 @@ async function beginCmd() {
|
|
|
38
48
|
}
|
|
39
49
|
])
|
|
40
50
|
|
|
41
|
-
console.log(`Your choice was ${answer.choice}`)
|
|
42
51
|
if (answer.choice === "1") {
|
|
43
52
|
console.log(chalk.green("Continuing as current user..."))
|
|
44
53
|
console.log(chalk.green("jvcs --help for help"))
|
|
45
54
|
}
|
|
46
55
|
else {
|
|
47
56
|
console.log(chalk.green("logging out..."))
|
|
48
|
-
|
|
57
|
+
try {
|
|
58
|
+
if (fs.existsSync(config)) {
|
|
59
|
+
fs.unlinkSync(config)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
console.log(chalk.yellow("Warning: Could not remove config file properly."));
|
|
64
|
+
}
|
|
49
65
|
console.log(chalk.green("Logged out Successfully"))
|
|
50
66
|
console.log(chalk.green("Please login or signup again (jvcs begin) to use version control system"))
|
|
51
67
|
console.log(chalk.green("jvcs --help for help"))
|
|
@@ -80,6 +96,14 @@ async function beginCmd() {
|
|
|
80
96
|
{
|
|
81
97
|
type: 'input',
|
|
82
98
|
name: 'username',
|
|
99
|
+
validate: function (input) {
|
|
100
|
+
// Ensure no spaces or weird special characters in username
|
|
101
|
+
if (!/^[a-zA-Z0-9_]+$/.test(input)) {
|
|
102
|
+
return "Username can only contain alphanumeric characters and underscores";
|
|
103
|
+
}
|
|
104
|
+
if (input.length < 3) return "Username must be at least 3 characters long";
|
|
105
|
+
return true;
|
|
106
|
+
},
|
|
83
107
|
filter: function (input) {
|
|
84
108
|
return input.trim()
|
|
85
109
|
}
|
|
@@ -139,6 +163,7 @@ async function beginCmd() {
|
|
|
139
163
|
}
|
|
140
164
|
catch (error) {
|
|
141
165
|
console.log(chalk.red(error))
|
|
166
|
+
process.exit(1);
|
|
142
167
|
}
|
|
143
168
|
}
|
|
144
169
|
else {
|
|
@@ -194,6 +219,7 @@ async function beginCmd() {
|
|
|
194
219
|
}
|
|
195
220
|
catch (error) {
|
|
196
221
|
console.log(chalk.red(error))
|
|
222
|
+
process.exit(1);
|
|
197
223
|
}
|
|
198
224
|
}
|
|
199
225
|
}
|
package/controllers/init.js
CHANGED
|
@@ -6,16 +6,16 @@ const { getGlobalConfig, checkGlobalConfig } = require("./utility")
|
|
|
6
6
|
|
|
7
7
|
async function initCmd() {
|
|
8
8
|
|
|
9
|
-
if(!checkGlobalConfig()) {
|
|
9
|
+
if (!checkGlobalConfig()) {
|
|
10
10
|
console.log(chalk.red("No existing session found. Please login or signup."))
|
|
11
11
|
console.log(chalk.green("jvcs --help for help"))
|
|
12
12
|
return
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
let configData = null
|
|
16
16
|
configData = getGlobalConfig()
|
|
17
|
-
|
|
18
|
-
if(!configData) {
|
|
17
|
+
|
|
18
|
+
if (!configData) {
|
|
19
19
|
console.log(chalk.red("No existing session found. Please login or signup."))
|
|
20
20
|
console.log(chalk.green("jvcs --help for help"))
|
|
21
21
|
return
|
|
@@ -25,36 +25,45 @@ async function initCmd() {
|
|
|
25
25
|
const cwd = process.cwd()
|
|
26
26
|
const home = require("os").homedir()
|
|
27
27
|
|
|
28
|
-
if(cwd ===
|
|
28
|
+
if (cwd === home) {
|
|
29
29
|
console.log(chalk.red("Cannot initialize a repository in your home directory."));
|
|
30
30
|
console.log(chalk.yellow("Hint: navigate to a project folder and run 'jvcs init' there."));
|
|
31
31
|
process.exit(1);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
const repoPath = path.join(cwd,".jvcs")
|
|
35
|
-
if(fssync.existsSync(repoPath)) {
|
|
34
|
+
const repoPath = path.join(cwd, ".jvcs")
|
|
35
|
+
if (fssync.existsSync(repoPath)) {
|
|
36
36
|
console.log(chalk.yellow("Repository already is initialized."));
|
|
37
|
-
process.exit(
|
|
37
|
+
process.exit(0);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
40
|
+
try {
|
|
41
|
+
fssync.mkdirSync(repoPath)
|
|
42
|
+
fssync.mkdirSync(path.join(repoPath, "commits"))
|
|
43
|
+
fssync.mkdirSync(path.join(repoPath, "staging"))
|
|
44
|
+
|
|
45
|
+
const config = {
|
|
46
|
+
repoName: path.basename(cwd),
|
|
47
|
+
createdAt: new Date().toISOString(),
|
|
48
|
+
remote: null,
|
|
49
|
+
owner: {
|
|
50
|
+
username: configData.username,
|
|
51
|
+
email: configData.email
|
|
52
|
+
}
|
|
51
53
|
}
|
|
52
|
-
}
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
fssync.writeFileSync(path.join(repoPath, "config.json"), JSON.stringify(config, null, 2))
|
|
56
|
+
fssync.writeFileSync(path.join(repoPath, "HEAD"), "");
|
|
56
57
|
|
|
57
|
-
|
|
58
|
+
console.log(chalk.green(`Initialized empty JVCS repository in ${repoPath}`));
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
if (fssync.existsSync(repoPath)) {
|
|
62
|
+
fssync.rmSync(repoPath, { recursive: true, force: true });
|
|
63
|
+
}
|
|
64
|
+
console.log(chalk.red(`Failed to initialize repository: ${error.message}`));
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
58
67
|
}
|
|
59
68
|
|
|
60
69
|
module.exports = initCmd
|
package/controllers/status.js
CHANGED
|
@@ -1,17 +1,9 @@
|
|
|
1
|
-
// Untracked files
|
|
2
|
-
// Files that exist in your working directory (project folder) but have never been added to staging or committed.
|
|
3
|
-
|
|
4
|
-
// Changes to be committed
|
|
5
|
-
// Files that are in the staging area (.jvcs/staging) — meaning, you’ve already added them using jvcs add, but haven’t committed yet.
|
|
6
|
-
|
|
7
|
-
// Changes not staged for commit
|
|
8
|
-
// Files that were already added to staging earlier, but you modified them again in your working directory after staging — i.e., the staged copy and working copy are different.
|
|
9
|
-
|
|
10
1
|
const fs = require("fs");
|
|
11
2
|
const path = require("path");
|
|
12
3
|
const crypto = require("crypto");
|
|
13
4
|
const chalk = require("chalk");
|
|
14
|
-
const {
|
|
5
|
+
const { getGlobalConfig, checkforjvcs } = require("./utility");
|
|
6
|
+
const { minimatch } = require("minimatch");
|
|
15
7
|
|
|
16
8
|
// normalize relative path to use forward slashes for consistent comparisons
|
|
17
9
|
function normalizeRel(p) {
|
|
@@ -24,10 +16,26 @@ function hashfile(filepath) {
|
|
|
24
16
|
return crypto.createHash("sha256").update(data).digest("hex")
|
|
25
17
|
}
|
|
26
18
|
catch(error) {
|
|
27
|
-
|
|
19
|
+
return null;
|
|
28
20
|
}
|
|
29
21
|
}
|
|
30
22
|
|
|
23
|
+
function loadIgnorePatterns() {
|
|
24
|
+
const ignorePath = path.join(process.cwd(), ".jvcsignore");
|
|
25
|
+
if(!fs.existsSync(ignorePath)) return [];
|
|
26
|
+
|
|
27
|
+
const content = fs.readFileSync(ignorePath, "utf-8");
|
|
28
|
+
return content
|
|
29
|
+
.split(/[\n,]+/)
|
|
30
|
+
.map(line => line.trim())
|
|
31
|
+
.filter(line => line.length > 0 && !line.startsWith("#"));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function isIgnored(relativePath, ignorePatterns = []) {
|
|
35
|
+
return ignorePatterns.some(pattern =>
|
|
36
|
+
minimatch(relativePath, pattern, { dot: true })
|
|
37
|
+
);
|
|
38
|
+
}
|
|
31
39
|
|
|
32
40
|
function getAllFiles(dir, rootDir=dir, collected=[]) {
|
|
33
41
|
|
|
@@ -39,11 +47,12 @@ function getAllFiles(dir, rootDir=dir, collected=[]) {
|
|
|
39
47
|
const fullPath = path.join(dir,entry.name)
|
|
40
48
|
const rel = normalizeRel(path.relative(rootDir,fullPath))
|
|
41
49
|
|
|
42
|
-
if(entry.isDirectory() && (entry.name === ".jvcs" || entry.name === "
|
|
43
|
-
|
|
50
|
+
if(entry.isDirectory() && (entry.name === ".jvcs" || entry.name === ".git"))
|
|
51
|
+
continue;
|
|
44
52
|
|
|
45
|
-
|
|
46
|
-
|
|
53
|
+
// Skip internal files from being hashed/tracked in cwd maps
|
|
54
|
+
if(entry.isFile() && (entry.name === "meta.json" || entry.name === "jvcs_hashcode.json" || entry.name === ".jvcsignore"))
|
|
55
|
+
continue;
|
|
47
56
|
|
|
48
57
|
if(entry.isFile()) {
|
|
49
58
|
collected.push(rel);
|
|
@@ -51,7 +60,6 @@ function getAllFiles(dir, rootDir=dir, collected=[]) {
|
|
|
51
60
|
else if(entry.isDirectory()) {
|
|
52
61
|
getAllFiles(fullPath, rootDir, collected);
|
|
53
62
|
}
|
|
54
|
-
|
|
55
63
|
}
|
|
56
64
|
|
|
57
65
|
return collected
|
|
@@ -59,21 +67,16 @@ function getAllFiles(dir, rootDir=dir, collected=[]) {
|
|
|
59
67
|
|
|
60
68
|
async function statusCmd() {
|
|
61
69
|
|
|
62
|
-
if(!checkGlobalConfig()) {
|
|
63
|
-
console.log(chalk.red("No existing session found. Please login or signup."));
|
|
64
|
-
console.log(chalk.green("jvcs --help for help"));
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
70
|
const configData = getGlobalConfig();
|
|
69
71
|
if(!configData) {
|
|
70
72
|
console.log(chalk.red("No existing session found. Please login or signup."));
|
|
71
|
-
|
|
73
|
+
console.log(chalk.green("jvcs --help for help"));
|
|
74
|
+
process.exit(1);
|
|
72
75
|
}
|
|
73
76
|
|
|
74
77
|
if(!checkforjvcs()) {
|
|
75
|
-
console.log(chalk.red("Repository is not initialized or is deleted."));
|
|
76
|
-
|
|
78
|
+
console.log(chalk.red("Repository is not initialized or is deleted. Please create it."));
|
|
79
|
+
process.exit(1);
|
|
77
80
|
}
|
|
78
81
|
|
|
79
82
|
const cwd = process.cwd()
|
|
@@ -84,77 +87,130 @@ async function statusCmd() {
|
|
|
84
87
|
|
|
85
88
|
if(!fs.existsSync(jvcsDir)) {
|
|
86
89
|
console.log(chalk.red("No repository exists. Please create one using 'jvcs init'"))
|
|
87
|
-
|
|
90
|
+
process.exit(1);
|
|
88
91
|
}
|
|
89
92
|
|
|
90
|
-
|
|
93
|
+
const ignorePatterns = loadIgnorePatterns();
|
|
94
|
+
|
|
95
|
+
// 1. Collect hashes for CWD
|
|
91
96
|
const cwdFiles = getAllFiles(cwd, cwd, []);
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
const cwdMap = new Map();
|
|
98
|
+
for(const f of cwdFiles) {
|
|
99
|
+
if (!isIgnored(f, ignorePatterns)) {
|
|
100
|
+
const h = hashfile(path.join(cwd, f));
|
|
101
|
+
if (h) cwdMap.set(f, h);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// 2. Collect hashes for HEAD
|
|
106
|
+
const headMap = new Map();
|
|
107
|
+
if (fs.existsSync(commitDir) && fs.existsSync(headFile)) {
|
|
108
|
+
const headFileContent = fs.readFileSync(headFile, "utf-8").trim();
|
|
109
|
+
if (headFileContent) {
|
|
110
|
+
const commitPath = path.join(commitDir, headFileContent);
|
|
111
|
+
if (fs.existsSync(commitPath)) {
|
|
112
|
+
const commitFiles = getAllFiles(commitPath, commitPath, []);
|
|
113
|
+
for (const f of commitFiles) {
|
|
114
|
+
const h = hashfile(path.join(commitPath, f));
|
|
115
|
+
if (h) headMap.set(f, h);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
100
118
|
}
|
|
101
119
|
}
|
|
102
120
|
|
|
103
|
-
//
|
|
104
|
-
const
|
|
105
|
-
const
|
|
121
|
+
// 3. Collect hashes for Staging (Index)
|
|
122
|
+
const stagingMap = new Map();
|
|
123
|
+
const hashPath = path.join(stagingDir, "jvcs_hashcode.json");
|
|
124
|
+
if (fs.existsSync(hashPath)) {
|
|
125
|
+
try {
|
|
126
|
+
const data = JSON.parse(fs.readFileSync(hashPath, "utf-8"));
|
|
127
|
+
for (const [key, val] of Object.entries(data)) {
|
|
128
|
+
stagingMap.set(normalizeRel(key), val.hash);
|
|
129
|
+
}
|
|
130
|
+
} catch(e) {}
|
|
131
|
+
} else {
|
|
132
|
+
// Fallback
|
|
133
|
+
if (fs.existsSync(stagingDir)) {
|
|
134
|
+
const stFiles = getAllFiles(stagingDir, stagingDir, []);
|
|
135
|
+
for(const f of stFiles) {
|
|
136
|
+
const h = hashfile(path.join(stagingDir, f));
|
|
137
|
+
if (h) stagingMap.set(f, h);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
106
141
|
|
|
107
|
-
//
|
|
108
|
-
const untracked = cwdFiles.filter(f => !stagedSet.has(f) && !committedSet.has(f));
|
|
142
|
+
// --- CALCULATE DIFFS ---
|
|
109
143
|
|
|
110
|
-
//
|
|
111
|
-
const
|
|
144
|
+
// Untracked files
|
|
145
|
+
const untracked = [];
|
|
146
|
+
for (const f of cwdMap.keys()) {
|
|
147
|
+
if (!stagingMap.has(f)) {
|
|
148
|
+
untracked.push(f);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
112
151
|
|
|
113
|
-
//
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if(!fs.existsSync(cwdFilePath) || !fs.existsSync(stagedFilePath))
|
|
119
|
-
return false
|
|
152
|
+
// Staged changes (Diff between Staging and HEAD)
|
|
153
|
+
const stagedAdded = [];
|
|
154
|
+
const stagedModified = [];
|
|
155
|
+
const stagedDeleted = [];
|
|
120
156
|
|
|
121
|
-
|
|
122
|
-
|
|
157
|
+
for (const [f, sHash] of stagingMap.entries()) {
|
|
158
|
+
if (!headMap.has(f)) {
|
|
159
|
+
stagedAdded.push(f);
|
|
160
|
+
} else if (headMap.get(f) !== sHash) {
|
|
161
|
+
stagedModified.push(f);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
for (const f of headMap.keys()) {
|
|
165
|
+
if (!stagingMap.has(f)) {
|
|
166
|
+
stagedDeleted.push(f);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
123
169
|
|
|
124
|
-
|
|
125
|
-
|
|
170
|
+
// Unstaged changes (Diff between CWD and Staging)
|
|
171
|
+
const unstagedModified = [];
|
|
172
|
+
const unstagedDeleted = [];
|
|
126
173
|
|
|
174
|
+
for (const [f, sHash] of stagingMap.entries()) {
|
|
175
|
+
if (!cwdMap.has(f)) {
|
|
176
|
+
unstagedDeleted.push(f);
|
|
177
|
+
} else if (cwdMap.get(f) !== sHash) {
|
|
178
|
+
unstagedModified.push(f);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
127
181
|
|
|
128
|
-
//
|
|
182
|
+
// --- OUTPUT ---
|
|
129
183
|
console.log(chalk.bold.blue(`\nOn branch: main (default)`));
|
|
130
184
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
185
|
+
const hasStaged = stagedAdded.length > 0 || stagedModified.length > 0 || stagedDeleted.length > 0;
|
|
186
|
+
console.log(chalk.bold.green("\nChanges to be committed:"));
|
|
187
|
+
if (hasStaged) {
|
|
188
|
+
stagedAdded.forEach(f => console.log(chalk.green(`\tnew file: ${f}`)));
|
|
189
|
+
stagedModified.forEach(f => console.log(chalk.green(`\tmodified: ${f}`)));
|
|
190
|
+
stagedDeleted.forEach(f => console.log(chalk.green(`\tdeleted: ${f}`)));
|
|
191
|
+
} else {
|
|
136
192
|
console.log(chalk.gray("\tNo changes added to commit"));
|
|
137
193
|
}
|
|
138
194
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
195
|
+
const hasUnstaged = unstagedModified.length > 0 || unstagedDeleted.length > 0;
|
|
196
|
+
console.log(chalk.bold.yellow("\nChanges not staged for commit:"));
|
|
197
|
+
if (hasUnstaged) {
|
|
198
|
+
unstagedModified.forEach(f => console.log(chalk.yellow(`\tmodified: ${f}`)));
|
|
199
|
+
unstagedDeleted.forEach(f => console.log(chalk.yellow(`\tdeleted: ${f}`)));
|
|
200
|
+
} else {
|
|
144
201
|
console.log(chalk.gray("\tNo modified files detected"));
|
|
145
202
|
}
|
|
146
203
|
|
|
147
|
-
console.log(chalk.bold.red("\nUntracked files
|
|
148
|
-
if(untracked.length > 0) {
|
|
204
|
+
console.log(chalk.bold.red("\nUntracked files:"));
|
|
205
|
+
if (untracked.length > 0) {
|
|
149
206
|
untracked.forEach(f => console.log(chalk.red(`\t${f}`)));
|
|
150
|
-
}
|
|
151
|
-
else {
|
|
207
|
+
} else {
|
|
152
208
|
console.log(chalk.gray("\tNo untracked files"));
|
|
153
209
|
}
|
|
154
210
|
|
|
155
211
|
console.log(chalk.gray("\n(use 'jvcs add <file>' to stage changes)"));
|
|
156
212
|
console.log(chalk.gray("(use 'jvcs commit -m \"message\"' to commit changes)"));
|
|
157
|
-
console.log(chalk.gray("(use 'jvcs unstage <file>/<folder> to unstage a file/folder
|
|
213
|
+
console.log(chalk.gray("(use 'jvcs unstage <file>/<folder>' to unstage a file/folder)"));
|
|
158
214
|
}
|
|
159
215
|
|
|
160
|
-
module.exports = statusCmd
|
|
216
|
+
module.exports = statusCmd;
|
package/index.js
CHANGED