Skip to content

Commit

Permalink
🚒 Fixes cloning empty repositories
Browse files Browse the repository at this point in the history
  • Loading branch information
guyzmo committed May 4, 2017
1 parent e89d557 commit b260b2c
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 48 deletions.
24 changes: 14 additions & 10 deletions git_repo/services/ext/bitbucket.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,6 @@ def list(self, user, _long=False):
'/'.join([user.username, repo.name]), # name
]

def get_repository(self, user, repo):
try:
return next(self.bb.repositoryByOwnerAndRepositoryName(owner=user, repository_name=repo))
except HTTPError as err:
raise ResourceNotFoundError('Cannot retrieve repository: {}/{} does not exists.'.format(user, repo))

def _format_gist(self, gist):
return gist.split('/')[-1] if gist.startswith('http') else gist

Expand Down Expand Up @@ -240,10 +234,6 @@ def gist_delete(self, gist_id):
raise ResourceNotFoundError("Could not find snippet {}.".format(gist_id)) from err
raise ResourceError("Couldn't delete snippet: {}".format(err)) from err

@staticmethod
def get_project_default_branch(project):
return project.mainbranch.get('name', 'master')

def request_create(self, onto_user, onto_repo, from_branch, onto_branch, title=None, description=None, auto_slug=False, edit=None):
try:
onto_project = self.get_repository(onto_user, onto_repo)
Expand Down Expand Up @@ -485,3 +475,17 @@ def user(self):
except (HTTPError, AttributeError) as err:
raise ResourceError("Couldn't find the current user: {}".format(err)) from err


def get_repository(self, user, repo):
try:
return next(self.bb.repositoryByOwnerAndRepositoryName(owner=user, repository_name=repo))
except HTTPError as err:
raise ResourceNotFoundError('Cannot retrieve repository: {}/{} does not exists.'.format(user, repo))

@staticmethod
def is_repository_empty(project):
return project.size == 0

@staticmethod
def get_project_default_branch(project):
return project.mainbranch.get('name', 'master')
24 changes: 14 additions & 10 deletions git_repo/services/ext/github.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,6 @@ def list(self, user, _long=False):
else:
print("Cannot show repository {}: {}".format('/'.join([user, repo.name]), err))

def get_repository(self, user, repo):
repository = self.gh.repository(user, repo)
if not repository:
raise ResourceNotFoundError('Cannot delete: repository {}/{} does not exists.'.format(user, repo))
return repository

def _format_gist(self, gist):
return gist.split('https://gist.github.com/')[-1].split('.git')[0]

Expand Down Expand Up @@ -231,10 +225,6 @@ def gist_delete(self, gist_id):
raise ResourceNotFoundError('Could not find gist')
gist.delete()

@staticmethod
def get_project_default_branch(project):
return project.default_branch or 'master'

def request_create(self, onto_user, onto_repo, from_branch, onto_branch, title=None, description=None, auto_slug=False, edit=None):
onto_project = self.gh.repository(onto_user, onto_repo)

Expand Down Expand Up @@ -373,3 +363,17 @@ def get_parent_project_url(self, user, project, rw=True):
def user(self):
return self.gh.user().login

def get_repository(self, user, repo):
repository = self.gh.repository(user, repo)
if not repository:
raise ResourceNotFoundError('Cannot delete: repository {}/{} does not exists.'.format(user, repo))
return repository

@staticmethod
def is_repository_empty(project):
return project.size == 0

@staticmethod
def get_project_default_branch(project):
return project.default_branch or 'master'

30 changes: 19 additions & 11 deletions git_repo/services/ext/gitlab.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,6 @@ def list(self, user, _long=False):
repo.name_with_namespace, # name
]

def get_repository(self, user, repo):
try:
return self.gl.projects.get('{}/{}'.format(user, repo))
except GitlabGetError as err:
if err.response_code == 404:
raise ResourceNotFoundError("Cannot get: repository {}/{} does not exists.".format(user, repo)) from err

@classmethod
def get_auth_token(cls, login, password, prompt=None):
gl = gitlab.Gitlab(url='https://{}'.format(cls.fqdn), email=login, password=password)
Expand Down Expand Up @@ -257,10 +250,6 @@ def gist_delete(self, snippet):

