| LEFT | RIGHT | 
|---|
| 1 # This file is part of the Adblock Plus web scripts, | 1 # This file is part of the Adblock Plus web scripts, | 
| 2 # Copyright (C) 2006-present eyeo GmbH | 2 # Copyright (C) 2006-present eyeo GmbH | 
| 3 # | 3 # | 
| 4 # Adblock Plus is free software: you can redistribute it and/or modify | 4 # Adblock Plus is free software: you can redistribute it and/or modify | 
| 5 # it under the terms of the GNU General Public License version 3 as | 5 # it under the terms of the GNU General Public License version 3 as | 
| 6 # published by the Free Software Foundation. | 6 # published by the Free Software Foundation. | 
| 7 # | 7 # | 
| 8 # Adblock Plus is distributed in the hope that it will be useful, | 8 # Adblock Plus is distributed in the hope that it will be useful, | 
| 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of | 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 46 import zipfile | 46 import zipfile | 
| 47 import contextlib | 47 import contextlib | 
| 48 from xml.dom.minidom import parse as parseXml | 48 from xml.dom.minidom import parse as parseXml | 
| 49 | 49 | 
| 50 from Crypto.PublicKey import RSA | 50 from Crypto.PublicKey import RSA | 
| 51 from Crypto.Signature import PKCS1_v1_5 | 51 from Crypto.Signature import PKCS1_v1_5 | 
| 52 import Crypto.Hash.SHA256 | 52 import Crypto.Hash.SHA256 | 
| 53 | 53 | 
| 54 from sitescripts.extensions.utils import ( | 54 from sitescripts.extensions.utils import ( | 
| 55     compareVersions, Configuration, | 55     compareVersions, Configuration, | 
| 56     writeAndroidUpdateManifest | 56     writeAndroidUpdateManifest, | 
| 57 ) | 57 ) | 
| 58 from sitescripts.utils import get_config, get_template | 58 from sitescripts.utils import get_config, get_template | 
| 59 | 59 | 
| 60 MAX_BUILDS = 50 | 60 MAX_BUILDS = 50 | 
| 61 | 61 | 
| 62 | 62 | 
| 63 # Google and Microsoft APIs use HTTP error codes with error message in | 63 # Google and Microsoft APIs use HTTP error codes with error message in | 
| 64 # body. So we add the response body to the HTTPError to get more | 64 # body. So we add the response body to the HTTPError to get more | 
| 65 # meaningful error messages. | 65 # meaningful error messages. | 
| 66 class HTTPErrorBodyHandler(urllib2.HTTPDefaultErrorHandler): | 66 class HTTPErrorBodyHandler(urllib2.HTTPDefaultErrorHandler): | 
| (...skipping 28 matching lines...) Expand all  Loading... | 
| 95 | 95 | 
| 96     def hasChanges(self): | 96     def hasChanges(self): | 
| 97         return self.revision != self.previousRevision | 97         return self.revision != self.previousRevision | 
| 98 | 98 | 
| 99     def getCurrentRevision(self): | 99     def getCurrentRevision(self): | 
| 100         """ | 100         """ | 
| 101             retrieves the current revision ID from the repository | 101             retrieves the current revision ID from the repository | 
| 102         """ | 102         """ | 
| 103         command = [ | 103         command = [ | 
| 104             'hg', 'id', '-i', '-r', self.config.revision, '--config', | 104             'hg', 'id', '-i', '-r', self.config.revision, '--config', | 
| 105             'defaults.id=', self.config.repository | 105             'defaults.id=', self.config.repository, | 
| 106         ] | 106         ] | 
| 107         return subprocess.check_output(command).strip() | 107         return subprocess.check_output(command).strip() | 
| 108 | 108 | 
| 109     def getCurrentBuild(self): | 109     def getCurrentBuild(self): | 
| 110         """ | 110         """ | 
| 111             calculates the (typically numerical) build ID for the current build | 111             calculates the (typically numerical) build ID for the current build | 
| 112         """ | 112         """ | 
| 113         command = ['hg', 'id', '-n', '--config', 'defaults.id=', self.tempdir] | 113         command = ['hg', 'id', '-n', '--config', 'defaults.id=', self.tempdir] | 
| 114         build = subprocess.check_output(command).strip() | 114         build = subprocess.check_output(command).strip() | 
| 115         return build | 115         return build | 
| 116 | 116 | 
| 117     def getChanges(self): | 117     def getChanges(self): | 
| 118         """ | 118         """ | 
| 119           retrieve changes between the current and previous ("first") revision | 119           retrieve changes between the current and previous ("first") revision | 
| 120         """ | 120         """ | 
| 121         command = [ | 121         command = [ | 
| 122             'hg', 'log', '-R', self.tempdir, '-r', | 122             'hg', 'log', '-R', self.tempdir, '-r', | 
| 123             'reverse(ancestors({}))'.format(self.config.revision), '-l', '50', | 123             'reverse(ancestors({}))'.format(self.config.revision), '-l', '50', | 
| 124             '--encoding', 'utf-8', '--template', | 124             '--encoding', 'utf-8', '--template', | 
| 125             '{date|isodate}\\0{author|person}\\0{rev}\\0{desc}\\0\\0', | 125             '{date|isodate}\\0{author|person}\\0{rev}\\0{desc}\\0\\0', | 
| 126             '--config', 'defaults.log=' | 126             '--config', 'defaults.log=', | 
| 127         ] | 127         ] | 
| 128         result = subprocess.check_output(command).decode('utf-8') | 128         result = subprocess.check_output(command).decode('utf-8') | 
| 129 | 129 | 
| 130         for change in result.split('\x00\x00'): | 130         for change in result.split('\x00\x00'): | 
| 131             if change: | 131             if change: | 
| 132                 date, author, revision, description = change.split('\x00') | 132                 date, author, revision, description = change.split('\x00') | 
| 133                 yield {'date': date, 'author': author, 'revision': revision, 'de
     scription': description} | 133                 yield {'date': date, 'author': author, 'revision': revision, 'de
     scription': description} | 
| 134 | 134 | 
| 135     def copyRepository(self): | 135     def copyRepository(self): | 
| 136         """ | 136         """ | 
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 278             os.makedirs(baseDir) | 278             os.makedirs(baseDir) | 
| 279 | 279 | 
| 280         # ABP for Android used to have its own update manifest format. We need t
     o | 280         # ABP for Android used to have its own update manifest format. We need t
     o | 
| 281         # generate both that and the new one in the libadblockplus format as lon
     g | 281         # generate both that and the new one in the libadblockplus format as lon
     g | 
| 282         # as a significant amount of users is on an old version. | 282         # as a significant amount of users is on an old version. | 
| 283         if self.config.type == 'android': | 283         if self.config.type == 'android': | 
| 284             newManifestPath = os.path.join(baseDir, 'update.json') | 284             newManifestPath = os.path.join(baseDir, 'update.json') | 
| 285             writeAndroidUpdateManifest(newManifestPath, [{ | 285             writeAndroidUpdateManifest(newManifestPath, [{ | 
| 286                 'basename': self.basename, | 286                 'basename': self.basename, | 
| 287                 'version': self.version, | 287                 'version': self.version, | 
| 288                 'updateURL': self.updateURL | 288                 'updateURL': self.updateURL, | 
| 289             }]) | 289             }]) | 
| 290 | 290 | 
| 291         template = get_template(get_config().get('extensions', templateName), | 291         template = get_template(get_config().get('extensions', templateName), | 
| 292                                 autoescape=autoescape) | 292                                 autoescape=autoescape) | 
| 293         template.stream({'extensions': [self]}).dump(manifestPath) | 293         template.stream({'extensions': [self]}).dump(manifestPath) | 
| 294 | 294 | 
| 295     def writeIEUpdateManifest(self, versions): | 295     def writeIEUpdateManifest(self, versions): | 
| 296         """ | 296         """ | 
| 297           Writes update.json file for the latest IE build | 297           Writes update.json file for the latest IE build | 
| 298         """ | 298         """ | 
| 299         if len(versions) == 0: | 299         if len(versions) == 0: | 
| 300             return | 300             return | 
| 301 | 301 | 
| 302         version = versions[0] | 302         version = versions[0] | 
| 303         packageName = self.basename + '-' + version + self.config.packageSuffix | 303         packageName = self.basename + '-' + version + self.config.packageSuffix | 
| 304         updateURL = urlparse.urljoin(self.config.nightliesURL, self.basename + '
     /' + packageName + '?update') | 304         updateURL = urlparse.urljoin(self.config.nightliesURL, self.basename + '
     /' + packageName + '?update') | 
| 305         baseDir = os.path.join(self.config.nightliesDirectory, self.basename) | 305         baseDir = os.path.join(self.config.nightliesDirectory, self.basename) | 
| 306         manifestPath = os.path.join(baseDir, 'update.json') | 306         manifestPath = os.path.join(baseDir, 'update.json') | 
| 307 | 307 | 
| 308         from sitescripts.extensions.utils import writeIEUpdateManifest as doWrit
     e | 308         from sitescripts.extensions.utils import writeIEUpdateManifest as doWrit
     e | 
| 309         doWrite(manifestPath, [{ | 309         doWrite(manifestPath, [{ | 
| 310             'basename': self.basename, | 310             'basename': self.basename, | 
| 311             'version': version, | 311             'version': version, | 
| 312             'updateURL': updateURL | 312             'updateURL': updateURL, | 
| 313         }]) | 313         }]) | 
| 314 | 314 | 
| 315         for suffix in ['-x86.msi', '-x64.msi', '-gpo-x86.msi', '-gpo-x64.msi']: | 315         for suffix in ['-x86.msi', '-x64.msi', '-gpo-x86.msi', '-gpo-x64.msi']: | 
| 316             linkPath = os.path.join(baseDir, '00latest%s' % suffix) | 316             linkPath = os.path.join(baseDir, '00latest%s' % suffix) | 
| 317             outputPath = os.path.join(baseDir, self.basename + '-' + version + s
     uffix) | 317             outputPath = os.path.join(baseDir, self.basename + '-' + version + s
     uffix) | 
| 318             self.symlink_or_copy(outputPath, linkPath) | 318             self.symlink_or_copy(outputPath, linkPath) | 
| 319 | 319 | 
| 320     def build(self): | 320     def build(self): | 
| 321         """ | 321         """ | 
| 322           run the build command in the tempdir | 322           run the build command in the tempdir | 
| 323         """ | 323         """ | 
| 324         baseDir = os.path.join(self.config.nightliesDirectory, self.basename) | 324         baseDir = os.path.join(self.config.nightliesDirectory, self.basename) | 
| 325         if not os.path.exists(baseDir): | 325         if not os.path.exists(baseDir): | 
| 326             os.makedirs(baseDir) | 326             os.makedirs(baseDir) | 
| 327         outputFile = '%s-%s%s' % (self.basename, self.version, self.config.packa
     geSuffix) | 327         outputFile = '%s-%s%s' % (self.basename, self.version, self.config.packa
     geSuffix) | 
| 328         self.path = os.path.join(baseDir, outputFile) | 328         self.path = os.path.join(baseDir, outputFile) | 
| 329         self.updateURL = urlparse.urljoin(self.config.nightliesURL, self.basenam
     e + '/' + outputFile + '?update') | 329         self.updateURL = urlparse.urljoin(self.config.nightliesURL, self.basenam
     e + '/' + outputFile + '?update') | 
| 330 | 330 | 
| 331         if self.config.type == 'android': | 331         if self.config.type == 'android': | 
| 332             apkFile = open(self.path, 'wb') | 332             apkFile = open(self.path, 'wb') | 
| 333 | 333 | 
| 334             try: | 334             try: | 
| 335                 try: | 335                 try: | 
| 336                     port = get_config().get('extensions', 'androidBuildPort') | 336                     port = get_config().get('extensions', 'androidBuildPort') | 
| 337                 except ConfigParser.NoOptionError: | 337                 except ConfigParser.NoOptionError: | 
| 338                     port = '22' | 338                     port = '22' | 
| 339                 command = ['ssh', '-p', port, get_config().get('extensions', 'an
     droidBuildHost')] | 339                 command = ['ssh', '-p', port, get_config().get('extensions', 'an
     droidBuildHost')] | 
| 340                 command.extend(map(pipes.quote, [ | 340                 command.extend(map(pipes.quote, [ | 
| 341                     '/home/android/bin/makedebugbuild.py', '--revision', | 341                     '/home/android/bin/makedebugbuild.py', '--revision', | 
| 342                     self.buildNum, '--version', self.version, '--stdout' | 342                     self.buildNum, '--version', self.version, '--stdout', | 
| 343                 ])) | 343                 ])) | 
| 344                 subprocess.check_call(command, stdout=apkFile, close_fds=True) | 344                 subprocess.check_call(command, stdout=apkFile, close_fds=True) | 
| 345             except: | 345             except: | 
| 346                 # clear broken output if any | 346                 # clear broken output if any | 
| 347                 if os.path.exists(self.path): | 347                 if os.path.exists(self.path): | 
| 348                     os.remove(self.path) | 348                     os.remove(self.path) | 
| 349                 raise | 349                 raise | 
| 350         else: | 350         else: | 
| 351             env = os.environ | 351             env = os.environ | 
| 352             spiderMonkeyBinary = self.config.spiderMonkeyBinary | 352             spiderMonkeyBinary = self.config.spiderMonkeyBinary | 
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 406             packageFile = self.basename + '-' + version + self.config.packageSuf
     fix | 406             packageFile = self.basename + '-' + version + self.config.packageSuf
     fix | 
| 407             changelogFile = self.basename + '-' + version + '.changelog.xhtml' | 407             changelogFile = self.basename + '-' + version + '.changelog.xhtml' | 
| 408             if not os.path.exists(os.path.join(baseDir, packageFile)): | 408             if not os.path.exists(os.path.join(baseDir, packageFile)): | 
| 409                 # Oops | 409                 # Oops | 
| 410                 continue | 410                 continue | 
| 411 | 411 | 
| 412             link = { | 412             link = { | 
| 413                 'version': version, | 413                 'version': version, | 
| 414                 'download': packageFile, | 414                 'download': packageFile, | 
| 415                 'mtime': os.path.getmtime(os.path.join(baseDir, packageFile)), | 415                 'mtime': os.path.getmtime(os.path.join(baseDir, packageFile)), | 
| 416                 'size': os.path.getsize(os.path.join(baseDir, packageFile)) | 416                 'size': os.path.getsize(os.path.join(baseDir, packageFile)), | 
| 417             } | 417             } | 
| 418             if os.path.exists(os.path.join(baseDir, changelogFile)): | 418             if os.path.exists(os.path.join(baseDir, changelogFile)): | 
| 419                 link['changelog'] = changelogFile | 419                 link['changelog'] = changelogFile | 
| 420             links.append(link) | 420             links.append(link) | 
| 421         template = get_template(get_config().get('extensions', 'nightlyIndexPage
     ')) | 421         template = get_template(get_config().get('extensions', 'nightlyIndexPage
     ')) | 
| 422         template.stream({'config': self.config, 'links': links}).dump(outputPath
     ) | 422         template.stream({'config': self.config, 'links': links}).dump(outputPath
     ) | 
| 423 | 423 | 
| 424     def read_downloads_lockfile(self): | 424     def read_downloads_lockfile(self): | 
| 425         path = get_config().get('extensions', 'downloadLockFile') | 425         path = get_config().get('extensions', 'downloadLockFile') | 
| 426         try: | 426         try: | 
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 516         config = get_config() | 516         config = get_config() | 
| 517 | 517 | 
| 518         upload_url = ('https://addons.mozilla.org/api/v3/addons/{}/' | 518         upload_url = ('https://addons.mozilla.org/api/v3/addons/{}/' | 
| 519                       'versions/{}/').format(self.extensionID, self.version) | 519                       'versions/{}/').format(self.extensionID, self.version) | 
| 520 | 520 | 
| 521         with open(self.path, 'rb') as file: | 521         with open(self.path, 'rb') as file: | 
| 522             data, content_type = urllib3.filepost.encode_multipart_formdata({ | 522             data, content_type = urllib3.filepost.encode_multipart_formdata({ | 
| 523                 'upload': ( | 523                 'upload': ( | 
| 524                     os.path.basename(self.path), | 524                     os.path.basename(self.path), | 
| 525                     file.read(), | 525                     file.read(), | 
| 526                     'application/x-xpinstall' | 526                     'application/x-xpinstall', | 
| 527                 ) | 527                 ), | 
| 528             }) | 528             }) | 
| 529 | 529 | 
| 530         request = self.generate_mozilla_jwt_request( | 530         request = self.generate_mozilla_jwt_request( | 
| 531             config.get('extensions', 'amo_key'), | 531             config.get('extensions', 'amo_key'), | 
| 532             config.get('extensions', 'amo_secret'), | 532             config.get('extensions', 'amo_secret'), | 
| 533             upload_url, | 533             upload_url, | 
| 534             'PUT', | 534             'PUT', | 
| 535             data, | 535             data, | 
| 536             [('Content-Type', content_type)], | 536             [('Content-Type', content_type)], | 
| 537         ) | 537         ) | 
| 538 | 538 | 
| 539         try: | 539         try: | 
| 540             urllib2.urlopen(request).close() | 540             urllib2.urlopen(request).close() | 
| 541         except urllib2.HTTPError as e: | 541         except urllib2.HTTPError as e: | 
| 542             try: | 542             try: | 
| 543                 logging.error(e.read()) | 543                 logging.error(e.read()) | 
| 544             finally: | 544             finally: | 
| 545                 e.close() | 545                 e.close() | 
| 546             raise | 546             raise | 
| 547 | 547 | 
| 548         self.add_to_downloads_lockfile( | 548         self.add_to_downloads_lockfile( | 
| 549             self.config.type, | 549             self.config.type, | 
| 550             { | 550             { | 
| 551                 'buildtype': 'devbuild', | 551                 'buildtype': 'devbuild', | 
| 552                 'app_id': self.extensionID, | 552                 'app_id': self.extensionID, | 
| 553                 'version': self.version, | 553                 'version': self.version, | 
| 554             } | 554             }, | 
| 555         ) | 555         ) | 
| 556         os.remove(self.path) | 556         os.remove(self.path) | 
| 557 | 557 | 
| 558     def download_from_mozilla_addons(self, buildtype, version, app_id): | 558     def download_from_mozilla_addons(self, buildtype, version, app_id): | 
| 559         config = get_config() | 559         config = get_config() | 
| 560         iss = config.get('extensions', 'amo_key') | 560         iss = config.get('extensions', 'amo_key') | 
| 561         secret = config.get('extensions', 'amo_secret') | 561         secret = config.get('extensions', 'amo_secret') | 
| 562 | 562 | 
| 563         url = ('https://addons.mozilla.org/api/v3/addons/{}/' | 563         url = ('https://addons.mozilla.org/api/v3/addons/{}/' | 
| 564                'versions/{}/').format(app_id, version) | 564                'versions/{}/').format(app_id, version) | 
| 565 | 565 | 
| 566         request = self.generate_mozilla_jwt_request( | 566         request = self.generate_mozilla_jwt_request( | 
| 567             iss, secret, url, 'GET', | 567             iss, secret, url, 'GET', | 
| 568         ) | 568         ) | 
| 569         response = json.load(urllib2.urlopen(request)) | 569         response = json.load(urllib2.urlopen(request)) | 
| 570 | 570 | 
| 571         filename = '{}-{}.xpi'.format(self.basename, version) | 571         filename = '{}-{}.xpi'.format(self.basename, version) | 
| 572         self.path = os.path.join( | 572         self.path = os.path.join( | 
| 573             config.get('extensions', 'nightliesDirectory'), | 573             config.get('extensions', 'nightliesDirectory'), | 
| 574             self.basename, | 574             self.basename, | 
| 575             filename | 575             filename, | 
| 576         ) | 576         ) | 
| 577 | 577 | 
| 578         necessary = ['passed_review', 'reviewed', 'processed', 'valid'] | 578         necessary = ['passed_review', 'reviewed', 'processed', 'valid'] | 
| 579         if all(response[x] for x in necessary): | 579         if all(response[x] for x in necessary): | 
| 580             download_url = response['files'][0]['download_url'] | 580             download_url = response['files'][0]['download_url'] | 
| 581             checksum = response['files'][0]['hash'] | 581             checksum = response['files'][0]['hash'] | 
| 582 | 582 | 
| 583             request = self.generate_mozilla_jwt_request( | 583             request = self.generate_mozilla_jwt_request( | 
| 584                 iss, secret, download_url, 'GET', | 584                 iss, secret, download_url, 'GET', | 
| 585             ) | 585             ) | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
| 596             if returned_checksum != checksum: | 596             if returned_checksum != checksum: | 
| 597                 logging.error('Checksum could not be verified: {} vs {}' | 597                 logging.error('Checksum could not be verified: {} vs {}' | 
| 598                               ''.format(checksum, returned_checksum)) | 598                               ''.format(checksum, returned_checksum)) | 
| 599 | 599 | 
| 600             with open(self.path, 'w') as fp: | 600             with open(self.path, 'w') as fp: | 
| 601                 fp.write(file_content) | 601                 fp.write(file_content) | 
| 602 | 602 | 
| 603             self.update_link = os.path.join( | 603             self.update_link = os.path.join( | 
| 604                 config.get('extensions', 'nightliesURL'), | 604                 config.get('extensions', 'nightliesURL'), | 
| 605                 self.basename, | 605                 self.basename, | 
| 606                 filename | 606                 filename, | 
| 607             ) | 607             ) | 
| 608 | 608 | 
| 609             self.remove_from_downloads_lockfile(self.config.type, | 609             self.remove_from_downloads_lockfile(self.config.type, | 
| 610                                                 'version', | 610                                                 'version', | 
| 611                                                 version) | 611                                                 version) | 
| 612         elif not response['passed_review'] or not response['valid']: | 612         elif not response['passed_review'] or not response['valid']: | 
| 613             # When the review failed for any reason, we want to know about it | 613             # When the review failed for any reason, we want to know about it | 
| 614             logging.error(json.dumps(response, indent=4)) | 614             logging.error(json.dumps(response, indent=4)) | 
| 615             self.remove_from_downloads_lockfile(self.config.type, | 615             self.remove_from_downloads_lockfile(self.config.type, | 
| 616                                                 'version', | 616                                                 'version', | 
| 617                                                 version) | 617                                                 version) | 
| 618 | 618 | 
| 619     def uploadToChromeWebStore(self): | 619     def uploadToChromeWebStore(self): | 
| 620 | 620 | 
| 621         opener = urllib2.build_opener(HTTPErrorBodyHandler) | 621         opener = urllib2.build_opener(HTTPErrorBodyHandler) | 
| 622 | 622 | 
| 623         # use refresh token to obtain a valid access token | 623         # use refresh token to obtain a valid access token | 
| 624         # https://developers.google.com/accounts/docs/OAuth2WebServer#refresh | 624         # https://developers.google.com/accounts/docs/OAuth2WebServer#refresh | 
| 625 | 625 | 
| 626         response = json.load(opener.open( | 626         response = json.load(opener.open( | 
| 627             'https://accounts.google.com/o/oauth2/token', | 627             'https://accounts.google.com/o/oauth2/token', | 
| 628 | 628 | 
| 629             urlencode([ | 629             urlencode([ | 
| 630                 ('refresh_token', self.config.refreshToken), | 630                 ('refresh_token', self.config.refreshToken), | 
| 631                 ('client_id', self.config.clientID), | 631                 ('client_id', self.config.clientID), | 
| 632                 ('client_secret', self.config.clientSecret), | 632                 ('client_secret', self.config.clientSecret), | 
| 633                 ('grant_type', 'refresh_token'), | 633                 ('grant_type', 'refresh_token'), | 
| 634             ]) | 634             ]), | 
| 635         )) | 635         )) | 
| 636 | 636 | 
| 637         auth_token = '%s %s' % (response['token_type'], response['access_token']
     ) | 637         auth_token = '%s %s' % (response['token_type'], response['access_token']
     ) | 
| 638 | 638 | 
| 639         # upload a new version with the Chrome Web Store API | 639         # upload a new version with the Chrome Web Store API | 
| 640         # https://developer.chrome.com/webstore/using_webstore_api#uploadexisitn
     g | 640         # https://developer.chrome.com/webstore/using_webstore_api#uploadexisitn
     g | 
| 641 | 641 | 
| 642         request = urllib2.Request('https://www.googleapis.com/upload/chromewebst
     ore/v1.1/items/' + self.config.devbuildGalleryID) | 642         request = urllib2.Request('https://www.googleapis.com/upload/chromewebst
     ore/v1.1/items/' + self.config.devbuildGalleryID) | 
| 643         request.get_method = lambda: 'PUT' | 643         request.get_method = lambda: 'PUT' | 
| 644         request.add_header('Authorization', auth_token) | 644         request.add_header('Authorization', auth_token) | 
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 742     def upload_to_windows_store(self): | 742     def upload_to_windows_store(self): | 
| 743         opener = urllib2.build_opener(HTTPErrorBodyHandler) | 743         opener = urllib2.build_opener(HTTPErrorBodyHandler) | 
| 744 | 744 | 
| 745         headers = {'Authorization': self.get_windows_store_access_token(), | 745         headers = {'Authorization': self.get_windows_store_access_token(), | 
| 746                    'Content-type': 'application/json'} | 746                    'Content-type': 'application/json'} | 
| 747 | 747 | 
| 748         # Get application | 748         # Get application | 
| 749         # https://docs.microsoft.com/en-us/windows/uwp/monetize/get-an-app | 749         # https://docs.microsoft.com/en-us/windows/uwp/monetize/get-an-app | 
| 750         api_path = '{}/v1.0/my/applications/{}'.format( | 750         api_path = '{}/v1.0/my/applications/{}'.format( | 
| 751             'https://manage.devcenter.microsoft.com', | 751             'https://manage.devcenter.microsoft.com', | 
| 752             self.config.devbuildGalleryID | 752             self.config.devbuildGalleryID, | 
| 753         ) | 753         ) | 
| 754 | 754 | 
| 755         request = urllib2.Request(api_path, None, headers) | 755         request = urllib2.Request(api_path, None, headers) | 
| 756         with contextlib.closing(opener.open(request)) as response: | 756         with contextlib.closing(opener.open(request)) as response: | 
| 757             app_obj = json.load(response) | 757             app_obj = json.load(response) | 
| 758 | 758 | 
| 759         # Delete existing in-progress submission | 759         # Delete existing in-progress submission | 
| 760         # https://docs.microsoft.com/en-us/windows/uwp/monetize/delete-an-app-su
     bmission | 760         # https://docs.microsoft.com/en-us/windows/uwp/monetize/delete-an-app-su
     bmission | 
| 761         submissions_path = api_path + '/submissions' | 761         submissions_path = api_path + '/submissions' | 
| 762         if 'pendingApplicationSubmission' in app_obj: | 762         if 'pendingApplicationSubmission' in app_obj: | 
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 889                         # write update manifest | 889                         # write update manifest | 
| 890                         self.writeUpdateManifest() | 890                         self.writeUpdateManifest() | 
| 891 | 891 | 
| 892                         # retire old builds | 892                         # retire old builds | 
| 893                         versions = self.retireBuilds() | 893                         versions = self.retireBuilds() | 
| 894                         # update index page | 894                         # update index page | 
| 895                         self.updateIndex(versions) | 895                         self.updateIndex(versions) | 
| 896 | 896 | 
| 897                         # Update soft link to latest build | 897                         # Update soft link to latest build | 
| 898                         baseDir = os.path.join( | 898                         baseDir = os.path.join( | 
| 899                             self.config.nightliesDirectory, self.basename | 899                             self.config.nightliesDirectory, self.basename, | 
| 900                         ) | 900                         ) | 
| 901                         linkPath = os.path.join( | 901                         linkPath = os.path.join( | 
| 902                             baseDir, '00latest' + self.config.packageSuffix | 902                             baseDir, '00latest' + self.config.packageSuffix, | 
| 903                         ) | 903                         ) | 
| 904 | 904 | 
| 905                         self.symlink_or_copy(self.path, linkPath) | 905                         self.symlink_or_copy(self.path, linkPath) | 
| 906             finally: | 906             finally: | 
| 907                 # clean up | 907                 # clean up | 
| 908                 if self.tempdir: | 908                 if self.tempdir: | 
| 909                     shutil.rmtree(self.tempdir, ignore_errors=True) | 909                     shutil.rmtree(self.tempdir, ignore_errors=True) | 
| 910 | 910 | 
| 911 | 911 | 
| 912 def main(download=False): | 912 def main(download=False): | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
| 936 | 936 | 
| 937     file = open(nightlyConfigFile, 'wb') | 937     file = open(nightlyConfigFile, 'wb') | 
| 938     nightlyConfig.write(file) | 938     nightlyConfig.write(file) | 
| 939 | 939 | 
| 940 | 940 | 
| 941 if __name__ == '__main__': | 941 if __name__ == '__main__': | 
| 942     parser = argparse.ArgumentParser() | 942     parser = argparse.ArgumentParser() | 
| 943     parser.add_argument('--download', action='store_true', default=False) | 943     parser.add_argument('--download', action='store_true', default=False) | 
| 944     args = parser.parse_args() | 944     args = parser.parse_args() | 
| 945     main(args.download) | 945     main(args.download) | 
| LEFT | RIGHT | 
|---|