diff mbox

[RFC,kteam-tools] apply-stable-patches: add option to check commits tagged with 'Fixes:'

Message ID 1424979780-11697-1-git-send-email-luis.henriques@canonical.com
State New
Headers show

Commit Message

Luis Henriques Feb. 26, 2015, 7:43 p.m. UTC
This commit adds a new option to also check for commits that have not been
tagged for stable but that contain a 'Fixes:' tag, for a SHA1 that is on
the current branch (both directly or with a 'commit <SHA1> upstream').

Note that this new option does NOT actually apply any patch!  It simply
stores them in a new directory ('Possible-Fixes').  These patches require
extra attention as are likely not suitable for stable trees.

Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
---
 stable/apply-stable-patches | 95 ++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 89 insertions(+), 6 deletions(-)

Comments

Kamal Mostafa March 4, 2015, 5:36 p.m. UTC | #1
This looks good to me, Luis.  Thanks for the new feature!

 -Kamal

On Thu, 2015-02-26 at 19:43 +0000, Luis Henriques wrote:
> This commit adds a new option to also check for commits that have not been
> tagged for stable but that contain a 'Fixes:' tag, for a SHA1 that is on
> the current branch (both directly or with a 'commit <SHA1> upstream').
> 
> Note that this new option does NOT actually apply any patch!  It simply
> stores them in a new directory ('Possible-Fixes').  These patches require
> extra attention as are likely not suitable for stable trees.
> 
> Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
> ---
>  stable/apply-stable-patches | 95 ++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 89 insertions(+), 6 deletions(-)
> 
> diff --git a/stable/apply-stable-patches b/stable/apply-stable-patches
> index 12f8376c34a0..ed3e27c3a4ad 100755
> --- a/stable/apply-stable-patches
> +++ b/stable/apply-stable-patches
> @@ -76,6 +76,12 @@ class Cmdline:
>  
>          --sob            Add 'Signed-off-by:' line to the patches
>  
> +        --check-fixes    Also check for commits that have not been tagged for stable
> +                         but that contain a 'Fixes: <SHA1>' line for a SHA1 that is
> +                         on the current branch.  A new directory ('Possible-Fixes')
> +                         will be created with these patches, but they will NOT be
> +                         applied.
> +
>          --check-already  Check for already committed ('commit {sha} upstream.')
>                           patches
>  
> @@ -118,8 +124,8 @@ class Cmdline:
>          try:
>              optsShort = ''
>              optsLong  = ['help', 'range=', 'sob', 'verbose', 'config=',
> -                         'check-already', 'stop-on-fail', 'debug=',
> -                         'name=', 'email=']
> +                         'check-already', 'stop-on-fail', 'check-fixes',
> +                          'debug=', 'name=', 'email=']
>              opts, args = getopt(argv[1:], optsShort, optsLong)
>  
>              for opt, val in opts:
> @@ -135,6 +141,9 @@ class Cmdline:
>                  elif (opt == '--check-already'):
>                      self.cfg['check_already'] = True
>  
> +                elif (opt == '--check-fixes'):
> +                    self.cfg['check_fixes'] = True
> +
>                  elif (opt == '--stop-on-fail'):
>                      self.cfg['stop_on_fail'] = True
>  
> @@ -295,6 +304,35 @@ class ApplyStablePatches(StdApp):
>                  temp = dst.name
>          rename(temp, patch)
>  
> +    # Check if we have SHA1 in the current branch
> +    def check_fix(self, sha1, branch, merge_base):
> +        # First, look for stable updates commits since the merge base:
> +        # Look for commits with "commit <SHA1> upstream." ...
> +        status, res = run_command("git log -1 --grep='^commit %s.* upstream.$' %s..HEAD" % (sha1, merge_base))
> +        if status != 0:
> +            stdo("\nError processing fix for '%s'.  Ignoring...\n" % (sha1))
> +            return False
> +        if res[0]:
> +            return True
> +
> +        # ...or "[ Upstream commit <SHA1> ]"
> +        status, res = run_command("git log --grep='^\[ Upstream commit %s.* \]$' %s..HEAD" % (sha1, merge_base))
> +        if status != 0:
> +            stdo("\nError processing fix for '%s'.  Ignoring...\n" % (sha1))
> +            return False
> +        if res[0]:
> +            return True
> +
> +        # Finally, see if it finds it in the git history (slower operation)
> +        status, res = run_command("git branch --contains %s %s" % (sha1, branch))
> +        if status != 0:
> +            stdo("\nError processing fix for '%s'.  Ignoring...\n" % (sha1))
> +            return False
> +        if branch == res[0].strip(" *"):
> +            return True
> +
> +        return False
> +
>      # main
>      #
>      def main(self):
> @@ -315,6 +353,12 @@ class ApplyStablePatches(StdApp):
>              if 'sob' not in self.cfg:
>                  raise CmdlineError('No "Signed-off-by:" given, you must specify --sob=<sob> option')
>  
> +            # get current branch name
> +            status, result = run_command("git rev-parse --abbrev-ref HEAD")
> +            if status != 0:
> +                raise GitError("\n".join(result))
> +            cur_branch = result[0].strip()
> +
>              # Fetch latest upstream changes
>              stdo("Fetching upstream commits from linux master repository...")
>              status, result = run_command("git fetch -q %s master" %
> @@ -323,6 +367,11 @@ class ApplyStablePatches(StdApp):
>              if status != 0:
>                  raise GitError("\n".join(result))
>  
> +            if 'check_already' in self.cfg or 'check_fixes' in self.cfg:
> +		status, result = run_command('git show-branch --merge-base HEAD master')
> +		if status == 0:
> +		    merge_base=result[0].strip()
> +
>              # Find commits marked for stable in the provided range, and
>              # save hints added for which versions the commit should be
>              # backported or cherry-picked
> @@ -335,7 +384,9 @@ class ApplyStablePatches(StdApp):
>              cc = 1
>              ccstable = compile(r'^\s*Cc:.*\b(stable)\b.*', IGNORECASE | MULTILINE)
>              cchint = compile(r'((?P<for>\b(for)\b)|(?P<gr>\s*>\s*)|(?P<ge>\s*>=\s*)|(\s*))(?P<v>[v]*)(?P<kver>[0-9]\.[0-9][^\s+,\]]*)(?P<plus>[+]*)[,\]]*((?P<only>[\s]+only)|(?P<later>[\s]+and later)|(\s*))')
> +            fixes = compile(r'^\s*Fixes:\s*([a-f0-9]+).*', IGNORECASE | MULTILINE)
>              forstable = []
> +            fixeslist = []
>              for c in result:
>                  stdo("\rLooking for stable commits inside provided range (%d/%d)..."
>                       % (cc, len(result)))
> @@ -358,6 +409,13 @@ class ApplyStablePatches(StdApp):
>                      if 'verbose' in self.cfg and forvers:
>                          print("")
>                      forstable.append([c, forvers])
> +                elif 'check_fixes' in self.cfg:
> +                    # search for 'Fixes: <SHA1>' lines
> +                    s = fixes.search(body)
> +                    if s:
> +                        sha1 = s.group(1)
> +                        if self.check_fix(sha1, cur_branch, merge_base):
> +                            fixeslist.append([c, sha1])
>                  cc += 1
>  
>              #stdo("\n")
> @@ -428,10 +486,6 @@ class ApplyStablePatches(StdApp):
>              if not path.exists(discarded_dir):
>                  mkdir(discarded_dir)
>              kernel = KernelVersion(Kernel().version())
> -	    if 'check_already' in self.cfg:
> -		status, result = run_command('git show-branch --merge-base HEAD master')
> -		if status == 0:
> -		    merge_base=result[0].strip()
>              for change in forstable:
>                  status, title = run_command('git log -n 1 --format=%%s %s' % (change[0]))
>                  if status != 0:
> @@ -507,6 +561,35 @@ class ApplyStablePatches(StdApp):
>                      move(filename, applied_dir)
>                  print("success")
>  
> +            if 'check_fixes' in self.cfg:
> +                stdo("\n\rPossible fixes found:\n")
> +                fixes_dir = 'Possible-Fixes'
> +                if not path.exists(fixes_dir):
> +                    mkdir(fixes_dir)
> +
> +                for change in fixeslist:
> +                    status, title = run_command('git log -n 1 --format=%%s %s' % (change[0]))
> +                    if status != 0:
> +                        eout(result)
> +                        continue
> +                    print('Commit "%s" fixes %s' % (title[0], change[1]))
> +                    status, result = run_command('git format-patch -k %s^..%s' % (change[0], change[0]))
> +                    if status != 0:
> +                        eout(result)
> +                        continue
> +                    filename = result[0]
> +                    short_sha_pfx = '%s-' % change[0][:8]
> +                    newfilename = filename.replace('0001-', short_sha_pfx, 1)
> +                    rename(filename, newfilename)
> +                    filename = newfilename
> +
> +                    fixes_file = '%s/%s' % (fixes_dir, filename)
> +                    if path.exists(fixes_file):
> +                        remove(filename)
> +                        continue
> +                    self.modify_patch(filename, change[0], self.cfg['sob'], ccstable)
> +                    move(filename, fixes_file)
> +
>          # Handle the user presses <ctrl-C>.
>          #
>          except KeyboardInterrupt:
Luis Henriques March 4, 2015, 5:45 p.m. UTC | #2
Cheers,
--
Luís
diff mbox

Patch

diff --git a/stable/apply-stable-patches b/stable/apply-stable-patches
index 12f8376c34a0..ed3e27c3a4ad 100755
--- a/stable/apply-stable-patches
+++ b/stable/apply-stable-patches
@@ -76,6 +76,12 @@  class Cmdline:
 
         --sob            Add 'Signed-off-by:' line to the patches
 
+        --check-fixes    Also check for commits that have not been tagged for stable
+                         but that contain a 'Fixes: <SHA1>' line for a SHA1 that is
+                         on the current branch.  A new directory ('Possible-Fixes')
+                         will be created with these patches, but they will NOT be
+                         applied.
+
         --check-already  Check for already committed ('commit {sha} upstream.')
                          patches
 
@@ -118,8 +124,8 @@  class Cmdline:
         try:
             optsShort = ''
             optsLong  = ['help', 'range=', 'sob', 'verbose', 'config=',
-                         'check-already', 'stop-on-fail', 'debug=',
-                         'name=', 'email=']
+                         'check-already', 'stop-on-fail', 'check-fixes',
+                          'debug=', 'name=', 'email=']
             opts, args = getopt(argv[1:], optsShort, optsLong)
 
             for opt, val in opts:
