[patch 01/11] Fix typo: comitter->committer

Subsystems: the rest

DORMANTno replies

12 messages, 2 authors, 2016-06-15 · open the first message on its own page

[patch 01/11] Fix typo: comitter->committer

From: Paolo 'Blaisorblade' Giarrusso <hidden>
Date: 2016-06-15 22:42:06

Found casually in commit.__init__, while profiling stg series.
And yes, I went checking that git has no typo.

Signed-off-by: Paolo 'Blaisorblade' Giarrusso <redacted>
---

 stgit/git.py |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/stgit/git.py b/stgit/git.py
--- a/stgit/git.py
+++ b/stgit/git.py
@@ -56,7 +56,7 @@ class Commit:
                 self.__parent = field[1]
             if field[0] == 'author':
                 self.__author = field[1]
-            if field[0] == 'comitter':
+            if field[0] == 'committer':
                 self.__committer = field[1]
         self.__log = ''.join(lines[i:])
 

[patch 02/11] Make "empty patch" checking optional in "series" command.

From: Paolo 'Blaisorblade' Giarrusso <hidden>
Date: 2016-06-15 22:42:06

That's just too slow, and quilt doesn't do it, so user will live with it.
Don't know if there's a reason to allow dropping the fanciness here
entirely, but I think there's no user doing one-liner scripts with quilt
series. And anyway, for that you can do "stg applied; stg unapplied".

Actually, with this patch you must ask explicitly the checking.

Signed-off-by: Paolo 'Blaisorblade' Giarrusso <redacted>
---

 stgit/commands/series.py |   11 +++++++----
 1 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/stgit/commands/series.py b/stgit/commands/series.py
