comparison rhodecode/lib/vcs/backends/git/repository.py @ 4116:ffd45b185016 rhodecode-2.2.5-gpl

Imported some of the GPLv3'd changes from RhodeCode v2.2.5. This imports changes between changesets 21af6c4eab3d and 6177597791c2 in RhodeCode's original repository, including only changes to Python files and HTML. RhodeCode clearly licensed its changes to these files under GPLv3 in their /LICENSE file, which states the following: The Python code and integrated HTML are licensed under the GPLv3 license. (See: https://code.rhodecode.com/rhodecode/files/v2.2.5/LICENSE or http://web.archive.org/web/20140512193334/https://code.rhodecode.com/rhodecode/files/f3b123159901f15426d18e3dc395e8369f70ebe0/LICENSE for an online copy of that LICENSE file) Conservancy reviewed these changes and confirmed that they can be licensed as a whole to the Kallithea project under GPLv3-only. While some of the contents committed herein are clearly licensed GPLv3-or-later, on the whole we must assume the are GPLv3-only, since the statement above from RhodeCode indicates that they intend GPLv3-only as their license, per GPLv3ยง14 and other relevant sections of GPLv3.
author Bradley M. Kuhn <bkuhn@sfconservancy.org>
date Wed, 02 Jul 2014 19:03:13 -0400
parents a5888ca796b5
children 7e5f8c12a3fc
comparison
equal deleted inserted replaced
4115:8b7294a804a0 4116:ffd45b185016
18 import posixpath 18 import posixpath
19 import string 19 import string
20 20
21 from dulwich.objects import Tag 21 from dulwich.objects import Tag
22 from dulwich.repo import Repo, NotGitRepository 22 from dulwich.repo import Repo, NotGitRepository
23 from dulwich.config import ConfigFile
23 24
24 from rhodecode.lib.vcs import subprocessio 25 from rhodecode.lib.vcs import subprocessio
25 from rhodecode.lib.vcs.backends.base import BaseRepository, CollectionGenerator 26 from rhodecode.lib.vcs.backends.base import BaseRepository, CollectionGenerator
26 from rhodecode.lib.vcs.conf import settings 27 from rhodecode.lib.vcs.conf import settings
27 28
37 from rhodecode.lib.vcs.utils.hgcompat import ( 38 from rhodecode.lib.vcs.utils.hgcompat import (
38 hg_url, httpbasicauthhandler, httpdigestauthhandler 39 hg_url, httpbasicauthhandler, httpdigestauthhandler
39 ) 40 )
40 41
41 from .changeset import GitChangeset 42 from .changeset import GitChangeset
42 from .config import ConfigFile
43 from .inmemory import GitInMemoryChangeset 43 from .inmemory import GitInMemoryChangeset
44 from .workdir import GitWorkdir 44 from .workdir import GitWorkdir
45 45
46 SHA_PATTERN = re.compile(r'^[[0-9a-fA-F]{12}|[0-9a-fA-F]{40}]$') 46 SHA_PATTERN = re.compile(r'^[[0-9a-fA-F]{12}|[0-9a-fA-F]{40}]$')
47 47
163 return self._run_git_command(cmd, **opts) 163 return self._run_git_command(cmd, **opts)
164 164
165 @classmethod 165 @classmethod
166 def _check_url(cls, url): 166 def _check_url(cls, url):
167 """ 167 """
168 Functon will check given url and try to verify if it's a valid 168 Function will check given url and try to verify if it's a valid
169 link. Sometimes it may happened that mercurial will issue basic 169 link. Sometimes it may happened that git will issue basic
170 auth request that can cause whole API to hang when used from python 170 auth request that can cause whole API to hang when used from python
171 or other external calls. 171 or other external calls.
172 172
173 On failures it'll raise urllib2.HTTPError 173 On failures it'll raise urllib2.HTTPError, exception is also thrown
174 when the return code is non 200
174 """ 175 """
175 176
176 # check first if it's not an local url 177 # check first if it's not an local url
177 if os.path.isdir(url) or url.startswith('file:'): 178 if os.path.isdir(url) or url.startswith('file:'):
178 return True 179 return True
179 180
180 if('+' in url[:url.find('://')]): 181 if '+' in url[:url.find('://')]:
181 url = url[url.find('+') + 1:] 182 url = url[url.find('+') + 1:]
182 183
183 handlers = [] 184 handlers = []
184 test_uri, authinfo = hg_url(url).authinfo() 185 url_obj = hg_url(url)
186 test_uri, authinfo = url_obj.authinfo()
187 url_obj.passwd = '*****'
188 cleaned_uri = str(url_obj)
189
185 if not test_uri.endswith('info/refs'): 190 if not test_uri.endswith('info/refs'):
186 test_uri = test_uri.rstrip('/') + '/info/refs' 191 test_uri = test_uri.rstrip('/') + '/info/refs'
192
187 if authinfo: 193 if authinfo:
188 #create a password manager 194 #create a password manager
189 passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm() 195 passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
190 passmgr.add_password(*authinfo) 196 passmgr.add_password(*authinfo)
191 197
200 cu = "%s%s" % (test_uri, qs) 206 cu = "%s%s" % (test_uri, qs)
201 req = urllib2.Request(cu, None, {}) 207 req = urllib2.Request(cu, None, {})
202 208
203 try: 209 try:
204 resp = o.open(req) 210 resp = o.open(req)
205 return resp.code == 200 211 if resp.code != 200:
212 raise Exception('Return Code is not 200')
206 except Exception, e: 213 except Exception, e:
207 # means it cannot be cloned 214 # means it cannot be cloned
208 raise urllib2.URLError("[%s] %s" % (url, e)) 215 raise urllib2.URLError("[%s] org_exc: %s" % (cleaned_uri, e))
216
217 # now detect if it's proper git repo
218 gitdata = resp.read()
219 if not 'service=git-upload-pack' in gitdata:
220 raise urllib2.URLError(
221 "url [%s] does not look like an git" % (cleaned_uri))
222
223 return True
209 224
210 def _get_repo(self, create, src_url=None, update_after_clone=False, 225 def _get_repo(self, create, src_url=None, update_after_clone=False,
211 bare=False): 226 bare=False):
212 if create and os.path.exists(self.path): 227 if create and os.path.exists(self.path):
213 raise RepositoryError("Location already exist") 228 raise RepositoryError("Location already exist")
218 if create and src_url: 233 if create and src_url:
219 GitRepository._check_url(src_url) 234 GitRepository._check_url(src_url)
220 self.clone(src_url, update_after_clone, bare) 235 self.clone(src_url, update_after_clone, bare)
221 return Repo(self.path) 236 return Repo(self.path)
222 elif create: 237 elif create:
223 os.mkdir(self.path) 238 os.makedirs(self.path)
224 if bare: 239 if bare:
225 return Repo.init_bare(self.path) 240 return Repo.init_bare(self.path)
226 else: 241 else:
227 return Repo.init(self.path) 242 return Repo.init(self.path)
228 else: 243 else:
272 if ((is_bstr and revision.isdigit() and len(revision) < 12) 287 if ((is_bstr and revision.isdigit() and len(revision) < 12)
273 or isinstance(revision, int) or is_null(revision)): 288 or isinstance(revision, int) or is_null(revision)):
274 try: 289 try:
275 revision = self.revisions[int(revision)] 290 revision = self.revisions[int(revision)]
276 except Exception: 291 except Exception:
277 raise ChangesetDoesNotExistError("Revision %s does not exist " 292 msg = ("Revision %s does not exist for %s" % (revision, self))
278 "for this repository" % (revision)) 293 raise ChangesetDoesNotExistError(msg)
279 294
280 elif is_bstr: 295 elif is_bstr:
281 # get by branch/tag name 296 # get by branch/tag name
282 _ref_revision = self._parsed_refs.get(revision) 297 _ref_revision = self._parsed_refs.get(revision)
283 if _ref_revision: # and _ref_revision[1] in ['H', 'RH', 'T']: 298 if _ref_revision: # and _ref_revision[1] in ['H', 'RH', 'T']:
287 # maybe it's a tag ? we don't have them in self.revisions 302 # maybe it's a tag ? we don't have them in self.revisions
288 if revision in _tags_shas: 303 if revision in _tags_shas:
289 return _tags_shas[_tags_shas.index(revision)] 304 return _tags_shas[_tags_shas.index(revision)]
290 305
291 elif not SHA_PATTERN.match(revision) or revision not in self.revisions: 306 elif not SHA_PATTERN.match(revision) or revision not in self.revisions:
292 raise ChangesetDoesNotExistError("Revision %s does not exist " 307 msg = ("Revision %s does not exist for %s" % (revision, self))
293 "for this repository" % (revision)) 308 raise ChangesetDoesNotExistError(msg)
294 309
295 # Ensure we return full id 310 # Ensure we return full id
296 if not SHA_PATTERN.match(str(revision)): 311 if not SHA_PATTERN.match(str(revision)):
297 raise ChangesetDoesNotExistError("Given revision %s not recognized" 312 raise ChangesetDoesNotExistError("Given revision %s not recognized"
298 % revision) 313 % revision)
346 else: 361 else:
347 return os.stat(he_path).st_mtime 362 return os.stat(he_path).st_mtime
348 363
349 @LazyProperty 364 @LazyProperty
350 def description(self): 365 def description(self):
351 idx_loc = '' if self.bare else '.git'
352 undefined_description = u'unknown' 366 undefined_description = u'unknown'
353 description_path = os.path.join(self.path, idx_loc, 'description') 367 _desc = self._repo.get_description()
354 if os.path.isfile(description_path): 368 return safe_unicode(_desc or undefined_description)
355 return safe_unicode(open(description_path).read())
356 else:
357 return undefined_description
358 369
359 @LazyProperty 370 @LazyProperty
360 def contact(self): 371 def contact(self):
361 undefined_contact = u'Unknown' 372 undefined_contact = u'Unknown'
362 return undefined_contact 373 return undefined_contact
629 working directory 640 working directory
630 :param bare: If set to ``True``, repository would be cloned into 641 :param bare: If set to ``True``, repository would be cloned into
631 *bare* git repository (no working directory at all). 642 *bare* git repository (no working directory at all).
632 """ 643 """
633 url = self._get_url(url) 644 url = self._get_url(url)
634 cmd = ['clone'] 645 cmd = ['clone', '-q']
635 if bare: 646 if bare:
636 cmd.append('--bare') 647 cmd.append('--bare')
637 elif not update_after_clone: 648 elif not update_after_clone:
638 cmd.append('--no-checkout') 649 cmd.append('--no-checkout')
639 cmd += ['--', '"%s"' % url, '"%s"' % self.path] 650 cmd += ['--', '"%s"' % url, '"%s"' % self.path]
663 refs.append(ref) 674 refs.append(ref)
664 refs = ' '.join(('+%s:%s' % (r, r) for r in refs)) 675 refs = ' '.join(('+%s:%s' % (r, r) for r in refs))
665 cmd = '''fetch %s -- %s''' % (url, refs) 676 cmd = '''fetch %s -- %s''' % (url, refs)
666 self.run_git_command(cmd) 677 self.run_git_command(cmd)
667 678
679 def _update_server_info(self):
680 """
681 runs gits update-server-info command in this repo instance
682 """
683 from dulwich.server import update_server_info
684 update_server_info(self._repo)
685
668 @LazyProperty 686 @LazyProperty
669 def workdir(self): 687 def workdir(self):
670 """ 688 """
671 Returns ``Workdir`` instance for this repository. 689 Returns ``Workdir`` instance for this repository.
672 """ 690 """