summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO15
-rw-r--r--lib/git/refs.py46
-rw-r--r--test/git/test_base.py16
-rw-r--r--test/testlib/helper.py4
4 files changed, 67 insertions, 14 deletions
diff --git a/TODO b/TODO
index afda659a..db77df67 100644
--- a/TODO
+++ b/TODO
@@ -11,7 +11,8 @@ General
a sha or ref unless cat-file is used where it must be a sha
* Overhaul command caching - currently its possible to create many instances of
the std-in command types, as it appears they are not killed when the repo gets
- deleted.
+ deleted. A clear() method could already help to allow long-running programs
+ to remove cached commands after an idle time.
* References should be parsed 'manually' to get around command invocation, but
be sure to be able to read packed refs.
@@ -64,7 +65,6 @@ Remote
Repo
----
-* Nice fetch/pull handling, at least supported/wired throuhg to the git command
* Blame: Read the blame format making assumptions about its structure,
currently regex are used a lot although we can deduct what will be next.
- Read data from a stream directly from git command
@@ -78,13 +78,4 @@ Tree
* Should return submodules during iteration ( identifies as commit )
* Work through test and check for test-case cleanup and completeness ( what about
testing whether it raises on invalid input ? ). See 6dc7799d44e1e5b9b77fd19b47309df69ec01a99
-
-Testing
--------
-* Create a test-repository that can be written to and changed in addition to the normal
- read-only testing scheme that operates on the own repository. Doing this could be a simple
- as forking a shared repo in a tmp directory. In that moment, we probably want to
- facility committing and checkouts as well.
- - Use these tests for git-remote as we need to test push
- - Also assure that the test-case setup is a bit more consistent ( Derive from TestCase, possibly
- make repo a class member instead of an instance member
+
diff --git a/lib/git/refs.py b/lib/git/refs.py
index 8c9d6672..9a03b6f5 100644
--- a/lib/git/refs.py
+++ b/lib/git/refs.py
@@ -174,6 +174,52 @@ class Head(Reference):
"""
return self.object
+ @classmethod
+ def reset(cls, repo, commit='HEAD', index=True, working_tree = False,
+ paths=None, **kwargs):
+ """
+ Reset the current head to the given commit optionally synchronizing
+ the index and working tree.
+
+ ``repo``
+ Repository containing commit
+
+ ``commit``
+ Commit object, Reference Object or string identifying a revision
+
+ ``index``
+ If True, the index will be set to match the given commit. Otherwise
+ it will not be touched.
+
+ ``working_tree``
+ If True, the working tree will be forcefully adjusted to match the given
+ commit, possibly overwriting uncommitted changes without warning.
+ If working_tree is True, index must be true as well
+
+ ``paths``
+ Single path or list of paths relative to the git root directory
+ that are to be reset. This allow to partially reset individual files.
+
+ ``kwargs``
+ Additional arguments passed to git-reset.
+
+ Returns
+ Head pointing to the specified commit
+ """
+ mode = "--soft"
+ if index:
+ mode = "--mixed"
+
+ if working_tree:
+ mode = "--hard"
+ if not index:
+ raise ValueError( "Cannot reset the working tree if the index is not reset as well")
+ # END working tree handling
+
+ repo.git.reset(mode, commit, paths, **kwargs)
+
+ # we always point to the active branch as it is the one changing
+ return repo.active_branch
class TagReference(Head):
"""
diff --git a/test/git/test_base.py b/test/git/test_base.py
index a7ef9374..3472608e 100644
--- a/test/git/test_base.py
+++ b/test/git/test_base.py
@@ -94,6 +94,22 @@ class TestBase(TestBase):
assert prev_object is not cur_object # but are different instances
# END for each head
+ @with_rw_repo('0.1.6')
+ def test_head_reset(self, rw_repo):
+ cur_head = rw_repo.head
+ new_head_commit = cur_head.commit.parents[0]
+ reset_head = Head.reset(rw_repo, new_head_commit, index=True) # index only
+ assert reset_head.commit == new_head_commit
+
+ self.failUnlessRaises(ValueError, Head.reset, rw_repo, new_head_commit, index=False, working_tree=True)
+ new_head_commit = new_head_commit.parents[0]
+ reset_head = Head.reset(rw_repo, new_head_commit, index=True, working_tree=True) # index + wt
+ assert reset_head.commit == new_head_commit
+
+ # paths
+ Head.reset(rw_repo, new_head_commit, paths = "lib")
+
+
def test_get_object_type_by_name(self):
for tname in base.Object.TYPES:
assert base.Object in get_object_type_by_name(tname).mro()
diff --git a/test/testlib/helper.py b/test/testlib/helper.py
index eef7876f..ab4b9f4e 100644
--- a/test/testlib/helper.py
+++ b/test/testlib/helper.py
@@ -100,7 +100,7 @@ def with_rw_repo(working_tree_ref):
def repo_creator(self):
repo_dir = tempfile.mktemp("non_bare_repo")
rw_repo = self.rorepo.clone(repo_dir, shared=True, bare=False, n=True)
- rw_repo.git.checkout(working_tree_ref)
+ rw_repo.git.checkout("-b", "master", working_tree_ref)
try:
return func(self, rw_repo)
finally:
@@ -134,7 +134,7 @@ def with_rw_and_rw_remote_repo(working_tree_ref):
rw_remote_repo = self.rorepo.clone(remote_repo_dir, shared=True, bare=True)
rw_repo = rw_remote_repo.clone(repo_dir, shared=True, bare=False, n=True) # recursive alternates info ?
- rw_repo.git.checkout(working_tree_ref)
+ rw_repo.git.checkout("-b", "master", working_tree_ref)
try:
return func(self, rw_repo, rw_remote_repo)
finally: