From ba46ead395c992e66c23d1b083edfe4db5086818 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Mon, 14 Nov 2016 11:34:57 +0100 Subject: git-qt-merge-mainlines: find related changes for conflicts Only shows author date instead of commit date for changes. And better to make sure rerere.enabled is disabled when analyzing the conflicts. Change-Id: I4268b55efb39cc94572117e46686cd5eaa6233c6 Reviewed-by: Edward Welbourne Reviewed-by: Frederik Gladhorn --- bin/git-qt-merge-mainlines | 61 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'bin') diff --git a/bin/git-qt-merge-mainlines b/bin/git-qt-merge-mainlines index 6e07b1d..4ade789 100755 --- a/bin/git-qt-merge-mainlines +++ b/bin/git-qt-merge-mainlines @@ -15,6 +15,7 @@ import sys import logging import subprocess import re +import warnings fnull = open(os.devnull, "w") @@ -26,6 +27,63 @@ class colors: FAIL = '\033[91m' ENDC = '\033[0m' +class BlameParser: + __begin = ('<' * 7, '=' * 7) + __end_map = {'merge': '=', 'diff3': '|'} + # One example line to parse (result from git blame -c --date=short): + # "ddd8ab31 (Andras Becsi 2014-06-13 18:17:07 +0200 414)bool GLSurface::InitializeOneOffInternal()" + __matcher = re.compile(r"([0-9a-f]+)\s+\((.*?)\s+\d+\)(.*)").match + + def __init__(self): + self.__end = (self.__from_git_config('merge.conflictstyle', 'merge', self.__end_map) * 7, '>' * 7) + + def __from_git_config(self, parameter, default, mapping): + try: + value = subprocess.check_output(['git', 'config', parameter]).decode('utf-8').strip() + except subprocess.CalledProcessError: + # When the value is unset + value = '' + try: + return mapping[value or default] + except KeyError: + raise ValueError('Unknown git config', parameter, value) + + def __parse_blame_line(self, codeline): + # Match a "git blame -c --date=short" output line + m = self.__matcher(codeline) + if m: + return m.group(1, 2, 3) + raise ValueError("Failed to parse blame line: %s" % (codeline)) + + def __get_blame_results(self, conflict): + cmd_git_blame = ["git", "blame", "-c", "--date=short", conflict] + blame_output = subprocess.check_output(cmd_git_blame).decode('utf-8') + return blame_output.split('\n') + + def parse(self, conflict): + results, scan = {}, False + for line in self.__get_blame_results(conflict): + if not line.strip(): + continue + sha1, info, code = self.__parse_blame_line(line) + if any(code.startswith(b) for b in self.__begin): + scan = True + continue + if any(code.startswith(e) for e in self.__end): + scan = False + if scan: + results[sha1] = info + + return results.items() + +# Try to find related commits for the conflicts +def check_conflicts(module, config, from_ref, conflicts): + results = '' + blameparser = BlameParser() + for conflict in conflicts: + changes = blameparser.parse(conflict) + results += conflict + ':\n\t' + '\n\t'.join('%s %s' %c for c in changes) + '\n' + return results # Replace all occurrences of searchExp in one file def replaceInFile(file, searchExp, replaceExp): @@ -108,6 +166,9 @@ def wip_merge(module, config, from_ref): git_amend = "git commit --amend --no-edit" subprocess.check_call(git_amend.split(), stdout=fnull) + related = check_conflicts(module, config, from_ref, conflicts) + print("Related: ", related) + except Exception as e: logging.error("Create WIP change failed: %s", str(e)) return False -- cgit v1.2.3