@@ -135,6 +141,9 @@  class Cmdline:
                 elif (opt == '--check-already'):
                     self.cfg['check_already'] = True
 
+                elif (opt == '--check-fixes'):
+                    self.cfg['check_fixes'] = True
+
                 elif (opt == '--stop-on-fail'):
                     self.cfg['stop_on_fail'] = True
 
@@ -295,6 +304,35 @@  class ApplyStablePatches(StdApp):
                 temp = dst.name
         rename(temp, patch)
 
+    # Check if we have SHA1 in the current branch
+    def check_fix(self, sha1, branch, merge_base):
+        # First, look for stable updates commits since the merge base:
+        # Look for commits with "commit <SHA1> upstream." ...
+        status, res = run_command("git log -1 --grep='^commit %s.* upstream.$' %s..HEAD" % (sha1, merge_base))
+        if status != 0:
+            stdo("\nError processing fix for '%s'.  Ignoring...\n" % (sha1))
+            return False
+        if res[0]:
+            return True
+
+        # ...or "[ Upstream commit <SHA1> ]"
+        status, res = run_command("git log --grep='^\[ Upstream commit %s.* \]$' %s..HEAD" % (sha1, merge_base))
+        if status != 0:
+            stdo("\nError processing fix for '%s'.  Ignoring...\n" % (sha1))
+            return False
+        if res[0]:
+            return True
+
+        # Finally, see if it finds it in the git history (slower operation)
+        status, res = run_command("git branch --contains %s %s" % (sha1, branch))
+        if status != 0:
+            stdo("\nError processing fix for '%s'.  Ignoring...\n" % (sha1))
+            return False
+        if branch == res[0].strip(" *"):
+            return True
+
+        return False
+
     # main
     #
     def main(self):
