Implement Git series
Ugit
supports a lot of basic git operations. All of them are wrapped into the Operations namespace to make it manageable.
1 InitOperation
This operation supports the init
command parameter, which has two steps.
- Clear the
.ugit
folder - Create the
HEAD
tomaster
branch
2 BranchOperation
This operation is designed to manipulate the branch. For examples
- Show all branches
- Create one branch
- …
There is no secret in BranchOperation
just read and write ref/heads
folder. Each file of them represents the branch. HEAD
is pointing to the current branch in the ref: refs/head/<branch-name>
format.
3 TagOperation
It’s same with BranchOperation
but this time it focuses on ref/tags
folder.
4 AddOperation
This operation’s responsibility is to add file or directory to the stage index.
5 TreeOperation
This operation is one of the backbone of ugit
. It writes and reads tree of content of working directory, index and repo.
Working Tree
Working tree represents the current working directory. The result will be a dictionary which key is relative file path and value is blob’s object id.
Stage Index Tree
It will retrieve and update .ugit/index
file.
Repo Tree
We can read the checked-in folder and blob according to the tree object id, vice verse.
6 CommitOperation
This operation has main tree responsibilities.
- Create/Get a commit
- Show a previous commit according to the commit id.
- Show all object ids by given commit ids.
Firstly of all, what’s the commit like?
tree <tree-object-id>
parent <parent1-commit-id>
parent <parent2-commit-id2><message>
A commit may have zero (first commit)or multiple parents (merge commit).
We can retrieve the parents commit according the parent
property. So, it doesn’t have challenge to show all commit by given commit id. We have also to leverage the TreeOperation
to get all objects.
7 DiffOperation
As the distribution VSC tool, it’s expected to compare and merge two snapshot s of repo. DiffOperation
completes two major jobs
- Compare the difference of trees and blob files.
- Merge them.
Given that we have two trees: A and B. Both of them are represent by the a dictionary which key is the file relative path and value is the file object id. So it comes to four cases. (NaN means this file object id doesn’t exist)
We leverage diff
command when come to compare the two files.
diff --unified --show-c-function --label a/{file-a} --label b/{file-b} {tempfile}
How to merge them? For each file object, just reuse MergeBlob
method for diff result from two trees.
diff -DHEAD {headfile} {otherfile}
8 RemoteOperation
Since ugit
is a distributed tool, it should support sync with remote repo. To simply the implementation, we support fetch
and push
operation in the same file system.
Fetch
How does the fetch
do?
- Get all the reference in the
ref/
folder, which includebranch
andtag
- Create the corresponding reference in the local
remote
folder. - Get all the objects by the commit object id.
- Write them down if doesn’t exist.
Push
We have to push local reference to remote, like branch
or tag
. First we have to check whether remote reference is ancestor. If not which means someone has forward the remote repo. This push may be dangerous.
- Push the missing object in the remote
- Update the remote reference.