--- a/stgit/commands/series.py
+++ b/stgit/commands/series.py
@@ -31,7 +31,10 @@ Show all the patches in the series. The 
 with a '+' and the unapplied ones with a '-'. The current patch is
 prefixed with a '>'. Empty patches are prefixed with a '0'."""
 
-options = []
+options = [make_option('-e', '--empty',
+                       help = 'check whether patches are empty '
+                       '(much slower)',
+                       action = 'store_true') ]
 
 
 def func(parser, options, args):
@@ -43,19 +46,19 @@ def func(parser, options, args):
     applied = crt_series.get_applied()
     if len(applied) > 0:
         for p in applied [0:-1]:
-            if crt_series.empty_patch(p):
+            if options.empty and crt_series.empty_patch(p):
                 print '0', p
             else:
                 print '+', p
         p = applied[-1]
 
-        if crt_series.empty_patch(p):
+        if options.empty and crt_series.empty_patch(p):
             print '0>%s' % p
         else:
             print '> %s' % p
 
     for p in crt_series.get_unapplied():
-        if crt_series.empty_patch(p):
+        if options.empty and crt_series.empty_patch(p):
             print '0', p
         else:
             print '-', p

[patch 04/11] Fix "mail" command when description contains "From" lines

From: Paolo 'Blaisorblade' Giarrusso <hidden>
Date: 2016-06-15 22:42:06

For kernel patches, the "From" line from the email is often preserved in
the patch itself, and the one from the email is sometimes lost, so I add an
explicit one. And mail barfes on this.
Fix it up.

Signed-off-by: Paolo 'Blaisorblade' Giarrusso <redacted>
---

 stgit/commands/mail.py |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/stgit/commands/mail.py b/stgit/commands/mail.py
--- a/stgit/commands/mail.py
+++ b/stgit/commands/mail.py
@@ -122,7 +122,7 @@ def __parse_addresses(string):
         elif re.match('(to|cc|bcc):\s+', line, re.I):
             to_addr_list += __addr_list(line)
 
-    if len(from_addr_list) != 1:
+    if len(from_addr_list) == 0:
         raise CmdException, 'No "From" address'
     if len(to_addr_list) == 0:
         raise CmdException, 'No "To/Cc/Bcc" addresses'

[patch 03/11] stg diff / files: don't update directory cache unless needed

From: Paolo 'Blaisorblade' Giarrusso <hidden>
Date: 2016-06-15 22:42:06

Do git-update-cache only when diffing with the working tree, not otherwise.
Spending something like 1min for a stg files is bad - yes, my laptop
was really busy and the Linux tree was probably cache-cold, but that's just
not needed.

Also, in diffstat we currently do it both by hand and by calling git.diff.
And in files there's no need at all for that - even the comments says that
"files" has only to do with committed changes.

Signed-off-by: Paolo 'Blaisorblade' Giarrusso <redacted>
---

 stgit/git.py |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)
diff --git a/stgit/git.py b/stgit/git.py
--- a/stgit/git.py
+++ b/stgit/git.py
@@ -376,11 +376,11 @@ def status(files = [], modified = False,
 def diff(files = [], rev1 = 'HEAD', rev2 = None, out_fd = None):
     """Show the diff between rev1 and rev2
     """
-    os.system('git-update-cache --refresh > /dev/null')
 
     if rev2:
         diff_str = _output(['git-diff-tree', '-p', rev1, rev2] + files)
     else:
+        os.system('git-update-cache --refresh > /dev/null')
         diff_str = _output(['git-diff-cache', '-p', rev1] + files)
 
     if out_fd:
@@ -392,7 +392,6 @@ def diffstat(files = [], rev1 = 'HEAD', 
     """Return the diffstat between rev1 and rev2
     """
 
-    os.system('git-update-cache --refresh > /dev/null')
     p=popen2.Popen3('git-apply --stat')
     diff(files, rev1, rev2, p.tochild)
     p.tochild.close()
@@ -404,7 +403,6 @@ def diffstat(files = [], rev1 = 'HEAD', 
 def files(rev1, rev2):
     """Return the files modified between rev1 and rev2
     """
-    os.system('git-update-cache --refresh > /dev/null')
 
     str = ''
     for line in _output_lines('git-diff-tree -r %s %s' % (rev1, rev2)):

[patch 11/11] Detect description in quilt patches

From: Paolo 'Blaisorblade' Giarrusso <hidden>
Date: 2016-06-15 22:42:06

From: Paolo 'Blaisorblade' Giarrusso <redacted>

The current logic imports the whole quilt patch as description - the changes
themselves are correctly applied, luckily, but the description must be fixed up
by hand.
So, detect "Index: " lines as patch start. I've heard rumors that also
Subversion generates this format, so we become compatible with it, too.

Signed-off-by: Paolo 'Blaisorblade' Giarrusso <redacted>
---

 stgit/commands/imprt.py |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/stgit/commands/imprt.py b/stgit/commands/imprt.py
--- a/stgit/commands/imprt.py
+++ b/stgit/commands/imprt.py
@@ -96,7 +96,8 @@ def __parse_mail(filename = None):
 
     # the rest of the patch description
     for line in f:
-        if re.match('---\s*$', line) or re.match('diff -', line):
+        if re.match('---\s*$', line) or re.match('diff -', line) or \
+                re.match('^Index: ', line):
             break
         else:
             descr += line

[patch 06/11] Avoid allowing --undo if it doesn't change anything

From: Paolo 'Blaisorblade' Giarrusso <hidden>
Date: 2016-06-15 22:42:06

From: Paolo 'Blaisorblade' Giarrusso <redacted>

Avoid top/bottom backup files identical to current ones. Simply remove
them.

Also, change restore_old_boundaries() to handle gracefully the new
situation rather than print an exception.

Signed-off-by: Paolo 'Blaisorblade' Giarrusso <redacted>
---

 stgit/commands/push.py |    6 ++++--
 stgit/stack.py         |   17 +++++++++++++----
 2 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/stgit/commands/push.py b/stgit/commands/push.py
--- a/stgit/commands/push.py
+++ b/stgit/commands/push.py
@@ -66,8 +66,10 @@ def func(parser, options, args):
         print 'Undoing the "%s" push...' % patch,
         sys.stdout.flush()
         resolved_all()
-        crt_series.undo_push()
-        print 'done'
+        if crt_series.undo_push():
+            print 'done'
+        else:
+            print 'done (patch unchanged)'
         print_crt_patch()
 
         return
diff --git a/stgit/stack.py b/stgit/stack.py
--- a/stgit/stack.py
+++ b/stgit/stack.py
@@ -170,7 +170,11 @@ class Patch:
 
     def set_bottom(self, string, backup = False):
         if backup:
-            self.__set_field('bottom.old', self.__get_field('bottom'))
+            curr = self.__get_field('bottom')
+            if curr != string:
+                self.__set_field('bottom.old', curr)
+            else:
+                self.__set_field('bottom.old', None)
         self.__set_field('bottom', string)
 
     def get_top(self):
@@ -178,7 +182,11 @@ class Patch:
 
     def set_top(self, string, backup = False):
         if backup:
-            self.__set_field('top.old', self.__get_field('top'))
+            curr = self.__get_field('top')
+            if curr != string:
+                self.__set_field('top.old', curr)
+            else:
+                self.__set_field('top.old', None)
         self.__set_field('top', string)
 
     def restore_old_boundaries(self):
@@ -188,8 +196,9 @@ class Patch:
         if top and bottom:
             self.__set_field('bottom', bottom)
             self.__set_field('top', top)
+            return True
         else:
-            raise StackException, 'No patch undo information'
+            return False
 
     def get_description(self):
         return self.__get_field('description', True)
@@ -571,7 +580,7 @@ class Series:
         patch = Patch(name, self.__patch_dir)
         git.reset()
         self.pop_patch(name)
-        patch.restore_old_boundaries()
+        return patch.restore_old_boundaries()
 
     def pop_patch(self, name):
         """Pops the top patch from the stack

