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 _VerifyPush(self, new_branch, rename_from=None, delete=False): """Verify that |new_branch| has been created. Args: new_branch: The new remote branch to create (or delete). rename_from: If set, |rename_from| is being renamed to |new_branch|. delete: If set, |new_branch| is being deleted. """ # Pushes all operate on remote branch refs. new_branch = git.NormalizeRef(new_branch) # Calculate source and destination revisions. suffixes = ['', '-new-special-branch', '-old-special-branch'] if delete: src_revs = [''] * len(suffixes) elif rename_from is not None: rename_from = git.NormalizeRef(rename_from) rename_from_tracking = git.NormalizeRemoteRef('cros', rename_from) src_revs = [ '%s%s' % (rename_from_tracking, suffix) for suffix in suffixes ] else: src_revs = [ CHROMITE_REVISION, SPECIAL_REVISION1, SPECIAL_REVISION2 ] dest_revs = ['%s%s' % (new_branch, suffix) for suffix in suffixes] # Verify pushes happened correctly. for src_rev, dest_rev in zip(src_revs, dest_revs): cmd = ['push', '%s:%s' % (src_rev, dest_rev)] self.rc_mock.assertCommandContains(cmd) if rename_from is not None: cmd = ['push', ':%s' % (rename_from, )] self.rc_mock.assertCommandContains(cmd)
def _ProcessCheckout(self, src_manifest, src_checkout): """Performs per-checkout push operations. Args: src_manifest: The ManifestCheckout object for the current manifest. src_checkout: The ProjectCheckout object to process. """ if not src_checkout.IsBranchableProject(): # We don't have the ability to push branches to this repository. Just # use TOT instead. return checkout_name = src_checkout['name'] remote = src_checkout['push_remote'] src_ref = src_checkout['revision'] suffix = self._GetBranchSuffix(src_manifest, src_checkout) # The source/destination branches depend on options. if self.rename_to: # Rename flow. Both src and dst branches exist. src_branch = '%s%s' % (self.branch_name, suffix) dst_branch = '%s%s' % (self.rename_to, suffix) elif self._run.options.delete_branch: # Delete flow. Only dst branch exists. src_branch = None dst_branch = '%s%s' % (self.branch_name, suffix) else: # Create flow (default). Only dst branch exists. Source # for the branch will just be src_ref. src_branch = None dst_branch = '%s%s' % (self.branch_name, suffix) # Normalize branch refs to remote. We only process remote branches. src_branch = git.NormalizeRemoteRef(remote, src_branch) dst_branch = git.NormalizeRemoteRef(remote, dst_branch) # Determine whether src/dst branches exist now, by getting their sha1s. if src_branch: src_sha1 = self._GetSHA1(src_checkout, src_branch) elif git.IsSHA1(src_ref): src_sha1 = src_ref dst_sha1 = self._GetSHA1(src_checkout, dst_branch) # Complain if the branch already exists, unless that is expected. force = self._run.options.force_create or self._run.options.delete_branch if dst_sha1 and not force: # We are either creating a branch or renaming a branch, and the # destination branch unexpectedly exists. Accept this only if the # destination branch is already at the revision we want. if src_sha1 != dst_sha1: raise BranchError( 'Checkout %s already contains branch %s. Run with ' '--force-create to overwrite.' % (checkout_name, dst_branch)) logging.info( 'Checkout %s already contains branch %s and it already' ' points to revision %s', checkout_name, dst_branch, dst_sha1) elif self._run.options.delete_branch: # Delete the dst_branch, if it exists. if dst_sha1: self._DeleteBranch(src_checkout, dst_branch) else: raise BranchError( 'Checkout %s does not contain branch %s to delete.' % (checkout_name, dst_branch)) elif self.rename_to: # Copy src_branch to dst_branch, if it exists, then delete src_branch. if src_sha1: self._CopyBranch(src_checkout, src_branch, dst_branch) self._DeleteBranch(src_checkout, src_branch) else: raise BranchError( 'Checkout %s does not contain branch %s to rename.' % (checkout_name, src_branch)) else: # Copy src_ref to dst_branch. self._CopyBranch(src_checkout, src_ref, dst_branch, force=self._run.options.force_create)