| | 304 | |
| | 305 | class BzrFetcher(interfaces.IFetcher): |
| | 306 | """ Bazaar Fetcher. |
| | 307 | Example:: |
| | 308 | >>> import minitage.core.fetchers.scm |
| | 309 | >>> bzr = scm.BzrFetcher() |
| | 310 | >>> bzr.fetch_or_update('http://uri','/dir',{revision='last:1'}) |
| | 311 | """ |
| | 312 | |
| | 313 | def __init__(self, config = None): |
| | 314 | self.config = config |
| | 315 | interfaces.IFetcher.__init__(self, 'bazaar', 'bzr', config, '.bzr') |
| | 316 | self.log = logging.getLogger(__logger__) |
| | 317 | |
| | 318 | def update(self, dest, uri = None, opts=None): |
| | 319 | """Update a package. |
| | 320 | Arguments: |
| | 321 | - uri : check out/update uri |
| | 322 | - dest: destination to fetch to |
| | 323 | - opts : arguments for the fetcher |
| | 324 | |
| | 325 | - revision: particular revision to deal with. |
| | 326 | |
| | 327 | Exceptions: |
| | 328 | - InvalidBazaarRepositoryError in case of repo problems |
| | 329 | - interfaces.FetchErrorin case of fetch problems |
| | 330 | - interfaces.InvalidUrlError in case of uri is invalid |
| | 331 | """ |
| | 332 | self.log.debug('Updating %s / %s' % (dest, uri)) |
| | 333 | if opts is None: |
| | 334 | opts = {} |
| | 335 | revision = opts.get('revision','last:1') |
| | 336 | args = opts.get('args','') |
| | 337 | if not uri or self.is_valid_src_uri(uri): |
| | 338 | if uri and self._has_uri_changed(dest, uri): |
| | 339 | self._remove_versionned_directories(dest) |
| | 340 | self._scm_cmd('init %s' % (dest)) |
| | 341 | if not os.path.isdir('%s/%s' % (dest, self.metadata_directory)): |
| | 342 | message = 'Unexpected fetch error on \'%s\'\n' % uri |
| | 343 | message += 'The directory \'%s\' is not ' |
| | 344 | message += 'a valid bazaar repository' % (dest) |
| | 345 | raise InvalidBazaarRepositoryError(message) |
| | 346 | if uri: |
| | 347 | self._scm_cmd('pull --overwrite -r%s %s -d %s' % (revision, uri, dest)) |
| | 348 | else: |
| | 349 | self._scm_cmd('pull --overwrite -r%s -d %s' % (revision, dest)) |
| | 350 | if not os.path.isdir('%s/%s' % (dest, self.metadata_directory)): |
| | 351 | message = 'Unexpected fetch error on \'%s\'\n' % uri |
| | 352 | message += 'The directory \'%s\' is not ' |
| | 353 | message += 'a valid bazaar repository' % (dest, uri) |
| | 354 | raise InvalidBazaarRepositoryError(message) |
| | 355 | else: |
| | 356 | raise interfaces.InvalidUrlError('this uri \'%s\' is invalid' % uri) |
| | 357 | |
| | 358 | def fetch(self, dest, uri, opts=None): |
| | 359 | """Fetch a package. |
| | 360 | Arguments: |
| | 361 | - uri : check out/update uri |
| | 362 | - dest: destination to fetch to |
| | 363 | - opts : arguments for the fetcher |
| | 364 | |
| | 365 | - revision: particular revision to deal with. |
| | 366 | - args: misc arguments to give |
| | 367 | |
| | 368 | Exceptions: |
| | 369 | - InvalidBazaarRepositoryError in case of repo problems |
| | 370 | - interfaces.FetchErrorin case of fetch problems |
| | 371 | - interfaces.InvalidUrlError in case of uri is invalid |
| | 372 | """ |
| | 373 | if opts is None: |
| | 374 | opts = {} |
| | 375 | revision = opts.get('revision','last:1') |
| | 376 | args = opts.get('args','') |
| | 377 | # move directory that musnt be there ! |
| | 378 | if os.path.isdir(dest): |
| | 379 | os.rename(dest, '%s.old.%s' \ |
| | 380 | % (dest, datetime.datetime.now().strftime('%d%m%y%H%M%S')) |
| | 381 | ) |
| | 382 | if self.is_valid_src_uri(uri): |
| | 383 | self._scm_cmd('checkout -r %s %s %s %s' % (revision, args, uri, dest)) |
| | 384 | if not os.path.isdir('%s/%s' % (dest, self.metadata_directory)): |
| | 385 | message = 'Unexpected fetch error on \'%s\'\n' % uri |
| | 386 | message += 'The directory \'%s\' is not ' |
| | 387 | message += 'a valid bazaar repository' % (dest, uri) |
| | 388 | raise InvalidBazaarRepositoryError(message) |
| | 389 | else: |
| | 390 | raise interfaces.InvalidUrlError('this uri \'%s\' is invalid' % uri) |
| | 391 | |
| | 392 | def fetch_or_update(self, dest, uri, opts = None): |
| | 393 | """See interface.""" |
| | 394 | if os.path.isdir('%s/%s' % (dest, self.metadata_directory)): |
| | 395 | self.update(dest, uri, opts) |
| | 396 | else: |
| | 397 | self.fetch(dest, uri, opts) |
| | 398 | |
| | 399 | def is_valid_src_uri(self, uri): |
| | 400 | """See interface.""" |
| | 401 | match = interfaces.URI_REGEX.match(uri) |
| | 402 | if match \ |
| | 403 | and match.groups()[1] \ |
| | 404 | in ['file', 'bzr', 'sftp', 'http', |
| | 405 | 'https', 'bzr+http', 'bzr+https', |
| | 406 | 'bzr+ssh', 'svn+file', |
| | 407 | 'svn', 'svn+http', 'svn+https']: |
| | 408 | return True |
| | 409 | return False |
| | 410 | |
| | 411 | def match(self, switch): |
| | 412 | """See interface.""" |
| | 413 | if switch == 'bzr': |
| | 414 | return True |
| | 415 | return False |
| | 416 | |
| | 417 | |
| | 418 | def get_uri(self, dest): |
| | 419 | """get bazaar url""" |
| | 420 | self._check_scm_presence() |
| | 421 | try: |
| | 422 | cwd = os.getcwd() |
| | 423 | os.chdir(dest) |
| | 424 | self.log.debug('Running %s %s in %s' % ( |
| | 425 | self.executable, |
| | 426 | ' info 2>&1|egrep "(checkout of branch|parent branch)"|cut -d: -f 2,3', |
| | 427 | dest |
| | 428 | )) |
| | 429 | process = subprocess.Popen( |
| | 430 | '%s %s' % ( |
| | 431 | self.executable, |
| | 432 | ' info 2>&1|egrep "(checkout of branch|parent branch)"|cut -d: -f 2,3', |
| | 433 | ), |
| | 434 | shell = True, stdout=subprocess.PIPE |
| | 435 | ) |
| | 436 | ret = process.wait() |
| | 437 | if ret != 0: |
| | 438 | message = '%s failed to achieve correctly.' % self.name |
| | 439 | raise interfaces.FetcherRuntimeError(message) |
| | 440 | dest_uri = re.sub( |
| | 441 | '([^=]*=)\s*(.*)', |
| | 442 | '\\2', |
| | 443 | process.stdout.read().strip() |
| | 444 | ) |
| | 445 | os.chdir(cwd) |
| | 446 | return dest_uri |
| | 447 | except Exception, instance: |
| | 448 | os.chdir(cwd) |
| | 449 | raise instance |
| | 450 | |
| | 451 | def _has_uri_changed(self, dest, uri): |
| | 452 | """See interface.""" |
| | 453 | # file is removed on the local uris |
| | 454 | uri = uri.replace('file://', '') |
| | 455 | # in case we were not bzr before |
| | 456 | if not os.path.isdir('%s/%s' % (dest, self.metadata_directory)): |
| | 457 | return True |
| | 458 | elif uri != self.get_uri(dest): |
| | 459 | return True |
| | 460 | return False |
| | 461 | |
| | 462 | |
| | 463 | |
| | 464 | |