myvcs 0.1.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/.myvcsignore +1 -0
- package/Controllers/addRepo.js +94 -0
- package/Controllers/commitRepo.js +49 -0
- package/Controllers/config.js +36 -0
- package/Controllers/initRepo.js +29 -0
- package/Controllers/pullRepo.js +64 -0
- package/Controllers/pushRepo.js +49 -0
- package/Controllers/revertRepo.js +23 -0
- package/Controllers/showCommits.js +18 -0
- package/README.md +43 -0
- package/config/aws-config.js +13 -0
- package/config/vcsConfig.js +73 -0
- package/index.js +73 -0
- package/package.json +26 -0
package/.myvcsignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
node_modules
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import fs from "fs/promises"
|
|
2
|
+
import path from "path"
|
|
3
|
+
async function readIgnoreFile() {
|
|
4
|
+
const ignorePath = path.join(process.cwd(), ".myvcsignore");
|
|
5
|
+
|
|
6
|
+
try {
|
|
7
|
+
// Check if file exists
|
|
8
|
+
await fs.access(ignorePath);
|
|
9
|
+
|
|
10
|
+
// Read file content
|
|
11
|
+
const content = await fs.readFile(ignorePath, "utf-8");
|
|
12
|
+
|
|
13
|
+
// Split into lines and clean up
|
|
14
|
+
const patterns = content
|
|
15
|
+
.split("\n") // Split by newline
|
|
16
|
+
.map(line => line.trim()) // Remove whitespace
|
|
17
|
+
.filter(line => line.length > 0) // Remove empty lines
|
|
18
|
+
.filter(line => !line.startsWith("#")); // Remove comments
|
|
19
|
+
|
|
20
|
+
return patterns;
|
|
21
|
+
|
|
22
|
+
} catch {
|
|
23
|
+
// File doesn't exist - return default ignores
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const ignoreList = await readIgnoreFile();
|
|
28
|
+
async function checkExists(path) {
|
|
29
|
+
try {
|
|
30
|
+
await fs.access(path);
|
|
31
|
+
return true; // Exists
|
|
32
|
+
} catch {
|
|
33
|
+
return false; // Doesn't exist
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async function addRepo(filePath){
|
|
37
|
+
const repoPath=path.resolve(process.cwd(),".myvcs");
|
|
38
|
+
const stagingPath=path.resolve(repoPath,"staging");
|
|
39
|
+
const repoExists=await checkExists(repoPath);
|
|
40
|
+
if (!repoExists) {
|
|
41
|
+
console.log("Not a repository. Run 'myvcs init' first.");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
try{
|
|
45
|
+
await fs.mkdir(stagingPath,{recursive:true});
|
|
46
|
+
const fileName=path.basename(filePath);
|
|
47
|
+
if(fileName==".") addAllFiles(process.cwd(),stagingPath);
|
|
48
|
+
else if(ignoreList && ignoreList.includes(fileName)){
|
|
49
|
+
console.log("File not added to staging area Ignored!!")
|
|
50
|
+
}
|
|
51
|
+
else{
|
|
52
|
+
await fs.copyFile(filePath,path.join(stagingPath,fileName));
|
|
53
|
+
console.log(`File ${fileName} added to staging area`);
|
|
54
|
+
}
|
|
55
|
+
}catch(err){
|
|
56
|
+
console.error("Failed to add file to staging area!! ",err)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async function shouldIgnore(filename) {
|
|
60
|
+
|
|
61
|
+
// Ignore specific files/folders
|
|
62
|
+
if (ignoreList && ignoreList.includes(filename)) return true;
|
|
63
|
+
|
|
64
|
+
// Ignore hidden files (starting with .)
|
|
65
|
+
if (filename.startsWith(".")) return true;
|
|
66
|
+
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
async function addAllFiles(directory,stagingPath,baseDir=process.cwd()){
|
|
70
|
+
const items=await fs.readdir(directory);
|
|
71
|
+
let addedCount=0;
|
|
72
|
+
for(const item of items){
|
|
73
|
+
if(await shouldIgnore(item)) continue;
|
|
74
|
+
const fullPath=path.join(directory,item);
|
|
75
|
+
const stat=await fs.stat(fullPath);
|
|
76
|
+
if(stat.isDirectory()){
|
|
77
|
+
const count=await addAllFiles(fullPath,stagingPath);
|
|
78
|
+
addedCount+=count;
|
|
79
|
+
}
|
|
80
|
+
else{
|
|
81
|
+
const relativePath=path.relative(baseDir,fullPath);
|
|
82
|
+
const destPath=path.join(stagingPath,relativePath);
|
|
83
|
+
await fs.mkdir(path.dirname(destPath),{recursive:true});
|
|
84
|
+
await fs.copyFile(fullPath,destPath);
|
|
85
|
+
addedCount++;
|
|
86
|
+
console.log(`added file ${relativePath}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if(directory==baseDir){
|
|
90
|
+
console.log(`Added ${addedCount} files to staging area`);
|
|
91
|
+
}
|
|
92
|
+
return addedCount;
|
|
93
|
+
}
|
|
94
|
+
export {addRepo}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import fs from "fs/promises"
|
|
2
|
+
import path from "path"
|
|
3
|
+
import { v5 as uuidv5 } from 'uuid';
|
|
4
|
+
import dotenv from "dotenv"
|
|
5
|
+
dotenv.config();
|
|
6
|
+
function generateCommitID(message) {
|
|
7
|
+
return uuidv5(message, process.env.MY_NAMESPACE);
|
|
8
|
+
}
|
|
9
|
+
async function commitRepo(message){
|
|
10
|
+
const repoPath=path.resolve(process.cwd(),".myvcs");
|
|
11
|
+
const commitPath=path.resolve(repoPath,"commits");
|
|
12
|
+
const stagedPath=path.resolve(repoPath,"staging");
|
|
13
|
+
const commitId=generateCommitID(message);
|
|
14
|
+
const thisCommitPath=path.resolve(path.join(commitPath,commitId));
|
|
15
|
+
const commitsJsonPath = path.join(commitPath, "commits.json");
|
|
16
|
+
try{
|
|
17
|
+
await fs.mkdir(commitPath,{recursive:true});
|
|
18
|
+
await fs.mkdir(thisCommitPath,{recursive:true});
|
|
19
|
+
const files=await fs.readdir(stagedPath);
|
|
20
|
+
for(const file of files){
|
|
21
|
+
await fs.copyFile(path.join(stagedPath,file),path.join(thisCommitPath,file));
|
|
22
|
+
}
|
|
23
|
+
let commits = [];
|
|
24
|
+
try {
|
|
25
|
+
const data = await fs.readFile(commitsJsonPath, 'utf-8');
|
|
26
|
+
commits = JSON.parse(data);
|
|
27
|
+
} catch (err) {
|
|
28
|
+
// File doesn't exist yet, start with empty array
|
|
29
|
+
if (err.code !== 'ENOENT') throw err;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Append new commit
|
|
33
|
+
commits.push({
|
|
34
|
+
commitId,
|
|
35
|
+
message,
|
|
36
|
+
date: new Date().toISOString()
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Write back to file
|
|
40
|
+
await fs.writeFile(commitsJsonPath, JSON.stringify(commits, null, 2));
|
|
41
|
+
console.log(`commit done ${commitId} with message ${message}`);
|
|
42
|
+
}catch(err){
|
|
43
|
+
console.error("Commit failed!! ",err);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export {commitRepo}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {readConfig,setConfigValue} from "../config/vcsConfig.js"
|
|
2
|
+
|
|
3
|
+
export function showConfig(){
|
|
4
|
+
try{
|
|
5
|
+
const config=readConfig();
|
|
6
|
+
console.log("CURRENT CONGIGURATION");
|
|
7
|
+
console.log("======================");
|
|
8
|
+
|
|
9
|
+
for(const [key,value] of Object.entries(config)){
|
|
10
|
+
console.log(`${key}:${value||"Not set"}`)
|
|
11
|
+
}
|
|
12
|
+
console.log("");
|
|
13
|
+
}catch(err){
|
|
14
|
+
console.log(`Error: ${err}`);
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function setConfig(key,value){
|
|
20
|
+
try{
|
|
21
|
+
const validKeys=["username","email"];
|
|
22
|
+
if(!validKeys.includes(key)){
|
|
23
|
+
console.log(`Invalid Config Key ${key}`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
if(key=="username"){
|
|
27
|
+
if(!/^[a-zA-Z0-9_-]+$/.test(value)){
|
|
28
|
+
console.log("username must only contain letters,underscores and hyphen");
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
setConfigValue(key,value);
|
|
33
|
+
}catch(e){
|
|
34
|
+
console.error(e);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import fs from "fs/promises"
|
|
2
|
+
import path from "path"
|
|
3
|
+
import dotenv from "dotenv"
|
|
4
|
+
import {initConfig,setConfigValue} from "../config/vcsConfig.js"
|
|
5
|
+
dotenv.config();
|
|
6
|
+
async function initRepo(){
|
|
7
|
+
const repoPath=path.resolve(process.cwd(),".myvcs");
|
|
8
|
+
const commitPath=path.resolve(repoPath,"commits");
|
|
9
|
+
const currentFolder = path.basename(process.cwd());
|
|
10
|
+
try{
|
|
11
|
+
await fs.mkdir(repoPath,{recursive:true});
|
|
12
|
+
await fs.mkdir(commitPath,{recursive:true});
|
|
13
|
+
await fs.writeFile(
|
|
14
|
+
path.join(repoPath,"config.json"),
|
|
15
|
+
JSON.stringify({bucket:process.env.S3_BUCKET})
|
|
16
|
+
)
|
|
17
|
+
initConfig();
|
|
18
|
+
setConfigValue("repoName",currentFolder);
|
|
19
|
+
console.log("Repository Initialised!",repoPath)
|
|
20
|
+
console.log("\nNext steps:");
|
|
21
|
+
console.log(" 1. Set your username: myvcs config set username <your-username>");
|
|
22
|
+
console.log(" 2. Set your email: myvcs config set email <your-email>");
|
|
23
|
+
console.log(" 3. Start tracking files: myvcs add <file>");
|
|
24
|
+
}catch(err){
|
|
25
|
+
console.error("Repository initialisation failed! ",err);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export {initRepo}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import fs from "fs/promises"
|
|
2
|
+
import path from "path"
|
|
3
|
+
import {S3,S3_BUCKET} from "../config/aws-config.js"
|
|
4
|
+
import {getUsername,getConfigValue} from "../config/vcsConfig.js"
|
|
5
|
+
async function pullRepo(){
|
|
6
|
+
const repoPath=path.resolve(process.cwd(),".myvcs");
|
|
7
|
+
const commitsPath=path.resolve(repoPath,"commits");
|
|
8
|
+
const username=getUsername();
|
|
9
|
+
const repoName=getConfigValue("repoName");
|
|
10
|
+
try{
|
|
11
|
+
const data = await S3.listObjectsV2({
|
|
12
|
+
Bucket:S3_BUCKET,
|
|
13
|
+
Prefix:`commits/${username}/${repoName}`
|
|
14
|
+
}).promise();
|
|
15
|
+
const objects=data.Contents;
|
|
16
|
+
console.log(`Found ${objects.length} files to pull`);
|
|
17
|
+
for(const object of objects){
|
|
18
|
+
const key=object.Key;
|
|
19
|
+
console.log(key);
|
|
20
|
+
// Remove 'commits/' prefix to get relative path
|
|
21
|
+
const relativePath = key.replace('commits/', ''); // e.g., 'a0f0a67b.../hello.txt'
|
|
22
|
+
const localFilePath = path.join(commitsPath, relativePath);
|
|
23
|
+
// Create parent directory if needed
|
|
24
|
+
const localDir = path.dirname(localFilePath);
|
|
25
|
+
await fs.mkdir(localDir, {recursive: true});
|
|
26
|
+
const params={
|
|
27
|
+
Bucket: S3_BUCKET,
|
|
28
|
+
Key:key
|
|
29
|
+
}
|
|
30
|
+
const fileContent=await S3.getObject(params).promise();
|
|
31
|
+
await fs.writeFile(localFilePath,fileContent.Body);
|
|
32
|
+
console.log(`Downloaded: ${relativePath}`);
|
|
33
|
+
}
|
|
34
|
+
console.log("Pulled all commits");
|
|
35
|
+
const commitsJsonPath=path.resolve(commitsPath,"commits.json");
|
|
36
|
+
const commitsData=await fs.readFile(commitsJsonPath,'utf-8');
|
|
37
|
+
const commits=JSON.parse(commitsData);
|
|
38
|
+
if(commits.length==0){
|
|
39
|
+
console.log("No commits to Restore");
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const latestCommit=commits[commits.length-1];
|
|
43
|
+
const latestCommitId=latestCommit.commitId;
|
|
44
|
+
const latestPathCommit=path.join(commitsPath,latestCommitId);
|
|
45
|
+
|
|
46
|
+
console.log(`Restoring files from commit: ${latestCommitId}`);
|
|
47
|
+
console.log(`Message: ${latestCommit.message}`);
|
|
48
|
+
|
|
49
|
+
const files=await fs.readdir(latestPathCommit);
|
|
50
|
+
|
|
51
|
+
for(const file of files){
|
|
52
|
+
const sourcePath=path.join(latestPathCommit,file);
|
|
53
|
+
const destPath=path.join(process.cwd(),file);
|
|
54
|
+
|
|
55
|
+
await fs.copyFile(sourcePath,destPath);
|
|
56
|
+
console.log(`Restored ${file} \n`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
}catch(err){
|
|
60
|
+
console.log("Error pulling from S3!! ",err);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export {pullRepo}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import fs from "fs/promises"
|
|
2
|
+
import path from "path"
|
|
3
|
+
import {S3,S3_BUCKET} from "../config/aws-config.js"
|
|
4
|
+
import {getUsername,getConfigValue} from "../config/vcsConfig.js"
|
|
5
|
+
async function pushRepo(){
|
|
6
|
+
const repoPath=path.resolve(process.cwd(),".myvcs");
|
|
7
|
+
const commitsPath=path.resolve(repoPath,"commits");
|
|
8
|
+
const username=getUsername();
|
|
9
|
+
const repoName=getConfigValue("repoName");
|
|
10
|
+
try{
|
|
11
|
+
const commitDirs=await fs.readdir(commitsPath);
|
|
12
|
+
console.log(commitDirs);
|
|
13
|
+
for(const dir of commitDirs){
|
|
14
|
+
const dirPath=path.join(commitsPath,dir);
|
|
15
|
+
// CHECK IF IT'S A DIRECTORY FIRST
|
|
16
|
+
const stats = await fs.stat(dirPath);
|
|
17
|
+
if(!stats.isDirectory()){
|
|
18
|
+
// If it's commits.json, upload it separately
|
|
19
|
+
if(dir === 'commits.json'){
|
|
20
|
+
const fileContent = await fs.readFile(dirPath);
|
|
21
|
+
const params = {
|
|
22
|
+
Bucket: S3_BUCKET,
|
|
23
|
+
Key: `commits/${username}/${repoName}/commits.json`,
|
|
24
|
+
Body: fileContent
|
|
25
|
+
};
|
|
26
|
+
await S3.upload(params).promise();
|
|
27
|
+
console.log('commits.json uploaded to S3');
|
|
28
|
+
}
|
|
29
|
+
continue; // Skip to next item
|
|
30
|
+
}
|
|
31
|
+
const files=await fs.readdir(dirPath);
|
|
32
|
+
for(const file of files){
|
|
33
|
+
const filePath=path.join(dirPath,file);
|
|
34
|
+
const fileContent=await fs.readFile(filePath);
|
|
35
|
+
const params={
|
|
36
|
+
Bucket:S3_BUCKET,
|
|
37
|
+
Key:`commits/${username}/${repoName}/${dir}/${file}`,
|
|
38
|
+
Body:fileContent
|
|
39
|
+
}
|
|
40
|
+
await S3.upload(params).promise();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
console.log("All commits pushed to myVCS")
|
|
44
|
+
}catch(err){
|
|
45
|
+
console.error("Error in pushing code to GitHub!!",err);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export {pushRepo}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import fs from "fs/promises"
|
|
2
|
+
import path from "path"
|
|
3
|
+
|
|
4
|
+
async function revertRepo(commitID){
|
|
5
|
+
const repoPath=path.resolve(process.cwd(),".myvcs");
|
|
6
|
+
const commitPath=path.resolve(repoPath,"commits");
|
|
7
|
+
const thisCommit=path.join(commitPath,commitID);
|
|
8
|
+
const parentDir=path.resolve(repoPath,"..");
|
|
9
|
+
try{
|
|
10
|
+
const files=await fs.readdir(thisCommit);
|
|
11
|
+
|
|
12
|
+
for(const file of files){
|
|
13
|
+
await fs.copyFile(path.join(thisCommit,file),path.join(parentDir,file));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
console.log(`Reverted to commitId:${commitID} successfully!!`);
|
|
17
|
+
}
|
|
18
|
+
catch(err){
|
|
19
|
+
console.log("Unable to Revert!! ",err);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export {revertRepo}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import fs from "fs/promises"
|
|
2
|
+
import path from "path"
|
|
3
|
+
|
|
4
|
+
async function showCommits(){
|
|
5
|
+
const repoPath=path.resolve(process.cwd(),".myvcs");
|
|
6
|
+
const commitPath=path.join(repoPath,"commits");
|
|
7
|
+
const commitJSONPath=path.join(commitPath,"commits.json");
|
|
8
|
+
try{
|
|
9
|
+
const fileContent=await fs.readFile(commitJSONPath,'utf-8');
|
|
10
|
+
const commits=JSON.parse(fileContent);
|
|
11
|
+
console.log(commits);
|
|
12
|
+
}
|
|
13
|
+
catch(err){
|
|
14
|
+
console.log("No commits ",err)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export {showCommits}
|
package/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# MyVCS
|
|
2
|
+
|
|
3
|
+
A simple version control system with S3 cloud storage.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
```bash
|
|
7
|
+
npm install -g myvcs
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Setup
|
|
11
|
+
```
|
|
12
|
+
Initialize a repository:
|
|
13
|
+
```bash
|
|
14
|
+
myvcs init
|
|
15
|
+
myvcs config set username your-username
|
|
16
|
+
myvcs config set email your-email
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
```bash
|
|
21
|
+
# Add files
|
|
22
|
+
myvcs add file.txt
|
|
23
|
+
myvcs add . # Add all files
|
|
24
|
+
|
|
25
|
+
# Commit
|
|
26
|
+
myvcs commit "Your commit message"
|
|
27
|
+
|
|
28
|
+
# Push to cloud
|
|
29
|
+
myvcs push
|
|
30
|
+
|
|
31
|
+
# Pull from cloud
|
|
32
|
+
myvcs pull
|
|
33
|
+
|
|
34
|
+
# View commits
|
|
35
|
+
myvcs list commits
|
|
36
|
+
|
|
37
|
+
# Revert to a commit
|
|
38
|
+
myvcs revert <commitID>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## License
|
|
42
|
+
|
|
43
|
+
MIT
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import aws from "aws-sdk"
|
|
2
|
+
|
|
3
|
+
aws.config.update({
|
|
4
|
+
region: process.env.AWS_REGION || "ap-south-1",
|
|
5
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
|
|
6
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const S3=new aws.S3();
|
|
10
|
+
const S3_BUCKET="amzn-777";
|
|
11
|
+
|
|
12
|
+
export {S3,S3_BUCKET}
|
|
13
|
+
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import fs from "fs"
|
|
2
|
+
import path from "path"
|
|
3
|
+
|
|
4
|
+
function getConfigPath(){
|
|
5
|
+
return path.join(process.cwd(),".myvcs","config.json");
|
|
6
|
+
}
|
|
7
|
+
function configDirExists(){
|
|
8
|
+
const configDir=path.join(process.cwd(),".myvcs");
|
|
9
|
+
return fs.existsSync(configDir);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function initConfig(){
|
|
13
|
+
const defaultConfig={
|
|
14
|
+
"username":null,
|
|
15
|
+
"email":null
|
|
16
|
+
}
|
|
17
|
+
writeConfig(defaultConfig);
|
|
18
|
+
}
|
|
19
|
+
function readConfig(){
|
|
20
|
+
if(!configDirExists()){
|
|
21
|
+
throw new Error("myvcs not initialised.. Run 'myvcs init' first!!");
|
|
22
|
+
}
|
|
23
|
+
const configPath=getConfigPath();
|
|
24
|
+
|
|
25
|
+
if(!fs.existsSync(configPath)){
|
|
26
|
+
return {
|
|
27
|
+
"username":null,
|
|
28
|
+
"email":null
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
try{
|
|
33
|
+
const data=fs.readFileSync(configPath,'utf-8');
|
|
34
|
+
return JSON.parse(data);
|
|
35
|
+
}catch(err){
|
|
36
|
+
throw new Error(`Failed to read config: ${error.message}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function writeConfig(config){
|
|
40
|
+
if(!configDirExists){
|
|
41
|
+
throw new Error("Not a myvcs repository. Run 'myvcs init' first.");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const configPath=getConfigPath();
|
|
45
|
+
|
|
46
|
+
try{
|
|
47
|
+
fs.writeFileSync(configPath,JSON.stringify(config,null,2));
|
|
48
|
+
return true;
|
|
49
|
+
}catch(err){
|
|
50
|
+
throw new Error("Not a myvcs repository. Run 'myvcs init' first.")
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function setConfigValue(key,value){
|
|
54
|
+
const config=readConfig();
|
|
55
|
+
config[key]=value;
|
|
56
|
+
writeConfig(config);
|
|
57
|
+
console.log(`Config Updated ${key}=${value}`);
|
|
58
|
+
}
|
|
59
|
+
function getConfigValue(key) {
|
|
60
|
+
const config = readConfig();
|
|
61
|
+
return config[key];
|
|
62
|
+
}
|
|
63
|
+
function getUsername(){
|
|
64
|
+
const username=getConfigValue("username");
|
|
65
|
+
if(!username){
|
|
66
|
+
throw new Error(
|
|
67
|
+
"Username not configured. Please set your username with:\n" +
|
|
68
|
+
" myvcs config set username <your-username>"
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
return username;
|
|
72
|
+
}
|
|
73
|
+
export {initConfig,readConfig,setConfigValue,getUsername,getConfigValue}
|
package/index.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import yargs from "yargs/yargs"
|
|
3
|
+
import {hideBin} from "yargs/helpers"
|
|
4
|
+
import {initRepo} from "./Controllers/initRepo.js"
|
|
5
|
+
import { addRepo } from "./Controllers/addRepo.js";
|
|
6
|
+
import { commitRepo } from "./Controllers/commitRepo.js";
|
|
7
|
+
import { pushRepo } from "./Controllers/pushRepo.js";
|
|
8
|
+
import { pullRepo } from "./Controllers/pullRepo.js";
|
|
9
|
+
import {revertRepo} from "./Controllers/revertRepo.js"
|
|
10
|
+
import {showCommits} from "./Controllers/showCommits.js"
|
|
11
|
+
import {showConfig,setConfig} from "./Controllers/config.js"
|
|
12
|
+
yargs(hideBin(process.argv))
|
|
13
|
+
.command("init","initialise a new repository",{},initRepo)
|
|
14
|
+
.command("add <file>","Add a file to repo/staging area use 'add .' to add all files",
|
|
15
|
+
(yargs)=>{
|
|
16
|
+
yargs.positional("file",{
|
|
17
|
+
describe:"add file to staging area",
|
|
18
|
+
type:"string"
|
|
19
|
+
})
|
|
20
|
+
},async (argv)=>{
|
|
21
|
+
await addRepo(argv.file);
|
|
22
|
+
}
|
|
23
|
+
)
|
|
24
|
+
.command("commit <message>","commit files added to staging area",
|
|
25
|
+
(yagrs)=>{
|
|
26
|
+
yagrs.positional("message",{
|
|
27
|
+
describe:"commit file from staging area",
|
|
28
|
+
type:"string"
|
|
29
|
+
})
|
|
30
|
+
},
|
|
31
|
+
(argv)=>{
|
|
32
|
+
commitRepo(argv.message);
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
.command("push","push commits to cloud storage",{},pushRepo)
|
|
36
|
+
.command("pull","pull commits from cloud to local system",{},pullRepo)
|
|
37
|
+
.command("revert <commitID>","revert back to specified commitID",
|
|
38
|
+
(yargs)=>{
|
|
39
|
+
yargs.positional("commitID",{
|
|
40
|
+
describe:"commitID to revert",
|
|
41
|
+
type:"string"
|
|
42
|
+
})
|
|
43
|
+
},
|
|
44
|
+
(argv)=>{
|
|
45
|
+
revertRepo(argv.commitID);
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
.command("list commits","show all commmits",{},showCommits)
|
|
49
|
+
.command("config","configure myVCS on your system",
|
|
50
|
+
(yargs)=>{
|
|
51
|
+
return yargs
|
|
52
|
+
.command("set <key> <value>","set a config value",
|
|
53
|
+
(yargs)=>{
|
|
54
|
+
yargs
|
|
55
|
+
.positional("key",{
|
|
56
|
+
describe:"config key (username)",
|
|
57
|
+
type:"string"
|
|
58
|
+
})
|
|
59
|
+
.positional("value",{
|
|
60
|
+
describe:"config value",
|
|
61
|
+
type:"string"
|
|
62
|
+
})
|
|
63
|
+
},
|
|
64
|
+
(argv)=>{
|
|
65
|
+
setConfig(argv.key,argv.value);
|
|
66
|
+
}
|
|
67
|
+
)
|
|
68
|
+
.command("list","show config details",{},showConfig)
|
|
69
|
+
.demandCommand(1,"Please specify a config suncommand")
|
|
70
|
+
}
|
|
71
|
+
)
|
|
72
|
+
.demandCommand(1,"you need atleast one command")
|
|
73
|
+
.help().argv;
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "myvcs",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
7
|
+
},
|
|
8
|
+
"keywords": ["vcs", "version-control", "git", "s3", "cloud-storage"],
|
|
9
|
+
"type": "module",
|
|
10
|
+
"author": "Amarnath Vasanth amarnathvasanth39@gmail.com",
|
|
11
|
+
"license": "ISC",
|
|
12
|
+
"description": "A simple version control system with S3 cloud storage",
|
|
13
|
+
"bin": {
|
|
14
|
+
"myvcs": "./index.js"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/yourusername/myvcs.git"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"aws-sdk": "^2.1693.0",
|
|
22
|
+
"dotenv": "^17.2.3",
|
|
23
|
+
"uuid": "^13.0.0",
|
|
24
|
+
"yargs": "^18.0.0"
|
|
25
|
+
}
|
|
26
|
+
}
|