[patch 07/11] Implement fast-forward when only tree (but not commits) match

From: Paolo 'Blaisorblade' Giarrusso <hidden>
Date: 2016-06-15 22:42:06

From: Paolo 'Blaisorblade' Giarrusso <redacted>

When the "bottom" commit and the HEAD don't match, but they refer to the
same tree (for instance after a refresh where only the description
changed), we can still fast-forward, by keeping the same top tree and
calling git-commit-tree (which only requires the tree object) with the new
parent. I've altered git.commit to allow this.

Btw, I've also avoided the use of .commitmsg and switched to piping the
description.

Signed-off-by: Paolo 'Blaisorblade' Giarrusso <redacted>
---

 stgit/git.py   |   30 ++++++++++++++++--------------
 stgit/stack.py |   35 +++++++++++++++++++++++++++++++----
 2 files changed, 47 insertions(+), 18 deletions(-)
diff --git a/stgit/git.py b/stgit/git.py
--- a/stgit/git.py
+++ b/stgit/git.py
@@ -119,8 +119,12 @@ def _output(cmd):
         raise GitException, '%s failed' % str(cmd)
     return string
 
-def _output_one_line(cmd):
+def _output_one_line(cmd, file_desc = None):
     p=popen2.Popen3(cmd)
+    if file_desc != None:
+        for line in file_desc:
+            p.tochild.write(line)
+        p.tochild.close()
     string = p.fromchild.readline().strip()
     if p.wait():
         raise GitException, '%s failed' % str(cmd)
