start a tutorial of first steps
authorHervé Cauwelier <herve@itaapy.com>
Tue, 15 Sep 2009 20:28:14 +0000 (22:28 +0200)
committerHervé Cauwelier <herve@itaapy.com>
Tue, 15 Sep 2009 20:28:14 +0000 (22:28 +0200)
docs/tutorial/0-introduction.txt [new file with mode: 0644]
docs/tutorial/1-initial-commit [new file with mode: 0644]

diff --git a/docs/tutorial/0-introduction.txt b/docs/tutorial/0-introduction.txt
new file mode 100644 (file)
index 0000000..b525fd4
--- /dev/null
@@ -0,0 +1,105 @@
+================
+Dulwich Tutorial
+================
+
+Introduction
+============
+
+Git repository format
+---------------------
+
+For a better understanding of Dulwich, we'll start by explaining most of the
+Git secrets.
+
+Open the ".git" folder of any Git-managed repository. You'll find folders
+like "branches", "hooks"... We're only interested in "objects" here. Open it.
+
+You'll mostly see 2 hex-digits folders. Git identifies content by its SHA-1
+digest. The 2 hex-digits plus the 38 hex-digits of files inside these folders
+form the 40 characters (or 20 bytes) id of Git objects you'll manage in
+Dulwich.
+
+We'll first study the three main objects:
+
+- The Commit;
+
+- The Tree;
+
+- The Blob.
+
+The Commit
+----------
+
+You're used to generate commits using Git. You have set up your name and
+e-mail, and you know how to see the history using "git log".
+
+A commit file looks like this::
+
+  commit <content length><NUL>tree <tree sha>
+  parent <parent sha>
+  [parent <parent sha> if several parents from merges]
+  author <author name> <author e-mail> <timestamp> <timezone>
+  committer <author name> <author e-mail> <timestamp> <timezone>
+  <commit message>
+
+But where are the changes you commited? The commit contains a reference to a
+tree.
+
+The Tree
+--------
+
+A tree is a collection of file information, the state of your working copy at
+a given point in time.
+
+A tree file looks like this::
+
+  tree <content length><NUL><file mode> <filename><NUL><blob sha>...
+
+And repeats for every file in the tree. A real example from Dulwich itself::
+
+Note that for a unknown reason, the SHA-1 digest is in binary form here.
+
+The file mode is like the octal argument you could give to the "chmod"
+command.  Except it is in extended form to tell regular files from
+directories and other types.
+
+We now know how our files are referenced but we haven't found their actual
+content yet. That's where the reference to a blob comes in.
+
+The Blob
+--------
+
+A blob is simply the content of files you are versionning.
+
+A blob file looks like this::
+
+  blob <content length><NUL><content>
+
+If you change a single line, another blob will be generated by Git at commit
+time. This is how Git can fastly checkout any version in time.
+
+On the opposite, several identical files with different filenames generate
+only one blob. That's mostly how renames are so cheap and efficient in Git.
+
+Dulwich Objects
+---------------
+
+Dulwich implements these three objects with an API to easily access the
+information you need, while abstracting some more secrets Git is using to
+accelerate operations and reduce space.
+
+More About Git formats
+----------------------
+
+These three objects make 90 % of a Git repository. The rest is branch
+information and optimizations.
+
+For instance there is an index of the current state of the working copy.
+There are also pack files to group several small objects in a single indexed
+file.
+
+You'll find more detailled explanations and examples here:
+http://www-cs-students.stanford.edu/~blynn/gitmagic/ch08.html
+
+Just note that recent versions of Git compress object files using zlib.
diff --git a/docs/tutorial/1-initial-commit b/docs/tutorial/1-initial-commit
new file mode 100644 (file)
index 0000000..4cc38f4
--- /dev/null
@@ -0,0 +1,122 @@
+================
+Dulwich Tutorial
+================
+
+The Repository
+==============
+
+After this introduction, let's start directly with code::
+
+  >>> from dulwich.repo import Repo
+
+The access to every object is through the Repo object. You can open an
+existing repository or you can create a new one. There are two types of Git
+repositories:
+
+  Regular Repositories -- They are the ones you create using "git init" and
+  you daily use. They contain a ".git" folder.
+
+  Bare Repositories -- There is not ".git" folder. The top-level folder
+  contains itself the "branches", "hooks"... folders. These are used for
+  published repositories (mirrors).
+
+Let's create a folder and turn it into a repository, like "git init" would::
+
+  >>> from os import mkdir
+  >>> mkdir("myrepo")
+  >>> repo = Repo.init("myrepo")
+  >>> repo
+  <Repo at '/tmp/myrepo/'>
+
+You can already look a the structure of the "myrepo/.git" folder, though it
+is mostly empty for now.
+
+Initial commit
+==============
+
+When you use Git, you generally add or modify content. As our repository is
+empty for now, we'll start by adding a new file::
+
+  >>> from dulwich.objects import Blob
+  >>> blob = Blob.from_string("My file content")
+  >>> blob.id
+  '456a1e689eb87b947be24562e830421cd799388c'
+
+Of course you could create a blob from an existing file using "from_file"
+instead.
+
+As said in the introduction, file content is separed from file name. Let's
+give this content a name::
+
+  >>> from dulwich.objects import Tree
+  >>> tree = Tree()
+  >>> tree.add(0100644, "spam", blob.id)
+
+Note that "0100644" is the octal form for a regular file with common
+permissions. You can hardcode them or you can use the ``stat`` module.
+
+The tree state of our repository still needs to be placed in time. That's the
+job of the commit::
+
+  >>> from dulwich.objects import Commit
+  >>> from time import time
+  >>> commit = Commit()
+  >>> commit.tree = tree.id
+  >>> commit.author = commit.committer = "Your Name <your.email@example.com>"
+  >>> commit.commit_time = commit.author_time = int(time())
+  >>> tz = parse_timezone('-0200')
+  >>> commit.commit_timezone = commit.author_timezone = tz
+  >>> commit.encoding = "UTF-8"
+  >>> commit.message = "Initial commit"
+
+Note that the initial commit has no parents.
+
+At this point, the repository is still empty because all operations happen in
+memory. Let's "commit" it.
+
+  >>> object_store = repo.object_store
+  >>> object_store.add_object(blob)
+
+Now the ".git/objects" folder contains a first SHA-1 file. Let's continue
+saving the changes::
+
+  >>> object_store.add_object(tree)
+  >>> object_store.add_object(commit)
+
+Now the physical repository contains three objects but still has no branch.
+Let's create the master branch like Git would::
+
+  >>> repo.refs['refs/heads/master'] = commit.id
+
+The master branch now has a commit where to start, but Git itself would not
+known what is the current branch. That's another reference::
+
+  >>> repo.refs['HEAD'] = 'ref: refs/heads/master'
+
+Now our repository is officialy tracking a branch named "master" refering to a
+single commit.
+
+Playing again with Git
+======================
+
+At this point you can come back to the shell, go into the "myrepo" folder and
+type "git status" to let Git confirm that this is a regular repository on
+branch "master".
+
+Git will tell you that the file "spam" is deleted, which is normal because
+Git is comparing the repository state with the current working copy. And we
+have absolutely no working copy using Dulwich because we don't need it at
+all!
+
+You can checkout the last state using ``git checkout -f``. The force flag
+will prevent Git from complaining that there are uncommitted changes in the
+checkout.
+
+The file ``spam`` appears and with no surprise::
+
+  $ cat spam
+  My file content
+
+contains the same bytes as the blob.
+
+Remember to reload the repository when you modify it outside of Dulwich!