def add_remote(repo, name, url): """Add a remote to the Git repository.""" with sh.pushd(repo): try: git.remote("add", name, url) except sh.ErrorReturnCode_3: git.remote("set-url", name, url) git.fetch(name)
def main(): with tempfile.TemporaryDirectory() as tmpdir: info('Created tmp directory ' + tmpdir) os.chdir(tmpdir) git.clone(WIKI_DIR, 'openafs-wiki', _fg=True) os.chdir('openafs-wiki') git.remote('add', 'gerrit', 'ssh://gerrit.openafs.org/openafs-wiki.git') git.fetch('gerrit', _fg=True) git.reset('gerrit/master', '--hard', _fg=True) update_page('devel/GerritsForMaster.mdwn', 'master') update_page('devel/GerritsForStable.mdwn', 'openafs-stable-1_8_x') update_page('devel/GerritsForOldStable.mdwn', 'openafs-stable-1_6_x') try: git.commit('-m', 'update gerrit list', _fg=True) except ErrorReturnCode_1: print('No changes') else: git.push('gerrit', 'HEAD:refs/heads/master', _fg=True)
def repo_remote_url(repo_path): with Submodule(repo_path): output = StringIO() git.remote("get-url", "origin", _out=output) return output.getvalue().strip()
def sync_branches(self, repo, bitbucket_account_id, bitbucket_access_token, github_account_id, github_access_token): repo_name = repo['name'] prefixed_repo_name = self.prefix + repo_name github_link = repo['github_link'] bitbucket_link = repo['bitbucket_link'] # Boolean: whether the repo is a new migration to GitHub new_migration = repo['new_migration'] # Use this instead of setting the authenticated link as a new remote. # Remote links get stored in git config github_link_domain = github_link.split("//")[1] authenticated_github_link = f"https://{github_account_id}:{github_access_token}@{github_link_domain}" bitbucket_link_domain = bitbucket_link.split("//")[1] authenticated_bitbucket_link = f"https://{bitbucket_account_id}:{bitbucket_access_token}@{bitbucket_link_domain}" # Set remote to bitbucket git.remote('set-url', 'origin', bitbucket_link) self.log.debug("Syncing branches. Set origin to Bitbucket", repo_name=repo_name, bitbucket_link=bitbucket_link) # Fetch branches from origin (bitbucket) self.log.info("Fetching refs (branches) from origin", repo_name=repo_name) # git.fetch('origin') git.fetch(authenticated_bitbucket_link) self.log.debug("Fetched refs (branches) from BitBucket", result="SUCCESS", repo_name=repo_name) # List remote branches remote_branches = git.branch("-r").split("\n") remote_branches = [ remote.lstrip().rstrip() for remote in remote_branches if (remote and not re.match("^.*/HEAD -> .*$", remote)) ] try: # if master exists on origin, move that to the start of the array # pushing 'master' first makes it the default branch on github remote_branches.remove('origin/master') remote_branches = ['origin/master'] + remote_branches except Exception: # 'master' did not exist on origin pass success_branches = [] failed_branches = [] # Push changes to each branch individually, log error if any fails and continue to next branch for remote in remote_branches: [remote_name, branch_name] = remote.split('/', 1) self.log.info("Syncing branch for repository", repo_name=repo_name, branch_name=branch_name) if (remote_name == 'origin'): # Different way to handle master branches, support prefixing. if (branch_name == "master"): master_branch_refspecs = [] prefix_exists = self.master_branch_prefix != "" if (prefix_exists): # Order is IMPORTANT, 'master' should be added before prefixed_master. # Default branch is the first branch that is pushed to GitHub if (new_migration): master_branch_refspecs.append( f"refs/remotes/origin/{branch_name}:refs/heads/{branch_name}" ) prefixed_master_branch_name = self.master_branch_prefix + branch_name master_branch_refspecs.append( f"refs/remotes/origin/{branch_name}:refs/heads/{prefixed_master_branch_name}" ) else: master_branch_refspecs.append( f"refs/remotes/origin/{branch_name}:refs/heads/{branch_name}" ) for branch_refspec in master_branch_refspecs: target_branch_name = branch_refspec.split('/')[-1] try: self.log.info( "Pushing branch for repository", repo_name=prefixed_repo_name, repo_prefix=self.prefix, branch_name=branch_name, target_branch_name=target_branch_name) git.push(authenticated_github_link, branch_refspec) # Success on syncing current branch self.log.debug( "Successfully synced branch for repository", result="SUCCESS", repo_name=prefixed_repo_name, repo_prefix=self.prefix, branch_name=branch_name, target_branch_name=target_branch_name) success_branches.append(branch_name) except ErrorReturnCode as e: # Redact or remove the access token before logging stderr = utils.StringUtils.redact_error( e.stderr, github_access_token, "<ACCESS-TOKEN>") self.log.error( "Failed to push changes to origin branch", result="FAILED", repo_name=prefixed_repo_name, repo_prefix=self.prefix, branch_name=branch_name, target_branch_name=target_branch_name, exit_code=e.exit_code, stderr=stderr) failed_branches.append(branch_name) continue # Continue to the next master_branch_refspec continue # Continue to the next branch branch_refspec = f"refs/remotes/origin/{branch_name}:refs/heads/{branch_name}" try: self.log.info("Pushing branch for repository", repo_name=prefixed_repo_name, repo_prefix=self.prefix, branch_name=branch_name, target_branch_name=branch_name) git.push(authenticated_github_link, branch_refspec) # Success on syncing current branch self.log.debug("Successfully synced branch for repository", result="SUCCESS", repo_name=prefixed_repo_name, repo_prefix=self.prefix, branch_name=branch_name, target_branch_name=branch_name) success_branches.append(branch_name) except ErrorReturnCode as e: # Redact or remove the access token before logging stderr = utils.StringUtils.redact_error( e.stderr, github_access_token, "<ACCESS-TOKEN>") self.log.error("Failed to push changes to origin branch", result="FAILED", repo_name=prefixed_repo_name, repo_prefix=self.prefix, branch_name=branch_name, target_branch_name=branch_name, exit_code=e.exit_code, stderr=stderr) failed_branches.append(branch_name) continue else: continue all_remote_branches = [ branch_name.split('origin/')[1] for branch_name in remote_branches ] branches_sync_success = set(all_remote_branches) == set( success_branches) return branches_sync_success, all_remote_branches, failed_branches
def sync_tags(self, repo, bitbucket_account_id, bitbucket_access_token, github_account_id, github_access_token): # Everytime, tags are fetched from remote (bitbucket) and then pushed to github repo_name = repo['name'] prefixed_repo_name = self.prefix + repo_name github_link = repo['github_link'] bitbucket_link = repo['bitbucket_link'] # Use this instead of setting the authenticated link as a new remote. # Remote links get stored in git config github_link_domain = github_link.split("//")[1] authenticated_github_link = f"https://{github_account_id}:{github_access_token}@{github_link_domain}" bitbucket_link_domain = bitbucket_link.split("//")[1] authenticated_bitbucket_link = f"https://{bitbucket_account_id}:{bitbucket_access_token}@{bitbucket_link_domain}" git.remote('set-url', 'origin', bitbucket_link) self.log.debug("Syncing Tags. Set origin to BitBucket", repo_name=repo_name, bitbucket_link=bitbucket_link) # Fetch tags from origin (bitbucket) self.log.info("Fetching refs (tags) from origin", repo_name=repo_name) # git.fetch('origin') git.fetch(authenticated_bitbucket_link) self.log.debug("Fetched refs (tags) from BitBucket", result="SUCCESS", repo_name=repo_name) # List all tags tags = git.tag().split('\n') tags = [tag.lstrip().rstrip() for tag in tags if tag] success_tags = [] failed_tags = [] # Set origin to github # git.remote('set-url', 'origin', github_link) self.log.debug("Syncing tags. Set origin to Github", repo_name=prefixed_repo_name, repo_prefix=self.prefix, github_link=github_link) # Push each tag individually, log error if any fails and continue to next tag for tag_name in tags: self.log.info("Syncing tag for repository", repo_name=repo_name, tag_name=tag_name) try: tag_refspec = f"refs/tags/{tag_name}:refs/tags/{tag_name}" git.push(authenticated_github_link, tag_refspec) self.log.debug("Pushed tag for repository", result="SUCCESS", repo_name=prefixed_repo_name, repo_prefix=self.prefix, tag_name=tag_name) success_tags.append(tag_name) except ErrorReturnCode as e: # Redact or remove the access token before logging stderr = utils.StringUtils.redact_error( e.stderr, github_access_token, "<ACCESS-TOKEN>") self.log.error("Failed to push tag to github", result="FAILED", repo_name=prefixed_repo_name, repo_prefix=self.prefix, tag_name=tag_name, exit_code=e.exit_code, stderr=stderr) failed_tags.append(tag_name) continue tags_sync_success = set(tags) == set(success_tags) return tags_sync_success, tags, failed_tags