jvcs 1.0.2 → 1.0.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/.env CHANGED
@@ -1,4 +1,4 @@
1
- CLIENT_ID='835069827989-3spob55ioa2ocudi3mo8u2ni2ecqohh7.apps.googleusercontent.com';
2
- CLIENT_SECRET='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';
3
- REDIRECT_URI='https://developers.google.com/oauthplayground';
4
- REFRESH_TOKEN='1//046r33XEFgQbICgYIARAAGAQSNwF-L9Ir_HV79cxAU_xla01zIvHyko6dBz0xoJ9Xhb0UQTbEqdf2czDvhkFFZUszyUQWzYw-5WQ';
1
+ CLIENT_ID=835069827989-3spob55ioa2ocudi3mo8u2ni2ecqohh7.apps.googleusercontent.com
2
+ CLIENT_SECRET=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
3
+ REDIRECT_URI=https://developers.google.com/oauthplayground
4
+ REFRESH_TOKEN=1//04wJgrjHWoDOZCgYIARAAGAQSNwF-L9Iryvz_RHMDkqyYlK2wv9TiVMsvq1eghHFnbS868U-zraLb44f8dEPvpNjJEmex_IcMxUE
package/.jvcs/HEAD ADDED
@@ -0,0 +1 @@
1
+ 3a1169c8-ec67-4ce5-8024-ab4f08d7b609
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env node
2
+
3
+ const yargs = require("yargs");
4
+ const { hideBin } = require("yargs/helpers");
5
+ const chalk = require("chalk");
6
+ const dotenv = require("dotenv")
7
+ dotenv.config()
8
+
9
+ const beginCmd = require("./controllers/begin")
10
+ const initCmd = require("./controllers/init")
11
+ const addCmd = require("./controllers/add")
12
+ const commitCmd = require("./controllers/commit")
13
+ const unstageCmd = require("./controllers/unstage")
14
+ const logCmd = require("./controllers/log");
15
+ const pushCmd = require("./controllers/push");
16
+
17
+
18
+ yargs(hideBin(process.argv))
19
+ .scriptName("jvcs")
20
+ .command(
21
+ "begin",
22
+ chalk.blue("Initialize the Version Control System (login/signup).\n"),
23
+ {},
24
+ async () => {
25
+ try {
26
+ await beginCmd()
27
+ }
28
+ catch(error) {
29
+ console.log(chalk.red(error))
30
+ }
31
+ }
32
+ )
33
+ .command(
34
+ "init",
35
+ chalk.blue("Create an empty repository.\n"),
36
+ {},
37
+ async () => {
38
+ try {
39
+ await initCmd()
40
+ }
41
+ catch(error) {
42
+ console.log(chalk.red(error))
43
+ }
44
+ }
45
+ )
46
+ .command(
47
+ "add <paths...>",
48
+ chalk.blue(
49
+ `Add files or folders to the staging area.
50
+
51
+ Command | Description
52
+ ---------------------------------|-------------------
53
+ jvcs add . | all files/folders
54
+ jvcs add <file1> <file2> | multiple files
55
+ jvcs add <folder1> <folder2> | multiple folders
56
+ jvcs add <file> <folder> | files and folders\n`
57
+ ),
58
+ (yargs)=> {
59
+ return yargs.positional("paths", {
60
+ type: 'string',
61
+ describe: 'Files and folders to stage'
62
+ })
63
+ },
64
+ async (argv) => {
65
+ try {
66
+ await addCmd(argv.paths)
67
+ }
68
+ catch(error) {
69
+ console.log(chalk.red(error))
70
+ }
71
+ }
72
+ )
73
+ .command(
74
+ "commit <message>",
75
+ chalk.blue("Commit all the files/folders inside staging area\n"),
76
+ (yargs)=> {
77
+ return yargs.positional("message", {
78
+ type: 'string',
79
+ describe: 'Some message with your commit'
80
+ })
81
+ },
82
+ async (argv)=> {
83
+ try {
84
+ await commitCmd(argv.message)
85
+ }
86
+ catch(error) {
87
+ console.log(chalk.red(error))
88
+ }
89
+ }
90
+ )
91
+ .command(
92
+ "unstage <paths...>",
93
+ chalk.blue(`
94
+ Remove files and folders from staging area
95
+
96
+ Command | Description
97
+ ---------------------------------|-------------------
98
+ jvcs unstage . | all files/folders
99
+ jvcs unstage <file1> <file2> | multiple files
100
+ jvcs unstage <folder1> <folder2> | multiple folders
101
+ jvcs unstage <file> <folder> | files and folders\n
102
+ `),
103
+ (yargs)=> {
104
+ return yargs.positional("paths", {
105
+ type: 'string',
106
+ describe: 'Files and folders to unstage'
107
+ })
108
+ },
109
+ async (argv)=> {
110
+ try {
111
+ await unstageCmd(argv.paths)
112
+ }
113
+ catch(error) {
114
+ console.log(chalk.red(error))
115
+ }
116
+ }
117
+ )
118
+ .command(
119
+ "log",
120
+ "show details of all commits",
121
+ {},
122
+ async ()=> {
123
+ try {
124
+ await logCmd()
125
+ }
126
+ catch(error) {
127
+ console.log(chalk.red(error))
128
+ }
129
+ }
130
+ )
131
+ .command(
132
+ "push",
133
+ "Push all the commits to remote",
134
+ {},
135
+ async ()=> {
136
+ try {
137
+ await pushCmd()
138
+ }
139
+ catch(error) {
140
+ console.log(chalk.red(error))
141
+ }
142
+ }
143
+ )
144
+ .demandCommand(1, chalk.yellow("You need at least one command"))
145
+ .help()
146
+ .parse();
@@ -0,0 +1,6 @@
1
+ {
2
+ "index.js": {
3
+ "hash": "ba4b020c3a1b7cd4e9bb5d8ea1979236ced22891fff322dc38c567917a04eb03",
4
+ "time": "2025-10-27T17:03:25.838Z"
5
+ }
6
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "author": "jagdish",
3
+ "id": "3a1169c8-ec67-4ce5-8024-ab4f08d7b609",
4
+ "message": "m2",
5
+ "timeStamp": "2025-10-27T17:04:27.217Z",
6
+ "parentId": "c362f97f-997b-499a-bb45-9e67f298f61e"
7
+ }
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env node
2
+
3
+ const yargs = require("yargs");
4
+ const { hideBin } = require("yargs/helpers");
5
+ const chalk = require("chalk");
6
+ const dotenv = require("dotenv")
7
+ dotenv.config()
8
+
9
+ const beginCmd = require("./controllers/begin")
10
+ const initCmd = require("./controllers/init")
11
+ const addCmd = require("./controllers/add")
12
+ const commitCmd = require("./controllers/commit")
13
+ const unstageCmd = require("./controllers/unstage")
14
+ const logCmd = require("./controllers/log");
15
+ const pushCmd = require("./controllers/push");
16
+
17
+
18
+ yargs(hideBin(process.argv))
19
+ .scriptName("jvcs")
20
+ .command(
21
+ "begin",
22
+ chalk.blue("Initialize the Version Control System (login/signup).\n"),
23
+ {},
24
+ async () => {
25
+ try {
26
+ await beginCmd()
27
+ }
28
+ catch(error) {
29
+ console.log(chalk.red(error))
30
+ }
31
+ }
32
+ )
33
+ .command(
34
+ "init",
35
+ chalk.blue("Create an empty repository.\n"),
36
+ {},
37
+ async () => {
38
+ try {
39
+ await initCmd()
40
+ }
41
+ catch(error) {
42
+ console.log(chalk.red(error))
43
+ }
44
+ }
45
+ )
46
+ .command(
47
+ "add <paths...>",
48
+ chalk.blue(
49
+ `Add files or folders to the staging area.
50
+
51
+ Command | Description
52
+ ---------------------------------|-------------------
53
+ jvcs add . | all files/folders
54
+ jvcs add <file1> <file2> | multiple files
55
+ jvcs add <folder1> <folder2> | multiple folders
56
+ jvcs add <file> <folder> | files and folders\n`
57
+ ),
58
+ (yargs)=> {
59
+ return yargs.positional("paths", {
60
+ type: 'string',
61
+ describe: 'Files and folders to stage'
62
+ })
63
+ },
64
+ async (argv) => {
65
+ try {
66
+ await addCmd(argv.paths)
67
+ }
68
+ catch(error) {
69
+ console.log(chalk.red(error))
70
+ }
71
+ }
72
+ )
73
+ .command(
74
+ "commit <message>",
75
+ chalk.blue("Commit all the files/folders inside staging area\n"),
76
+ (yargs)=> {
77
+ return yargs.positional("message", {
78
+ type: 'string',
79
+ describe: 'Some message with your commit'
80
+ })
81
+ },
82
+ async (argv)=> {
83
+ try {
84
+ await commitCmd(argv.message)
85
+ }
86
+ catch(error) {
87
+ console.log(chalk.red(error))
88
+ }
89
+ }
90
+ )
91
+ .command(
92
+ "unstage <paths...>",
93
+ chalk.blue(`
94
+ Remove files and folders from staging area
95
+
96
+ Command | Description
97
+ ---------------------------------|-------------------
98
+ jvcs unstage . | all files/folders
99
+ jvcs unstage <file1> <file2> | multiple files
100
+ jvcs unstage <folder1> <folder2> | multiple folders
101
+ jvcs unstage <file> <folder> | files and folders\n
102
+ `),
103
+ (yargs)=> {
104
+ return yargs.positional("paths", {
105
+ type: 'string',
106
+ describe: 'Files and folders to unstage'
107
+ })
108
+ },
109
+ async (argv)=> {
110
+ try {
111
+ await unstageCmd(argv.paths)
112
+ }
113
+ catch(error) {
114
+ console.log(chalk.red(error))
115
+ }
116
+ }
117
+ )
118
+ .command(
119
+ "log",
120
+ "show details of all commits",
121
+ {},
122
+ async ()=> {
123
+ try {
124
+ await logCmd()
125
+ }
126
+ catch(error) {
127
+ console.log(chalk.red(error))
128
+ }
129
+ }
130
+ )
131
+ .command(
132
+ "push",
133
+ "Push all the commits to remote",
134
+ {},
135
+ async ()=> {
136
+ try {
137
+ await pushCmd()
138
+ }
139
+ catch(error) {
140
+ console.log(chalk.red(error))
141
+ }
142
+ }
143
+ )
144
+ .demandCommand(1, chalk.yellow("You need at least one command"))
145
+ .help()
146
+ .parse();
@@ -0,0 +1,6 @@
1
+ {
2
+ "index.js": {
3
+ "hash": "ba4b020c3a1b7cd4e9bb5d8ea1979236ced22891fff322dc38c567917a04eb03",
4
+ "time": "2025-10-27T17:03:25.838Z"
5
+ }
6
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "author": "jagdish",
3
+ "id": "c362f97f-997b-499a-bb45-9e67f298f61e",
4
+ "message": "m1",
5
+ "timeStamp": "2025-10-27T17:03:35.670Z",
6
+ "parentId": null
7
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "repoName": "backend2",
3
+ "createdAt": "2025-10-27T17:03:18.444Z",
4
+ "remote": null,
5
+ "owner": {
6
+ "username": "jagdish",
7
+ "email": "pathakjijagdish1@gmail.com"
8
+ }
9
+ }
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env node
2
+
3
+ const yargs = require("yargs");
4
+ const { hideBin } = require("yargs/helpers");
5
+ const chalk = require("chalk");
6
+ const dotenv = require("dotenv")
7
+ dotenv.config()
8
+
9
+ const beginCmd = require("./controllers/begin")
10
+ const initCmd = require("./controllers/init")
11
+ const addCmd = require("./controllers/add")
12
+ const commitCmd = require("./controllers/commit")
13
+ const unstageCmd = require("./controllers/unstage")
14
+ const logCmd = require("./controllers/log");
15
+ const pushCmd = require("./controllers/push");
16
+
17
+
18
+ yargs(hideBin(process.argv))
19
+ .scriptName("jvcs")
20
+ .command(
21
+ "begin",
22
+ chalk.blue("Initialize the Version Control System (login/signup).\n"),
23
+ {},
24
+ async () => {
25
+ try {
26
+ await beginCmd()
27
+ }
28
+ catch(error) {
29
+ console.log(chalk.red(error))
30
+ }
31
+ }
32
+ )
33
+ .command(
34
+ "init",
35
+ chalk.blue("Create an empty repository.\n"),
36
+ {},
37
+ async () => {
38
+ try {
39
+ await initCmd()
40
+ }
41
+ catch(error) {
42
+ console.log(chalk.red(error))
43
+ }
44
+ }
45
+ )
46
+ .command(
47
+ "add <paths...>",
48
+ chalk.blue(
49
+ `Add files or folders to the staging area.
50
+
51
+ Command | Description
52
+ ---------------------------------|-------------------
53
+ jvcs add . | all files/folders
54
+ jvcs add <file1> <file2> | multiple files
55
+ jvcs add <folder1> <folder2> | multiple folders
56
+ jvcs add <file> <folder> | files and folders\n`
57
+ ),
58
+ (yargs)=> {
59
+ return yargs.positional("paths", {
60
+ type: 'string',
61
+ describe: 'Files and folders to stage'
62
+ })
63
+ },
64
+ async (argv) => {
65
+ try {
66
+ await addCmd(argv.paths)
67
+ }
68
+ catch(error) {
69
+ console.log(chalk.red(error))
70
+ }
71
+ }
72
+ )
73
+ .command(
74
+ "commit <message>",
75
+ chalk.blue("Commit all the files/folders inside staging area\n"),
76
+ (yargs)=> {
77
+ return yargs.positional("message", {
78
+ type: 'string',
79
+ describe: 'Some message with your commit'
80
+ })
81
+ },
82
+ async (argv)=> {
83
+ try {
84
+ await commitCmd(argv.message)
85
+ }
86
+ catch(error) {
87
+ console.log(chalk.red(error))
88
+ }
89
+ }
90
+ )
91
+ .command(
92
+ "unstage <paths...>",
93
+ chalk.blue(`
94
+ Remove files and folders from staging area
95
+
96
+ Command | Description
97
+ ---------------------------------|-------------------
98
+ jvcs unstage . | all files/folders
99
+ jvcs unstage <file1> <file2> | multiple files
100
+ jvcs unstage <folder1> <folder2> | multiple folders
101
+ jvcs unstage <file> <folder> | files and folders\n
102
+ `),
103
+ (yargs)=> {
104
+ return yargs.positional("paths", {
105
+ type: 'string',
106
+ describe: 'Files and folders to unstage'
107
+ })
108
+ },
109
+ async (argv)=> {
110
+ try {
111
+ await unstageCmd(argv.paths)
112
+ }
113
+ catch(error) {
114
+ console.log(chalk.red(error))
115
+ }
116
+ }
117
+ )
118
+ .command(
119
+ "log",
120
+ "show details of all commits",
121
+ {},
122
+ async ()=> {
123
+ try {
124
+ await logCmd()
125
+ }
126
+ catch(error) {
127
+ console.log(chalk.red(error))
128
+ }
129
+ }
130
+ )
131
+ .command(
132
+ "push",
133
+ "Push all the commits to remote",
134
+ {},
135
+ async ()=> {
136
+ try {
137
+ await pushCmd()
138
+ }
139
+ catch(error) {
140
+ console.log(chalk.red(error))
141
+ }
142
+ }
143
+ )
144
+ .demandCommand(1, chalk.yellow("You need at least one command"))
145
+ .help()
146
+ .parse();
@@ -0,0 +1,6 @@
1
+ {
2
+ "index.js": {
3
+ "hash": "ba4b020c3a1b7cd4e9bb5d8ea1979236ced22891fff322dc38c567917a04eb03",
4
+ "time": "2025-10-27T17:03:25.838Z"
5
+ }
6
+ }
@@ -0,0 +1,56 @@
1
+ const { drive } = require("../config/drive-config");
2
+
3
+ async function getDirectoryStructure(username,reponame,commitId) {
4
+
5
+
6
+ async function findOrCreateFolder(name,parentId=null) {
7
+
8
+ const query = [
9
+ `name='${name}'`,
10
+ "mimeType='application/vnd.google-apps.folder'",
11
+ "trashed=false"
12
+ ]
13
+
14
+ if(parentId) {
15
+ query.push(`'${parentId}' in parents`)
16
+ }
17
+
18
+ const res = await drive.files.list({
19
+ q: query.join(" and "),
20
+ fields: "files(id,name)"
21
+ })
22
+
23
+ if (res.data.files.length > 0)
24
+ return { id: res.data.files[0].id, alreadyExists: true };
25
+
26
+ const folderMetaData = {
27
+ name,
28
+ mimeType: "application/vnd.google-apps.folder",
29
+ }
30
+ if(parentId) folderMetaData.parents = [parentId];
31
+
32
+ const folder = await drive.files.create({
33
+ resource: folderMetaData,
34
+ fields: "id"
35
+ })
36
+
37
+ return { id: folder.data.id, alreadyExists: false };
38
+ }
39
+
40
+ // Build folder hierarchy in drive
41
+ const githubClone = await findOrCreateFolder("GithubClone");
42
+ const userFolder = await findOrCreateFolder(username,githubClone.id)
43
+ const repoFolder = await findOrCreateFolder(reponame,userFolder.id)
44
+ const commitFolderName = `commit_${commitId}`
45
+ const commitFolder = await findOrCreateFolder(commitFolderName,repoFolder.id)
46
+
47
+ return {
48
+ githubClone: githubClone.id,
49
+ userFolder: userFolder.id,
50
+ repoFolder: repoFolder.id,
51
+ commitFolder: commitFolder.id,
52
+ commitAlreadyExists: commitFolder.alreadyExists
53
+ }
54
+ }
55
+
56
+ module.exports = getDirectoryStructure
@@ -1,135 +1,145 @@
1
- const fs = require("fs");
2
- const fsPromises = require("fs").promises;
3
- const path = require("path");
4
- const chalk = require("chalk");
5
- const { drive } = require("../config/drive-config");
6
- const saveData = require("../controllers/saveData");
7
- const { checkInitialization, checkRepoExists, getCLIConfig } = require("./utils");
8
-
9
- async function pushCmd(reponame) {
10
- try {
11
- if (!checkInitialization()) return;
12
- if (!checkRepoExists(reponame)) return;
1
+ const fs = require("fs")
2
+ const path = require("path")
3
+ const chalk = require("chalk")
4
+ const { drive } = require("../config/drive-config")
5
+ const { getGlobalConfig, checkGlobalConfig, checkforjvcs } = require("./utility")
6
+ const getDirectoryStructure = require("./driveUtility")
13
7
 
14
- const repoPath = path.join(process.cwd(), `.${reponame}`);
15
- const commitFolder = path.join(repoPath, "commits");
8
+ async function uploadFile(localFile, parentId) {
16
9
 
17
- const config = await getCLIConfig();
18
- if (!config) return console.log(chalk.red("Could not read CLI configuration."));
10
+ try {
19
11
 
20
- console.log(chalk.blue("Pushing commits for user:"), chalk.green(config.username));
12
+ const fileName = path.basename(localFile)
13
+ const fileMetaData = {
14
+ name: fileName,
15
+ parents: [parentId]
16
+ }
21
17
 
22
- // Check commits locally
23
- const commitDirs = await fsPromises.readdir(commitFolder);
24
- if (!commitDirs.length) {
25
- console.log(chalk.yellow("⚠ No commits to push."));
26
- return;
18
+ const media = {
19
+ mimeType: "application/octet-stream",
20
+ body: fs.createReadStream(localFile),
27
21
  }
28
22
 
29
- // Ensure user folder exists in Google Drive
30
- let userFolderId;
31
- const userFolderRes = await drive.files.list({
32
- q: `name='${config.username}' and '1ahuoMCN_Ls5kGF2KPUGLbRZb9kGVMe0V' in parents and mimeType='application/vnd.google-apps.folder' and trashed=false`,
33
- fields: "files(id, name)"
34
- });
23
+ const res = await drive.files.create({
24
+ resource: fileMetaData,
25
+ media,
26
+ fields: "id"
27
+ })
28
+
29
+ console.log(chalk.gray(` ↳ Uploaded: ${fileName}`));
30
+ return res.data.id;
31
+ }
32
+ catch(error) {
33
+ console.log(chalk.red(`Failed to upload ${filePath}: ${err.message}`));
34
+ }
35
+ }
36
+
37
+ async function uploadDirectory(localDir, parentId) {
38
+
39
+ const entries = fs.readdirSync(localDir, {withFileTypes: true})
40
+
41
+ for(const entry of entries) {
42
+
43
+ const entryPath = path.join(localDir,entry.name)
44
+
45
+ if(entry.isDirectory()) {
46
+ const folderMeta = {
47
+ name: entry.name,
48
+ mimeType: "application/vnd.google-apps.folder",
49
+ parents: [parentId],
50
+ }
35
51
 
36
- if (userFolderRes.data.files.length) {
37
- userFolderId = userFolderRes.data.files[0].id;
38
- } else {
39
52
  const folder = await drive.files.create({
40
- requestBody: {
41
- name: config.username,
42
- mimeType: "application/vnd.google-apps.folder",
43
- parents: ["1ahuoMCN_Ls5kGF2KPUGLbRZb9kGVMe0V"]
44
- },
45
- fields: "id, name"
46
- });
47
- userFolderId = folder.data.id;
48
- console.log(chalk.green(`Created user folder in Drive.`));
53
+ resource: folderMeta,
54
+ fields: "id"
55
+ })
56
+
57
+ await uploadDirectory(entryPath,folder.data.id)
58
+ }
59
+ else {
60
+ await uploadFile(entryPath,parentId)
49
61
  }
62
+ }
63
+ }
50
64
 
51
- // Ensure repo folder exists
52
- let repoFolderId;
53
- const repoFolderRes = await drive.files.list({
54
- q: `name='${reponame}' and '${userFolderId}' in parents and mimeType='application/vnd.google-apps.folder' and trashed=false`,
55
- fields: "files(id, name)"
56
- });
65
+ async function pushCmd() {
57
66
 
58
- if (repoFolderRes.data.files.length) {
59
- repoFolderId = repoFolderRes.data.files[0].id;
60
- } else {
61
- const folder = await drive.files.create({
62
- requestBody: {
63
- name: reponame,
64
- mimeType: "application/vnd.google-apps.folder",
65
- parents: [userFolderId]
66
- },
67
- fields: "id, name"
68
- });
69
- repoFolderId = folder.data.id;
70
- console.log(chalk.green(`Created repo folder '${reponame}' in Drive.`));
67
+ try {
68
+
69
+ if(!checkGlobalConfig()) {
70
+ console.log(chalk.red("No existing session found. Please login or signup."))
71
+ console.log(chalk.green("jvcs --help for help"))
72
+ return
73
+ }
74
+
75
+ let configData = getGlobalConfig()
76
+
77
+ if(!configData) {
78
+ console.log(chalk.red("No existing session found. Please login or signup."))
79
+ console.log(chalk.green("jvcs --help for help"))
80
+ return
81
+ }
82
+
83
+ if(!checkforjvcs()) {
84
+ console.log(chalk.red("Repository is not initialized or is deleted. Please create it."))
85
+ return
71
86
  }
87
+
88
+ const cwd = process.cwd()
89
+ const jvcsDir = path.join(cwd,".jvcs")
90
+ const commitDir = path.join(jvcsDir,"commits")
91
+ const reponame = path.basename(process.cwd())
92
+
93
+ if(!fs.existsSync(commitDir)) {
94
+ console.log(chalk.yellow("No commits to push"))
95
+ return
96
+ }
97
+
98
+ // storing the name of commit folders
99
+ const commitFolders = fs.readdirSync(commitDir, {withFileTypes: true}).filter((e)=> e.isDirectory()).map((e)=> e.name)
100
+ if(commitFolders.length === 0) {
101
+ console.log(chalk.yellow('No commits to push'))
102
+ return
103
+ }
104
+
105
+ console.log(chalk.blue("Pushing commits of ",reponame," to cloud storage..."))
72
106
 
73
- // List existing commits in Drive
74
- const driveCommitsRes = await drive.files.list({
75
- q: `'${repoFolderId}' in parents and mimeType='application/vnd.google-apps.folder' and trashed=false`,
76
- fields: "files(name, id)"
77
- });
78
- const driveCommitNames = driveCommitsRes.data.files.map(f => f.name);
79
-
80
- // Upload commits
81
- for (const commitDir of commitDirs) {
82
- if (driveCommitNames.includes(commitDir)) {
83
- console.log(chalk.yellow(`Commit '${commitDir}' already exists on Drive, skipping.`));
107
+ for(const commitId of commitFolders) {
108
+
109
+ const commitFolder = path.join(commitDir,commitId)
110
+ const metaPath = path.join(commitFolder,"meta.json")
111
+
112
+ if(!fs.existsSync(metaPath)) {
113
+ console.log(chalk.yellow(`Skipping ${commitId} (no meta.json found)`));
84
114
  continue;
85
115
  }
86
116
 
87
- const folderPath = path.join(commitFolder, commitDir);
117
+ const metaData = JSON.parse(fs.readFileSync(metaPath,"utf-8"))
118
+ const { author, message, timeStamp } = metaData;
88
119
 
89
- const commitFolderRes = await drive.files.create({
90
- requestBody: {
91
- name: commitDir,
92
- mimeType: "application/vnd.google-apps.folder",
93
- parents: [repoFolderId]
94
- },
95
- fields: "id, name"
96
- });
97
- const commitFolderId = commitFolderRes.data.id;
120
+ console.log(chalk.green(`\n Uploading commit:`));
121
+ console.log(chalk.gray(` id: ${commitId}`));
122
+ console.log(chalk.gray(` message: ${message}`));
123
+ console.log(chalk.gray(` author: ${author}`));
124
+ console.log(chalk.gray(` time: ${timeStamp}`));
98
125
 
99
- await uploadFolder(folderPath, commitFolderId);
126
+ const { commitFolderId : driveCommitId , commitAlreadyExists } = await getDirectoryStructure(configData.username,reponame,commitId)
127
+
128
+ if (commitAlreadyExists) {
129
+ console.log(chalk.yellow(`Skipping ${commitId} (already uploaded)`));
130
+ continue;
131
+ }
100
132
 
101
- console.log(chalk.green(`Commit '${commitDir}' pushed successfully.`));
133
+ await uploadDirectory(commitFolder,driveCommitId)
134
+ console.log(chalk.green(`Commit ${commitId} uploaded successfully!`));
102
135
  }
103
-
104
- } catch(error) {
105
- console.log(chalk.red("Error in pushCmd:"), error.message);
136
+
137
+ console.log(chalk.bold.green("\nAll commits pushed successfully!"));
106
138
  }
107
- }
108
-
109
- // Helper to recursively upload folder to Drive
110
- async function uploadFolder(folderPath, parentId) {
111
- const items = await fsPromises.readdir(folderPath);
112
- for (const item of items) {
113
- const fullPath = path.join(folderPath, item);
114
- const stats = await fsPromises.stat(fullPath);
115
- if (stats.isDirectory()) {
116
- const folder = await drive.files.create({
117
- requestBody: {
118
- name: item,
119
- mimeType: "application/vnd.google-apps.folder",
120
- parents: [parentId]
121
- },
122
- fields: "id, name"
123
- });
124
- await uploadFolder(fullPath, folder.data.id);
125
- } else {
126
- await drive.files.create({
127
- requestBody: { name: item, parents: [parentId] },
128
- media: { body: fs.createReadStream(fullPath) },
129
- fields: "id, name"
130
- });
131
- }
139
+ catch(error) {
140
+ console.log(chalk.red.bold("\nPush Failed"));
141
+ console.error(chalk.red(error.stack || error.message || error));
132
142
  }
133
143
  }
134
144
 
135
- module.exports = pushCmd;
145
+ module.exports = pushCmd
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  const yargs = require("yargs");
4
4
  const { hideBin } = require("yargs/helpers");
@@ -11,7 +11,9 @@ const initCmd = require("./controllers/init")
11
11
  const addCmd = require("./controllers/add")
12
12
  const commitCmd = require("./controllers/commit")
13
13
  const unstageCmd = require("./controllers/unstage")
14
- const logCmd = require("./controllers/log")
14
+ const logCmd = require("./controllers/log");
15
+ const pushCmd = require("./controllers/push");
16
+
15
17
 
16
18
  yargs(hideBin(process.argv))
17
19
  .scriptName("jvcs")
@@ -126,6 +128,19 @@ yargs(hideBin(process.argv))
126
128
  }
127
129
  }
128
130
  )
131
+ .command(
132
+ "push",
133
+ "Push all the commits to remote",
134
+ {},
135
+ async ()=> {
136
+ try {
137
+ await pushCmd()
138
+ }
139
+ catch(error) {
140
+ console.log(chalk.red(error))
141
+ }
142
+ }
143
+ )
129
144
  .demandCommand(1, chalk.yellow("You need at least one command"))
130
145
  .help()
131
146
  .parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jvcs",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "bin": {
5
5
  "jvcs": "./index.js"
6
6
  },
@@ -1,98 +0,0 @@
1
- const fs = require("fs");
2
- const fsPromises = require("fs").promises;
3
- const path = require("path");
4
- const chalk = require("chalk");
5
- const { drive } = require("../config/drive-config");
6
- const { checkInitialization, checkRepoExists, getCLIConfig } = require("./utils");
7
-
8
- async function pullCmd(reponame) {
9
- try {
10
- if (!checkInitialization()) return;
11
- if (!checkRepoExists(reponame)) return;
12
-
13
- const repoPath = path.join(process.cwd(), `.${reponame}`);
14
- const commitFolder = path.join(repoPath, "commits");
15
- if (!fs.existsSync(commitFolder)) fs.mkdirSync(commitFolder, { recursive: true });
16
-
17
- const config = await getCLIConfig();
18
- if (!config) return console.log(chalk.red("Could not read CLI configuration."));
19
-
20
- console.log(chalk.blue("Pulling commits for user:"), chalk.green(config.username));
21
-
22
- // 1️⃣ Find user folder in Drive
23
- const userFolderRes = await drive.files.list({
24
- q: `name='${config.username}' and '1ahuoMCN_Ls5kGF2KPUGLbRZb9kGVMe0V' in parents and mimeType='application/vnd.google-apps.folder' and trashed=false`,
25
- fields: "files(id, name)"
26
- });
27
- if (!userFolderRes.data.files.length) {
28
- console.log(chalk.yellow("⚠ No user folder found on Drive."));
29
- return;
30
- }
31
- const userFolderId = userFolderRes.data.files[0].id;
32
-
33
- // 2️⃣ Find repo folder in Drive
34
- const repoFolderRes = await drive.files.list({
35
- q: `name='${reponame}' and '${userFolderId}' in parents and mimeType='application/vnd.google-apps.folder' and trashed=false`,
36
- fields: "files(id, name)"
37
- });
38
- if (!repoFolderRes.data.files.length) {
39
- console.log(chalk.yellow(`⚠ Repository '${reponame}' not found on Drive.`));
40
- return;
41
- }
42
- const repoFolderId = repoFolderRes.data.files[0].id;
43
-
44
- // 3️⃣ Get commit folders in Drive
45
- const driveCommitsRes = await drive.files.list({
46
- q: `'${repoFolderId}' in parents and mimeType='application/vnd.google-apps.folder' and trashed=false`,
47
- fields: "files(name, id)"
48
- });
49
- const driveCommits = driveCommitsRes.data.files;
50
- if (!driveCommits.length) {
51
- console.log(chalk.yellow("⚠ No commits found on Drive."));
52
- return;
53
- }
54
-
55
- // 4️⃣ Get local commit folders
56
- const localCommits = await fsPromises.readdir(commitFolder);
57
-
58
- // 5️⃣ Download only missing commits
59
- for (const commit of driveCommits) {
60
- if (localCommits.includes(commit.name)) {
61
- console.log(chalk.gray(`✔ Commit '${commit.name}' already exists locally.`));
62
- continue;
63
- }
64
- const localCommitPath = path.join(commitFolder, commit.name);
65
- await fsPromises.mkdir(localCommitPath, { recursive: true });
66
- await downloadFolder(commit.id, localCommitPath);
67
- console.log(chalk.green(`⬇ Pulled new commit '${commit.name}' successfully.`));
68
- }
69
-
70
- console.log(chalk.blue("Pull complete! Local repo is now up to date."));
71
-
72
- } catch (error) {
73
- console.log(chalk.red("Error in pullCmd:"), error.message);
74
- }
75
- }
76
-
77
- // Recursive folder download helper
78
- async function downloadFolder(folderId, destPath) {
79
- const res = await drive.files.list({
80
- q: `'${folderId}' in parents and trashed=false`,
81
- fields: "files(id, name, mimeType)"
82
- });
83
- for (const file of res.data.files) {
84
- const localPath = path.join(destPath, file.name);
85
- if (file.mimeType === "application/vnd.google-apps.folder") {
86
- await fsPromises.mkdir(localPath, { recursive: true });
87
- await downloadFolder(file.id, localPath);
88
- } else {
89
- const dest = fs.createWriteStream(localPath);
90
- await drive.files.get({ fileId: file.id, alt: "media" }, { responseType: "stream" })
91
- .then(res => new Promise((resolve, reject) => {
92
- res.data.on("end", resolve).on("error", reject).pipe(dest);
93
- }));
94
- }
95
- }
96
- }
97
-
98
- module.exports = pullCmd;
@@ -1,110 +0,0 @@
1
- const fs = require("fs");
2
- const fsPromises = require("fs").promises;
3
- const path = require("path");
4
- const { v4: uuidv4 } = require("uuid");
5
- const chalk = require("chalk");
6
- const { drive } = require("../config/drive-config");
7
- const { checkInitialization, checkRepoExists, getCLIConfig } = require("./utils");
8
-
9
- async function revertCmd(commitId, reponame) {
10
- try {
11
- if (!checkInitialization()) return;
12
- if (!checkRepoExists(reponame)) return;
13
-
14
- const repoPath = path.join(process.cwd(), `.${reponame}`);
15
- const commitFolder = path.join(repoPath, "commits");
16
- if (!fs.existsSync(commitFolder)) fs.mkdirSync(commitFolder, { recursive: true });
17
-
18
- const config = await getCLIConfig();
19
- if (!config) return console.log(chalk.red("Could not read CLI configuration."));
20
-
21
- // 1️⃣ Get user folder
22
- const userFolderRes = await drive.files.list({
23
- q: `name='${config.username}' and '1ahuoMCN_Ls5kGF2KPUGLbRZb9kGVMe0V' in parents and mimeType='application/vnd.google-apps.folder' and trashed=false`,
24
- fields: "files(id, name)"
25
- });
26
- if (!userFolderRes.data.files.length) return console.log(chalk.red("User folder not found on Drive."));
27
- const userFolderId = userFolderRes.data.files[0].id;
28
-
29
- // 2️⃣ Get repo folder
30
- const repoFolderRes = await drive.files.list({
31
- q: `name='${reponame}' and '${userFolderId}' in parents and mimeType='application/vnd.google-apps.folder' and trashed=false`,
32
- fields: "files(id, name)"
33
- });
34
- if (!repoFolderRes.data.files.length) return console.log(chalk.red("Repo folder not found on Drive."));
35
- const repoFolderId = repoFolderRes.data.files[0].id;
36
-
37
- // 3️⃣ Get commit folder
38
- const commitRes = await drive.files.list({
39
- q: `name='${commitId}' and '${repoFolderId}' in parents and mimeType='application/vnd.google-apps.folder' and trashed=false`,
40
- fields: "files(id, name)"
41
- });
42
- if (!commitRes.data.files.length) return console.log(chalk.red(`Commit '${commitId}' not found on Drive.`));
43
- const driveCommitId = commitRes.data.files[0].id;
44
-
45
- // 4️⃣ Create new revert commit folder locally
46
- const newCommitId = `revert_${commitId}_${uuidv4()}`;
47
- const newCommitPath = path.join(commitFolder, newCommitId);
48
- await fsPromises.mkdir(newCommitPath, { recursive: true });
49
-
50
- // 5️⃣ Recursively download commit files from Drive
51
- await downloadFolderFromDrive(driveCommitId, newCommitPath);
52
-
53
- // 6️⃣ Clean working directory (except hidden files)
54
- const cwd = process.cwd();
55
- const entries = await fsPromises.readdir(cwd);
56
- for (const entry of entries) {
57
- if (entry.startsWith(".")) continue;
58
- await fsPromises.rm(path.join(cwd, entry), { recursive: true, force: true });
59
- }
60
-
61
- // 7️⃣ Copy new revert commit into working directory
62
- await copyFolderRecursive(newCommitPath, cwd);
63
-
64
- console.log(chalk.green(`Reverted to commit '${commitId}'. New revert commit: '${newCommitId}'`));
65
-
66
- } catch (err) {
67
- console.log(chalk.red("Error in revertCmd:"), err.message);
68
- }
69
- }
70
-
71
- // Recursive download helper
72
- async function downloadFolderFromDrive(folderId, localPath) {
73
- const res = await drive.files.list({
74
- q: `'${folderId}' in parents and trashed=false`,
75
- fields: "files(id, name, mimeType)"
76
- });
77
-
78
- for (const file of res.data.files) {
79
- const filePath = path.join(localPath, file.name);
80
- if (file.mimeType === "application/vnd.google-apps.folder") {
81
- await fsPromises.mkdir(filePath, { recursive: true });
82
- await downloadFolderFromDrive(file.id, filePath);
83
- } else {
84
- const destStream = fs.createWriteStream(filePath);
85
- await new Promise((resolve, reject) => {
86
- drive.files.get({ fileId: file.id, alt: "media" }, { responseType: "stream" }, (err, response) => {
87
- if (err) return reject(err);
88
- response.data.pipe(destStream).on("finish", resolve).on("error", reject);
89
- });
90
- });
91
- }
92
- }
93
- }
94
-
95
- // Recursive copy helper
96
- async function copyFolderRecursive(src, dest) {
97
- const entries = await fsPromises.readdir(src, { withFileTypes: true });
98
- for (const entry of entries) {
99
- const srcPath = path.join(src, entry.name);
100
- const destPath = path.join(dest, entry.name);
101
- if (entry.isDirectory()) {
102
- await fsPromises.mkdir(destPath, { recursive: true });
103
- await copyFolderRecursive(srcPath, destPath);
104
- } else {
105
- await fsPromises.copyFile(srcPath, destPath);
106
- }
107
- }
108
- }
109
-
110
- module.exports = revertCmd;