return snippet.delete()

@staticmethod
def get_project_default_branch(project):
return project.default_branch or 'master'

def request_create(self, onto_user, onto_repo, from_branch, onto_branch, title=None, description=None, auto_slug=False, edit=None):
try:
onto_project = self.gl.projects.get('/'.join([onto_user, onto_repo]))
Expand Down Expand Up @@ -374,3 +363,22 @@ def get_parent_project_url(self, user, project, rw=True):
def user(self):
return self.gl.user.username

def get_repository(self, user, repo):
try:
return self.gl.projects.get('{}/{}'.format(user, repo))
except GitlabGetError as err:
if err.response_code == 404:
raise ResourceNotFoundError("Cannot get: repository {}/{} does not exists.".format(user, repo)) from err

@staticmethod
def get_project_default_branch(project):
return project.default_branch or 'master'

@staticmethod
def is_repository_empty(project):
try:
project.repository_tree()
return True
except gitlab.exceptions.GitlabGetError:
return False

41 changes: 26 additions & 15 deletions git_repo/services/ext/gogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,6 @@ def get_auth_token(cls, login, password, prompt=None):
token = gg.create_token(auth, name, login)
return token.token

@staticmethod
def get_project_default_branch(project):
# TODO get default branch
return 'master'

@property
def user(self):
return self.gg.username
Expand Down Expand Up @@ -200,16 +195,6 @@ def list(self, user, _long=False):
repo['full_name'], # name
]

def get_repository(self, user, repo):
try:
return self.gg.repository(user, repo)
except ApiFailure as err:
if err.status_code == 404:
raise ResourceNotFoundError("Cannot get: repository {}/{} does not exists.".format(user, repo)) from err
raise ResourceError("Unhandled error: {}".format(err)) from err
except Exception as err:
raise ResourceError("Unhandled exception: {}".format(err)) from err

def gist_list(self, gist=None):
raise NotImplementedError

Expand All @@ -233,3 +218,29 @@ def request_list(self, user, repo):

def request_fetch(self, user, repo, request, pull=False):
raise NotImplementedError

def get_repository(self, user, repo):
try:
return self.gg.repository(user, repo)
except ApiFailure as err:
if err.status_code == 404:
raise ResourceNotFoundError("Cannot get: repository {}/{} does not exists.".format(user, repo)) from err
raise ResourceError("Unhandled error: {}".format(err)) from err
except Exception as err:
raise ResourceError("Unhandled exception: {}".format(err)) from err

@staticmethod
def get_project_default_branch(project):
# not yet in gogs_client
# cf https://github.com/unfoldingWord-dev/python-gogs-client/pull/8
if hasattr(project, 'default_branch'):
return project.default_branch
return 'master'

@staticmethod
def is_repository_empty(project):
# not yet in gogs_client
# cf https://github.com/unfoldingWord-dev/python-gogs-client/pull/9
if hasattr(project, 'empty'):
return project.empty()
return False
16 changes: 14 additions & 2 deletions git_repo/services/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,12 +329,17 @@ def clone(self, user, repo, branch=None, rw=True):
'''
log.info('Cloning {}…'.format(repo))

project = self.get_repository(user, repo)
if not branch:
project = self.get_repository(user, repo)
branch = self.get_project_default_branch(project)

is_empty = self.is_repository_empty(project)
if is_empty:
self.repository.init()

remote, *_ = self.add(user=user, repo=repo, tracking=True, rw=rw)
self.pull(remote, branch)
if not is_empty:
self.pull(remote, branch)

def add(self, repo, user=None, name=None, tracking=False, alone=False, rw=True, auto_slug=False):
'''Adding repository as remote
Expand Down Expand Up @@ -578,6 +583,13 @@ def get_parent_project_url(self, user, repo, rw=True): #pragma: no cover
def user(self): #pragma: no cover
raise NotImplementedError

@staticmethod
def is_repository_empty(project):
raise NotImplementedError

@staticmethod
def get_project_default_branch(project):
raise NotImplementedError

