diff --git a/qutil/git.py b/qutil/git.py new file mode 100644 index 0000000000000000000000000000000000000000..c129f3b460fb440d5e85b36ab65b53395b31871f --- /dev/null +++ b/qutil/git.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +""" +Created on Mon Aug 14 18:36:43 2023 + +@author: Simon Humpohl +""" +from dataclasses import dataclass +from pathlib import Path +import logging +import tkinter +from subprocess import check_output, check_call + +try: + import git +except ImportError: + git = None + + +@dataclass +class SimpleRepo: + """Re-implementation of the GitPython functionality that we use""" + repo_path: Path + + @property + def name(self): + return self.repo_path.name + + def get_status(self) -> str: + """Returns modified/untracked files and submodules""" + check_output(['git', 'status', '--short'], cwd=self.repo_path) + + def add_all(self): + check_call(['git', 'add', '--all'], cwd=self.repo_path) + + def commit_staged_changes(self, msg): + check_call(['git', 'commit', '-m', msg], cwd=self.repo_path) + + def get_submodules(self): + sms = check_output(['git', 'submodule'], cwd=self.repo_path).splitlines() + folders = [] + for sm in sms.trim(): + hash_val, folder, *_ = sm.trim().split() + folders.append(SimpleRepo(Path(folder).absolute())) + return folders + + def current_hash(self): + raise NotImplementedError('todo') + + +def auto_commit(repo: SimpleRepo): + msg = 'Automatic commit. Lets hope this is nothing that needs explanation.' + repo.add_all() + repo.commit_staged_changes(msg) + + +def manual_commit(repo: SimpleRepo, name: str): + while status := repo.get_status(): + title = f'Manual commit: {name}' + + msg = (f'The repository {repo.name} is dirty. ' + 'Commit, ignore or stash the changes and press OK. ' + 'Pressing cancel will raise a KeyboardInterrupt.\n\n' + f'{status}') + + if not tkinter.messagebox.askokcancel(title, msg): + raise KeyboardInterrupt(name) + + +class GitRules: + auto_commit: set + auto_push: dict + + def process(self, repo: SimpleRepo): + if not repo.get_status(): + return + + for sm in repo.get_submodules(): + self.process(sm) + + if not repo.get_status(): + return + + if repo.repo_path in auto_commit: + auto_commit(repo) + else: + manual_commit(repo)