@@ -286,7 +290,7 @@ def update_cache(files = [], force = Fal
     return True
 
 def commit(message, files = [], parents = [], allowempty = False,
-           cache_update = True,
+           cache_update = True, tree_id = None,
            author_name = None, author_email = None, author_date = None,
            committer_name = None, committer_email = None):
     """Commit the current tree to repository
@@ -298,15 +302,15 @@ def commit(message, files = [], parents 
             raise GitException, 'No changes to commit'
 
     # get the commit message
-    f = file('.commitmsg', 'w+')
-    if message[-1:] == '\n':
-        f.write(message)
-    else:
-        print >> f, message
-    f.close()
+    if message[-1:] != '\n':
+        message += '\n'
 
+    must_switch = True
     # write the index to repository
-    tree_id = _output_one_line('git-write-tree')
+    if tree_id == None:
+        tree_id = _output_one_line('git-write-tree')
+    else:
+        must_switch = False
 
     # the commit
     cmd = ''
@@ -326,11 +330,9 @@ def commit(message, files = [], parents 
     for p in parents:
         cmd += ' -p %s' % p
 
-    cmd += ' < .commitmsg'
-
-    commit_id = _output_one_line(cmd)
-    __set_head(commit_id)
-    os.remove('.commitmsg')
+    commit_id = _output_one_line(cmd, message)
+    if must_switch:
+        __set_head(commit_id)
 
     return commit_id
 
diff --git a/stgit/stack.py b/stgit/stack.py
--- a/stgit/stack.py
+++ b/stgit/stack.py
@@ -495,13 +495,40 @@ class Series:
             # top != bottom always since we have a commit for each patch
             if head == bottom:
                 # reset the backup information
-                patch.set_bottom(bottom, backup = True)
+                patch.set_bottom(head, backup = True)
                 patch.set_top(top, backup = True)
 
             else:
-                top = head
-                # stop the fast-forwarding, must do a real merge
-                break
+                head_tree = git.get_commit(head).get_tree()
+                bottom_tree = git.get_commit(bottom).get_tree()
+                if head_tree == bottom_tree:
+                    # We must just reparent this patch and create a new commit
+                    # for it
+                    descr = patch.get_description()
+                    author_name = patch.get_authname()
+                    author_email = patch.get_authemail()
+                    author_date = patch.get_authdate()
+                    committer_name = patch.get_commname()
+                    committer_email = patch.get_commemail()
+
+                    top_tree = git.get_commit(top).get_tree()
+
+                    top = git.commit(message = descr, parents = [head],
+                                     cache_update = False,
+                                     tree_id = top_tree,
+                                     allowempty = True,
+                                     author_name = author_name,
+                                     author_email = author_email,
+                                     author_date = author_date,
+                                     committer_name = committer_name,
+                                     committer_email = committer_email)
+
+                    patch.set_bottom(head, backup = True)
+                    patch.set_top(top, backup = True)
+                else:
+                    top = head
+                    # stop the fast-forwarding, must do a real merge
+                    break
 
             forwarded+=1
             unapplied.remove(name)

[patch 05/11] Make "stg files" output match "quilt files" one

From: Paolo 'Blaisorblade' Giarrusso <hidden>
Date: 2016-06-15 22:42:06

I'm used to doing vi $(quilt files), which is impossible with stgit.
Add an option (-b/--base) to request the normal behaviour, but make it
non-default as the current output is useful.

Signed-off-by: Paolo 'Blaisorblade' Giarrusso <redacted>
---

 stgit/commands/files.py |    5 +++++
 stgit/git.py            |   10 ++++++++++
 2 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/stgit/commands/files.py b/stgit/commands/files.py
--- a/stgit/commands/files.py
+++ b/stgit/commands/files.py
@@ -35,6 +35,9 @@ command. Use the 'diff' or 'status' comm
 
 options = [make_option('-s', '--stat',
                        help = 'show the diff stat',
+                       action = 'store_true'),
+           make_option('-b', '--bare',
+                       help = 'bare file names (useful for scripting)',
                        action = 'store_true')]
 
 
@@ -53,5 +56,7 @@ def func(parser, options, args):
 
     if options.stat:
         print git.diffstat(rev1 = rev1, rev2 = rev2)
+    elif options.bare:
+        print git.barefiles(rev1, rev2)
     else:
         print git.files(rev1, rev2)
diff --git a/stgit/git.py b/stgit/git.py
--- a/stgit/git.py
+++ b/stgit/git.py
@@ -410,6 +410,16 @@ def files(rev1, rev2):
 
     return str.rstrip()
 
+def barefiles(rev1, rev2):
+    """Return the files modified between rev1 and rev2, without status info
+    """
+
+    str = ''
+    for line in _output_lines('git-diff-tree -r %s %s' % (rev1, rev2)):
+        str += '%s\n' % line.rstrip().split(' ',4)[-1].split('\t',1)[-1]
+
+    return str.rstrip()
+
 def checkout(files = [], tree_id = None, force = False):
     """Check out the given or all files
     """

[patch 08/11] Fix "stg clean" when stack is empty

From: Paolo 'Blaisorblade' Giarrusso <hidden>
Date: 2016-06-15 22:42:06

From: Paolo 'Blaisorblade' Giarrusso <redacted>

It crashes on accessing 1st element of an empty array.

Signed-off-by: Paolo 'Blaisorblade' Giarrusso <redacted>
---

 stgit/commands/clean.py |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/stgit/commands/clean.py b/stgit/commands/clean.py
--- a/stgit/commands/clean.py
+++ b/stgit/commands/clean.py
@@ -65,7 +65,8 @@ def func(parser, options, args):
 
     if options.applied:
         applied = crt_series.get_applied()
-        crt_series.pop_patch(applied[0])
+        if applied != []:
+            crt_series.pop_patch(applied[0])
         __delete_empty(applied, True)
 
     if options.unapplied:

[patch 09/11] Allow mailing a given patch list

From: Paolo 'Blaisorblade' Giarrusso <hidden>
Date: 2016-06-15 22:42:06

From: Paolo 'Blaisorblade' Giarrusso <redacted>

I tried to mail a cherry-picked subset of my series and that didn't work - using
stg export and quilt was even worse, so I had to code something.

Signed-off-by: Paolo 'Blaisorblade' Giarrusso <redacted>
---

 stgit/commands/mail.py |   15 ++++++---------
 1 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/stgit/commands/mail.py b/stgit/commands/mail.py
--- a/stgit/commands/mail.py
+++ b/stgit/commands/mail.py
@@ -26,7 +26,7 @@ from stgit.config import config
 
 
 help = 'send a patch or series of patches by e-mail'
-usage = """%prog [options] [<patch>]
+usage = """%prog [options] [<patch> [<patch2...]]
 
 Send a patch or a range of patches (defaulting to the applied patches)
 by e-mail using the 'smtpserver' configuration option. The From
@@ -265,9 +265,6 @@ def func(parser, options, args):
     """Send the patches by e-mail using the patchmail.tmpl file as
     a template
     """
-    if len(args) > 1:
-        parser.error('incorrect number of arguments')
-
     if not config.has_option('stgit', 'smtpserver'):
         raise CmdException, 'smtpserver not defined'
     smtpserver = config.get('stgit', 'smtpserver')
@@ -281,11 +278,11 @@ def func(parser, options, args):
 
     applied = crt_series.get_applied()
 
-    if len(args) == 1:
-        if args[0] in applied:
-            patches = [args[0]]
-        else:
-            raise CmdException, 'Patch "%s" not applied' % args[0]
+    if len(args) >= 1:
+        for patch in args:
+            if not patch in applied:
+                raise CmdException, 'Patch "%s" not applied' % patch
+            patches = args
     elif options.all:
         patches = applied
     elif options.range:

[patch 10/11] Fix "stg mail" address parsing for hyphen

From: Paolo 'Blaisorblade' Giarrusso <hidden>
Date: 2016-06-15 22:42:06

From: Paolo 'Blaisorblade' Giarrusso <redacted>

Tried sending an email cc'ing LKML - watched my postfix queue - and saw
kernel@vger.kernel.org as delivery address! What had happened? StGIT didn't like
"linux-kernel" ! Fix the regexp.

I just added an hyphen to both sections (yes, there are plenty of domain names
including hyphens, and I tested the problem there too). Don't know if other
chars are missing.

Signed-off-by: Paolo 'Blaisorblade' Giarrusso <redacted>
---

 stgit/commands/mail.py |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/stgit/commands/mail.py b/stgit/commands/mail.py
--- a/stgit/commands/mail.py
+++ b/stgit/commands/mail.py
@@ -112,7 +112,7 @@ def __parse_addresses(string):
     """Return a two elements tuple: (from, [to])
     """
     def __addr_list(string):
-        return re.split('.*?([\w\.]+@[\w\.]+)', string)[1:-1:2]
+        return re.split('.*?([-\w\.]+@[-\w\.]+)', string)[1:-1:2]
 
     from_addr_list = []
     to_addr_list = []

Re: [patch 02/11] Make "empty patch" checking optional in "series" command.

From: Catalin Marinas <hidden>
Date: 2016-06-15 22:42:06

On Fri, 2005-09-16 at 21:35 +0200, Paolo 'Blaisorblade' Giarrusso wrote:
That's just too slow, and quilt doesn't do it, so user will live with it.
Don't know if there's a reason to allow dropping the fanciness here
entirely, but I think there's no user doing one-liner scripts with quilt
series. And anyway, for that you can do "stg applied; stg unapplied".

Actually, with this patch you must ask explicitly the checking.
All the 11 patches applied. Thanks.

One note about this one - we could store the tree id as well in the
patch information since it is generated by git.commit() anyway and it
would make the checking simpler. Anyway, in the meantime this patch is
OK.

-- 
Catalin
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help