Skip to content

Commit

Permalink
Merge remote-tracking branch 'fraser/feature/push'
Browse files Browse the repository at this point in the history
  • Loading branch information
jdavid committed Sep 2, 2013
2 parents d5c0a23 + 134d87a commit bde9639
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 34 deletions.
1 change: 1 addition & 0 deletions docs/remotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ The Remote type
.. autoattribute:: pygit2.Remote.refspec_count
.. automethod:: pygit2.Remote.get_refspec
.. automethod:: pygit2.Remote.fetch
.. automethod:: pygit2.Remote.push
.. automethod:: pygit2.Remote.save
66 changes: 66 additions & 0 deletions src/remote.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,10 +218,76 @@ Remote_save(Remote *self, PyObject *args)
}


int
push_status_foreach_callback(const char *ref, const char *msg, void *data)
{
const char **msg_dst = (const char **)data;
if (msg != NULL && *msg_dst == NULL)
*msg_dst = msg;
return 0;
}

PyDoc_STRVAR(Remote_push__doc__,
"push(refspec)\n"
"\n"
"Push the given refspec to the remote. Raises ``GitError`` on error.");

PyObject *
Remote_push(Remote *self, PyObject *args)
{
git_push *push = NULL;
const char *refspec = NULL;
const char *msg = NULL;
int err;

if (!PyArg_ParseTuple(args, "s", &refspec))
return NULL;

err = git_push_new(&push, self->remote);
if (err < 0)
return Error_set(err);

err = git_push_add_refspec(push, refspec);
if (err < 0)
goto error;

err = git_push_finish(push);
if (err < 0)
goto error;

if (!git_push_unpack_ok(push)) {
git_push_free(push);
PyErr_SetString(GitError, "Remote failed to unpack objects");
return NULL;
}

err = git_push_status_foreach(push, push_status_foreach_callback, &msg);
if (err < 0)
goto error;
if (msg != NULL) {
git_push_free(push);
PyErr_SetString(GitError, msg);
return NULL;
}

err = git_push_update_tips(push);
if (err < 0)
goto error;

git_push_free(push);
Py_RETURN_NONE;

error:
git_push_free(push);
return Error_set(err);
}


PyMethodDef Remote_methods[] = {
METHOD(Remote, fetch, METH_NOARGS),
METHOD(Remote, save, METH_NOARGS),
METHOD(Remote, get_refspec, METH_O),
METHOD(Remote, push, METH_VARARGS),
{NULL}
};

Expand Down
5 changes: 2 additions & 3 deletions test/test_blob.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,12 @@ def test_create_blob_fromworkdir(self):


def test_create_blob_outside_workdir(self):
path = join(dirname(__file__), 'data', self.repo_dir + '.tar')
path = __file__
self.assertRaises(KeyError, self.repo.create_blob_fromworkdir, path)


def test_create_blob_fromdisk(self):
path = join(dirname(__file__), 'data', self.repo_dir + '.tar')
blob_oid = self.repo.create_blob_fromdisk(path)
blob_oid = self.repo.create_blob_fromdisk(__file__)
blob = self.repo[blob_oid]

self.assertTrue(isinstance(blob, pygit2.Blob))
Expand Down
40 changes: 40 additions & 0 deletions test/test_remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,45 @@ def test_fetch(self):
self.assertEqual(stats['received_objects'], REMOTE_REPO_OBJECTS)


class PushTestCase(unittest.TestCase):
def setUp(self):
self.origin_ctxtmgr = utils.TemporaryRepository(('git', 'testrepo.git'))
self.clone_ctxtmgr = utils.TemporaryRepository(('git', 'testrepo.git'))
self.origin = pygit2.Repository(self.origin_ctxtmgr.__enter__())
self.clone = pygit2.Repository(self.clone_ctxtmgr.__enter__())
self.remote = self.clone.create_remote('origin', self.origin.path)

def tearDown(self):
self.origin_ctxtmgr.__exit__(None, None, None)
self.clone_ctxtmgr.__exit__(None, None, None)

def test_push_fast_forward_commits_to_remote_succeeds(self):
tip = self.clone[self.clone.head.target]
oid = self.clone.create_commit(
'refs/heads/master', tip.author, tip.author, 'empty commit',
tip.tree.oid, [tip.oid]
)
self.remote.push('refs/heads/master')
self.assertEqual(self.origin[self.origin.head.target].oid, oid)

def test_push_when_up_to_date_succeeds(self):
self.remote.push('refs/heads/master')
origin_tip = self.origin[self.origin.head.target].oid
clone_tip = self.clone[self.clone.head.target].oid
self.assertEqual(origin_tip, clone_tip)