'''
register all services by importing their modules, from the ext pagckage
Expand Down
1 change: 1 addition & 0 deletions tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,7 @@ def action_clone(self, namespace, repository):
with self.mockup_git(namespace, repository):
local_slug = self.service.format_path(namespace=namespace, repository=repository, rw=True)
self.set_mock_popen_commands([
('git init', b'Initialized empty Git repository in /tmp/bar/.git/', b'', 0),
('git remote add all {}'.format(local_slug), b'', b'', 0),
('git remote add {} {}'.format(self.service.name, local_slug), b'', b'', 0),
('git version', b'git version 2.8.0', b'', 0),
Expand Down
41 changes: 41 additions & 0 deletions tests/integration/cassettes/test_gitlab_test_04_clone.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,47 @@
},
"url": "https://gitlab.com/api/v3/projects/guyzmo%2Fgit-repo"
}
},
{
"recorded_at": "2017-05-04T10:32:22",
"request": {
"body": {
"encoding": "utf-8",
"string": ""
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "identity",
"Connection": "keep-alive",
"PRIVATE-TOKEN": "<PRIVATE_KEY_GITLAB>",
"User-Agent": "python-requests/2.13.0"
},
"method": "GET",
"uri": "https://gitlab.com/api/v3/projects/1016797/repository/tree"
},
"response": {
"body": {
"encoding": null,
"string": "[{\"id\":\"996e370ca098a6f8ad4de7f290337be3d2872847\",\"name\":\"git_repo\",\"type\":\"tree\",\"path\":\"git_repo\",\"mode\":\"040000\"},{\"id\":\"14b7a932a44744ef896569fa61eff6c765cfb24b\",\"name\":\"tests\",\"type\":\"tree\",\"path\":\"tests\",\"mode\":\"040000\"},{\"id\":\"51ceaea89e237f5886f409bcb078d6dbe0bcbb23\",\"name\":\".editorconfig\",\"type\":\"blob\",\"path\":\".editorconfig\",\"mode\":\"100644\"},{\"id\":\"7a5782d8822078d2230887e3359dd48452c6a3de\",\"name\":\".gitignore\",\"type\":\"blob\",\"path\":\".gitignore\",\"mode\":\"100644\"},{\"id\":\"d0a4e8237e65ef257110a6c6ec9274e88f993fa6\",\"name\":\".gitlab-ci.yml\",\"type\":\"blob\",\"path\":\".gitlab-ci.yml\",\"mode\":\"100644\"},{\"id\":\"0f3b6b1adf2c419dc5e391917236d82fff7ab40a\",\"name\":\".travis.yml\",\"type\":\"blob\",\"path\":\".travis.yml\",\"mode\":\"100644\"},{\"id\":\"c767d63f397a24306badb542b64a8b33aac42d37\",\"name\":\"LICENSE\",\"type\":\"blob\",\"path\":\"LICENSE\",\"mode\":\"100644\"},{\"id\":\"f0cd0f60924cf80dbb2366f85621de52cd340c6f\",\"name\":\"MANIFEST.in\",\"type\":\"blob\",\"path\":\"MANIFEST.in\",\"mode\":\"100644\"},{\"id\":\"bcfa7d36f8abca75d5586e61cdb1765dd1f051ab\",\"name\":\"README.md\",\"type\":\"blob\",\"path\":\"README.md\",\"mode\":\"100644\"},{\"id\":\"afa2b3515e910d7f01eb4eb95480e0fbd9385f75\",\"name\":\"VERSION\",\"type\":\"blob\",\"path\":\"VERSION\",\"mode\":\"100644\"},{\"id\":\"559f42ec779c0df90883b99f2f2be4f14bd120ea\",\"name\":\"buildout.cfg\",\"type\":\"blob\",\"path\":\"buildout.cfg\",\"mode\":\"100644\"},{\"id\":\"b0abd8c1d717ce2bbecab572355798a2dbada6f1\",\"name\":\"requirements-test.txt\",\"type\":\"blob\",\"path\":\"requirements-test.txt\",\"mode\":\"100644\"},{\"id\":\"6a165a3f064946ee2553409091586e0e8ce06a83\",\"name\":\"requirements.txt\",\"type\":\"blob\",\"path\":\"requirements.txt\",\"mode\":\"100644\"},{\"id\":\"ec8880a7b98cf1e579552dc04f832121ade57396\",\"name\":\"setup.py\",\"type\":\"blob\",\"path\":\"setup.py\",\"mode\":\"100644\"},{\"id\":\"90999d5df1b573144a6e139f09b00ba9e3128f41\",\"name\":\"tox.ini\",\"type\":\"blob\",\"path\":\"tox.ini\",\"mode\":\"100644\"}]"
},
"headers": {
"Cache-Control": "max-age=0, private, must-revalidate",
"Content-Length": "1819",
"Content-Type": "application/json",
"Date": "Thu, 04 May 2017 10:32:22 GMT",
"Etag": "W/\"96885a58bce1762b8fa9c8dc3a428ac5\"",
"Server": "nginx",
"Strict-Transport-Security": "max-age=31536000",
"Vary": "Origin",
"X-Request-Id": "7aba5f66-61da-4832-8a08-32190375f7c1",
"X-Runtime": "0.100891"
},
"status": {
"code": 200,
"message": "OK"
},
"url": "https://gitlab.com/api/v3/projects/1016797/repository/tree"
}
}
],
"recorded_with": "betamax/0.5.1"
Expand Down
39 changes: 39 additions & 0 deletions tests/integration/cassettes/test_gitlab_test_19_request_fetch.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,45 @@
},
"url": "https://gitlab.com/api/v3/projects/<GITLAB_NAMESPACE>%2Fgit-repo"
}
},
{
"recorded_at": "2017-05-04T10:32:29",
"request": {
"body": {
"encoding": "utf-8",
"string": ""
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "identity",
"Connection": "keep-alive",
"PRIVATE-TOKEN": "<PRIVATE_KEY_GITLAB>",
"User-Agent": "python-requests/2.13.0"
},
"method": "GET",
"uri": "https://gitlab.com/api/v3/projects/1848932/repository/tree"
},
"response": {
"body": {
"encoding": null,
"string": "{\"message\":\"404 Project Not Found\"}"
},
"headers": {
"Cache-Control": "no-cache",
"Content-Length": "35",
"Content-Type": "application/json",
"Date": "Thu, 04 May 2017 10:32:29 GMT",
"Server": "nginx",
"Vary": "Origin",
"X-Request-Id": "405f9670-f3d3-4d9b-a04f-22d4d393224c",
"X-Runtime": "0.036389"
},
"status": {
"code": 404,
"message": "Not Found"
},
"url": "https://gitlab.com/api/v3/projects/1848932/repository/tree"
}
}
],
"recorded_with": "betamax/0.5.1"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,45 @@
},
"url": "https://gitlab.com/api/v3/projects/<GITLAB_NAMESPACE>%2Fgit-repo"
}
},
{
"recorded_at": "2017-05-04T10:32:34",
"request": {
"body": {
"encoding": "utf-8",
"string": ""
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "identity",
"Connection": "keep-alive",
"PRIVATE-TOKEN": "<PRIVATE_KEY_GITLAB>",
"User-Agent": "python-requests/2.13.0"
},
"method": "GET",
"uri": "https://gitlab.com/api/v3/projects/1848932/repository/tree"
},
"response": {
"body": {
"encoding": null,
"string": "{\"message\":\"404 Project Not Found\"}"
},
"headers": {
"Cache-Control": "no-cache",
"Content-Length": "35",
"Content-Type": "application/json",
"Date": "Thu, 04 May 2017 10:32:34 GMT",
"Server": "nginx",
"Vary": "Origin",
"X-Request-Id": "fe0f3be1-0c3d-4bb8-b9e1-b5f0353bc230",
"X-Runtime": "0.061090"
},
"status": {
"code": 404,
"message": "Not Found"
},
"url": "https://gitlab.com/api/v3/projects/1848932/repository/tree"
}
}
],
"recorded_with": "betamax/0.5.1"
Expand Down

0 comments on commit b260b2c

Please sign in to comment.