From c9b7d95a83672db9e8c038947ecbe15a167f045b Mon Sep 17 00:00:00 2001 From: mike cullerton Date: Fri, 28 Jan 2022 16:11:36 -0500 Subject: [PATCH] *** WIP *** Beginning of Git integration - added gitpython to Pipfile - started additions for api, model, service, and a test --- Pipfile | 1 + config/default.py | 7 ++++ crc/api.yml | 25 ++++++++++++++ crc/api/git_repo.py | 10 ++++++ crc/models/git_models.py | 34 +++++++++++++++++++ crc/services/git_service.py | 68 +++++++++++++++++++++++++++++++++++++ tests/test_git_service.py | 14 ++++++++ 7 files changed, 159 insertions(+) create mode 100644 crc/api/git_repo.py create mode 100644 crc/models/git_models.py create mode 100644 crc/services/git_service.py create mode 100644 tests/test_git_service.py diff --git a/Pipfile b/Pipfile index 9400d822..330ed968 100644 --- a/Pipfile +++ b/Pipfile @@ -43,6 +43,7 @@ werkzeug = "*" xlrd = "*" xlsxwriter = "*" pygithub = "*" +gitpython = "*" apscheduler = "*" connexion = {extras = [ "swagger-ui",], version = "*"} sentry-sdk = {extras = [ "flask",], version = "==0.14.4"} diff --git a/config/default.py b/config/default.py index 22ab87f1..a3b0b731 100644 --- a/config/default.py +++ b/config/default.py @@ -78,6 +78,13 @@ GITHUB_TOKEN = environ.get('GITHUB_TOKEN', None) GITHUB_REPO = environ.get('GITHUB_REPO', None) TARGET_BRANCH = environ.get('TARGET_BRANCH', None) +# Git settings, used by git_service +# The above Github settings--used in file_service, will likely be deprecated +# You can override these settings in instance/config +GIT_REMOTE = environ.get('GIT_REMOTE', None) +GIT_BRANCH = environ.get('GIT_BRANCH', None) +GIT_MERGE_BRANCH = environ.get('GIT_MERGE_BRANCH', None) # Developers can set this to 'all' in instance.config + # Email configuration DEFAULT_SENDER = 'uvacrconnect@virginia.edu' FALLBACK_EMAILS = ['askresearch@virginia.edu', 'sartographysupport@googlegroups.com'] diff --git a/crc/api.yml b/crc/api.yml index dca1a498..4cd55c39 100755 --- a/crc/api.yml +++ b/crc/api.yml @@ -1842,6 +1842,20 @@ paths: schema: $ref: "#/components/schemas/DataStore" + /git_repo: + get: + operationId: crc.api.git_repo.get_repo + summary: get current state of the git repo + tags: + - Git Repo + responses: + '200': + description: Current state of the git repo + content: + application/json: + schema: + $ref: "#/components/schemas/GitRepo" + components: securitySchemes: jwt: @@ -2527,3 +2541,14 @@ components: type: number format: integer example: 5 + GitRepo: + properties: + remote: + type: string + example: sartography/crconnect-workflow-specs + directory: + type: string + example: /home/cr-connect/sync_files + branch: + type: string + example: dev diff --git a/crc/api/git_repo.py b/crc/api/git_repo.py new file mode 100644 index 00000000..b49dae07 --- /dev/null +++ b/crc/api/git_repo.py @@ -0,0 +1,10 @@ +def get_repo(): + pass + + +def set_repo_branch(): + pass + + +def commit_repo_changes(): + pass diff --git a/crc/models/git_models.py b/crc/models/git_models.py new file mode 100644 index 00000000..71234301 --- /dev/null +++ b/crc/models/git_models.py @@ -0,0 +1,34 @@ +from crc import app, ma + + +class GitRepo(object): + # @classmethod + # def from_models(cls, model: FileModel, data_model, doc_dictionary): + # instance = cls() + # instance.id = model.id + + @classmethod + def from_repo(cls, repo): + instance = cls() + instance.directory = repo.working_dir + instance.branch = repo.active_branch + instance.merge_branch = app.config['GIT_MERGE_BRANCH'] + # instance.user = + # instance.changes = [item.a_path for item in repo.index.diff(None)] + # instance.untracked = + + +class GitCommit(object): + pass + + +class GitRepoSchema(ma.Schema): + class Meta: + model = GitRepo + fields = ["directory", "branch"] + + +class GitCommitSchema(ma.Schema): + class Meta: + model = GitCommit + fields = ["message", "files"] diff --git a/crc/services/git_service.py b/crc/services/git_service.py new file mode 100644 index 00000000..efe995c9 --- /dev/null +++ b/crc/services/git_service.py @@ -0,0 +1,68 @@ +from crc import app +from git import Repo, InvalidGitRepositoryError, NoSuchPathError + + +class GitService(object): + + @staticmethod + def get_repo(directory): + repo = None + try: + repo = Repo(directory) + except InvalidGitRepositoryError as ge: + # Thrown if the given repository appears to have an invalid format. + # TODO: I believe this means there is no .git directory + # So, git init? + print(ge) + except NoSuchPathError as pe: + # TODO: clone from remote? + print(pe) + except Exception as e: + print(e) + return repo + + def push_to_remote(self, comment): + directory = app.config['SYNC_FILE_ROOT'] + repo = self.get_repo(directory) + # get list of changed files + changes = [item.a_path for item in repo.index.diff(None)] + # get list of untracked files + untracked_files = repo.untracked_files + branches = self.get_branches(repo) + for branch in branches: + if branch != repo.active_branch: + print(f'Branch: {branch}') + diff = repo.git.diff(branch.name) + print('##########') + print('##########') + print('##########') + print(diff) + continue + + repo.index.add(changes) + repo.index.add(untracked_files) + # repo.index.commit(comment) + # repo.remotes.origin.push() + + print(repo) + return repo + + @staticmethod + def pull_from_remote(repo, branch): + repo.git.checkout(branch) + repo.remotes.origin.pull() + print(repo) + return repo + + @staticmethod + def compare_with_branch(repo, branch): + diff = repo.git.diff(branch) + return diff + + @staticmethod + def get_branches(repo): + branches = [] + refs = repo.remote().refs + for ref in refs: + branches.append(ref) + return branches diff --git a/tests/test_git_service.py b/tests/test_git_service.py new file mode 100644 index 00000000..52de6d1f --- /dev/null +++ b/tests/test_git_service.py @@ -0,0 +1,14 @@ +from tests.base_test import BaseTest + +from crc.services.git_service import GitService + + +# class TestGitService(BaseTest): + + # def test_push_to_remote(self): + # result = GitService().push_to_remote() + # print(result) + # + # def test_pull_from_remote(self): + # result = GitService.pull_from_remote() + # print(result)