Skip to content

MilderBronze/prsnl-git

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

17 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

digits = '13789'
# implement the method is_ascending

def is_ascending(reading: int) -> bool:
    if reading < 10:
        return True
    if reading % 10 <= (reading // 10) % 10:
        return False
    return is_ascending(reading // 10)

def smallest_reading(size: int) -> int:
    return int(digits[:size])

def largest_reading(size: int) -> int:
    return int(digits[-size:])

def next_reading():
    global digits
    # implement if is_ascending is True only then proceed.
    if not is_ascending(int(digits)):
        return digits

    digits = list(digits)
    i = len(digits) - 1

    while i >= 0:
        if int(digits[i]) == 9:
            i -= 1
            continue

        if i == len(digits) - 1 or int(digits[i]) + 1 < int(digits[i + 1]):
            digits[i] = str(int(digits[i]) + 1)

            for j in range(i + 1, len(digits)):
                digits[j] = str(int(digits[j - 1]) + 1)

            break
        else:
            i -= 1

    if i == -1:
        for j in range(len(digits)):
            digits[j] = str(j + 1)

    return ''.join(digits)

def prev_reading():
    global digits
    # implement if is_ascending is True only then proceed.
    if not is_ascending(int(digits)):
        return digits

    digits = list(digits)
    i = len(digits) - 1

    while i >= 0:
        if i == 0 and int(digits[0]) == 1:
            i -= 1
            continue

        if i > 0 and int(digits[i]) - 1 <= int(digits[i - 1]):
            i -= 1
            continue

        digits[i] = str(int(digits[i]) - 1)

        for j in range(i + 1, len(digits)):
            digits[j] = str(9 - (len(digits) - 1 - j))

        break

    if i == -1:
        for j in range(len(digits)):
            digits[j] = str(9 - (len(digits) - 1 - j))

    return ''.join(digits)


num: int
for i in range(20):
    num = prev_reading()
    digits = str(num)

print(num)

prsnl-git - A Simple Git Clone in Python


πŸ“– What is prsnl-git?

prsnl-git is a Python implementation of Git that demonstrates the core concepts and internals of version control systems. This project is for educational purposes to understand how Git works under the hood by implementing the fundamental data structures and operations.

Core Components

1. GitObject Class

  • Base class for all Git objects (Blob, Tree, Commit)
  • Handles serialization/deserialization with zlib compression
  • Generates SHA-1 hashes for object identification (real Git uses SHA-256 nowadays)

2. Blob Objects

  • Store actual file contents
  • Represent individual files in the repository

3. Tree Objects

  • Represent directory structures
  • Store references to blobs and other trees
  • Maintain file permissions and names

4. Commit Objects

  • Store metadata about commits (author, timestamp, message)
  • Reference tree objects and parent commits
  • Form the commit history chain

5. Repository Class

  • Manages the .git directory structure
  • Handles object storage and retrieval
  • Implements Git commands (init, add, commit, checkout, etc.)

Features

  • Repository Initialization - Create new Git repositories
  • File Staging - Add files to the staging area
  • Commit Creation - Create commits with messages and metadata
  • Branch Management - Create, switch, and delete branches
  • Commit History - View commit logs and history
  • Status Checking - Monitor repository state
  • Object Storage - Efficient storage using SHA-1 hashing and compression

πŸ“¦ Installation & Setup

Prerequisites

  • Python 3.7+
  • No external dependencies required (uses standard libraries only)

Quick Start

# Clone the repository
git clone https://github.com/MilderBronze/prsnl-git.git
cd git_clone

# Run prsnl-git commands
python main.py init
python main.py add README.md
python main.py commit -m "Initial commit"

πŸ’» Usage Examples

Initialize a Repository

python main.py init
# Output: Initialized empty Git repository in ./.git

Add Files to Staging

# Add single file
python main.py add main.py

# Add entire directory
python main.py add src/

# Add multiple files
python main.py add file1.py file2.py src/

Create Commits

python main.py commit -m "Add new feature"

Branch Operations

# List branches
python main.py branch

# Create new branch
python main.py checkout -b feature-branch

# Switch to existing branch
python main.py checkout main

# Delete branch
python main.py branch feature-branch -d

View Repository Status

# Check working directory status
python main.py status

# View commit history
python main.py log -n 5

πŸ—‚οΈ Project Structure

prsnl-git/
β”œβ”€β”€ main.py          # Main prsnl-git implementation
β”œβ”€β”€ README.md        # This file
└── .git/           # Git repository (created after init)
    β”œβ”€β”€ objects/    # Git objects database
    β”œβ”€β”€ refs/       # References and branches
    β”œβ”€β”€ HEAD        # Current branch pointer
    └── index       # Staging area

πŸ” How It Works

1. Object Storage

  • Files are stored as Blob objects with compressed content
  • Directories are represented as Tree objects with file references
  • Each object gets a unique SHA-1 hash

2. Staging Process

  • Files are read and converted to Blob objects
  • Object hashes are stored in the index (staging area)
  • Index tracks which files are ready for commit

3. Commit Process

  • Creates a Tree object from the current index
  • Generates a Commit object with metadata
  • Updates branch reference to point to new commit

4. Branch Management

  • Branches are just files pointing to commit hashes
  • Checkout updates HEAD and restores working directory
  • Branch creation copies current commit reference
  • Branches are just files pointing to commit hashes
  • Checkout updates HEAD and restores working directory
  • Branch creation copies current commit reference

Docker

Build the image (run from the project root where the Dockerfile is):

docker build -t khudkagit .

Run prsnl-git commands (the image uses ENTRYPOINT ["python","main.py"], so args are appended):

# initialize a repo (one-shot)
docker run --rm khudkagit init

# add a file
docker run --rm khudkagit add main.py

# commit
docker run --rm khudkagit commit -m "Initial commit"

Persist the .git folder on the host so container runs modify your repo:

  • Git Bash / MSYS:
docker run --rm -v /d/prsnl-git/.git:/app/.git khudkagit init
  • PowerShell:
docker run --rm -v "${PWD}\.git:/app/.git" khudkagit init

Open a shell inside the image (interactive):

# prefer sh for slim/alpine images
docker run --rm -it --entrypoint /bin/sh khudkagit

Start a long-lived container you can exec into later:

docker run -d --name khudkagit_container --entrypoint tail khudkagit -f /dev/null
docker exec -it khudkagit_container /bin/sh

Notes

  • Many slim images lack bash; use /bin/sh if bash is missing.
  • Use --rm for temporary runs so containers are removed after exit.
  • Naming containers (--name) is optional but makes docker exec, docker stop and docker rm easier.

About

this is just me learning python and quenching my curiosity about how Linus Torvalds created git in the first place.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors