def setUp(self): self.manifest_dir = os.path.join(self.tempdir, '.repo', 'manifests') # Initialize a repo instance here. local_repo = os.path.join(constants.SOURCE_ROOT, '.repo/repo/.git') # TODO(evanhernandez): This is a hack. Find a way to simplify this test. # We used to use the current checkout's manifests.git, but that caused # problems in production environemnts. remote_manifests = os.path.join(self.tempdir, 'remote', 'manifests.git') osutils.SafeMakedirs(remote_manifests) git.Init(remote_manifests) default_manifest = os.path.join(remote_manifests, 'default.xml') osutils.WriteFile( default_manifest, '<?xml version="1.0" encoding="UTF-8"?><manifest></manifest>') git.AddPath(default_manifest) git.Commit(remote_manifests, 'dummy commit', allow_empty=True) git.CreateBranch(remote_manifests, 'default') git.CreateBranch(remote_manifests, 'release-R23-2913.B') git.CreateBranch(remote_manifests, 'release-R23-2913.B-suffix') git.CreateBranch(remote_manifests, 'firmware-link-') # Create a copy of our existing manifests.git, but rewrite it so it # looks like a remote manifests.git. This is to avoid hitting the # network, and speeds things up in general. local_manifests = 'file://%s' % remote_manifests temp_manifests = os.path.join(self.tempdir, 'manifests.git') git.RunGit(self.tempdir, ['clone', '-n', '--bare', local_manifests]) git.RunGit(temp_manifests, [ 'fetch', '-f', '-u', local_manifests, 'refs/remotes/origin/*:refs/heads/*' ]) git.RunGit(temp_manifests, ['branch', '-D', 'default']) cros_build_lib.run([ 'repo', 'init', '-u', temp_manifests, '--repo-branch', 'default', '--repo-url', 'file://%s' % local_repo, ], cwd=self.tempdir) self.active_manifest = os.path.realpath( os.path.join(self.tempdir, '.repo', 'manifest.xml'))
def _FixUpManifests(self, repo_manifest): """Points the checkouts at the new branch in the manifests. Within the branch, make sure all manifests with projects that are "branchable" are checked out to "refs/heads/<new_branch>". Do this by updating all manifests in the known manifest projects. """ assert not self._run.options.delete_branch, 'Cannot fix a deleted branch.' # Use local branch ref. branch_ref = git.NormalizeRef(self.branch_name) logging.debug('Fixing manifest projects for new branch.') for project in site_config.params.MANIFEST_PROJECTS: manifest_checkout = repo_manifest.FindCheckout(project) manifest_dir = manifest_checkout['local_path'] push_remote = manifest_checkout['push_remote'] # Checkout revision can be either a sha1 or a branch ref. src_ref = manifest_checkout['revision'] if not git.IsSHA1(src_ref): src_ref = git.NormalizeRemoteRef(push_remote, src_ref) git.CreateBranch(manifest_dir, manifest_version.PUSH_BRANCH, src_ref) # We want to process default.xml and official.xml + their imports. pending_manifests = [ constants.DEFAULT_MANIFEST, constants.OFFICIAL_MANIFEST ] processed_manifests = [] while pending_manifests: # Canonicalize the manifest name (resolve dir and symlinks). manifest_path = os.path.join(manifest_dir, pending_manifests.pop()) manifest_path = os.path.realpath(manifest_path) # Don't process a manifest more than once. if manifest_path in processed_manifests: continue processed_manifests.append(manifest_path) if not os.path.exists(manifest_path): logging.info('Manifest not found: %s', manifest_path) continue logging.debug('Fixing manifest at %s.', manifest_path) included_manifests = self._UpdateManifest(manifest_path) pending_manifests += included_manifests git.RunGit(manifest_dir, ['add', '-A'], print_cmd=True) message = 'Fix up manifest after branching %s.' % branch_ref git.RunGit(manifest_dir, ['commit', '-m', message], print_cmd=True) push_to = git.RemoteRef(push_remote, branch_ref) git.GitPush(manifest_dir, manifest_version.PUSH_BRANCH, push_to, skip=self.skip_remote_push)
def _AdjustRepoCheckoutToLocalManifest(self, manifest_path): """Re-checkout repository based on patched internal manifest repository. This method clones the current state of 'manifest-internal' into a temp location, and then re-sync's the current repository to that manifest. This is intended to allow sync'ing with test manifest CLs included. It does NOT clean up afterwards. Args: manifest_path: Directory containing the already patched manifest. Normally SOURCE_ROOT/manifest or SOURCE_ROOT/manifest-internal. """ tmp_manifest_repo = tempfile.mkdtemp(prefix='patched_manifest') logging.info('Cloning manifest repository from %s to %s.', manifest_path, tmp_manifest_repo) repository.CloneGitRepo(tmp_manifest_repo, manifest_path) git.CreateBranch(tmp_manifest_repo, self.cros_source.branch or 'master') logging.info('Switching to local patched manifest repository:') logging.info('TMPDIR: %s', tmp_manifest_repo) logging.info(' %s', os.listdir(tmp_manifest_repo)) self.cros_source.Initialize(manifest_repo_url=tmp_manifest_repo) self.cros_source.Sync(detach=True)
def Checkout(self, sparse_checkout): """Checks out chrome into tmp checkout dir. Args: sparse_checkout: List of file paths to fetch. """ assert isinstance(sparse_checkout, list) sparse_checkout += ['codereview.settings', 'WATCHLISTS'] git.ShallowFetch(self._checkout_dir, constants.CHROMIUM_GOB_URL, sparse_checkout=sparse_checkout) git.CreateBranch(self._checkout_dir, 'auto-commit-branch', branch_point='origin/master')
def unpin(self, work_dir): """Unpin chrome.""" overlay = os.path.join(work_dir, 'overlay') print('Setting up working directory...') CloneWorkingRepo(overlay, OVERLAY_URL, OVERLAY, self.options.branch) print('Done') mask_file = os.path.join(overlay, MASK_FILE) if not os.path.exists(mask_file): raise Exception('Mask file not found. Is Chrome pinned?') git.CreateBranch(overlay, self.branch_name, track=True, branch_point='origin/%s' % self.options.branch) git.RmPath(mask_file) git.Commit(overlay, self.CommitMessage('Chrome: Unpin chrome')) git.UploadCL(overlay, OVERLAY_URL, self.options.branch, skip=self.options.dryrun)
def UpdateVersionFile(self, message, dry_run, push_to=None): """Update the version file with our current version. Args: message: Commit message. dry_run: Git dryrun. push_to: A git.RemoteRef object. """ if not self.version_file: raise VersionUpdateException( 'Cannot call UpdateVersionFile without ' 'an associated version_file') components = (('CHROMEOS_BUILD', self.build_number), ('CHROMEOS_BRANCH', self.branch_build_number), ('CHROMEOS_PATCH', self.patch_number), ('CHROME_BRANCH', self.chrome_branch)) with tempfile.NamedTemporaryFile(prefix='mvp', mode='w') as temp_fh: with open(self.version_file, 'r') as source_version_fh: for line in source_version_fh: for key, value in components: line = re.sub(self.KEY_VALUE_PATTERN % (key, ), '%s=%s\n' % (key, value), line) temp_fh.write(line) temp_fh.flush() repo_dir = os.path.dirname(self.version_file) logging.info('Updating version file to: %s', self.VersionString()) try: git.CreateBranch(repo_dir, PUSH_BRANCH) shutil.copyfile(temp_fh.name, self.version_file) _PushGitChanges(repo_dir, message, dry_run=dry_run, push_to=push_to) finally: # Update to the remote version that contains our changes. This is needed # to ensure that we don't build a release using a local commit. git.CleanAndCheckoutUpstream(repo_dir)
def CommonTestIncrementVersion(self, incr_type, version, chrome_branch=None): """Common test increment. Returns path to new incremented file.""" message = 'Incrementing cuz I sed so' self.mox.StubOutWithMock(git, 'CreateBranch') self.mox.StubOutWithMock(manifest_version, '_PushGitChanges') self.mox.StubOutWithMock(git, 'CleanAndCheckoutUpstream') git.CreateBranch(self.tempdir, manifest_version.PUSH_BRANCH) version_file = self.CreateFakeVersionFile( self.tempdir, version=version, chrome_branch=chrome_branch) manifest_version._PushGitChanges(self.tempdir, message, dry_run=False, push_to=None) git.CleanAndCheckoutUpstream(self.tempdir) self.mox.ReplayAll() info = manifest_version.VersionInfo(version_file=version_file, incr_type=incr_type) info.IncrementVersion(message, dry_run=False) self.mox.VerifyAll() return version_file
def pin(self, work_dir): """Pin chrome.""" overlay = os.path.join(work_dir, 'overlay') priv_overlay = os.path.join(work_dir, 'priv_overlay') print('Setting up working directory...') CloneWorkingRepo(overlay, OVERLAY_URL, OVERLAY, self.options.branch) CloneWorkingRepo(priv_overlay, PRIV_OVERLAY_URL, PRIV_OVERLAY, self.options.branch) print('Done') # Interesting paths. chrome_dir = os.path.join(overlay, constants.CHROME_CP) other_dirs = [ os.path.join(overlay, pkg) for pkg in constants.OTHER_CHROME_PACKAGES ] # Let the user pick what version to pin chrome to. uprev_list = UprevList(chrome_dir) choice = cros_build_lib.GetChoice('Versions of chrome to pin to:', uprev_list, group_size=5) pin_version = uprev_list.uprevs[choice] commit_subject = ('Chrome: Pin to version %s' % pin_version.from_parts.version) # Public branch. git.CreateBranch(overlay, self.branch_name, track=True, branch_point='origin/%s' % self.options.branch) target_sha = pin_version.sha + '~' ebs = [RevertStableEBuild(chrome_dir, target_sha)] for pkg_dir in other_dirs: ebs.append(RevertStableEBuild(pkg_dir, target_sha)) RevertBinhostConf(overlay, pin_version.conf_files, target_sha) git.RevertPath(os.path.join(overlay, 'chromeos', 'binhost'), 'chromium.json', target_sha) MaskNewerPackages(overlay, (eb for eb in ebs if eb)) pub_cid = git.Commit(overlay, 'Public overlay commit') if not pub_cid: raise Exception( "Don't know the commit ID of the public overlay CL.") # Find out what package directory the binhost configs should point to. binhost_dir = os.path.join(overlay, 'chromeos', 'binhost') target_file = os.path.join(binhost_dir, 'target', pin_version.conf_files[0]) host_file = os.path.join(binhost_dir, 'host', pin_version.conf_files[0]) conf_file = target_file if os.path.exists(target_file) else host_file conf_content = osutils.ReadFile(conf_file) match = re.search('/(?P<package_dir>[^/\n]*)/packages', conf_content) if not match: raise Exception('Failed to parse binhost conf %s' % conf_content.strip()) pkg_dir = match.group('package_dir') # Private branch. git.CreateBranch(priv_overlay, self.branch_name, track=True, branch_point='origin/%s' % self.options.branch) binhost_uprev = FindPrivateConfCL(priv_overlay, pkg_dir) if not binhost_uprev: raise Exception('Failed to find private binhost uprev.') target_sha = binhost_uprev.sha RevertBinhostConf(priv_overlay, binhost_uprev.conf_files, target_sha) git.RevertPath(os.path.join(priv_overlay, 'chromeos', 'binhost'), 'chrome.json', target_sha) commit_message = self.CommitMessage(commit_subject, pub_cid) priv_cid = git.Commit(priv_overlay, commit_message) if not priv_cid: raise Exception( "Don't know the commit ID of the private overlay CL.") # Update the commit message on the public overlay CL. commit_message = self.CommitMessage(commit_subject, '*' + priv_cid, pub_cid) git.Commit(overlay, commit_message, amend=True) # Upload the CLs. external_push = git.UploadCL(overlay, OVERLAY_URL, self.options.branch, skip=self.options.dryrun) print(external_push.output) internal_push = git.UploadCL(priv_overlay, PRIV_OVERLAY_URL, self.options.branch, skip=self.options.dryrun) print(internal_push.output) print('\n** Both of the changes above need to be submitted for chrome ' 'to be pinned. **\n')
def testDoesCommitExistInRepoWithAmbiguousBranchName(self): git1 = self._MakeRepo('git1', self.source) git.CreateBranch(git1, 'peach', track=True) self.CommitFile(git1, 'peach', 'Keep me.') self.assertTrue(git.DoesCommitExistInRepo(git1, 'peach'))
def IncrementVersion(self, message, dry_run, push_to=None): """Updates the version file by incrementing the patch component. Args: message: Commit message to use when incrementing the version. dry_run: Git dry_run. """ def IncrementOldValue(line, key, new_value): """Change key to new_value if found on line. Returns True if changed.""" old_value = self.FindValue(key, line) if old_value: temp_fh.write(line.replace(old_value, new_value, 1)) return True else: return False if not self.version_file: raise VersionUpdateException( 'Cannot call IncrementVersion without ' 'an associated version_file') if not self.incr_type or self.incr_type not in self.VALID_INCR_TYPES: raise VersionUpdateException( 'Need to specify the part of the version to' ' increment') if self.incr_type == 'chrome_branch': self.chrome_branch = str(int(self.chrome_branch) + 1) # Increment build_number for 'chrome_branch' incr_type to avoid # crbug.com/213075. if self.incr_type in ('build', 'chrome_branch'): self.build_number = str(int(self.build_number) + 1) self.branch_build_number = '0' self.patch_number = '0' elif self.incr_type == 'branch' and self.patch_number == '0': self.branch_build_number = str(int(self.branch_build_number) + 1) else: self.patch_number = str(int(self.patch_number) + 1) temp_file = tempfile.mkstemp(suffix='mvp', prefix='tmp', dir=None, text=True)[1] with open(self.version_file, 'r') as source_version_fh: with open(temp_file, 'w') as temp_fh: for line in source_version_fh: if IncrementOldValue(line, 'CHROMEOS_BUILD', self.build_number): pass elif IncrementOldValue(line, 'CHROMEOS_BRANCH', self.branch_build_number): pass elif IncrementOldValue(line, 'CHROMEOS_PATCH', self.patch_number): pass elif IncrementOldValue(line, 'CHROME_BRANCH', self.chrome_branch): pass else: temp_fh.write(line) temp_fh.close() source_version_fh.close() repo_dir = os.path.dirname(self.version_file) try: git.CreateBranch(repo_dir, PUSH_BRANCH) shutil.copyfile(temp_file, self.version_file) os.unlink(temp_file) _PushGitChanges(repo_dir, message, dry_run=dry_run, push_to=push_to) finally: # Update to the remote version that contains our changes. This is needed # to ensure that we don't build a release using a local commit. git.CleanAndCheckoutUpstream(repo_dir) return self.VersionString()