]> git.ipfire.org Git - thirdparty/bacula.git/commitdiff
update bgit.py
authorAlain Spineux <alain.spineux@baculasystems.com>
Tue, 2 Feb 2021 16:11:30 +0000 (17:11 +0100)
committerEric Bollengier <eric@baculasystems.com>
Thu, 24 Mar 2022 08:02:59 +0000 (09:02 +0100)
bacula/release/bgit.py

index 66f823ad95a601a8a3425e5e4e5a4c48e5722c54..fd965aa7e744b76157d98814e8a8946cc8997ff6 100755 (executable)
@@ -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)