From: "Karl Hasselström" <kha@treskal.com>
To: Catalin Marinas <catalin.marinas@gmail.com>
Cc: git@vger.kernel.org, "David Kågedal" <davidk@lysator.liu.se>
Subject: [StGit PATCH 05/10] Add "stg coalesce"
Date: Sun, 25 Nov 2007 21:51:25 +0100 [thread overview]
Message-ID: <20071125205125.7823.47538.stgit@yoghurt> (raw)
In-Reply-To: <20071125203717.7823.70046.stgit@yoghurt>
It coalesces two or more consecutive applied patches, with no need to
touch index/worktree, and no possibiliy of conflicts.
Future improvements could relax the "consecutive" and "applied"
restrictions, by building a new chain of commits just like "stg push"
will do once it's been converted to the new infrastructure.
Signed-off-by: Karl Hasselström <kha@treskal.com>
---
contrib/stgit-completion.bash | 2 +
stgit/commands/coalesce.py | 84 +++++++++++++++++++++++++++++++++++++++++
stgit/main.py | 2 +
stgit/utils.py | 11 +++++
t/t2600-coalesce.sh | 31 +++++++++++++++
5 files changed, 130 insertions(+), 0 deletions(-)
create mode 100644 stgit/commands/coalesce.py
create mode 100755 t/t2600-coalesce.sh
diff --git a/contrib/stgit-completion.bash b/contrib/stgit-completion.bash
index b3b23d4..b02eb64 100644
--- a/contrib/stgit-completion.bash
+++ b/contrib/stgit-completion.bash
@@ -18,6 +18,7 @@ _stg_commands="
diff
clean
clone
+ coalesce
commit
cp
edit
@@ -238,6 +239,7 @@ _stg ()
# repository commands
id) _stg_patches $command _all_patches ;;
# stack commands
+ coalesce) _stg_patches $command _applied_patches ;;
float) _stg_patches $command _all_patches ;;
goto) _stg_patches $command _all_other_patches ;;
hide) _stg_patches $command _unapplied_patches ;;
diff --git a/stgit/commands/coalesce.py b/stgit/commands/coalesce.py
new file mode 100644
index 0000000..c4c1cf8
--- /dev/null
+++ b/stgit/commands/coalesce.py
@@ -0,0 +1,84 @@
+# -*- coding: utf-8 -*-
+
+__copyright__ = """
+Copyright (C) 2007, Karl Hasselström <kha@treskal.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2 as
+published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+"""
+
+from optparse import make_option
+from stgit.out import *
+from stgit import utils
+from stgit.commands import common
+from stgit.lib import git, transaction
+
+help = 'coalesce two or more patches into one'
+usage = """%prog [options] <patches>
+
+Coalesce two or more patches, creating one big patch that contains all
+their changes. The patches must all be applied, and must be
+consecutive."""
+
+directory = common.DirectoryHasRepositoryLib()
+options = [make_option('-n', '--name', help = 'name of coalesced patch'),
+ make_option('-m', '--message',
+ help = 'commit message of coalesced patch')]
+
+def _coalesce(stack, name, msg, patches):
+ applied = stack.patchorder.applied
+
+ # Make sure the patches are consecutive.
+ applied_ix = dict((applied[i], i) for i in xrange(len(applied)))
+ ixes = list(sorted(applied_ix[p] for p in patches))
+ i0, i1 = ixes[0], ixes[-1]
+ if i1 - i0 + 1 != len(patches):
+ raise common.CmdException('The patches must be consecutive')
+
+ # Make a commit for the coalesced patch.
+ def bad_name(pn):
+ return pn not in patches and stack.patches.exists(pn)
+ if name and bad_name(name):
+ raise common.CmdException('Patch name "%s" already taken')
+ ps = [stack.patches.get(pn) for pn in applied[i0:i1+1]]
+ if msg == None:
+ msg = '\n\n'.join('%s\n\n%s' % (p.name.ljust(70, '-'),
+ p.commit.data.message)
+ for p in ps)
+ msg = utils.edit_string(msg, '.stgit-coalesce.txt').strip()
+ if not name:
+ name = utils.make_patch_name(msg, bad_name)
+ cd = git.Commitdata(tree = ps[-1].commit.data.tree,
+ parents = ps[0].commit.data.parents, message = msg)
+
+ # Rewrite refs.
+ trans = transaction.StackTransaction(stack, 'stg coalesce')
+ for pn in applied[i0:i1+1]:
+ trans.patches[pn] = None
+ parent = trans.patches[name] = stack.repository.commit(cd)
+ trans.applied = applied[:i0]
+ trans.applied.append(name)
+ for pn in applied[i1+1:]:
+ p = stack.patches.get(pn)
+ parent = trans.patches[pn] = stack.repository.commit(
+ p.commit.data.set_parent(parent))
+ trans.applied.append(pn)
+ trans.run()
+
+def func(parser, options, args):
+ stack = directory.repository.current_stack
+ applied = set(stack.patchorder.applied)
+ patches = set(common.parse_patches(args, list(stack.patchorder.applied)))
+ if len(patches) < 2:
+ raise common.CmdException('Need at least two patches')
+ _coalesce(stack, options.name, options.message, patches)
diff --git a/stgit/main.py b/stgit/main.py
index deaac91..384803b 100644
--- a/stgit/main.py
+++ b/stgit/main.py
@@ -64,6 +64,7 @@ commands = Commands({
'diff': 'diff',
'clean': 'clean',
'clone': 'clone',
+ 'coalesce': 'coalesce',
'commit': 'commit',
'edit': 'edit',
'export': 'export',
@@ -108,6 +109,7 @@ stackcommands = (
'applied',
'branch',
'clean',
+ 'coalesce',
'commit',
'float',
'goto',
diff --git a/stgit/utils.py b/stgit/utils.py
index b3f6232..688276c 100644
--- a/stgit/utils.py
+++ b/stgit/utils.py
@@ -189,6 +189,17 @@ def call_editor(filename):
raise EditorException, 'editor failed, exit code: %d' % err
out.done()
+def edit_string(s, filename):
+ f = file(filename, 'w')
+ f.write(s)
+ f.close()
+ call_editor(filename)
+ f = file(filename)
+ s = f.read()
+ f.close()
+ os.remove(filename)
+ return s
+
def patch_name_from_msg(msg):
"""Return a string to be used as a patch name. This is generated
from the top line of the string passed as argument."""
diff --git a/t/t2600-coalesce.sh b/t/t2600-coalesce.sh
new file mode 100755
index 0000000..f13a309
--- /dev/null
+++ b/t/t2600-coalesce.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+test_description='Run "stg coalesce"'
+
+. ./test-lib.sh
+
+test_expect_success 'Initialize StGit stack' '
+ stg init &&
+ for i in 0 1 2 3; do
+ stg new p$i -m "foo $i" &&
+ echo "foo $i" >> foo.txt &&
+ git add foo.txt &&
+ stg refresh
+ done
+'
+
+test_expect_success 'Coalesce some patches' '
+ [ "$(echo $(stg applied))" = "p0 p1 p2 p3" ] &&
+ [ "$(echo $(stg unapplied))" = "" ] &&
+ stg coalesce --name=q0 --message="wee woo" p1 p2 &&
+ [ "$(echo $(stg applied))" = "p0 q0 p3" ] &&
+ [ "$(echo $(stg unapplied))" = "" ]
+'
+
+test_expect_success 'Coalesce at stack top' '
+ stg coalesce --name=q1 --message="wee woo wham" q0 p3 &&
+ [ "$(echo $(stg applied))" = "p0 q1" ] &&
+ [ "$(echo $(stg unapplied))" = "" ]
+'
+
+test_done
next prev parent reply other threads:[~2007-11-25 20:52 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-11-25 20:50 [StGit PATCH 00/10] Infrastructure rewrite series Karl Hasselström
2007-11-25 20:51 ` [StGit PATCH 01/10] New StGit core infrastructure: repository operations Karl Hasselström
2007-11-25 20:51 ` [StGit PATCH 02/10] Write metadata files used by the old infrastructure Karl Hasselström
2007-11-25 20:51 ` [StGit PATCH 03/10] Upgrade older stacks to newest version Karl Hasselström
2007-11-25 20:51 ` [StGit PATCH 04/10] Let "stg clean" use the new infrastructure Karl Hasselström
2007-11-25 20:51 ` Karl Hasselström [this message]
2007-11-25 20:51 ` [StGit PATCH 06/10] Let "stg applied" and "stg unapplied" " Karl Hasselström
2007-11-25 20:51 ` [StGit PATCH 07/10] Teach the new infrastructure about the index and worktree Karl Hasselström
2007-11-26 8:31 ` Karl Hasselström
2007-11-26 8:56 ` David Kågedal
2007-11-26 10:44 ` Karl Hasselström
2007-11-25 20:51 ` [StGit PATCH 08/10] Let "stg clean" use the new transaction primitives Karl Hasselström
2007-11-25 20:51 ` [StGit PATCH 09/10] Let "stg goto" use the new infrastructure Karl Hasselström
2007-11-25 20:51 ` [StGit PATCH 10/10] Convert "stg uncommit" to " Karl Hasselström
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20071125205125.7823.47538.stgit@yoghurt \
--to=kha@treskal.com \
--cc=catalin.marinas@gmail.com \
--cc=davidk@lysator.liu.se \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.