diff options
-rw-r--r-- | doc/source/tutorial.rst | 124 | ||||
-rw-r--r-- | git/objects/submodule/base.py | 66 | ||||
-rw-r--r-- | git/refs/head.py | 21 | ||||
-rw-r--r-- | git/repo/base.py | 6 | ||||
-rw-r--r-- | git/test/lib/helper.py | 20 | ||||
-rw-r--r-- | git/test/test_docs.py | 9 | ||||
-rw-r--r-- | git/test/test_index.py | 7 | ||||
-rw-r--r-- | git/test/test_refs.py | 16 | ||||
-rw-r--r-- | git/test/test_remote.py | 16 | ||||
-rw-r--r-- | git/test/test_submodule.py | 85 |
10 files changed, 172 insertions, 198 deletions
diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst index 92020975..7ac2eeea 100644 --- a/doc/source/tutorial.rst +++ b/doc/source/tutorial.rst @@ -28,28 +28,28 @@ In the above example, the directory ``self.rorepo.working_tree_dir`` equals ``/U :language: python :start-after: # [2-test_init_repo_object] :end-before: # ![2-test_init_repo_object] - + A repo object provides high-level access to your data, it allows you to create and delete heads, tags and remotes and access the configuration of the repository. - + .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [3-test_init_repo_object] :end-before: # ![3-test_init_repo_object] Query the active branch, query untracked files or whether the repository data has been modified. - + .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [4-test_init_repo_object] :end-before: # ![4-test_init_repo_object] - + Clone from existing repositories or initialize new empty ones. .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [5-test_init_repo_object] :end-before: # ![5-test_init_repo_object] - + Archive the repository contents to a tar file. .. literalinclude:: ../../git/test/test_docs.py @@ -62,7 +62,7 @@ Advanced Repo Usage And of course, there is much more you can do with this type, most of the following will be explained in greater detail in specific tutorials. Don't worry if you don't understand some of these examples right away, as they may require a thorough understanding of gits inner workings. -Query relevant repository paths ... +Query relevant repository paths ... .. literalinclude:: ../../git/test/test_docs.py :language: python @@ -83,7 +83,7 @@ You can also create new heads ... :start-after: # [9-test_init_repo_object] :end-before: # ![9-test_init_repo_object] -... and tags ... +... and tags ... .. literalinclude:: ../../git/test/test_docs.py :language: python @@ -118,7 +118,7 @@ The :class:`index <git.index.base.IndexFile>` is also called stage in git-speak. :start-after: # [14-test_init_repo_object] :end-before: # ![14-test_init_repo_object] - + Examining References ******************** @@ -128,28 +128,28 @@ Examining References :language: python :start-after: # [1-test_references_and_objects] :end-before: # ![1-test_references_and_objects] - + :class:`Tags <git.refs.tag.TagReference>` are (usually immutable) references to a commit and/or a tag object. .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [2-test_references_and_objects] :end-before: # ![2-test_references_and_objects] - + A :class:`symbolic reference <git.refs.symbolic.SymbolicReference>` is a special case of a reference as it points to another reference instead of a commit. .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [3-test_references_and_objects] :end-before: # ![3-test_references_and_objects] - + Access the :class:`reflog <git.refs.log.RefLog>` easily. - + .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [4-test_references_and_objects] :end-before: # ![4-test_references_and_objects] - + Modifying References ******************** You can easily create and delete :class:`reference types <git.refs.reference.Reference>` or modify where they point to. @@ -165,7 +165,7 @@ Create or delete :class:`tags <git.refs.tag.TagReference>` the same way except y :language: python :start-after: # [6-test_references_and_objects] :end-before: # ![6-test_references_and_objects] - + Change the :class:`symbolic reference <git.refs.symbolic.SymbolicReference>` to switch branches cheaply (without adjusting the index or the working tree). .. literalinclude:: ../../git/test/test_docs.py @@ -185,29 +185,29 @@ In GitPython, all objects can be accessed through their common base, can be comp :language: python :start-after: # [8-test_references_and_objects] :end-before: # ![8-test_references_and_objects] - -Common fields are ... + +Common fields are ... .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [9-test_references_and_objects] :end-before: # ![9-test_references_and_objects] - + :class:`Index objects <git.objects.base.IndexObject>` are objects that can be put into git's index. These objects are trees, blobs and submodules which additionally know about their path in the file system as well as their mode. - + .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [10-test_references_and_objects] :end-before: # ![10-test_references_and_objects] - + Access :class:`blob <git.objects.blob.Blob>` data (or any object data) using streams. - + .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [11-test_references_and_objects] :end-before: # ![11-test_references_and_objects] - - + + The Commit object ***************** @@ -218,35 +218,35 @@ Obtain commits at the specified revision .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [12-test_references_and_objects] - :end-before: # ![12-test_references_and_objects] + :end-before: # ![12-test_references_and_objects] Iterate 50 commits, and if you need paging, you can specify a number of commits to skip. .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [13-test_references_and_objects] - :end-before: # ![13-test_references_and_objects] + :end-before: # ![13-test_references_and_objects] A commit object carries all sorts of meta-data .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [14-test_references_and_objects] - :end-before: # ![14-test_references_and_objects] + :end-before: # ![14-test_references_and_objects] Note: date time is represented in a ``seconds since epoch`` format. Conversion to human readable form can be accomplished with the various `time module <http://docs.python.org/library/time.html>`_ methods. .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [15-test_references_and_objects] - :end-before: # ![15-test_references_and_objects] + :end-before: # ![15-test_references_and_objects] You can traverse a commit's ancestry by chaining calls to ``parents`` .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [16-test_references_and_objects] - :end-before: # ![16-test_references_and_objects] + :end-before: # ![16-test_references_and_objects] The above corresponds to ``master^^^`` or ``master~3`` in git parlance. @@ -258,62 +258,62 @@ A :class:`tree <git.objects.tree.Tree>` records pointers to the contents of a di .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [17-test_references_and_objects] - :end-before: # ![17-test_references_and_objects] + :end-before: # ![17-test_references_and_objects] Once you have a tree, you can get its contents .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [18-test_references_and_objects] - :end-before: # ![18-test_references_and_objects] + :end-before: # ![18-test_references_and_objects] It is useful to know that a tree behaves like a list with the ability to query entries by name .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [19-test_references_and_objects] - :end-before: # ![19-test_references_and_objects] + :end-before: # ![19-test_references_and_objects] There is a convenience method that allows you to get a named sub-object from a tree with a syntax similar to how paths are written in a posix system .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [20-test_references_and_objects] - :end-before: # ![20-test_references_and_objects] + :end-before: # ![20-test_references_and_objects] You can also get a commit's root tree directly from the repository .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [21-test_references_and_objects] - :end-before: # ![21-test_references_and_objects] - + :end-before: # ![21-test_references_and_objects] + As trees allow direct access to their intermediate child entries only, use the traverse method to obtain an iterator to retrieve entries recursively .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [22-test_references_and_objects] - :end-before: # ![22-test_references_and_objects] - + :end-before: # ![22-test_references_and_objects] + .. note:: If trees return Submodule objects, they will assume that they exist at the current head's commit. The tree it originated from may be rooted at another commit though, that it doesn't know. That is why the caller would have to set the submodule's owning or parent commit using the ``set_parent_commit(my_commit)`` method. - + The Index Object **************** The git index is the stage containing changes to be written with the next commit or where merges finally have to take place. You may freely access and manipulate this information using the :class:`IndexFile <git.index.base.IndexFile>` object. Modify the index with ease - + .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [23-test_references_and_objects] - :end-before: # ![23-test_references_and_objects] - + :end-before: # ![23-test_references_and_objects] + Create new indices from other trees or as result of a merge. Write that result to a new index file for later inspection. .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [24-test_references_and_objects] - :end-before: # ![24-test_references_and_objects] - + :end-before: # ![24-test_references_and_objects] + Handling Remotes **************** @@ -322,10 +322,10 @@ Handling Remotes .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [25-test_references_and_objects] - :end-before: # ![25-test_references_and_objects] + :end-before: # ![25-test_references_and_objects] You can easily access configuration information for a remote by accessing options as if they where attributes. The modification of remote configuration is more explicit though. - + .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [26-test_references_and_objects] @@ -352,7 +352,7 @@ Here's an example executable that can be used in place of the `ssh_executable` a Please note that the script must be executable (i.e. `chomd +x script.sh`). `StrictHostKeyChecking=no` is used to avoid prompts asking to save the hosts key to `~/.ssh/known_hosts`, which happens in case you run this as daemon. You might also have a look at `Git.update_environment(...)` in case you want to setup a changed environment more permanently. - + Submodule Handling ****************** :class:`Submodules <git.objects.submodule.base.Submodule>` can be conveniently handled using the methods provided by GitPython, and as an added benefit, GitPython provides functionality which behave smarter and less error prone than its original c-git implementation, that is GitPython tries hard to keep your repository consistent when updating submodules recursively or adjusting the existing configuration. @@ -360,15 +360,19 @@ Submodule Handling .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [1-test_submodules] - :end-before: # ![1-test_submodules] + :end-before: # ![1-test_submodules] -In addition to the query functionality, you can move the submodule's repository to a different path <``move(...)``>, write its configuration <``config_writer().set_value(...).release()``>, update its working tree <``update(...)``>, and remove or add them <``remove(...)``, ``add(...)``>. +In addition to the query functionality, you can move the submodule's repository to a different path <``move(...)``>, +write its configuration <``config_writer().set_value(...).release()``>, update its working tree <``update(...)``>, +and remove or add them <``remove(...)``, ``add(...)``>. -If you obtained your submodule object by traversing a tree object which is not rooted at the head's commit, you have to inform the submodule about its actual commit to retrieve the data from by using the ``set_parent_commit(...)`` method. +If you obtained your submodule object by traversing a tree object which is not rooted at the head's commit, +you have to inform the submodule about its actual commit to retrieve the data from +by using the ``set_parent_commit(...)`` method. The special :class:`RootModule <git.objects.submodule.root.RootModule>` type allows you to treat your master repository as root of a hierarchy of submodules, which allows very convenient submodule handling. Its ``update(...)`` method is reimplemented to provide an advanced way of updating submodules as they change their values over time. The update method will track changes and make sure your working tree and submodule checkouts stay consistent, which is very useful in case submodules get deleted or added to name just two of the handled cases. -Additionally, GitPython adds functionality to track a specific branch, instead of just a commit. Supported by customized update methods, you are able to automatically update submodules to the latest revision available in the remote repository, as well as to keep track of changes and movements of these submodules. To use it, set the name of the branch you want to track to the ``submodule.$name.branch`` option of the *.gitmodules* file, and use GitPython update methods on the resulting repository with the ``to_latest_revision`` parameter turned on. In the latter case, the sha of your submodule will be ignored, instead a local tracking branch will be updated to the respective remote branch automatically, provided there are no local changes. The resulting behaviour is much like the one of svn::externals, which can be useful in times. +Additionally, GitPython adds functionality to track a specific branch, instead of just a commit. Supported by customized update methods, you are able to automatically update submodules to the latest revision available in the remote repository, as well as to keep track of changes and movements of these submodules. To use it, set the name of the branch you want to track to the ``submodule.$name.branch`` option of the *.gitmodules* file, and use GitPython update methods on the resulting repository with the ``to_latest_revision`` parameter turned on. In the latter case, the sha of your submodule will be ignored, instead a local tracking branch will be updated to the respective remote branch automatically, provided there are no local changes. The resulting behaviour is much like the one of svn::externals, which can be useful in times. Obtaining Diff Information ************************** @@ -380,7 +384,7 @@ Diffs can be made between the Index and Trees, Index and the working tree, trees .. literalinclude:: ../../git/test/test_docs.py :language: python :start-after: # [27-test_references_and_objects] - :end-before: # ![27-test_references_and_objects] + :end-before: # ![27-test_references_and_objects] The item returned is a DiffIndex which is essentially a list of Diff objects. It provides additional filtering to ease finding what you might be looking for. @@ -392,15 +396,15 @@ The item returned is a DiffIndex which is essentially a list of Diff objects. It Use the diff framework if you want to implement git-status like functionality. * A diff between the index and the commit's tree your HEAD points to - + * use ``repo.index.diff(repo.head.commit)`` - + * A diff between the index and the working tree - + * use ``repo.index.diff(None)`` - + * A list of untracked files - + * use ``repo.untracked_files`` Switching Branches @@ -411,7 +415,7 @@ To switch between branches similar to ``git checkout``, you effectively need to :language: python :start-after: # [29-test_references_and_objects] :end-before: # ![29-test_references_and_objects] - + The previous approach would brutally overwrite the user's changes in the working copy and index though and is less sophisticated than a ``git-checkout``. The latter will generally prevent you from destroying your work. Use the safer approach as follows. .. literalinclude:: ../../git/test/test_docs.py @@ -439,7 +443,7 @@ In case you are missing functionality as it has not been wrapped, you may conven :language: python :start-after: # [31-test_references_and_objects] :end-before: # ![31-test_references_and_objects] - + The return value will by default be a string of the standard output channel produced by the command. Keyword arguments translate to short and long keyword arguments on the command-line. @@ -457,14 +461,14 @@ The type of the database determines certain performance characteristics, such as GitDB ===== The GitDB is a pure-python implementation of the git object database. It is the default database to use in GitPython 0.3. Its uses less memory when handling huge files, but will be 2 to 5 times slower when extracting large quantities small of objects from densely packed repositories:: - + repo = Repo("path/to/repo", odbt=GitDB) GitCmdObjectDB ============== The git command database uses persistent git-cat-file instances to read repository information. These operate very fast under all conditions, but will consume additional memory for the process itself. When extracting large files, memory usage will be much higher than the one of the ``GitDB``:: - + repo = Repo("path/to/repo", odbt=GitCmdObjectDB) Git Command Debugging and Customization @@ -478,10 +482,10 @@ Using environment variables, you can further adjust the behaviour of the git com * If set to *full*, the executed git command _and_ its entire output on stdout and stderr will be shown as they happen **NOTE**: All logging is outputted using a Python logger, so make sure your program is configured to show INFO-level messages. If this is not the case, try adding the following to your program:: - + import logging logging.basicConfig(level=logging.INFO) - + * **GIT_PYTHON_GIT_EXECUTABLE** * If set, it should contain the full path to the git executable, e.g. *c:\\Program Files (x86)\\Git\\bin\\git.exe* on windows or */usr/bin/git* on linux. diff --git a/git/objects/submodule/base.py b/git/objects/submodule/base.py index bacfd8f0..6777b121 100644 --- a/git/objects/submodule/base.py +++ b/git/objects/submodule/base.py @@ -398,24 +398,20 @@ class Submodule(IndexObject, Iterable, Traversable): # otherwise there is a '-' character in front of the submodule listing # a38efa84daef914e4de58d1905a500d8d14aaf45 mymodule (v0.9.0-1-ga38efa8) # -a38efa84daef914e4de58d1905a500d8d14aaf45 submodules/intermediate/one - writer = sm.repo.config_writer() - writer.set_value(sm_section(name), 'url', url) - writer.release() + with sm.repo.config_writer() as writer: + writer.set_value(sm_section(name), 'url', url) # update configuration and index index = sm.repo.index - writer = sm.config_writer(index=index, write=False) - writer.set_value('url', url) - writer.set_value('path', path) - - sm._url = url - if not branch_is_default: - # store full path - writer.set_value(cls.k_head_option, br.path) - sm._branch_path = br.path - # END handle path - writer.release() - del(writer) + with sm.config_writer(index=index, write=False) as writer: + writer.set_value('url', url) + writer.set_value('path', path) + + sm._url = url + if not branch_is_default: + # store full path + writer.set_value(cls.k_head_option, br.path) + sm._branch_path = br.path # we deliberatly assume that our head matches our index ! sm.binsha = mrepo.head.commit.binsha @@ -542,9 +538,8 @@ class Submodule(IndexObject, Iterable, Traversable): # the default implementation will be offended and not update the repository # Maybe this is a good way to assure it doesn't get into our way, but # we want to stay backwards compatible too ... . Its so redundant ! - writer = self.repo.config_writer() - writer.set_value(sm_section(self.name), 'url', self.url) - writer.release() + with self.repo.config_writer() as writer: + writer.set_value(sm_section(self.name), 'url', self.url) # END handle dry_run # END handle initalization @@ -731,11 +726,9 @@ class Submodule(IndexObject, Iterable, Traversable): # END handle submodule doesn't exist # update configuration - writer = self.config_writer(index=index) # auto-write - writer.set_value('path', module_checkout_path) - self.path = module_checkout_path - writer.release() - del(writer) + with self.config_writer(index=index) as writer: # auto-write + writer.set_value('path', module_checkout_path) + self.path = module_checkout_path # END handle configuration flag except Exception: if renamed_module: @@ -898,13 +891,11 @@ class Submodule(IndexObject, Iterable, Traversable): # now git config - need the config intact, otherwise we can't query # information anymore - writer = self.repo.config_writer() - writer.remove_section(sm_section(self.name)) - writer.release() + with self.repo.config_writer() as writer: + writer.remove_section(sm_section(self.name)) - writer = self.config_writer() - writer.remove_section() - writer.release() + with self.config_writer() as writer: + writer.remove_section() # END delete configuration return self @@ -995,18 +986,15 @@ class Submodule(IndexObject, Iterable, Traversable): return self # .git/config - pw = self.repo.config_writer() - # As we ourselves didn't write anything about submodules into the parent .git/config, we will not require - # it to exist, and just ignore missing entries - if pw.has_section(sm_section(self.name)): - pw.rename_section(sm_section(self.name), sm_section(new_name)) - # end - pw.release() + with self.repo.config_writer() as pw: + # As we ourselves didn't write anything about submodules into the parent .git/config, + # we will not require it to exist, and just ignore missing entries. + if pw.has_section(sm_section(self.name)): + pw.rename_section(sm_section(self.name), sm_section(new_name)) # .gitmodules - cw = self.config_writer(write=True).config - cw.rename_section(sm_section(self.name), sm_section(new_name)) - cw.release() + with self.config_writer(write=True) as cw: + cw.config.rename_section(sm_section(self.name), sm_section(new_name)) self._name = new_name diff --git a/git/refs/head.py b/git/refs/head.py index fe820b10..a1d8ab46 100644 --- a/git/refs/head.py +++ b/git/refs/head.py @@ -133,18 +133,15 @@ class Head(Reference): raise ValueError("Incorrect parameter type: %r" % remote_reference) # END handle type - writer = self.config_writer() - if remote_reference is None: - writer.remove_option(self.k_config_remote) - writer.remove_option(self.k_config_remote_ref) - if len(writer.options()) == 0: - writer.remove_section() - # END handle remove section - else: - writer.set_value(self.k_config_remote, remote_reference.remote_name) - writer.set_value(self.k_config_remote_ref, Head.to_full_path(remote_reference.remote_head)) - # END handle ref value - writer.release() + with self.config_writer() as writer: + if remote_reference is None: + writer.remove_option(self.k_config_remote) + writer.remove_option(self.k_config_remote_ref) + if len(writer.options()) == 0: + writer.remove_section() + else: + writer.set_value(self.k_config_remote, remote_reference.remote_name) + writer.set_value(self.k_config_remote_ref, Head.to_full_path(remote_reference.remote_head)) return self diff --git a/git/repo/base.py b/git/repo/base.py index 26753bab..8b68b5ff 100644 --- a/git/repo/base.py +++ b/git/repo/base.py @@ -924,10 +924,8 @@ class Repo(object): # sure repo = cls(os.path.abspath(path), odbt=odbt) if repo.remotes: - writer = repo.remotes[0].config_writer - writer.set_value('url', repo.remotes[0].url.replace("\\\\", "\\").replace("\\", "/")) - # PY3: be sure cleanup is performed and lock is released - writer.release() + with repo.remotes[0].config_writer as writer: + writer.set_value('url', repo.remotes[0].url.replace("\\\\", "\\").replace("\\", "/")) # END handle remote repo return repo diff --git a/git/test/lib/helper.py b/git/test/lib/helper.py index 3c9374e7..e92ce8b4 100644 --- a/git/test/lib/helper.py +++ b/git/test/lib/helper.py @@ -237,16 +237,13 @@ def with_rw_and_rw_remote_repo(working_tree_ref): rw_remote_repo.daemon_export = True # this thing is just annoying ! - crw = rw_remote_repo.config_writer() - section = "daemon" - try: - crw.add_section(section) - except Exception: - pass - crw.set(section, "receivepack", True) - # release lock - crw.release() - del(crw) + with rw_remote_repo.config_writer() as crw: + section = "daemon" + try: + crw.add_section(section) + except Exception: + pass + crw.set(section, "receivepack", True) # initialize the remote - first do it as local remote and pull, then # we change the url to point to the daemon. The daemon should be started @@ -255,7 +252,8 @@ def with_rw_and_rw_remote_repo(working_tree_ref): d_remote.fetch() remote_repo_url = "git://localhost:%s%s" % (GIT_DAEMON_PORT, remote_repo_dir) - d_remote.config_writer.set('url', remote_repo_url) + with d_remote.config_writer as cw: + cw.set('url', remote_repo_url) temp_dir = osp(_mktemp()) gd = launch_git_daemon(temp_dir, '127.0.0.1', GIT_DAEMON_PORT) diff --git a/git/test/test_docs.py b/git/test/test_docs.py index 5c7ae7f0..e2bfcb21 100644 --- a/git/test/test_docs.py +++ b/git/test/test_docs.py @@ -39,8 +39,8 @@ class Tutorials(TestBase): # [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 - cw.release() # call release() to be sure changes are written and locks are released + with repo.config_writer(): # get a config writer to change configuration + pass # call release() to be sure changes are written and locks are released # ![3-test_init_repo_object] # [4-test_init_repo_object] @@ -398,9 +398,8 @@ class Tutorials(TestBase): # [26-test_references_and_objects] assert origin.url == repo.remotes.origin.url - cw = origin.config_writer - cw.set("pushurl", "other_url") - cw.release() + with origin.config_writer as cw: + cw.set("pushurl", "other_url") # Please note that in python 2, writing origin.config_writer.set(...) is totally safe. # In py3 __del__ calls can be delayed, thus not writing changes in time. diff --git a/git/test/test_index.py b/git/test/test_index.py index 01506c6f..34014064 100644 --- a/git/test/test_index.py +++ b/git/test/test_index.py @@ -412,10 +412,9 @@ class TestIndex(TestBase): uname = u"Thomas Müller" umail = "sd@company.com" - writer = rw_repo.config_writer() - writer.set_value("user", "name", uname) - writer.set_value("user", "email", umail) - writer.release() + with rw_repo.config_writer() as writer: + writer.set_value("user", "name", uname) + writer.set_value("user", "email", umail) self.assertEqual(writer.get_value("user", "name"), uname) # remove all of the files, provide a wild mix of paths, BaseIndexEntries, diff --git a/git/test/test_refs.py b/git/test/test_refs.py index 00b5232a..43f1dcc7 100644 --- a/git/test/test_refs.py +++ b/git/test/test_refs.py @@ -101,15 +101,13 @@ class TestRefs(TestBase): assert prev_object == cur_object # represent the same git object assert prev_object is not cur_object # but are different instances - writer = head.config_writer() - tv = "testopt" - writer.set_value(tv, 1) - assert writer.get_value(tv) == 1 - writer.release() + with head.config_writer() as writer: + tv = "testopt" + writer.set_value(tv, 1) + assert writer.get_value(tv) == 1 assert head.config_reader().get_value(tv) == 1 - writer = head.config_writer() - writer.remove_option(tv) - writer.release() + with head.config_writer() as writer: + writer.remove_option(tv) # after the clone, we might still have a tracking branch setup head.set_tracking_branch(None) @@ -175,7 +173,7 @@ class TestRefs(TestBase): def test_orig_head(self): assert type(self.rorepo.head.orig_head()) == SymbolicReference - + @with_rw_repo('0.1.6') def test_head_checkout_detached_head(self, rw_repo): res = rw_repo.remotes.origin.refs.master.checkout() diff --git a/git/test/test_remote.py b/git/test/test_remote.py index 3fd71a1f..7b52ccce 100644 --- a/git/test/test_remote.py +++ b/git/test/test_remote.py @@ -267,7 +267,8 @@ class TestRemote(TestBase): # put origin to git-url other_origin = other_repo.remotes.origin - other_origin.config_writer.set("url", remote_repo_url) + with other_origin.config_writer as cw: + cw.set("url", remote_repo_url) # it automatically creates alternates as remote_repo is shared as well. # It will use the transport though and ignore alternates when fetching # assert not other_repo.alternates # this would fail @@ -416,13 +417,12 @@ class TestRemote(TestBase): self.failUnlessRaises(IOError, reader.set, opt, "test") # change value - writer = remote.config_writer - new_val = "myval" - writer.set(opt, new_val) - assert writer.get(opt) == new_val - writer.set(opt, val) - assert writer.get(opt) == val - del(writer) + with remote.config_writer as writer: + new_val = "myval" + writer.set(opt, new_val) + assert writer.get(opt) == new_val + writer.set(opt, val) + assert writer.get(opt) == val assert getattr(remote, opt) == val # END for each default option key diff --git a/git/test/test_submodule.py b/git/test/test_submodule.py index be388e5d..46928f51 100644 --- a/git/test/test_submodule.py +++ b/git/test/test_submodule.py @@ -105,21 +105,25 @@ class TestSubmodule(TestBase): new_smclone_path = None # keep custom paths for later new_csmclone_path = None # if rwrepo.bare: - self.failUnlessRaises(InvalidGitRepositoryError, sm.config_writer) + with self.assertRaises(InvalidGitRepositoryError): + with sm.config_writer() as cw: + pass else: - writer = sm.config_writer() - # for faster checkout, set the url to the local path - new_smclone_path = to_native_path_linux(join_path_native(self.rorepo.working_tree_dir, sm.path)) - writer.set_value('url', new_smclone_path) - writer.release() - assert sm.config_reader().get_value('url') == new_smclone_path - assert sm.url == new_smclone_path + with sm.config_writer() as writer: + # for faster checkout, set the url to the local path + new_smclone_path = to_native_path_linux(join_path_native(self.rorepo.working_tree_dir, sm.path)) + writer.set_value('url', new_smclone_path) + writer.release() + assert sm.config_reader().get_value('url') == new_smclone_path + assert sm.url == new_smclone_path # END handle bare repo smold.config_reader() # cannot get a writer on historical submodules if not rwrepo.bare: - self.failUnlessRaises(ValueError, smold.config_writer) + with self.assertRaises(ValueError): + with smold.config_writer(): + pass # END handle bare repo # make the old into a new - this doesn't work as the name changed @@ -210,9 +214,8 @@ class TestSubmodule(TestBase): # adjust the path of the submodules module to point to the local destination new_csmclone_path = to_native_path_linux(join_path_native(self.rorepo.working_tree_dir, sm.path, csm.path)) - writer = csm.config_writer() - writer.set_value('url', new_csmclone_path) - writer.release() + with csm.config_writer() as writer: + writer.set_value('url', new_csmclone_path) assert csm.url == new_csmclone_path # dry-run does nothing @@ -274,9 +277,8 @@ class TestSubmodule(TestBase): # module() is supposed to point to gitdb, which has a child-submodule whose URL is still pointing # to github. To save time, we will change it to csm.set_parent_commit(csm.repo.head.commit) - cw = csm.config_writer() - cw.set_value('url', self._small_repo_url()) - cw.release() + with csm.config_writer() as cw: + cw.set_value('url', self._small_repo_url()) csm.repo.index.commit("adjusted URL to point to local source, instead of the internet") # We have modified the configuration, hence the index is dirty, and the @@ -284,12 +286,10 @@ class TestSubmodule(TestBase): # NOTE: As we did a few updates in the meanwhile, the indices were reset # Hence we create some changes csm.set_parent_commit(csm.repo.head.commit) - writer = sm.config_writer() - writer.set_value("somekey", "somevalue") - writer.release() - writer = csm.config_writer() - writer.set_value("okey", "ovalue") - writer.release() + with sm.config_writer() as writer: + writer.set_value("somekey", "somevalue") + with csm.config_writer() as writer: + writer.set_value("okey", "ovalue") self.failUnlessRaises(InvalidGitRepositoryError, sm.remove) # if we remove the dirty index, it would work sm.module().index.reset() @@ -452,8 +452,8 @@ class TestSubmodule(TestBase): assert len(rm.list_items(rm.module())) == 1 rm.config_reader() - w = rm.config_writer() - w.release() + with rm.config_writer(): + pass # deep traversal gitdb / async rsmsp = [sm.path for sm in rm.traverse()] @@ -478,9 +478,8 @@ class TestSubmodule(TestBase): assert not sm.module_exists() # was never updated after rwrepo's clone # assure we clone from a local source - writer = sm.config_writer() - writer.set_value('url', to_native_path_linux(join_path_native(self.rorepo.working_tree_dir, sm.path))) - writer.release() + with sm.config_writer() as writer: + writer.set_value('url', to_native_path_linux(join_path_native(self.rorepo.working_tree_dir, sm.path))) # dry-run does nothing sm.update(recursive=False, dry_run=True, progress=prog) @@ -488,9 +487,8 @@ class TestSubmodule(TestBase): sm.update(recursive=False) assert sm.module_exists() - writer = sm.config_writer() - writer.set_value('path', fp) # change path to something with prefix AFTER url change - writer.release() + with sm.config_writer() as writer: + writer.set_value('path', fp) # change path to something with prefix AFTER url change # update fails as list_items in such a situations cannot work, as it cannot # find the entry at the changed path @@ -577,9 +575,8 @@ class TestSubmodule(TestBase): # repository at the different url nsm.set_parent_commit(csmremoved) nsmurl = to_native_path_linux(join_path_native(self.rorepo.working_tree_dir, rsmsp[0])) - writer = nsm.config_writer() - writer.set_value('url', nsmurl) - writer.release() + with nsm.config_writer() as writer: + writer.set_value('url', nsmurl) csmpathchange = rwrepo.index.commit("changed url") nsm.set_parent_commit(csmpathchange) @@ -609,9 +606,8 @@ class TestSubmodule(TestBase): nsmm = nsm.module() prev_commit = nsmm.head.commit for branch in ("some_virtual_branch", cur_branch.name): - writer = nsm.config_writer() - writer.set_value(Submodule.k_head_option, git.Head.to_full_path(branch)) - writer.release() + with nsm.config_writer() as writer: + writer.set_value(Submodule.k_head_option, git.Head.to_full_path(branch)) csmbranchchange = rwrepo.index.commit("changed branch to %s" % branch) nsm.set_parent_commit(csmbranchchange) # END for each branch to change @@ -639,9 +635,8 @@ class TestSubmodule(TestBase): assert nsm.exists() and nsm.module_exists() and len(nsm.children()) >= 1 # assure we pull locally only nsmc = nsm.children()[0] - writer = nsmc.config_writer() - writer.set_value('url', subrepo_url) - writer.release() + with nsmc.config_writer() as writer: + writer.set_value('url', subrepo_url) rm.update(recursive=True, progress=prog, dry_run=True) # just to run the code rm.update(recursive=True, progress=prog) @@ -793,8 +788,8 @@ class TestSubmodule(TestBase): rsm = parent.submodule_update() assert_exists(sm) assert_exists(csm) - csm_writer = csm.config_writer().set_value('url', 'bar') - csm_writer.release() + with csm.config_writer().set_value('url', 'bar'): + pass csm.repo.index.commit("Have to commit submodule change for algorithm to pick it up") assert csm.url == 'bar' @@ -872,9 +867,8 @@ class TestSubmodule(TestBase): sm.repo.index.commit("added new file") # change designated submodule checkout branch to the new upstream feature branch - smcw = sm.config_writer() - smcw.set_value('branch', sm_fb.name) - smcw.release() + with sm.config_writer() as smcw: + smcw.set_value('branch', sm_fb.name) assert sm.repo.is_dirty(index=True, working_tree=False) sm.repo.index.commit("changed submodule branch to '%s'" % sm_fb) @@ -898,9 +892,8 @@ class TestSubmodule(TestBase): sm_source_repo.index.commit("new file added, to past of '%r'" % sm_fb) # Change designated submodule checkout branch to a new commit in its own past - smcw = sm.config_writer() - smcw.set_value('branch', sm_pfb.path) - smcw.release() + with sm.config_writer() as smcw: + smcw.set_value('branch', sm_pfb.path) sm.repo.index.commit("changed submodule branch to '%s'" % sm_pfb) # Test submodule updates - must fail if submodule is dirty |