Skip to content

Commit

Permalink
Reorganize the tutorial. This kills some of the duplication and
Browse files Browse the repository at this point in the history
fixes the testsuite to test all chapters.

It also adds a note in the conclusion indicating that the tutorial only
covers a part of Dulwich' functionality.
  • Loading branch information
jelmer committed Nov 26, 2010
1 parent a3348ae commit 89e2e22
Show file tree
Hide file tree
Showing 14 changed files with 143 additions and 249 deletions.
1 change: 1 addition & 0 deletions .bzrignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ dist
apidocs
*,cover
.testrepository
docs/tutorial/index.html
2 changes: 2 additions & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ James Westby <jw+debian@jameswestby.net>
John Carr <john.carr@unrouted.co.uk>
Dave Borowitz <dborowitz@google.com>

Hervé Cauwelier <herve@itaapy.com> wrote the original tutorial.

See the revision history for a full list of contributors.
5 changes: 5 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,13 @@
* Support parsing git mbox patches without a version tail, as generated by
Mercurial. (Jelmer Vernooij)

DOCUMENTATION

* Run the tutorial inside the test suite. (Jelmer Vernooij)

* Reorganized the tutorial. (Jelmer Vernooij)


0.6.2 2010-10-16

BUG FIXES
Expand Down
19 changes: 10 additions & 9 deletions docs/tutorial/0-introduction.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,16 @@ tree.
The Tree
--------

A tree is a collection of file information, the state of your working copy at
A tree is a collection of file information, the state of a single directory at
a given point in time.

A tree file looks like this::

tree <content length><NUL><file mode> <filename><NUL><blob sha>...
tree <content length><NUL><file mode> <filename><NUL><item sha>...

And repeats for every file in the tree.

Note that for a unknown reason, the SHA-1 digest is in binary form here.
Note that 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
Expand Down Expand Up @@ -88,14 +88,15 @@ 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.
These three objects make up most of the contents of a Git repository and are
used for the history. They can either appear as simple files on disk (one file
per object) or in a ``pack`` file, which is a container for a number of these
objects.

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.
The is also an index of the current state of the working copy in the
repository as well as files to track the existing branches and tags.

For a more detailled explanation of object formats and SHA-1 digests, see:
For a more detailed explanation of object formats and SHA-1 digests, see:
http://www-cs-students.stanford.edu/~blynn/gitmagic/ch08.html

Just note that recent versions of Git compress object files using zlib.
28 changes: 28 additions & 0 deletions docs/tutorial/1-repo.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
The Repository
==============

After this introduction, let's start directly with code::

>>> from dulwich.repo import Repo

The access to a repository 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). They do not have a working tree.

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 'myrepo'>

You can already look a the structure of the "myrepo/.git" folder, though it
is mostly empty for now.
88 changes: 0 additions & 88 deletions docs/tutorial/2-change-file.txt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,34 +1,13 @@
The Repository
==============
The object store
================

After this introduction, let's start directly with code::
The objects are stored in the ``object store`` of the repository.

>>> 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 'myrepo'>

You can already look a the structure of the "myrepo/.git" folder, though it
is mostly empty for now.
>>> repo = Repo.init("myrepo", mkdir=True)

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::
Expand Down Expand Up @@ -94,7 +73,7 @@ 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
Expand All @@ -115,5 +94,77 @@ blob::
$ cat spam
My file content

.. attention:: Remember to recreate the repo object when you modify the
repository outside of Dulwich!
Changing a File and Committing it
---------------------------------

Now we have a first commit, the next one will show a difference.

As seen in the introduction, it's about making a path in a tree point to a
new blob. The old blob will remain to compute the diff. The tree is altered
and the new commit'task is to point to this new version.

Let's first build the blob::

>>> from dulwich.objects import Blob
>>> spam = Blob.from_string("My new file content\n")
>>> spam.id
'16ee2682887a962f854ebd25a61db16ef4efe49f'

An alternative is to alter the previously constructed blob object::

>>> blob.data = "My new file content\n"
>>> blob.id
'16ee2682887a962f854ebd25a61db16ef4efe49f'

In any case, update the blob id known as "spam". You also have the
opportunity of changing its mode::

>>> tree["spam"] = (0100644, spam.id)

Now let's record the change::

>>> from dulwich.objects import Commit
>>> from time import time
>>> c2 = Commit()
>>> c2.tree = tree.id
>>> c2.parents = [commit.id]
>>> c2.author = c2.committer = "John Doe <john@example.com>"
>>> c2.commit_time = c2.author_time = int(time())
>>> c2.commit_timezone = c2.author_timezone = 0
>>> c2.encoding = "UTF-8"
>>> c2.message = 'Changing "spam"'

In this new commit we record the changed tree id, and most important, the
previous commit as the parent. Parents are actually a list because a commit
may happen to have several parents after merging branches.

Let's put the objects in the object store::

>>> repo.object_store.add_object(spam)
>>> repo.object_store.add_object(tree)
>>> repo.object_store.add_object(c2)

You can already ask git to introspect this commit using ``git show`` and the
value of ``c2.id`` as an argument. You'll see the difference will the
previous blob recorded as "spam".

The diff between the previous head and the new one can be printed using
write_tree_diff::

>>> from dulwich.patch import write_tree_diff
>>> import sys
>>> write_tree_diff(sys.stdout, repo.object_store, commit.tree, tree.id)
diff --git a/spam b/spam
index c55063a..16ee268 100644
--- a/spam
+++ b/spam
@@ -1,1 +1,1 @@
-My file content
+My new file content

You won't see it using git log because the head is still the previous
commit. It's easy to remedy::

>>> repo.refs['refs/heads/master'] = c2.id

Now all git tools will work as expected.
41 changes: 0 additions & 41 deletions docs/tutorial/3-add-file.txt

This file was deleted.

11 changes: 11 additions & 0 deletions docs/tutorial/3-conclusion.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Conclusion
==========

This tutorial currently only covers a small (but important) part of Dulwich.
It still needs to be extended to cover packs, tags, refs, reflogs and network
communication.

Dulwich is abstracting much of the Git plumbing, so there would be more to
see.

For now, that's all folks!
30 changes: 0 additions & 30 deletions docs/tutorial/4-remove-file.txt

This file was deleted.

Loading

0 comments on commit 89e2e22

Please sign in to comment.