From: Alain Spineux Date: Tue, 2 Feb 2021 16:11:30 +0000 (+0100) Subject: update bgit.py X-Git-Tag: Release-11.3.2~760 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cf66fb0ae3c46146ecffefb7d45b1973911ca3d5;p=thirdparty%2Fbacula.git update bgit.py --- diff --git a/bacula/release/bgit.py b/bacula/release/bgit.py index 66f823ad9..fd965aa7e 100755 --- a/bacula/release/bgit.py +++ b/bacula/release/bgit.py @@ -1,6 +1,8 @@ #!/usr/bin/env python2 +# -*- coding: utf-8 -* # this program compare two branche of GIT # and show the differences +from __future__ import print_function import sys import os import logging @@ -8,6 +10,8 @@ import collections import re import argparse import time +import codecs +import difflib try: import git @@ -19,7 +23,7 @@ except ImportError: def add_console_logger(): console=logging.StreamHandler() console.setFormatter(logging.Formatter('%(levelname)-3.3s %(filename)s:%(lineno)d %(message)s', '%H:%M:%S')) - console.setLevel(logging.DEBUG) # must be INFO for prod + console.setLevel(logging.INFO) # must be INFO for prod logging.getLogger().addHandler(console) return console @@ -27,44 +31,109 @@ def add_file_logger(filename): filelog=logging.FileHandler(filename) # %(asctime)s '%Y-%m-%d %H:%M:%S' filelog.setFormatter(logging.Formatter('%(asctime)s %(levelname)-3.3s %(filename)s:%(lineno)d %(message)s', '%H:%M:%S')) - filelog.setLevel(logging.DEBUG) + filelog.setLevel(logging.INFO) logging.getLogger().addHandler(filelog) return filelog -def run_cmp_branch(repo, args): - print args.branch1 - print args.branch2 +def run_cmp_branch(args): + repo=args.repo + if args.switch: + args.branch1, args.branch2=args.branch2, args.branch1 + if args.short_legend: + print("=== Compare branch %(branch1)s and %(branch2)s" % + dict(branch1=args.branch1, branch2=args.branch2)) + elif not args.no_legend: + print(cmp_branch_legend % dict(branch1=args.branch1, branch2=args.branch2)) # for commit in repo.iter_commits(args.branch1, max_count=10): # print commit.hexsha, commit.committed_date, commit.author.name, commit.message # print dir(repo) commons=repo.merge_base(args.branch1, args.branch2) if len(commons)!=1: - print "cannot find the unique common commit between", args.branch1, args.branch2 + print("cannot find the unique common commit between", args.branch1, args.branch2) common=commons[0] # make a list of all know commit in branch-2 - commits2=set() + commits2=set() # (authored_date, author_name, subject) + commits2b=set() # (author_name, subject) to detect modified patch + commits2m=dict() # (authored_date, author_name) to detect modified message for commit in repo.iter_commits(args.branch2): if commit.hexsha==common.hexsha: break subject=commit.message.split('\n', 1)[0] commits2.add((commit.authored_date, commit.author.name, subject)) - #print commit.committed_date, commit.author.name, subject + commits2b.add((commit.author.name, subject)) + commits2m[(commit.authored_date, commit.author.name)]=(subject, commit.hexsha[:8]) + #print(commit.committed_date, commit.author.name, subject) - # list and compare with commits of branch-& + # list and compare with commits of branch-1 for commit in repo.iter_commits(args.branch1): if commit.hexsha==common.hexsha: break subject=commit.message.split('\n', 1)[0] date=time.strftime("%Y-%m-%d %H:%M", time.gmtime(commit.authored_date)) + line='%s %s %s' % (date, commit.author.name, subject) + alt_subject, alt_sha=None, None + if args.sha: + line='%s %s' % (commit.hexsha[:8], line) if (commit.authored_date, commit.author.name, subject) in commits2: - print "=", date, commit.author.name, subject + prefix='=' + elif (commit.author.name, subject) in commits2b: + prefix='~' + elif (commit.authored_date, commit.author.name) in commits2m: + prefix='§' + alt_subject, alt_sha=commits2m[(commit.authored_date, commit.author.name)] else: - print "+", date, commit.author.name, subject + prefix='+' + print(prefix, codecs.encode(line, 'ascii', 'replace')) + if prefix=='§': + line2='%s%s %s %s' % ((alt_sha+' ' if args.sha else ''), ' '*len(date), commit.author.name, alt_subject) + print(prefix, codecs.encode(line2, 'ascii', 'replace')) + +def print_prefix(prefix, content): + for n, line in enumerate(content): + print('%s:%04d %s' % (prefix, n, line)) + +def resolve_cherry_pick(args): + repo=args.repo + git_dir=repo.git_dir + args.orig_head=os.path.join(git_dir, 'ORIG_HEAD') + cherry_pick_head=open(args.cherry_pick_head).read().rstrip() + orig_head=open(args.orig_head).read().rstrip() + print('You are trying to apply commit (C) %s on top of commit (O) %s' % (cherry_pick_head, orig_head)) + index=repo.index + print('The conflicting files are:') + for i, blob in enumerate(index.unmerged_blobs()): + print('%d: %s' % (i, blob, )) + print('Display files content (M = conflicting commit, C = cherry-pick, O = original):') + for i, blob in enumerate(index.unmerged_blobs()): + # index.unmerged_blobs()[blob][0] is the cherry-pick version before the conflicting commit + # index.unmerged_blobs()[blob][1] is the orig version version (before the conflicting commit) + # index.unmerged_blobs()[blob][2] is the cherry-pick version after the commit + fromlines=index.unmerged_blobs()[blob][0][1].data_stream.read().split('\n') + tolines=index.unmerged_blobs()[blob][2][1].data_stream.read().split('\n') + diff = difflib.unified_diff(fromlines, tolines, blob, blob, n=5) + for line in diff: + print('%d:M %s' % (i, line.rstrip())) + print_prefix('%d:C' % (i,), index.unmerged_blobs()[blob][2][1].data_stream.read().split('\n')) + print_prefix('%d:O' % (i,), index.unmerged_blobs()[blob][1][1].data_stream.read().split('\n')) + # + continue + for j, item in enumerate(index.unmerged_blobs()[blob]): + print(j, item[0], item[1].path) + print(len(item[1].data_stream.read().split('\n'))) + open('/tmp/bgit.%d' % (item[0], ), 'w').write(item[1].data_stream.read()) +# for line in item[1].data_stream.read().split('\n'): +# print(line) + +def run_res_conflict(args): + args.cherry_pick_head=os.path.join(args.repo.git_dir, 'CHERRY_PICK_HEAD') + if os.path.isfile(args.cherry_pick_head): + return resolve_cherry_pick(args) + print('Not a cherry-pick issue! Sorry only cherry-pick is supported for now.', file=sys.stderr) mainparser=argparse.ArgumentParser(description='git utility for bacula') subparsers=mainparser.add_subparsers(dest='command', metavar='', title='valid commands') @@ -72,10 +141,39 @@ subparsers=mainparser.add_subparsers(dest='command', metavar='', title='valid co git_parser=argparse.ArgumentParser(add_help=False) git_parser.add_argument('--git_dir', metavar='GIT-DIR', type=str, default='.', help='the directory with the .git sub dir') -parser=subparsers.add_parser('cmp_branch', parents=[git_parser, ], help='compare two branches, highligh commits missing in the second branch') - +cmp_branch_description="""Compare two branches given in the arguments. +Display all commits of the first branch starting from the node common to both +branches. +Commits that are in both branches with the same authored_date, author_name +and subject are prefixed with a '='. +Commits that are in both branches but with a different authored_date +are prefixed with a '~'. +Commits that have the same author_name and authored_date but a different subject +are prefixed with a '&' and both subject are shown. +Other commit are prefixed with a '+' that means that it was not found in +the second branch and could be added.""" + +cmp_branch_legend="""= Commits that are in both branches with the same authored_date, author_name and subject +~ Commits that are in both branches but with a different authored_date +& Commits that are in both branches with the same authored_date, author_name but with a subject that is different ++ Commits are in %(branch1)s but not in %(branch2)s +""" + +parser=subparsers.add_parser('cmp_branch', description=cmp_branch_description, parents=[git_parser, ], + help='compare two branches, highligh commits missing in the second branch') + +parser.add_argument('--switch', action='store_true', help='switch the two BRANCH parameters to ease use of xargs') +parser.add_argument('--sha', action='store_true', help='display the short sha1 of the commit') +parser.add_argument('--no-legend', action='store_true', help='don''t display the legend') +parser.add_argument('--short-legend', action='store_true', help='don''t display the legend') parser.add_argument('branch1', metavar='BRANCH-1', help='the first branch') parser.add_argument('branch2', metavar='BRANCH-2', help='the second branch') +parser.set_defaults(func=run_cmp_branch) + +res_conflict_legend="""description of res_conflict""" +parser=subparsers.add_parser('res_conflict', description=cmp_branch_description, parents=[git_parser, ], + help='help resolve conflic in the current branch') +parser.set_defaults(func=run_res_conflict) args=mainparser.parse_args() @@ -83,8 +181,8 @@ args=mainparser.parse_args() logging.getLogger().setLevel(logging.DEBUG) add_console_logger() -print args.git_dir -print "logging into gitstat.log" +#print args.git_dir +#print "logging into gitstat.log" add_file_logger('gitstat.log') # search the git repo @@ -94,7 +192,6 @@ if args.git_dir: path=os.getcwd() while path and not os.path.isdir(os.path.join(path, '.git')): path=os.path.dirname(path) - print path if path and os.path.isdir(os.path.join(path, '.git')): try: @@ -112,6 +209,6 @@ if args.git_dir: except git.exc.InvalidGitRepositoryError: parser.error("git repository not found in %s" % (args.git_dir,)) -if args.command=='cmp_branch': - run_cmp_branch(repo, args) +args.repo=repo +args.func(args)