def fetch_manifest(worktree, manifest_git_url, branch="master", profile="default", src="manifest/default"): """ Fetch the manifest for a worktree :param manifest_git_url: A git repository containing a 'manifest.xml' file, ala repo :param branch: The branch to use :param src: The path where to store the clone of the manifest Note: every changes made by the user directly in the manifest repo will be lost! """ manifest = worktree.get_project(src) if not manifest: clone_project(worktree, manifest_git_url, src=src) manifest = worktree.get_project(src) # Make sure manifest project is on the correct, up to date branch: git = qisrc.git.Git(manifest.path) git.set_remote("origin", manifest_git_url) git.set_tracking_branch(branch, "origin") git.checkout("-f", branch, quiet=True) git.fetch(quiet=True) git.reset("--hard", "origin/%s" % branch, quiet=True) filename = profile + ".xml" manifest_file = os.path.join(manifest.path, filename) if not os.path.exists(manifest_file): mess = "Could not find a file named '%s' " % filename mess += "in the repository: %s\n" % manifest_git_url raise Exception(mess) return manifest_file
def _create_repo(self, project, src=None, review=False, empty=False): """ Helper for self.create_repo """ if not src: src = project.replace(".git", "") if review: repo_srv = self.gerrit.ensure(project, dir=True) else: repo_srv = self.srv.ensure(project, dir=True) repo_url = "file://" + qisys.sh.to_posix_path(repo_srv.strpath) git = qisrc.git.Git(repo_srv.strpath) git.init("--bare") repo_src = self.src.ensure(src, dir=True) git = TestGit(repo_src.strpath) git.initialize() if review: remote_name = "gerrit" else: remote_name = "origin" git.set_remote(remote_name, repo_url) if not empty: git.push(remote_name, "master:master") return repo_src.strpath
def init_worktree(worktree, manifest_location, setup_review=True): """ (re)-intianlize a worktree given a manifest location. Clonie any missing repository, set the correct remote and tracking branch on every repository :param setup_review: Also set up the projects for review """ errors = list() manifest = qisrc.manifest.load(manifest_location) if not manifest.projects: return project_count = len(manifest.projects) ui.info(ui.green, "Initializing worktree ...") setup_ok = True for i, project in enumerate(manifest.projects): ui.info( ui.green, "*", ui.reset, "(%2i/%2i)" % (i+1, project_count), ui.blue, project.name) # Use the same branch for the project as the branch # for the manifest, unless explicitely set: p_revision = project.revision p_url = project.fetch_url p_remote = project.remote p_src = project.path wt_project = worktree.get_project(p_src) if not wt_project: # Maybe we just need to add the project to the worktree: wt_project = add_if_missing(worktree, p_src, p_remote, p_url) if not wt_project: wt_project = clone_project(worktree, p_url, src=p_src, branch=p_revision, remote=p_remote) p_path = wt_project.path if project.review and setup_review and setup_ok: worktree.set_project_review(p_src, True) # If setup failed once, no point in trying for every project setup_ok = qisrc.review.setup_project(p_path, project.name, project.review_url, p_revision) git = qisrc.git.Git(p_path) git.set_remote(p_remote, p_url) git.set_tracking_branch(p_revision, p_remote) cur_branch = git.get_current_branch() if cur_branch != p_revision: if not cur_branch: ui.warning("Project", project.name, "is on a detached HEAD", "but should be on", p_revision) else: ui.warning("Project", project.name, "is on", cur_branch, "but should be on", p_revision) worktree.set_git_project_config(p_src, p_remote, p_revision) if not setup_ok: qisrc.review.warn_gerrit()
def _sync_git(repo, url, branch, ref): git = qisrc.git.Git(repo) git.set_remote("origin", url) if git.get_current_branch() != branch: git.checkout("-B", branch) with git.transaction() as transaction: git.fetch("origin") if ref: to_reset = ref git.reset("--hard", to_reset) else: git.reset("--hard", "origin/%s" % branch) if not transaction.ok: raise Exception("Update failed\n" + transaction.output)
def _sync_manifest(self): """ Update the local manifest clone with the remote """ git = qisrc.git.Git(self.manifest_repo) git.set_remote("origin", self.manifest.url) if git.get_current_branch() != self.manifest.branch: git.checkout("-B", self.manifest.branch) with git.transaction() as transaction: git.fetch("origin") if self.manifest.ref: to_reset = self.manifest.ref git.reset("--hard", to_reset) else: git.reset("--hard", "origin/%s" % self.manifest.branch) if not transaction.ok: raise Exception("Update failed\n" + transaction.output)
def setup_project(project_path, project_name, review_url, branch): """ Setup a project for code review. * Figure out the user name * Add a remote called 'gerrit' * Add the hook :return: a boolean to tell wether it's worth trying for other projects """ git = qisrc.git.Git(project_path) # Extract server from url: # pylint: disable-msg=E1103 netloc = urlparse.urlsplit(review_url).netloc server = netloc.split(":")[0] # Get username qibuild_cfg = qibuild.config.QiBuildConfig() qibuild_cfg.read(create_if_missing=True) access = qibuild_cfg.get_server_access(server) if access: username = access.username else: username = ask_gerrit_username(server) if not username: return False # Add it to config so we ask only once qibuild_cfg.set_server_access(server, username) qibuild_cfg.write() # Set a remote named 'gerrit' remote_url = http_to_ssh(review_url, project_name, username) git.set_remote("gerrit", remote_url) # Configure review.remote in git/config so that # qisrc push knows what to do: git.set_config("review.remote", "gerrit") # Install the hook commit_hook = os.path.join(project_path, ".git", "hooks", "commit-msg") if os.path.exists(commit_hook): return True ui.info("Configuring project for code review ...", end="") (username, server, port) = parse_git_url(remote_url) fetch_gerrit_hook(project_path, username, server, port) ui.info(ui.green, "[OK]") return True
def add_if_missing(worktree, src, remote_name, remote_url): """ Add a project to a worktree if src is a already a git repo with the correct remote url (can happen when someone runs qisrc remove then qisrc sync ...) """ path = os.path.join(worktree.root, src) if not os.path.exists(path): return git_dir = os.path.join(path, ".git") if not os.path.exists(git_dir): raise Exception("%s already exists and is not a git repository" % path) if qisrc.git.is_submodule(path): repo_root = qisrc.git.get_repo_root(os.path.dirname(path)) raise Exception("%s is already a submodule of %s" % (path, repo_root)) git = qisrc.git.Git(path) git.set_remote(remote_name, remote_url) worktree.add_project(src) return worktree.get_project(src)
def _sync_manifest(self): """ Update the local manifest clone with the remote """ if not self.manifest.url: mess = """ \ No manifest set for worktree in {root} Please run `qisrc init MANIFEST_URL` """ raise Exception(mess.format(root=self.git_worktree.root)) git = qisrc.git.Git(self.manifest_repo) git.set_remote("origin", self.manifest.url) if git.get_current_branch() != self.manifest.branch: git.checkout("-B", self.manifest.branch) with git.transaction() as transaction: git.fetch("origin") if self.manifest.ref: to_reset = self.manifest.ref git.reset("--hard", to_reset) else: git.reset("--hard", "origin/%s" % self.manifest.branch) if not transaction.ok: raise Exception("Update failed\n" + transaction.output)
def test_set_remote(self): bar_url = create_git_repo(self.tmp, "bar", with_release_branch=True) work = os.path.join(self.tmp, "work") qibuild.sh.mkdir(work) bar_src = os.path.join(work, "bar") git = qisrc.git.Git(bar_src) git.clone(bar_url, "-o", "foo") # Must work: git.pull() git.set_remote("origin", bar_url) # Must NOT work: out, err_ = git.pull("origin", raises=False) self.assertFalse(out == 0) # Must work git.set_tracking_branch("master", "origin") git.pull() readme = read_readme(bar_src) self.assertEqual(readme, "bar\n") git.set_tracking_branch("stable", "origin", remote_branch="release-1.12") git.checkout("stable") git.pull() readme = read_readme(bar_src) self.assertEqual(readme, "bar on release-1.12\n")