Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 48 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,12 @@
### Notice:
This has not been fully tested on Windows yet, so if you are using Windows and have found some issues, please Raise an issue. :)
I am using the filesystem library to make it cross-platform.

## UPDATES:
1. Starting the development for windows also.
2. I will be using the strucuture:
```
YEET/
├── YEET.sln # Main solution file
├── YeetCore/ # Core functionality as static library
├── YeetUtils/ # Utility functions as static library
├── YeetCLI/ # Command-line interface executable
└── YeetTests/ # Test project
```
3. I am also adding Google Test to the project, for better and consistent testing. (This will take some time)


> All of the above changes will need some time to get fully tested and might break somethings.
> This new Update will be the biggest for the future of this project.

Hope this works out
I am using the filesystem library to make it cross-platform. Use Visual Studio, I've provided the `.sln` file or generate it from the `CMAKE` provided in VS.

# Introduction:
- This is a project to make my own version control with some improvements.
- Through this, I wanted to learn the backend of version control and make my grasp stronger on C++.
- I will be learning a lot about file system, hashing and generating diffs between files and commits.
- I will be learning a lot about file system, hashing and generating diffs between files.
- and use case of Graphs and Linked lists for history traversal.

## HOW TO USE IN LINUX ENVIRONMENT
1. Clone/Download this repository.
Expand All @@ -40,13 +22,44 @@ make
5. Go to `build/bin` and you will find the executable.
6. Run the executable file and initialize an empty yeet repo:
```bash
./yeet init .
./yeet init [path]
```
(Or better, don;t go to `build/bin` and
```bash
./build/bin/yeet init .
```

## Quick Reference

| Command | Description | Example |
|---------|-------------|---------|
| `yeet init .` | Initialize repository | `./yeet init .` |
| `yeet status` | Show changes | `./yeet status` |
| `yeet commit` | Create commit | `./yeet commit` |
| `yeet history` | View commit log | `./yeet history` |
| `yeet branch` | Manage branches | `./yeet branch` |
| `yeet checkout <branch>` | Switch branch | `./yeet checkout feature` |

---

## Known Limitations (working on them!)

- `yeet checkout` changes branch pointer but doesn't update working directory files yet
- All files are automatically staged - no manual `add` support yet
- Cannot choose base branch when creating new branches (uses current branch)
- Executable files are tracked but diffs are not displayed in status


## REPO STRUCTURE:
```
YEET/
├── YEET.sln # Main solution file
├── YeetCore/ # Core functionality as static library
├── YeetUtils/ # Utility functions as static library
├── YeetCLI/ # Command-line interface executable
└── YeetTests/ # Test project
```

## Make Sure:
For now, I have added cryptopp into the repositry itself, but later I will be removing it. So you might need to download it. (For now, no need to do the following steps)
> you have lcryptopp installed in your system. I am using fedora and I installed it using:
Expand All @@ -55,11 +68,6 @@ For now, I have added cryptopp into the repositry itself, but later I will be re
> ```
> Search according to your OS.

## CAREFUL
- For now, You can only make yeet init in the pwd, You can not do yeet init /home/abc/some/folder. This will not work. It will be executed but will give rise to complications. If you want to init in a folder, you have to cd to that folder and then run the command => `yeet init .`.
- You can only yeet init in a already made directory. You can not yeet init in a directory that does not exist.
- There is no option to base/rebase for the branch/checkout command

## Workflow diagrams:
The below are very minimal and abstracted view of the working of the project. You have to go throught the code to learn the details of the implementation.
1. ![Sequence Diagram](assets/Sequence_Diagram.png)
Expand All @@ -83,8 +91,20 @@ zlib-flate -uncompress < .yeet/objects/5d/8d5a1314ec0f6a5b7f8ac27dfbf53ed82bf3fe
- For now, I am leaving the locks and while writting and reading file. It might cause error at some cases.
- No structure Error handling for now.
- Temparary Path approach for storing objects => will do it later.
- Back traversal for full history tree => will work on it next.
- More robust Testing is needed. (Trying to implement it using GoogleTests.)
- The env variables approach need to change to config file approach.

### 🚧 Coming Soon

- **Checkout** - Reset working directory to match branch
- **Add** - Stage specific files
- **Merge** - Merge branches
- **Remote repositories** - Push/pull to remote
- **Tags** - Create version tags
- **Stash** - Save work in progress
- **Rebase** - Rewrite commit history
- **Delta encoding** - Space-efficient storage
- **`.yeetignore`** - Custom ignore patterns

## Brach
- [ ] Option to choose which branch I want to make my new branch from. (Currently the new branch will automatically start from the prev branch ie the branch you were in)
Expand Down
18 changes: 18 additions & 0 deletions SetupENVvars.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash

echo "Enter your name:"
read name
echo "Enter your email:"
read email

echo "export YEET_AUTHOR_NAME=\"$name\"" >> ~/.bashrc
echo "export YEET_AUTHOR_EMAIL=\"$email\"" >> ~/.bashrc

# only append to ~/.zshrc if it exists
if [ -f "$HOME/.zshrc" ]; then
echo "export YEET_AUTHOR_NAME=\"$name\"" >> "$HOME/.zshrc"
echo "export YEET_AUTHOR_EMAIL=\"$email\"" >> "$HOME/.zshrc"
fi

echo "Environment variables added to ~/.bashrc ans ~/.zshrc"
echo "Run 'source ~/.bashrc' or according to your terminal do changes to script, it only supports bash and zsh"
106 changes: 106 additions & 0 deletions YeetCLI/commands.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#include "./include/command.hpp"

int commands(int num_of_arg, char* argv[]){
// Flushing the cout and cerr.
std::cout<<std::unitbuf; // enbaling the unitbuf flag for automatic flushing for output. has no effect on input
std::cerr<<std::unitbuf;
std::cout<<"You are using cpp version: "<<__cplusplus<<std::endl; // To know my cpp version
std::string pwd = fs::current_path();

// TODO: instead of so many if-else, implement a map based approach
try{
if(num_of_arg==1){
std::cerr<<"No argument Provied! \n> Use Command: yeet init [Path] to initialize a repository \n> yeet commit to commit \n> yeet branch to see the branching options \n> yeet status to see the changes etc to the files etc. or refer docs\n";
return EXIT_FAILURE;
}

std::string command = argv[1];

if (num_of_arg == 3) {
if(command == "init"){
std::string path = argv[2];
if(fs::exists(path)){
YeetInit(path); // initialises a .init file
}
else{
std::cerr<<"The Path you provided doesn't exist!\nPlease check it and Retry."<<std::endl;
}
}

else if(command == "add"){
// TODO: Implement this functionality. currently everthing is added automatically
std::vector<std::string> File_names(num_of_arg - 2);
for(int i=2;i<num_of_arg;i++){
File_names[i] = argv[i];
}

// Then will pass this vector of std::string to the Add function
YeetAdd();
}

}

if(num_of_arg == 2){
if(command == "status"){
// Prints the total number of addiion and deletion happened since the last commit
YeetStatus(pwd);
}
else if(command == "commit"){
// Commits the current instance into history
Commit myCommitObject(pwd); // TODO: Improve this, I think this can be improved
myCommitObject.CommitMain();
}

else if(command == "history"){
if(is_yeet_repo(pwd)){
history::showHistory(pwd);
}
}


else if(command == "branch"){
// and yes, there is: TODO: Make a map of commands and there functions. yes!
std::cout<<"What you want to do?\ncreate a branch[1]\nsee all branches[2]\ndelete a branch[3]\nCurrent Branch[4]"<<std::endl;
int in;
std::cin>>in;
if(in == 1){
std::cout<<"BRANCH::Tell us the name of the branch (NO SPACES)"<<std::endl;
std::string BranchName;
std::cin>>BranchName;
Branch::createBranch(BranchName , fs::current_path());
}
else if(in == 2){
Branch::SeeBranches(fs::current_path());
}
else if(in == 3){
// TODO: Select what branch you want to delete. // idk if it's possible or not
std::cout<<"BRANCH:: This feature is currently under development"<<std::endl;
}
else if(in == 4){
Branch::currBranch(fs::current_path());
}

}
else if(command == "checkout"){
// It can be done by changing the value in the `Branch` file.
// `Branch` file should contain the name of the current branch we are in.
std::cout << "\033[1m\033[3mWhich branch you want to switch into:? (TYPE FULL EXACT NAME OF THAT BRANCH)\033[0m" << std::endl;
// TODO: I think I can parse the file and let the user select what branch they wanna checkout to
Branch::SeeBranches(std::filesystem::current_path());
std::string BranchName;
std::cin>>BranchName;
CheckOut::SwitchBranch(fs::current_path(), BranchName);
}
else if(command == "init"){
std::cout<<"ERROR::INIT::Add path name after the init to initialise a yeet repoLike \nyeet init [path]"<<std::endl;
}
}

}
catch(const std::exception& e){
// TODO write the number of arguments and the argv required for each command in the Documentation.
std::cout<<"ERROR:: ";
std::cerr << e.what() << "\nException Happened somewhere! Error:501 \n";
}
return EXIT_SUCCESS;
}
1 change: 1 addition & 0 deletions YeetCLI/include/command.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "../../YeetCore/include/commit.hpp"
#include "../../YeetCore/include/db.hpp"
#include "../../YeetCore/include/branch.hpp"
#include "../../YeetCore/include/history.hpp"
#include "../../YeetUtils/include/file_utils.hpp"
#include <filesystem>

Expand Down
105 changes: 2 additions & 103 deletions YeetCLI/main.cpp
Original file line number Diff line number Diff line change
@@ -1,106 +1,5 @@
#include <iostream>
#include "../YeetCore/include/controllers.hpp"
#include "../YeetCore/include/repository.hpp"
#include "../YeetCore/include/commit.hpp"
#include "../YeetCore/include/db.hpp"
#include "../YeetCore/include/branch.hpp"
#include <filesystem>
#include "./include/command.hpp"

int main(int num_of_arg, char* argv[]) {
// Flushing the cout and cerr.
std::cout<<std::unitbuf; // enbaling the unitbuf flag for automatic flushing for output. has no effect on input
std::cerr<<std::unitbuf;
std::cout<<"You are using cpp version: "<<__cplusplus<<std::endl; // To know my cpp version
std::string pwd = fs::current_path();

// TODO: instead of so many if-else, implement a map based approach
try{
if(num_of_arg==1){
std::cerr<<"No argument Provied! \n> Use Command: yeet init [Path] to initialize a repository \n> yeet commit to commit \n> yeet branch to see the branching options \n> yeet status to see the changes etc to the files etc. or refer docs\n";
return EXIT_FAILURE;
}

std::string command = argv[1];

if (num_of_arg == 3) {
if(command == "init"){
std::string path = argv[2];
if(fs::exists(path)){
YeetInit(path); // initialises a .init file
}
else{
std::cerr<<"The Path you provided doesn't exist!\nPlease check it and Retry."<<std::endl;
}
}

else if(command == "add"){
// TODO: Implement this functionality. currently everthing is added automatically
std::vector<std::string> File_names(num_of_arg - 2);
for(int i=2;i<num_of_arg;i++){
File_names[i] = argv[i];
}

// Then will pass this vector of std::string to the Add function
YeetAdd();
}

}

if(num_of_arg == 2){
if(command == "status"){
// Prints the total number of addiion and deletion happened since the last commit
YeetStatus(pwd);
}
else if(command == "commit"){
// Commits the current instance into history
Commit myCommitObject(pwd); // TODO: Improve this, I think this can be improved
myCommitObject.CommitMain();
}


else if(command == "branch"){
// and yes, there is: TODO: Make a map of commands and there functions. yes!
std::cout<<"What you want to do?\ncreate a branch[1]\nsee all branches[2]\ndelete a branch[3]\nCurrent Branch[4]"<<std::endl;
int in;
std::cin>>in;
if(in == 1){
std::cout<<"BRANCH::Tell us the name of the branch (NO SPACES)"<<std::endl;
std::string BranchName;
std::cin>>BranchName;
Branch::createBranch(BranchName , fs::current_path());
}
else if(in == 2){
Branch::SeeBranches(fs::current_path());
}
else if(in == 3){
// TODO: Select what branch you want to delete. // idk if it's possible or not
std::cout<<"BRANCH:: This feature is currently under development"<<std::endl;
}
else if(in == 4){
Branch::currBranch(fs::current_path());
}

}
else if(command == "checkout"){
// It can be done by changing the value in the `Branch` file.
// `Branch` file should contain the name of the current branch we are in.
std::cout << "\033[1m\033[3mWhich branch you want to switch into:? (TYPE FULL EXACT NAME OF THAT BRANCH)\033[0m" << std::endl;
// TODO: I think I can parse the file and let the user select what branch they wanna checkout to
Branch::SeeBranches(std::filesystem::current_path());
std::string BranchName;
std::cin>>BranchName;
CheckOut::SwitchBranch(fs::current_path(), BranchName);
}
else if(command == "init"){
std::cout<<"ERROR::INIT::Add path name after the init to initialise a yeet repoLike \nyeet init [path]"<<std::endl;
}
}

}
catch(const std::exception& e){
// TODO write the number of arguments and the argv required for each command in the Documentation.
std::cout<<"ERROR:: ";
std::cerr << e.what() << "\nException Happened somewhere! Error:501 \n";
}
return EXIT_SUCCESS;
return commands(num_of_arg, argv);
}
2 changes: 1 addition & 1 deletion YeetCore/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ add_library(YeetCore STATIC
branch.cpp
tree.cpp
commit.cpp
controllers.cpp
repository.cpp
db.cpp
refs_auth.cpp
history.cpp
)

# Include directories
Expand Down
Loading
Loading