def dump_revision_result(self, revision: str, file_name: str, data: Any, fmt: str = "json") -> None: IOUtils.dump(self.get_revision_dir(revision) / file_name, data, fmt) return
def get_all_revisions(self) -> List[str]: """ Returns the revisions of the history of the current branch, before (and include) the current revision. The revisions are sorted in chronological order, i.e., latest revision at last. Updates the results with "all_revisions.json". :requires: the project to be cloned. :return: the list of revisions of current branch history, sorted in chronological order. """ self.require_cloned() cmd_get_revisions = "git log --pretty='%H'" with IOUtils.cd(self.checkout_dir): # Revisions in chronological order all_revisions = BashUtils.run(cmd_get_revisions).split("\n")[:-1] all_revisions.reverse() # end with self.logger.info(self.logger_prefix + "All revisions count: {}".format(len(all_revisions))) if self.is_connected_to_results: self.results.dump_meta_result("all_revisions.json", all_revisions) # end if return all_revisions
def for_each_revision(self, func_revision: Callable[["Project", str], None], revisions: Iterable[str], is_auto_checkout: bool = True) -> None: """ Runs the func_revision for each revision. :param func_revision: the function to run, which takes a Project object and a string revision, and is able to access the ProjectResults. :param revisions: the revisions to run the function. :param is_auto_checkout: if set to False then will not automatically checkout each revision. """ if isinstance(revisions, list): revisions_count = len(revisions) else: revisions_count = "-" # end if for revision_idx, revision in enumerate(revisions): self.logger.info(self.logger_prefix + "Revision {}/{} <{}>".format( revision_idx + 1, revisions_count, revision)) if is_auto_checkout: self.checkout(revision, True) # end if with IOUtils.cd(self.checkout_dir): func_revision(self, revision) # end with # end for return
def load_from_file(cls, file: Path) -> Dict[str, "Macro"]: """ Loads the macros from a latex file. Will convert the value of the macros to int or float, if possible. :param file: the latex file. :return: the indexed dictionary of {macro.key, macro}. """ macros_indexed: Dict[str, Macro] = dict() lines: List[str] = IOUtils.load(file, "txt").split("\n") for line in lines: match = cls.RE_DEF_MACRO.fullmatch(line.strip()) if match is not None: key = match.group("key") value = match.group("value") # Try to convert to int, then (if failing) float. try: value = int(value) except: try: value = float(value) except: pass # end try, try macros_indexed[key] = Macro(key, value) # end if # end for return macros_indexed
def revision(self) -> str: """ Returns the current revision of the project. :requires: the project to be cloned. :return: the current revision of the project. """ self.require_cloned() cmd_get_current_revision = "git log --pretty='%H' -1" with IOUtils.cd(self.checkout_dir): revision = BashUtils.run(cmd_get_current_revision).strip() # end with return revision
def test_cd(self): with TestSupport.get_playground_path(): oldpath = Path.cwd() testpath = Path("./aaa").resolve() testpath.mkdir() with IOUtils.cd(testpath): # Checks if changed directory successfully self.assertEqual(testpath, Path.cwd()) # end with # Checks if returned to old directory successfully self.assertEqual(oldpath, Path.cwd()) # end with return
def update(self): """ Updates the cloned repo to the latest version of default branch. """ self.require_cloned() self.logger.info(self.logger_prefix + "Updating to latest version of branch {}".format( self.default_branch)) with IOUtils.cd(self.checkout_dir): self.checkout(self.default_branch, True) BashUtils.run("git pull") self.checkout(self.default_branch, True) # end with return
def checkout(self, revision: str, is_forced: bool = False) -> None: """ Checks out to the given revision. :requires: the project to be cloned. :param revision: the target revision. :param is_forced: if do force checkout or not. """ self.require_cloned() self.logger.info(self.logger_prefix + "Checking-out to {}".format(revision)) cmd_checkout = "git checkout {} {}".format("-f" if is_forced else "", revision) with IOUtils.cd(self.checkout_dir): BashUtils.run(cmd_checkout) # end with return
def clone(self, checkout_dir: Path = None, is_force_update: bool = False): """ Clones the project to path. The project will be checked-out to the default branch, latest revision. If the project is already cloned, then will only move the project to the given path, and check out to the default branch, latest revision. :param checkout_dir: the location to clone and checkout the project. :param is_force_update: if true, then will re-clone regardless of whether the project is cloned before. """ # Get default checkout path if checkout_dir is None: if self.checkout_dir is not None: checkout_dir = self.checkout_dir else: checkout_dir = self.default_checkout_dir # end if # end if # Respect is_force_update if is_force_update: self.remove() # end if checkout_dir.mkdir(parents=True, exist_ok=True) if self.checkout_dir is None: # Clone, if not done so self.logger.info(self.logger_prefix + "Cloning to {}".format(checkout_dir)) with IOUtils.cd(checkout_dir): cmd_clone = "git clone {} .".format(self.url) BashUtils.run(cmd_clone) # end with else: # Move, if has already cloned version self.logger.info(self.logger_prefix + "Already cloned to {}, moving to {}".format( self.checkout_dir, checkout_dir)) shutil.move(str(self.checkout_dir), str(checkout_dir)) # end if # Update checkout path self.checkout_dir = checkout_dir # Update repo self.update() return
def load_sample_projects_database(cls) -> List[Dict]: return IOUtils.load(cls.SAMPLE_PROJECTS_PATH)
def load_revision_result(self, revision: str, file_name: str, fmt: str = "json") -> Any: return IOUtils.load(self.get_revision_dir(revision) / file_name, fmt)
def dump_meta_result(self, file_name: str, data: Any, fmt: str = "json") -> None: IOUtils.dump(self.meta_dir / file_name, data, fmt) return
def load_meta_result(self, file_name: str, fmt: str = "json") -> Any: return IOUtils.load(self.meta_dir / file_name, fmt)