def test_push_non_fast_forward_commits_to_remote_fails(self):
tip = self.origin[self.origin.head.target]
oid = self.origin.create_commit(
'refs/heads/master', tip.author, tip.author, 'some commit',
tip.tree.oid, [tip.oid]
)
tip = self.clone[self.clone.head.target]
oid = self.clone.create_commit(
'refs/heads/master', tip.author, tip.author, 'other commit',
tip.tree.oid, [tip.oid]
)
self.assertRaises(pygit2.GitError, self.remote.push, 'refs/heads/master')

if __name__ == '__main__':
unittest.main()
6 changes: 3 additions & 3 deletions test/test_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def test_lookup_commit_prefix(self):

def test_get_path(self):
directory = realpath(self.repo.path)
expected = realpath(join(self._temp_dir, 'testrepo.git'))
expected = realpath(self.repo_path)
self.assertEqual(directory, expected)

def test_get_workdir(self):
Expand Down Expand Up @@ -179,12 +179,12 @@ def test_is_bare(self):

def test_get_path(self):
directory = realpath(self.repo.path)
expected = realpath(join(self._temp_dir, 'testrepo', '.git'))
expected = realpath(join(self.repo_path, '.git'))
self.assertEqual(directory, expected)

def test_get_workdir(self):
directory = realpath(self.repo.workdir)
expected = realpath(join(self._temp_dir, 'testrepo'))
expected = realpath(self.repo_path)
self.assertEqual(directory, expected)

def test_checkout_ref(self):
Expand Down
65 changes: 37 additions & 28 deletions test/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,27 @@ def rmtree(path):
shutil.rmtree(path, onerror=onerror)


class TemporaryRepository(object):
def __init__(self, repo_spec):
self.repo_spec = repo_spec

def __enter__(self):
container, name = self.repo_spec
repo_path = os.path.join(os.path.dirname(__file__), 'data', name)
self.temp_dir = tempfile.mkdtemp()
temp_repo_path = os.path.join(self.temp_dir, name)
if container == 'tar':
tar = tarfile.open('.'.join((repo_path, 'tar')))
tar.extractall(self.temp_dir)
tar.close()
else:
shutil.copytree(repo_path, temp_repo_path)
return temp_repo_path

def __exit__(self, exc_type, exc_value, traceback):
rmtree(self.temp_dir)


class NoRepoTestCase(unittest.TestCase):

def setUp(self):
Expand Down Expand Up @@ -103,45 +124,33 @@ def assertEqualSignature(self, a, b):
self.assertEqual(a.offset, b.offset)


class BareRepoTestCase(NoRepoTestCase):

repo_dir = 'testrepo.git'

class AutoRepoTestCase(NoRepoTestCase):
def setUp(self):
super(BareRepoTestCase, self).setUp()

repo_dir = self.repo_dir
repo_path = os.path.join(os.path.dirname(__file__), 'data', repo_dir)
temp_repo_path = os.path.join(self._temp_dir, repo_dir)

shutil.copytree(repo_path, temp_repo_path)

self.repo = pygit2.Repository(temp_repo_path)
super(AutoRepoTestCase, self).setUp()
self.repo_ctxtmgr = TemporaryRepository(self.repo_spec)
self.repo_path = self.repo_ctxtmgr.__enter__()
self.repo = pygit2.Repository(self.repo_path)

def tearDown(self):
self.repo_ctxtmgr.__exit__(None, None, None)
super(AutoRepoTestCase, self).tearDown()

class RepoTestCase(NoRepoTestCase):

repo_dir = 'testrepo'
class BareRepoTestCase(AutoRepoTestCase):

def setUp(self):
super(RepoTestCase, self).setUp()
repo_spec = 'git', 'testrepo.git'

repo_dir = self.repo_dir
repo_path = os.path.join(os.path.dirname(__file__), 'data', repo_dir)
temp_repo_path = os.path.join(self._temp_dir, repo_dir, '.git')

tar = tarfile.open(repo_path + '.tar')
tar.extractall(self._temp_dir)
tar.close()
class RepoTestCase(AutoRepoTestCase):

self.repo = pygit2.Repository(temp_repo_path)
repo_spec = 'tar', 'testrepo'


class DirtyRepoTestCase(RepoTestCase):
class DirtyRepoTestCase(AutoRepoTestCase):

repo_dir = 'dirtyrepo'
repo_spec = 'tar', 'dirtyrepo'


class EmptyRepoTestCase(RepoTestCase):
class EmptyRepoTestCase(AutoRepoTestCase):

repo_dir = 'emptyrepo'
repo_spec = 'tar', 'emptyrepo'

0 comments on commit bde9639

Please sign in to comment.