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 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.
- 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)
- Store actual file contents
- Represent individual files in the repository
- Represent directory structures
- Store references to blobs and other trees
- Maintain file permissions and names
- Store metadata about commits (author, timestamp, message)
- Reference tree objects and parent commits
- Form the commit history chain
- Manages the
.gitdirectory structure - Handles object storage and retrieval
- Implements Git commands (init, add, commit, checkout, etc.)
- 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
- Python 3.7+
- No external dependencies required (uses standard libraries only)
# 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"python main.py init
# Output: Initialized empty Git repository in ./.git# 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/python main.py commit -m "Add new feature"# 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# Check working directory status
python main.py status
# View commit history
python main.py log -n 5prsnl-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
- 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
- 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
- Creates a Tree object from the current index
- Generates a Commit object with metadata
- Updates branch reference to point to new commit
- 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
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 initOpen a shell inside the image (interactive):
# prefer sh for slim/alpine images
docker run --rm -it --entrypoint /bin/sh khudkagitStart 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/shNotes
- Many slim images lack
bash; use/bin/shifbashis missing. - Use
--rmfor temporary runs so containers are removed after exit. - Naming containers (
--name) is optional but makesdocker exec,docker stopanddocker rmeasier.