aboutsummaryrefslogtreecommitdiffstats
path: root/libbe/command/merge.py
diff options
context:
space:
mode:
authorGianluca Montecchi <gian@grys.it>2010-02-10 00:03:38 +0100
committerGianluca Montecchi <gian@grys.it>2010-02-10 00:03:38 +0100
commitc67a5863826771001f009e1ee90262ccb7a2e172 (patch)
tree64c7f83238685959bf40a13c876168071a085556 /libbe/command/merge.py
parenta60e599798d43ba930efc1f8e2f184d3e8262189 (diff)
parent50444209eee408dde7d240fdf59bfc9e82b714ce (diff)
downloadbugseverywhere-c67a5863826771001f009e1ee90262ccb7a2e172.tar.gz
Merged Trevor's tree
Diffstat (limited to 'libbe/command/merge.py')
-rw-r--r--libbe/command/merge.py189
1 files changed, 189 insertions, 0 deletions
diff --git a/libbe/command/merge.py b/libbe/command/merge.py
new file mode 100644
index 0000000..2dff59c
--- /dev/null
+++ b/libbe/command/merge.py
@@ -0,0 +1,189 @@
+# Copyright (C) 2008-2010 Gianluca Montecchi <gian@grys.it>
+# W. Trevor King <wking@drexel.edu>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# 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.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import copy
+import os
+
+import libbe
+import libbe.command
+import libbe.command.util
+
+
+class Merge (libbe.command.Command):
+ """Merge duplicate bugs
+
+ >>> import sys
+ >>> import libbe.bugdir
+ >>> import libbe.comment
+ >>> bd = libbe.bugdir.SimpleBugDir(memory=False)
+ >>> io = libbe.command.StringInputOutput()
+ >>> io.stdout = sys.stdout
+ >>> ui = libbe.command.UserInterface(io=io)
+ >>> ui.storage_callbacks.set_bugdir(bd)
+ >>> cmd = Merge(ui=ui)
+
+ >>> a = bd.bug_from_uuid('a')
+ >>> a.comment_root.time = 0
+ >>> dummy = a.new_comment('Testing')
+ >>> dummy.time = 1
+ >>> dummy = dummy.new_reply('Testing...')
+ >>> dummy.time = 2
+ >>> b = bd.bug_from_uuid('b')
+ >>> b.status = 'open'
+ >>> b.comment_root.time = 0
+ >>> dummy = b.new_comment('1 2')
+ >>> dummy.time = 1
+ >>> dummy = dummy.new_reply('1 2 3 4')
+ >>> dummy.time = 2
+
+ >>> ret = ui.run(cmd, args=['/a', '/b'])
+ Merged bugs #abc/a# and #abc/b#
+ >>> bd.flush_reload()
+ >>> a = bd.bug_from_uuid('a')
+ >>> a.load_comments()
+ >>> a_comments = sorted([c for c in a.comments()],
+ ... cmp=libbe.comment.cmp_time)
+ >>> mergeA = a_comments[0]
+ >>> mergeA.time = 3
+ >>> print a.string(show_comments=True) # doctest: +ELLIPSIS
+ ID : a
+ Short name : abc/a
+ Severity : minor
+ Status : open
+ Assigned :
+ Reporter :
+ Creator : John Doe <jdoe@example.com>
+ Created : ...
+ Bug A
+ --------- Comment ---------
+ Name: abc/a/...
+ From: ...
+ Date: ...
+ <BLANKLINE>
+ Testing
+ --------- Comment ---------
+ Name: abc/a/...
+ From: ...
+ Date: ...
+ <BLANKLINE>
+ Testing...
+ --------- Comment ---------
+ Name: abc/a/...
+ From: ...
+ Date: ...
+ <BLANKLINE>
+ Merged from bug #abc/b#
+ --------- Comment ---------
+ Name: abc/a/...
+ From: ...
+ Date: ...
+ <BLANKLINE>
+ 1 2
+ --------- Comment ---------
+ Name: abc/a/...
+ From: ...
+ Date: ...
+ <BLANKLINE>
+ 1 2 3 4
+ >>> b = bd.bug_from_uuid('b')
+ >>> b.load_comments()
+ >>> b_comments = sorted([c for c in b.comments()],
+ ... libbe.comment.cmp_time)
+ >>> mergeB = b_comments[0]
+ >>> mergeB.time = 3
+ >>> print b.string(show_comments=True) # doctest: +ELLIPSIS
+ ID : b
+ Short name : abc/b
+ Severity : minor
+ Status : closed
+ Assigned :
+ Reporter :
+ Creator : Jane Doe <jdoe@example.com>
+ Created : ...
+ Bug B
+ --------- Comment ---------
+ Name: abc/b/...
+ From: ...
+ Date: ...
+ <BLANKLINE>
+ 1 2
+ --------- Comment ---------
+ Name: abc/b/...
+ From: ...
+ Date: ...
+ <BLANKLINE>
+ 1 2 3 4
+ --------- Comment ---------
+ Name: abc/b/...
+ From: ...
+ Date: ...
+ <BLANKLINE>
+ Merged into bug #abc/a#
+ >>> print b.status
+ closed
+ >>> ui.cleanup()
+ >>> bd.cleanup()
+ """
+ name = 'merge'
+
+ def __init__(self, *args, **kwargs):
+ libbe.command.Command.__init__(self, *args, **kwargs)
+ self.args.extend([
+ libbe.command.Argument(
+ name='bug-id', metavar='BUG-ID', default=None,
+ completion_callback=libbe.command.util.complete_bug_id),
+ libbe.command.Argument(
+ name='bug-id-to-merge', metavar='BUG-ID', default=None,
+ completion_callback=libbe.command.util.complete_bug_id),
+ ])
+
+ def _run(self, **params):
+ bugdir = self._get_bugdir()
+ bugA,dummy_comment = \
+ libbe.command.util.bug_comment_from_user_id(
+ bugdir, params['bug-id'])
+ bugA.load_comments()
+ bugB,dummy_comment = \
+ libbe.command.util.bug_comment_from_user_id(
+ bugdir, params['bug-id-to-merge'])
+ bugB.load_comments()
+ mergeA = bugA.new_comment('Merged from bug #%s#' % bugB.id.long_user())
+ newCommTree = copy.deepcopy(bugB.comment_root)
+ for comment in newCommTree.traverse(): # all descendant comments
+ comment.bug = bugA
+ # uuids must be unique in storage
+ if comment.alt_id == None:
+ comment.storage = None
+ comment.alt_id = comment.uuid
+ comment.storage = bugdir.storage
+ comment.uuid = libbe.util.id.uuid_gen()
+ comment.save() # force onto disk under bugA
+
+ for comment in newCommTree: # just the child comments
+ mergeA.add_reply(comment, allow_time_inversion=True)
+ bugB.new_comment('Merged into bug #%s#' % bugA.id.long_user())
+ bugB.status = 'closed'
+ print >> self.stdout, 'Merged bugs #%s# and #%s#' \
+ % (bugA.id.user(), bugB.id.user())
+ return 0
+
+ def _long_help(self):
+ return """
+The second bug (B) is merged into the first (A). This adds merge
+comments to both bugs, closes B, and appends B's comment tree to A's
+merge comment.
+"""