def undo(self, ch_id, user): """ ch_id: change-id user: user of this request Undo a change # ToDo a revert option, which removes only that commit's change """ ch = Change.query.filter_by(id=ch_id).first() if not self.is_admin(user.id, ch.op_id) and not self.is_creator( user.id, ch.op_id): return False if ch is None: return False operation = Operation.query.filter_by(id=ch.op_id).first() if not ch or not operation: return False operation_path = fs.path.join(self.data_dir, operation.path) repo = git.Repo(operation_path) repo.git.clear_cache() try: file_content = repo.git.show(f'{ch.commit_hash}:main.ftml') with fs.open_fs(operation_path) as proj_fs: proj_fs.writetext('main.ftml', file_content) repo.index.add(['main.ftml']) cm = repo.index.commit(f"checkout to {ch.commit_hash}") change = Change(ch.op_id, user.id, cm.hexsha) db.session.add(change) db.session.commit() return True except Exception as ex: logging.debug(ex) return False
def save_file(self, p_id, content, user, comment=""): """ p_id: project-id, content: content of the file to be saved # ToDo save change in schema """ project = Project.query.filter_by(id=p_id).first() if not project: return False with fs.open_fs(self.data_dir) as data: """ old file is read, the diff between old and new is calculated and stored as 'Change' in changes table. comment for each change is optional """ old_data = data.readtext(fs.path.combine(project.path, 'main.ftml')) old_data_lines = old_data.splitlines() content_lines = content.splitlines() diff = difflib.unified_diff(old_data_lines, content_lines, lineterm='') diff_content = '\n'.join(list(diff)) data.writetext(fs.path.combine(project.path, 'main.ftml'), content) # commit changes if comment is not None if diff_content != "": # commit to git repository project_path = fs.path.combine(self.data_dir, project.path) repo = git.Repo(project_path) repo.git.clear_cache() repo.index.add(['main.ftml']) cm = repo.index.commit("committing changes") # change db table change = Change(p_id, user.id, cm.hexsha) db.session.add(change) db.session.commit() return True return False
def test_change_content(self): with self.app.app_context(): p_id = get_recent_pid(self.fm, self.user) ch = Change(int(p_id), 8, "", "Version changed", "some comment") db.session.add(ch) db.session.commit() data = {"token": self.token, "p_id": p_id} get_proj_url = url_join(self.url, 'get_project_by_id') res = requests.get(get_proj_url, data=data) content = json.loads(res.text)["content"] change = Change.query.order_by(Change.created_at.desc()).first() data = {"token": self.token, "ch_id": change.id} get_change_content_url = url_join(self.url, 'get_change_content') res = requests.get(get_change_content_url, data=data).json() change_content = res["content"] assert content.strip() == change_content.strip()
def test_change(self): """ since file needs to be saved to inflict changes, changes during integration tests have to be manually inserted """ with self.app.app_context(): p_id = get_recent_pid(self.fm, self.user) ch = Change(int(p_id), 8, "", "Version1", "some comment") db.session.add(ch) db.session.commit() data = {"token": self.token, "p_id": p_id} # test 'get all changes' request url = url_join(self.url, 'get_all_changes') r = requests.get(url, data=data) changes = json.loads(r.text)["changes"] assert len(changes) == 1 assert changes[0]["comment"] == "some comment"
def test_set_version_name(self): with self.app.app_context(): p_id = int(get_recent_pid(self.fm, self.user)) ch = Change(int(p_id), 8, "", "Version changed", "some comment") db.session.add(ch) db.session.commit() change = Change.query.filter_by(p_id=p_id).order_by( Change.created_at.desc()).first() data = { "token": self.token, "ch_id": change.id, "p_id": p_id, "version_name": "Test Version Name" } url = url_join(self.url, 'set_version_name') res = requests.post(url, data=data).json() assert res["success"] is True with self.app.app_context(): change = Change.query.filter_by(id=change.id).first() assert change.version_name == "Test Version Name"