@@ -315,6 +353,12 @@  class ApplyStablePatches(StdApp):
             if 'sob' not in self.cfg:
                 raise CmdlineError('No "Signed-off-by:" given, you must specify --sob=<sob> option')
 
+            # get current branch name
+            status, result = run_command("git rev-parse --abbrev-ref HEAD")
+            if status != 0:
+                raise GitError("\n".join(result))
+            cur_branch = result[0].strip()
+
             # Fetch latest upstream changes
             stdo("Fetching upstream commits from linux master repository...")
             status, result = run_command("git fetch -q %s master" %
@@ -323,6 +367,11 @@  class ApplyStablePatches(StdApp):
             if status != 0:
                 raise GitError("\n".join(result))
 
+            if 'check_already' in self.cfg or 'check_fixes' in self.cfg:
+		status, result = run_command('git show-branch --merge-base HEAD master')
+		if status == 0:
+		    merge_base=result[0].strip()
+
             # Find commits marked for stable in the provided range, and
             # save hints added for which versions the commit should be
             # backported or cherry-picked
@@ -335,7 +384,9 @@  class ApplyStablePatches(StdApp):
             cc = 1
             ccstable = compile(r'^\s*Cc:.*\b(stable)\b.*', IGNORECASE | MULTILINE)
             cchint = compile(r'((?P<for>\b(for)\b)|(?P<gr>\s*>\s*)|(?P<ge>\s*>=\s*)|(\s*))(?P<v>[v]*)(?P<kver>[0-9]\.[0-9][^\s+,\]]*)(?P<plus>[+]*)[,\]]*((?P<only>[\s]+only)|(?P<later>[\s]+and later)|(\s*))')
+            fixes = compile(r'^\s*Fixes:\s*([a-f0-9]+).*', IGNORECASE | MULTILINE)
             forstable = []
+            fixeslist = []
             for c in result:
                 stdo("\rLooking for stable commits inside provided range (%d/%d)..."
                      % (cc, len(result)))
@@ -358,6 +409,13 @@  class ApplyStablePatches(StdApp):
                     if 'verbose' in self.cfg and forvers:
                         print("")
                     forstable.append([c, forvers])
+                elif 'check_fixes' in self.cfg:
+                    # search for 'Fixes: <SHA1>' lines
+                    s = fixes.search(body)
+                    if s:
+                        sha1 = s.group(1)
+                        if self.check_fix(sha1, cur_branch, merge_base):
+                            fixeslist.append([c, sha1])
                 cc += 1
 
             #stdo("\n")
@@ -428,10 +486,6 @@  class ApplyStablePatches(StdApp):
             if not path.exists(discarded_dir):
                 mkdir(discarded_dir)
             kernel = KernelVersion(Kernel().version())
-	    if 'check_already' in self.cfg:
-		status, result = run_command('git show-branch --merge-base HEAD master')
-		if status == 0:
-		    merge_base=result[0].strip()
             for change in forstable:
                 status, title = run_command('git log -n 1 --format=%%s %s' % (change[0]))
                 if status != 0:
@@ -507,6 +561,35 @@  class ApplyStablePatches(StdApp):
                     move(filename, applied_dir)
                 print("success")
 
+            if 'check_fixes' in self.cfg:
+                stdo("\n\rPossible fixes found:\n")
+                fixes_dir = 'Possible-Fixes'
+                if not path.exists(fixes_dir):
+                    mkdir(fixes_dir)
+
+                for change in fixeslist:
+                    status, title = run_command('git log -n 1 --format=%%s %s' % (change[0]))
+                    if status != 0:
+                        eout(result)
+                        continue
+                    print('Commit "%s" fixes %s' % (title[0], change[1]))
+                    status, result = run_command('git format-patch -k %s^..%s' % (change[0], change[0]))
+                    if status != 0:
+                        eout(result)
+                        continue
+                    filename = result[0]
+                    short_sha_pfx = '%s-' % change[0][:8]
+                    newfilename = filename.replace('0001-', short_sha_pfx, 1)
+                    rename(filename, newfilename)
+                    filename = newfilename
+
+                    fixes_file = '%s/%s' % (fixes_dir, filename)
+                    if path.exists(fixes_file):
+                        remove(filename)
+                        continue
+                    self.modify_patch(filename, change[0], self.cfg['sob'], ccstable)
+                    move(filename, fixes_file)
+
         # Handle the user presses <ctrl-C>.
         #
         except KeyboardInterrupt: