diff options
Diffstat (limited to 'git/test/test_docs.py')
-rw-r--r-- | git/test/test_docs.py | 142 |
1 files changed, 134 insertions, 8 deletions
diff --git a/git/test/test_docs.py b/git/test/test_docs.py index 6befb9ea..9a04784d 100644 --- a/git/test/test_docs.py +++ b/git/test/test_docs.py @@ -21,14 +21,14 @@ class Tutorials(TestBase): # For all you know, the first argument to Repo is a path to the repository # you want to work with repo = Repo(self.rorepo.working_tree_dir) - assert repo.bare == False + assert not repo.bare # ![1-test_init_repo_object] # [2-test_init_repo_object] - bare_empty_repo = Repo.init(join(rw_dir, 'bare-repo'), bare=True) - assert bare_empty_repo.bare == True + bare_repo = Repo.init(join(rw_dir, 'bare-repo'), bare=True) + assert bare_repo.bare # ![2-test_init_repo_object] - + # [3-test_init_repo_object] repo.config_reader() # get a config reader for read-only access cw = repo.config_writer() # get a config writer to change configuration @@ -41,16 +41,142 @@ class Tutorials(TestBase): repo.untracked_files # ['my_untracked_file'] # ![4-test_init_repo_object] - + # [5-test_init_repo_object] - assert repo.clone(join(rw_dir, 'to/this/path')).__class__ is Repo + cloned_repo = repo.clone(join(rw_dir, 'to/this/path')) + assert cloned_repo.__class__ is Repo # clone an existing repository assert Repo.init(join(rw_dir, 'path/for/new/repo')).__class__ is Repo # ![5-test_init_repo_object] - + # [6-test_init_repo_object] - repo.archive(open(join(rw_dir, 'repo.tar'), 'w')) + repo.archive(open(join(rw_dir, 'repo.tar'), 'wb')) # ![6-test_init_repo_object] + # repository paths + # [7-test_init_repo_object] + assert os.path.isdir(cloned_repo.working_tree_dir) # directory with your work files + assert cloned_repo.git_dir.startswith(cloned_repo.working_tree_dir) # directory containing the git repository + assert bare_repo.working_tree_dir is None # bare repositories have no working tree + # ![7-test_init_repo_object] + + # heads, tags and references + # heads are branches in git-speak + # [8-test_init_repo_object] + assert repo.head.ref == repo.heads.master # head is a symbolic reference pointing to master + assert repo.tags['0.3.5'] == repo.tag('refs/tags/0.3.5') # you can access tags in various ways too + assert repo.refs.master == repo.heads['master'] # .refs provides access to all refs, i.e. heads ... + assert repo.refs['origin/master'] == repo.remotes.origin.refs.master # ... remotes ... + assert repo.refs['0.3.5'] == repo.tags['0.3.5'] # ... and tags + # ![8-test_init_repo_object] + + # create a new head/branch + # [9-test_init_repo_object] + new_branch = cloned_repo.create_head('feature') # create a new branch ... + assert cloned_repo.active_branch != new_branch # which wasn't checked out yet ... + assert new_branch.commit == cloned_repo.active_branch.commit # and which points to the checked-out commit + # It's easy to let a branch point to the previous commit, without affecting anything else + # Each reference provides access to the git object it points to, usually commits + assert new_branch.set_commit('HEAD~1').commit == cloned_repo.active_branch.commit.parents[0] + # ![9-test_init_repo_object] + + # create a new tag reference + # [10-test_init_repo_object] + past = cloned_repo.create_tag('past', ref=new_branch, + message="This is a tag-object pointing to %s" % new_branch.name) + assert past.commit == new_branch.commit # the tag points to the specified commit + assert past.tag.message.startswith("This is") # and its object carries the message provided + + now = cloned_repo.create_tag('now') # This is a tag-reference. It may not carry meta-data + assert now.tag is None + # ![10-test_init_repo_object] + + # Object handling + # [11-test_init_repo_object] + assert now.commit.message != past.commit.message + # You can read objects directly through binary streams, no working tree required + assert (now.commit.tree / 'VERSION').data_stream.read().decode('ascii').startswith('0') + + # You can traverse trees as well to handle all contained files of a particular commit + file_count = 0 + tree_count = 0 + tree = past.commit.tree + for item in tree.traverse(): + file_count += item.type == 'blob' + tree_count += item.type == 'tree' + assert file_count and tree_count # we have accumulated all directories and files + assert len(tree.blobs) + len(tree.trees) == len(tree) # a tree is iterable itself to traverse its children + # ![11-test_init_repo_object] + + # remotes allow handling push, pull and fetch operations + # [12-test_init_repo_object] + from git import RemoteProgress + + class MyProgressPrinter(RemoteProgress): + def update(self, op_code, cur_count, max_count=None, message=''): + print(op_code, cur_count, max_count, cur_count / (max_count or 100.0), message or "NO MESSAGE") + # end + + assert len(cloned_repo.remotes) == 1 # we have been cloned, so there should be one remote + assert len(bare_repo.remotes) == 0 # this one was just initialized + origin = bare_repo.create_remote('origin', url=cloned_repo.working_tree_dir) + assert origin.exists() + for fetch_info in origin.fetch(progress=MyProgressPrinter()): + print("Updated %s to %s" % (fetch_info.ref, fetch_info.commit)) + # create a local branch at the latest fetched master. We specify the name statically, but you have all + # information to do it programatically as well. + bare_master = bare_repo.create_head('master', origin.refs.master) + bare_repo.head.set_reference(bare_master) + assert not bare_repo.delete_remote(origin).exists() + # push and pull behave very similarly + # ![12-test_init_repo_object] + + # index + # [13-test_init_repo_object] + assert new_branch.checkout() == cloned_repo.active_branch # checking out a branch adjusts the working tree + assert new_branch.commit == past.commit # Now the past is checked out + + new_file_path = os.path.join(cloned_repo.working_tree_dir, 'my-new-file') + open(new_file_path, 'wb').close() # create new file in working tree + cloned_repo.index.add([new_file_path]) # add it to the index + # Commit the changes to deviate masters history + cloned_repo.index.commit("Added a new file in the past - for later merege") + + # prepare a merge + master = cloned_repo.heads.master # right-hand side is ahead of us, in the future + merge_base = cloned_repo.merge_base(new_branch, master) # allwos for a three-way merge + cloned_repo.index.merge_tree(master, base=merge_base) # write the merge result into index + cloned_repo.index.commit("Merged past and now into future ;)", + parent_commits=(new_branch.commit, master.commit)) + + # now new_branch is ahead of master, which probably should be checked out and reset softly. + # note that all these operations didn't touch the working tree, as we managed it ourselves. + # This definitely requires you to know what you are doing :) ! + assert os.path.basename(new_file_path) in new_branch.commit.tree # new file is now in tree + master.commit = new_branch.commit # let master point to most recent commit + cloned_repo.head.reference = master # we adjusted just the reference, not the working tree or index + # ![13-test_init_repo_object] + + # submodules + + # [14-test_init_repo_object] + # create a new submodule and check it out on the spot, setup to track master branch of `bare_repo` + # As our GitPython repository has submodules already that point to github, make sure we don't + # interact with them + for sm in cloned_repo.submodules: + assert not sm.remove().exists() # after removal, the sm doesn't exist anymore + sm = cloned_repo.create_submodule('mysubrepo', 'path/to/subrepo', url=bare_repo.git_dir, branch='master') + + # .gitmodules was written and added to the index, which is now being committed + cloned_repo.index.commit("Added submodule") + assert sm.exists() and sm.module_exists() # this submodule is defintely available + sm.remove(module=True, configuration=False) # remove the working tree + assert sm.exists() and not sm.module_exists() # the submodule itself is still available + + # update all submodules, non-recursively to save time, this method is very powerful, go have a look + cloned_repo.submodule_update(recursive=False) + assert sm.module_exists() # The submodules working tree was checked out by update + # ![14-test_init_repo_object] + @with_rw_directory def test_add_file_and_commit(self, rw_dir): import git |